danicoin/tests/IntegrationTests/IntegrationTests.cpp
2016-01-18 15:33:29 +00:00

221 lines
6.2 KiB
C++

// Copyright (c) 2011-2016 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "gtest/gtest.h"
#include <Logging/LoggerRef.h>
#include "../IntegrationTestLib/BaseFunctionalTests.h"
#include "../IntegrationTestLib/NodeObserver.h"
#include "WalletLegacy/WalletLegacy.h"
#include "WalletLegacyObserver.h"
using namespace CryptoNote;
using namespace Logging;
extern Tests::Common::BaseFunctionalTestsConfig baseCfg;
// extern System::Dispatcher globalDispatcher;
struct TotalWalletBalance {
TotalWalletBalance(uint64_t actual_ = 0, uint64_t pending_ = 0)
: actual(actual_), pending(pending_) {}
TotalWalletBalance(IWalletLegacy& wallet)
: TotalWalletBalance(wallet.actualBalance(), wallet.pendingBalance()) {}
uint64_t actual = 0;
uint64_t pending = 0;
uint64_t total() const {
return actual + pending;
}
};
class IntegrationTest : public Tests::Common::BaseFunctionalTests, public ::testing::Test {
public:
IntegrationTest() :
currency(CryptoNote::CurrencyBuilder(log).testnet(true).currency()),
BaseFunctionalTests(currency, dispatcher, baseCfg),
logger(log, "IntegrationTest") {
}
~IntegrationTest() {
wallets.clear();
inodes.clear();
stopTestnet();
}
void makeINodes() {
for (auto& n : nodeDaemons) {
std::unique_ptr<INode> node;
n->makeINode(node);
inodes.push_back(std::move(node));
}
}
void makeWallets() {
for (auto& n: inodes) {
std::unique_ptr<CryptoNote::IWalletLegacy> wallet(new CryptoNote::WalletLegacy(m_currency, *n));
std::unique_ptr<WalletLegacyObserver> observer(new WalletLegacyObserver());
wallet->initAndGenerate(walletPassword);
wallet->addObserver(observer.get());
wallets.push_back(std::move(wallet));
walletObservers.push_back(std::move(observer));
}
}
void mineBlocksFor(size_t node, const std::string& address, size_t blockCount) {
auto prevHeight = nodeDaemons[node]->getLocalHeight();
nodeDaemons[node]->startMining(1, address);
do {
std::this_thread::sleep_for(std::chrono::seconds(1));
} while (prevHeight + blockCount < nodeDaemons[node]->getLocalHeight());
nodeDaemons[node]->stopMining();
}
void printWalletBalances() {
for (auto& w: wallets) {
logger(INFO) << "Wallet " << w->getAddress().substr(0, 6);
logger(INFO) << " " << currency.formatAmount(w->actualBalance()) << " actual / " << currency.formatAmount(w->pendingBalance()) << " pending";
}
}
void mineEmptyBlocks(size_t nodeNum, size_t blocksCount) {
}
void mineMoneyForWallet(size_t nodeNum, size_t walletNum) {
auto& wallet = *wallets[walletNum];
auto& node = *nodeDaemons[nodeNum];
node.startMining(1, wallet.getAddress());
walletObservers[walletNum]->waitActualBalanceChange();
node.stopMining();
while (node.getLocalHeight() > walletObservers[walletNum]->getCurrentHeight()) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
std::error_code transferMoney(size_t srcWallet, size_t dstWallet, uint64_t amount, uint64_t fee) {
logger(INFO)
<< "Transferring from " << wallets[srcWallet]->getAddress().substr(0, 6)
<< " to " << wallets[dstWallet]->getAddress().substr(0, 6) << " " << currency.formatAmount(amount);
CryptoNote::WalletLegacyTransfer tr;
tr.address = wallets[dstWallet]->getAddress();
tr.amount = amount;
std::error_code result;
auto txId = wallets[srcWallet]->sendTransaction(tr, fee);
logger(DEBUGGING) << "Transaction id = " << txId;
return walletObservers[srcWallet]->waitSendResult(txId);
}
void checkIncomingTransfer(size_t dstWallet, uint64_t amount) {
startMining(1);
auto txId = walletObservers[dstWallet]->waitExternalTransaction();
stopMining();
WalletLegacyTransaction txInfo;
ASSERT_TRUE(wallets[dstWallet]->getTransaction(txId, txInfo));
ASSERT_EQ(txInfo.totalAmount, amount);
}
System::Dispatcher dispatcher;
std::string walletPassword = "pass";
CryptoNote::Currency currency;
Logging::ConsoleLogger log;
Logging::LoggerRef logger;
std::vector<std::unique_ptr<INode>> inodes;
std::vector<std::unique_ptr<IWalletLegacy>> wallets;
std::vector<std::unique_ptr<WalletLegacyObserver>> walletObservers;
};
TEST_F(IntegrationTest, Wallet2Wallet) {
const uint64_t FEE = 1000000;
launchTestnet(2);
logger(INFO) << "Testnet launched";
makeINodes();
makeWallets();
logger(INFO) << "Created wallets";
mineMoneyForWallet(0, 0);
logger(INFO) << "Mined money";
printWalletBalances();
TotalWalletBalance w0pre(*wallets[0]);
TotalWalletBalance w1pre(*wallets[1]);
auto sendAmount = w0pre.actual / 2;
ASSERT_TRUE(!transferMoney(0, 1, sendAmount, currency.minimumFee()));
ASSERT_NO_FATAL_FAILURE(checkIncomingTransfer(1, sendAmount));
printWalletBalances();
TotalWalletBalance w0after(*wallets[0]);
TotalWalletBalance w1after(*wallets[1]);
// check total
ASSERT_EQ(w0pre.total() + w1pre.total() - currency.minimumFee(), w0after.total() + w1after.total());
// check diff
ASSERT_EQ(sendAmount, w1after.total() - w1pre.total());
}
TEST_F(IntegrationTest, BlockPropagationSpeed) {
launchTestnet(3, Line);
makeINodes();
{
std::unique_ptr<CryptoNote::INode>& localNode = inodes.front();
std::unique_ptr<CryptoNote::INode>& remoteNode = inodes.back();
std::unique_ptr<CryptoNote::IWalletLegacy> wallet;
makeWallet(wallet, localNode);
NodeObserver localObserver(*localNode);
NodeObserver remoteObserver(*remoteNode);
const size_t BLOCKS_COUNT = 10;
nodeDaemons.front()->startMining(1, wallet->getAddress());
for (size_t blockNumber = 0; blockNumber < BLOCKS_COUNT; ++blockNumber) {
uint32_t localHeight = localObserver.waitLastKnownBlockHeightUpdated();
uint32_t remoteHeight = 0;
while (remoteHeight != localHeight) {
ASSERT_TRUE(remoteObserver.waitLastKnownBlockHeightUpdated(std::chrono::milliseconds(5000), remoteHeight));
}
logger(INFO) << "Iteration " << blockNumber + 1 << ": " << "height = " << localHeight;
}
nodeDaemons.front()->stopMining();
}
}