Merge #9974: Add basic Qt wallet test

9576b01 Enable xvfb in travis to allow running test_bitcoin-qt (Russell Yanofsky)
9e6817e Add new test_bitcoin-qt static library dependencies (Russell Yanofsky)
2754ef1 Add simple qt wallet test sending a transaction (Russell Yanofsky)
b61b34c Add braces to if statements in Qt test_main (Russell Yanofsky)
cc9503c Make qt test compatible with TestChain100Setup framework (Russell Yanofsky)
91e3035 Make test_bitcoin.cpp compatible with Qt Test framework (Russell Yanofsky)

Tree-SHA512: da491181848b8c39138e997ae5ff2df0b16eef2d9cdd0a965229b1a28d4fa862d5f1ef314a1736e5050e88858f329124d15c689659fc6e50fefde769ba24e523
This commit is contained in:
Jonas Schnelli 2017-03-17 14:30:48 +01:00
commit b9f930b383
No known key found for this signature in database
GPG key ID: 1EB776BB03C7922D
9 changed files with 206 additions and 38 deletions

View file

@ -32,7 +32,7 @@ env:
# bitcoind
- HOST=x86_64-unknown-linux-gnu PACKAGES="bc python3-zmq" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER"
# No wallet
- HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
- HOST=x86_64-unknown-linux-gnu PACKAGES="python3 xvfb" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
# Cross-Mac
- HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy"
@ -50,6 +50,8 @@ before_script:
- if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
# Start xvfb if needed, as documented at https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
- if [ "$RUN_TESTS" = "true" -a "${DEP_OPTS#*NO_QT=1}" = "$DEP_OPTS" ]; then export DISPLAY=:99.0; /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; fi
script:
- if [ "$CHECK_DOC" = 1 -a "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys; fi
- if [ "$CHECK_DOC" = 1 -a "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then git fetch --unshallow; fi

View file

@ -11,7 +11,9 @@ TEST_QT_MOC_CPP = \
qt/test/moc_uritests.cpp
if ENABLE_WALLET
TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp
TEST_QT_MOC_CPP += \
qt/test/moc_paymentservertests.cpp \
qt/test/moc_wallettests.cpp
endif
TEST_QT_H = \
@ -19,7 +21,16 @@ TEST_QT_H = \
qt/test/rpcnestedtests.h \
qt/test/uritests.h \
qt/test/paymentrequestdata.h \
qt/test/paymentservertests.h
qt/test/paymentservertests.h \
qt/test/wallettests.h
TEST_BITCOIN_CPP = \
test/test_bitcoin.cpp \
test/testutil.cpp
TEST_BITCOIN_H = \
test/test_bitcoin.h \
test/testutil.h
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
@ -29,10 +40,13 @@ qt_test_test_bitcoin_qt_SOURCES = \
qt/test/rpcnestedtests.cpp \
qt/test/test_main.cpp \
qt/test/uritests.cpp \
$(TEST_QT_H)
$(TEST_QT_H) \
$(TEST_BITCOIN_CPP) \
$(TEST_BITCOIN_H)
if ENABLE_WALLET
qt_test_test_bitcoin_qt_SOURCES += \
qt/test/paymentservertests.cpp
qt/test/paymentservertests.cpp \
qt/test/wallettests.cpp
endif
nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)

View file

@ -127,6 +127,7 @@ BITCOIN_TESTS =\
test/streams_tests.cpp \
test/test_bitcoin.cpp \
test/test_bitcoin.h \
test/test_bitcoin_main.cpp \
test/test_random.h \
test/testutil.cpp \
test/testutil.h \

View file

@ -148,9 +148,13 @@ void RPCNestedTests::rpcNestedTests()
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
#endif
UnloadBlockIndex();
delete pcoinsTip;
pcoinsTip = nullptr;
delete pcoinsdbview;
pcoinsdbview = nullptr;
delete pblocktree;
pblocktree = nullptr;
boost::filesystem::remove_all(boost::filesystem::path(path));
}

View file

@ -7,7 +7,6 @@
#endif
#include "chainparams.h"
#include "key.h"
#include "rpcnestedtests.h"
#include "util.h"
#include "uritests.h"
@ -15,20 +14,31 @@
#ifdef ENABLE_WALLET
#include "paymentservertests.h"
#include "wallettests.h"
#endif
#include <QCoreApplication>
#include <QApplication>
#include <QObject>
#include <QTest>
#include <openssl/ssl.h>
#if defined(QT_STATICPLUGIN) && QT_VERSION < 0x050000
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
#if QT_VERSION < 0x050000
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
#else
#if defined(QT_QPA_PLATFORM_XCB)
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_WINDOWS)
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_COCOA)
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
#endif
#endif
#endif
extern void noui_connect();
@ -36,7 +46,6 @@ extern void noui_connect();
// This is all you need to run all the tests
int main(int argc, char *argv[])
{
ECC_Start();
SetupEnvironment();
SetupNetworking();
SelectParams(CBaseChainParams::MAIN);
@ -45,27 +54,36 @@ int main(int argc, char *argv[])
bool fInvalid = false;
// Don't remove this, it's needed to access
// QCoreApplication:: in the tests
QCoreApplication app(argc, argv);
// QApplication:: and QCoreApplication:: in the tests
QApplication app(argc, argv);
app.setApplicationName("Bitcoin-Qt-test");
SSL_library_init();
URITests test1;
if (QTest::qExec(&test1) != 0)
if (QTest::qExec(&test1) != 0) {
fInvalid = true;
}
#ifdef ENABLE_WALLET
PaymentServerTests test2;
if (QTest::qExec(&test2) != 0)
if (QTest::qExec(&test2) != 0) {
fInvalid = true;
}
#endif
RPCNestedTests test3;
if (QTest::qExec(&test3) != 0)
if (QTest::qExec(&test3) != 0) {
fInvalid = true;
}
CompatTests test4;
if (QTest::qExec(&test4) != 0)
if (QTest::qExec(&test4) != 0) {
fInvalid = true;
}
#ifdef ENABLE_WALLET
WalletTests test5;
if (QTest::qExec(&test5) != 0) {
fInvalid = true;
}
#endif
ECC_Stop();
return fInvalid;
}

104
src/qt/test/wallettests.cpp Normal file
View file

@ -0,0 +1,104 @@
#include "wallettests.h"
#include "qt/bitcoinamountfield.h"
#include "qt/optionsmodel.h"
#include "qt/platformstyle.h"
#include "qt/qvalidatedlineedit.h"
#include "qt/sendcoinsdialog.h"
#include "qt/sendcoinsentry.h"
#include "qt/transactiontablemodel.h"
#include "qt/walletmodel.h"
#include "test/test_bitcoin.h"
#include "validation.h"
#include "wallet/wallet.h"
#include <QAbstractButton>
#include <QApplication>
#include <QTimer>
#include <QVBoxLayout>
namespace
{
//! Press "Yes" button in modal send confirmation dialog.
void ConfirmSend()
{
QTimer::singleShot(0, Qt::PreciseTimer, []() {
for (QWidget* widget : QApplication::topLevelWidgets()) {
if (widget->inherits("SendConfirmationDialog")) {
SendConfirmationDialog* dialog = qobject_cast<SendConfirmationDialog*>(widget);
QAbstractButton* button = dialog->button(QMessageBox::Yes);
button->setEnabled(true);
button->click();
}
}
});
}
//! Send coins to address and return txid.
uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CBitcoinAddress& address, CAmount amount)
{
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(address.ToString()));
entry->findChild<BitcoinAmountField*>("payAmount")->setValue(amount);
uint256 txid;
boost::signals2::scoped_connection c = wallet.NotifyTransactionChanged.connect([&txid](CWallet*, const uint256& hash, ChangeType status) {
if (status == CT_NEW) txid = hash;
});
ConfirmSend();
QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked");
return txid;
}
//! Find index of txid in transaction list.
QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
{
QString hash = QString::fromStdString(txid.ToString());
int rows = model.rowCount({});
for (int row = 0; row < rows; ++row) {
QModelIndex index = model.index(row, 0, {});
if (model.data(index, TransactionTableModel::TxHashRole) == hash) {
return index;
}
}
return {};
}
}
//! Simple qt wallet tests.
void WalletTests::walletTests()
{
// Set up wallet and chain with 101 blocks (1 mature block for spending).
TestChain100Setup test;
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
bitdb.MakeMock();
CWallet wallet("wallet_test.dat");
bool firstRun;
wallet.LoadWallet(firstRun);
{
LOCK(wallet.cs_wallet);
wallet.SetAddressBook(test.coinbaseKey.GetPubKey().GetID(), "", "receive");
wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
}
wallet.ScanForWalletTransactions(chainActive.Genesis(), true);
wallet.SetBroadcastTransactions(true);
// Create widgets for sending coins and listing transactions.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
SendCoinsDialog sendCoinsDialog(platformStyle.get());
OptionsModel optionsModel;
WalletModel walletModel(platformStyle.get(), &wallet, &optionsModel);
sendCoinsDialog.setModel(&walletModel);
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 101);
uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 5 * COIN);
uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 10 * COIN);
QCOMPARE(transactionTableModel->rowCount({}), 103);
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
bitdb.Flush(true);
bitdb.Reset();
}

15
src/qt/test/wallettests.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef BITCOIN_QT_TEST_WALLETTESTS_H
#define BITCOIN_QT_TEST_WALLETTESTS_H
#include <QObject>
#include <QTest>
class WalletTests : public QObject
{
Q_OBJECT
private Q_SLOTS:
void walletTests();
};
#endif // BITCOIN_QT_TEST_WALLETTESTS_H

View file

@ -2,8 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#define BOOST_TEST_MODULE Bitcoin Test Suite
#include "test_bitcoin.h"
#include "chainparams.h"
@ -27,10 +25,8 @@
#include <memory>
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
std::unique_ptr<CConnman> g_connman;
FastRandomContext insecure_rand_ctx(true);
extern bool fPrintToConsole;
@ -69,11 +65,14 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pblocktree = new CBlockTreeDB(1 << 20, true);
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
BOOST_REQUIRE(InitBlockIndex(chainparams));
if (!InitBlockIndex(chainparams)) {
throw std::runtime_error("InitBlockIndex failed.");
}
{
CValidationState state;
bool ok = ActivateBestChain(state, chainparams);
BOOST_REQUIRE(ok);
if (!ActivateBestChain(state, chainparams)) {
throw std::runtime_error("ActivateBestChain failed.");
}
}
nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++)
@ -150,18 +149,3 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn) {
return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight,
spendsCoinbase, sigOpCost, lp);
}
void Shutdown(void* parg)
{
exit(EXIT_SUCCESS);
}
void StartShutdown()
{
exit(EXIT_SUCCESS);
}
bool ShutdownRequested()
{
return false;
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#define BOOST_TEST_MODULE Bitcoin Test Suite
#include "net.h"
#include <boost/test/unit_test.hpp>
std::unique_ptr<CConnman> g_connman;
void Shutdown(void* parg)
{
exit(EXIT_SUCCESS);
}
void StartShutdown()
{
exit(EXIT_SUCCESS);
}
bool ShutdownRequested()
{
return false;
}