danicoin/tests/unit_tests/test_inprocess_node.cpp

288 lines
9.3 KiB
C++
Raw Normal View History

// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "gtest/gtest.h"
#include <system_error>
#include "EventWaiter.h"
#include "ICoreStub.h"
#include "ICryptonoteProtocolQueryStub.h"
#include "inprocess_node/InProcessNode.h"
struct CallbackStatus {
CallbackStatus() {}
bool wait() { return waiter.wait_for(std::chrono::milliseconds(3000)); }
bool ok() { return waiter.wait_for(std::chrono::milliseconds(3000)) && !static_cast<bool>(code); }
void setStatus(const std::error_code& ec) { code = ec; waiter.notify(); }
std::error_code getStatus() const { return code; }
std::error_code code;
EventWaiter waiter;
};
class InProcessNode : public ::testing::Test {
public:
InProcessNode() : node(coreStub, protocolQueryStub) {}
void SetUp();
protected:
void initNode();
ICoreStub coreStub;
ICryptonoteProtocolQueryStub protocolQueryStub;
CryptoNote::InProcessNode node;
};
void InProcessNode::SetUp() {
initNode();
}
void InProcessNode::initNode() {
CallbackStatus status;
node.init([&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.ok());
}
TEST_F(InProcessNode, initOk) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
CallbackStatus status;
newNode.init([&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.ok());
}
TEST_F(InProcessNode, doubleInit) {
CallbackStatus status;
node.init([&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
std::error_code ec = status.getStatus();
ASSERT_NE(ec, std::error_code());
}
TEST_F(InProcessNode, shutdownNotInited) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
ASSERT_FALSE(newNode.shutdown());
}
TEST_F(InProcessNode, shutdown) {
ASSERT_TRUE(node.shutdown());
}
TEST_F(InProcessNode, getPeersCountSuccess) {
protocolQueryStub.setPeerCount(1);
ASSERT_EQ(1, node.getPeerCount());
}
TEST_F(InProcessNode, getLastLocalBlockHeightSuccess) {
crypto::hash ignore;
coreStub.set_blockchain_top(10, ignore, true);
ASSERT_EQ(10, node.getLastLocalBlockHeight());
}
TEST_F(InProcessNode, getLastLocalBlockHeightFailure) {
crypto::hash ignore;
coreStub.set_blockchain_top(10, ignore, false);
ASSERT_ANY_THROW(node.getLastLocalBlockHeight());
}
TEST_F(InProcessNode, getLastKnownBlockHeightSuccess) {
protocolQueryStub.setObservedHeight(10);
ASSERT_EQ(10, node.getLastKnownBlockHeight());
}
TEST_F(InProcessNode, getTransactionOutsGlobalIndicesSuccess) {
crypto::hash ignore;
std::vector<uint64_t> indices;
std::vector<uint64_t> expectedIndices;
uint64_t start = 10;
std::generate_n(std::back_inserter(expectedIndices), 5, [&start] () { return start++; });
coreStub.set_outputs_gindexs(expectedIndices, true);
CallbackStatus status;
node.getTransactionOutsGlobalIndices(ignore, indices, [&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.ok());
ASSERT_EQ(expectedIndices.size(), indices.size());
std::sort(indices.begin(), indices.end());
ASSERT_TRUE(std::equal(indices.begin(), indices.end(), expectedIndices.begin()));
}
TEST_F(InProcessNode, getTransactionOutsGlobalIndicesFailure) {
crypto::hash ignore;
std::vector<uint64_t> indices;
coreStub.set_outputs_gindexs(indices, false);
CallbackStatus status;
node.getTransactionOutsGlobalIndices(ignore, indices, [&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
ASSERT_NE(std::error_code(), status.getStatus());
}
TEST_F(InProcessNode, getRandomOutsByAmountsSuccess) {
crypto::public_key ignoredPublicKey;
crypto::secret_key ignoredSectetKey;
crypto::generate_keys(ignoredPublicKey, ignoredSectetKey);
cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response expectedResp;
cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount out;
out.amount = 10;
out.outs.push_back({ 11, ignoredPublicKey });
expectedResp.outs.push_back(out);
coreStub.set_random_outs(expectedResp, true);
std::vector<cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount> outs;
CallbackStatus status;
node.getRandomOutsByAmounts({1,2,3}, 1, outs, [&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.ok());
ASSERT_EQ(1, outs.size());
ASSERT_EQ(10, outs[0].amount);
ASSERT_EQ(1, outs[0].outs.size());
ASSERT_EQ(11, outs[0].outs.front().global_amount_index);
}
TEST_F(InProcessNode, getRandomOutsByAmountsFailure) {
cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response expectedResp;
coreStub.set_random_outs(expectedResp, false);
std::vector<cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount> outs;
CallbackStatus status;
node.getRandomOutsByAmounts({1,2,3}, 1, outs, [&status] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
ASSERT_NE(std::error_code(), status.getStatus());
}
TEST_F(InProcessNode, getPeerCountUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
ASSERT_ANY_THROW(newNode.getPeerCount());
}
TEST_F(InProcessNode, getLastLocalBlockHeightUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
ASSERT_ANY_THROW(newNode.getLastLocalBlockHeight());
}
TEST_F(InProcessNode, getLastKnownBlockHeightUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
ASSERT_ANY_THROW(newNode.getLastKnownBlockHeight());
}
TEST_F(InProcessNode, getNewBlocksUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
std::list<crypto::hash> knownBlockIds;
std::list<cryptonote::block_complete_entry> newBlocks;
uint64_t startHeight;
CallbackStatus status;
newNode.getNewBlocks(std::move(knownBlockIds), newBlocks, startHeight, [&] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
ASSERT_NE(std::error_code(), status.getStatus());
}
TEST_F(InProcessNode, getTransactionOutsGlobalIndicesUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
std::vector<uint64_t> outsGlobalIndices;
CallbackStatus status;
newNode.getTransactionOutsGlobalIndices(crypto::hash(), outsGlobalIndices, [&] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
ASSERT_NE(std::error_code(), status.getStatus());
}
TEST_F(InProcessNode, getRandomOutsByAmountsUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
std::vector<cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount> outs;
CallbackStatus status;
newNode.getRandomOutsByAmounts({1,2,3}, 1, outs, [&] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
ASSERT_NE(std::error_code(), status.getStatus());
}
TEST_F(InProcessNode, relayTransactionUninitialized) {
CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub);
CallbackStatus status;
newNode.relayTransaction(cryptonote::Transaction(), [&] (std::error_code ec) { status.setStatus(ec); });
ASSERT_TRUE(status.wait());
ASSERT_NE(std::error_code(), status.getStatus());
}
TEST_F(InProcessNode, getLastLocalBlockTimestamp) {
class GetBlockTimestampCore : public ICoreStub {
public:
GetBlockTimestampCore(uint64_t timestamp) : timestamp(timestamp) {}
virtual bool get_blockchain_top(uint64_t& height, crypto::hash& top_id) override {
return true;
}
virtual bool getBlockByHash(const crypto::hash &h, cryptonote::Block &blk) override {
blk.timestamp = timestamp;
return true;
}
uint64_t timestamp;
};
uint64_t expectedTimestamp = 1234567890;
GetBlockTimestampCore core(expectedTimestamp);
CryptoNote::InProcessNode newNode(core, protocolQueryStub);
CallbackStatus initStatus;
newNode.init([&initStatus] (std::error_code ec) { initStatus.setStatus(ec); });
ASSERT_TRUE(initStatus.wait());
uint64_t timestamp = newNode.getLastLocalBlockTimestamp();
ASSERT_EQ(expectedTimestamp, timestamp);
}
TEST_F(InProcessNode, getLastLocalBlockTimestampError) {
class GetBlockTimestampErrorCore : public ICoreStub {
public:
virtual bool get_blockchain_top(uint64_t& height, crypto::hash& top_id) override {
return true;
}
virtual bool getBlockByHash(const crypto::hash &h, cryptonote::Block &blk) override {
return false;
}
};
GetBlockTimestampErrorCore core;
CryptoNote::InProcessNode newNode(core, protocolQueryStub);
CallbackStatus initStatus;
newNode.init([&initStatus] (std::error_code ec) { initStatus.setStatus(ec); });
ASSERT_TRUE(initStatus.wait());
ASSERT_THROW(newNode.getLastLocalBlockTimestamp(), std::exception);
}
//TODO: make relayTransaction unit test
//TODO: make getNewBlocks unit test
//TODO: make queryBlocks unit test