Skip to content

Commit b9f930b

Browse files
committed
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
2 parents fcf556f + 9576b01 commit b9f930b

File tree

9 files changed

+206
-38
lines changed

9 files changed

+206
-38
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ env:
3232
# bitcoind
3333
- 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"
3434
# No wallet
35-
- 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"
35+
- 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"
3636
# Cross-Mac
3737
- 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"
3838

@@ -50,6 +50,8 @@ before_script:
5050
- 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
5151
- 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
5252
- make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
53+
# 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
54+
- 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
5355
script:
5456
- 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
5557
- if [ "$CHECK_DOC" = 1 -a "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then git fetch --unshallow; fi

src/Makefile.qttest.include

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,26 @@ TEST_QT_MOC_CPP = \
1111
qt/test/moc_uritests.cpp
1212

1313
if ENABLE_WALLET
14-
TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp
14+
TEST_QT_MOC_CPP += \
15+
qt/test/moc_paymentservertests.cpp \
16+
qt/test/moc_wallettests.cpp
1517
endif
1618

1719
TEST_QT_H = \
1820
qt/test/compattests.h \
1921
qt/test/rpcnestedtests.h \
2022
qt/test/uritests.h \
2123
qt/test/paymentrequestdata.h \
22-
qt/test/paymentservertests.h
24+
qt/test/paymentservertests.h \
25+
qt/test/wallettests.h
26+
27+
TEST_BITCOIN_CPP = \
28+
test/test_bitcoin.cpp \
29+
test/testutil.cpp
30+
31+
TEST_BITCOIN_H = \
32+
test/test_bitcoin.h \
33+
test/testutil.h
2334

2435
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
2536
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
@@ -29,10 +40,13 @@ qt_test_test_bitcoin_qt_SOURCES = \
2940
qt/test/rpcnestedtests.cpp \
3041
qt/test/test_main.cpp \
3142
qt/test/uritests.cpp \
32-
$(TEST_QT_H)
43+
$(TEST_QT_H) \
44+
$(TEST_BITCOIN_CPP) \
45+
$(TEST_BITCOIN_H)
3346
if ENABLE_WALLET
3447
qt_test_test_bitcoin_qt_SOURCES += \
35-
qt/test/paymentservertests.cpp
48+
qt/test/paymentservertests.cpp \
49+
qt/test/wallettests.cpp
3650
endif
3751

3852
nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ BITCOIN_TESTS =\
127127
test/streams_tests.cpp \
128128
test/test_bitcoin.cpp \
129129
test/test_bitcoin.h \
130+
test/test_bitcoin_main.cpp \
130131
test/test_random.h \
131132
test/testutil.cpp \
132133
test/testutil.h \

src/qt/test/rpcnestedtests.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,13 @@ void RPCNestedTests::rpcNestedTests()
148148
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
149149
#endif
150150

151+
UnloadBlockIndex();
151152
delete pcoinsTip;
153+
pcoinsTip = nullptr;
152154
delete pcoinsdbview;
155+
pcoinsdbview = nullptr;
153156
delete pblocktree;
157+
pblocktree = nullptr;
154158

155159
boost::filesystem::remove_all(boost::filesystem::path(path));
156160
}

src/qt/test/test_main.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,45 @@
77
#endif
88

99
#include "chainparams.h"
10-
#include "key.h"
1110
#include "rpcnestedtests.h"
1211
#include "util.h"
1312
#include "uritests.h"
1413
#include "compattests.h"
1514

1615
#ifdef ENABLE_WALLET
1716
#include "paymentservertests.h"
17+
#include "wallettests.h"
1818
#endif
1919

20-
#include <QCoreApplication>
20+
#include <QApplication>
2121
#include <QObject>
2222
#include <QTest>
2323

2424
#include <openssl/ssl.h>
2525

26-
#if defined(QT_STATICPLUGIN) && QT_VERSION < 0x050000
26+
#if defined(QT_STATICPLUGIN)
2727
#include <QtPlugin>
28+
#if QT_VERSION < 0x050000
2829
Q_IMPORT_PLUGIN(qcncodecs)
2930
Q_IMPORT_PLUGIN(qjpcodecs)
3031
Q_IMPORT_PLUGIN(qtwcodecs)
3132
Q_IMPORT_PLUGIN(qkrcodecs)
33+
#else
34+
#if defined(QT_QPA_PLATFORM_XCB)
35+
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
36+
#elif defined(QT_QPA_PLATFORM_WINDOWS)
37+
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
38+
#elif defined(QT_QPA_PLATFORM_COCOA)
39+
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
40+
#endif
41+
#endif
3242
#endif
3343

3444
extern void noui_connect();
3545

3646
// This is all you need to run all the tests
3747
int main(int argc, char *argv[])
3848
{
39-
ECC_Start();
4049
SetupEnvironment();
4150
SetupNetworking();
4251
SelectParams(CBaseChainParams::MAIN);
@@ -45,27 +54,36 @@ int main(int argc, char *argv[])
4554
bool fInvalid = false;
4655

4756
// Don't remove this, it's needed to access
48-
// QCoreApplication:: in the tests
49-
QCoreApplication app(argc, argv);
57+
// QApplication:: and QCoreApplication:: in the tests
58+
QApplication app(argc, argv);
5059
app.setApplicationName("Bitcoin-Qt-test");
5160

5261
SSL_library_init();
5362

5463
URITests test1;
55-
if (QTest::qExec(&test1) != 0)
64+
if (QTest::qExec(&test1) != 0) {
5665
fInvalid = true;
66+
}
5767
#ifdef ENABLE_WALLET
5868
PaymentServerTests test2;
59-
if (QTest::qExec(&test2) != 0)
69+
if (QTest::qExec(&test2) != 0) {
6070
fInvalid = true;
71+
}
6172
#endif
6273
RPCNestedTests test3;
63-
if (QTest::qExec(&test3) != 0)
74+
if (QTest::qExec(&test3) != 0) {
6475
fInvalid = true;
76+
}
6577
CompatTests test4;
66-
if (QTest::qExec(&test4) != 0)
78+
if (QTest::qExec(&test4) != 0) {
6779
fInvalid = true;
80+
}
81+
#ifdef ENABLE_WALLET
82+
WalletTests test5;
83+
if (QTest::qExec(&test5) != 0) {
84+
fInvalid = true;
85+
}
86+
#endif
6887

69-
ECC_Stop();
7088
return fInvalid;
7189
}

src/qt/test/wallettests.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#include "wallettests.h"
2+
3+
#include "qt/bitcoinamountfield.h"
4+
#include "qt/optionsmodel.h"
5+
#include "qt/platformstyle.h"
6+
#include "qt/qvalidatedlineedit.h"
7+
#include "qt/sendcoinsdialog.h"
8+
#include "qt/sendcoinsentry.h"
9+
#include "qt/transactiontablemodel.h"
10+
#include "qt/walletmodel.h"
11+
#include "test/test_bitcoin.h"
12+
#include "validation.h"
13+
#include "wallet/wallet.h"
14+
15+
#include <QAbstractButton>
16+
#include <QApplication>
17+
#include <QTimer>
18+
#include <QVBoxLayout>
19+
20+
namespace
21+
{
22+
//! Press "Yes" button in modal send confirmation dialog.
23+
void ConfirmSend()
24+
{
25+
QTimer::singleShot(0, Qt::PreciseTimer, []() {
26+
for (QWidget* widget : QApplication::topLevelWidgets()) {
27+
if (widget->inherits("SendConfirmationDialog")) {
28+
SendConfirmationDialog* dialog = qobject_cast<SendConfirmationDialog*>(widget);
29+
QAbstractButton* button = dialog->button(QMessageBox::Yes);
30+
button->setEnabled(true);
31+
button->click();
32+
}
33+
}
34+
});
35+
}
36+
37+
//! Send coins to address and return txid.
38+
uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CBitcoinAddress& address, CAmount amount)
39+
{
40+
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
41+
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
42+
entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(address.ToString()));
43+
entry->findChild<BitcoinAmountField*>("payAmount")->setValue(amount);
44+
uint256 txid;
45+
boost::signals2::scoped_connection c = wallet.NotifyTransactionChanged.connect([&txid](CWallet*, const uint256& hash, ChangeType status) {
46+
if (status == CT_NEW) txid = hash;
47+
});
48+
ConfirmSend();
49+
QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked");
50+
return txid;
51+
}
52+
53+
//! Find index of txid in transaction list.
54+
QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
55+
{
56+
QString hash = QString::fromStdString(txid.ToString());
57+
int rows = model.rowCount({});
58+
for (int row = 0; row < rows; ++row) {
59+
QModelIndex index = model.index(row, 0, {});
60+
if (model.data(index, TransactionTableModel::TxHashRole) == hash) {
61+
return index;
62+
}
63+
}
64+
return {};
65+
}
66+
}
67+
68+
//! Simple qt wallet tests.
69+
void WalletTests::walletTests()
70+
{
71+
// Set up wallet and chain with 101 blocks (1 mature block for spending).
72+
TestChain100Setup test;
73+
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
74+
bitdb.MakeMock();
75+
CWallet wallet("wallet_test.dat");
76+
bool firstRun;
77+
wallet.LoadWallet(firstRun);
78+
{
79+
LOCK(wallet.cs_wallet);
80+
wallet.SetAddressBook(test.coinbaseKey.GetPubKey().GetID(), "", "receive");
81+
wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
82+
}
83+
wallet.ScanForWalletTransactions(chainActive.Genesis(), true);
84+
wallet.SetBroadcastTransactions(true);
85+
86+
// Create widgets for sending coins and listing transactions.
87+
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
88+
SendCoinsDialog sendCoinsDialog(platformStyle.get());
89+
OptionsModel optionsModel;
90+
WalletModel walletModel(platformStyle.get(), &wallet, &optionsModel);
91+
sendCoinsDialog.setModel(&walletModel);
92+
93+
// Send two transactions, and verify they are added to transaction list.
94+
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
95+
QCOMPARE(transactionTableModel->rowCount({}), 101);
96+
uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 5 * COIN);
97+
uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 10 * COIN);
98+
QCOMPARE(transactionTableModel->rowCount({}), 103);
99+
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
100+
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
101+
102+
bitdb.Flush(true);
103+
bitdb.Reset();
104+
}

src/qt/test/wallettests.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef BITCOIN_QT_TEST_WALLETTESTS_H
2+
#define BITCOIN_QT_TEST_WALLETTESTS_H
3+
4+
#include <QObject>
5+
#include <QTest>
6+
7+
class WalletTests : public QObject
8+
{
9+
Q_OBJECT
10+
11+
private Q_SLOTS:
12+
void walletTests();
13+
};
14+
15+
#endif // BITCOIN_QT_TEST_WALLETTESTS_H

src/test/test_bitcoin.cpp

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#define BOOST_TEST_MODULE Bitcoin Test Suite
6-
75
#include "test_bitcoin.h"
86

97
#include "chainparams.h"
@@ -27,10 +25,8 @@
2725
#include <memory>
2826

2927
#include <boost/filesystem.hpp>
30-
#include <boost/test/unit_test.hpp>
3128
#include <boost/thread.hpp>
3229

33-
std::unique_ptr<CConnman> g_connman;
3430
FastRandomContext insecure_rand_ctx(true);
3531

3632
extern bool fPrintToConsole;
@@ -69,11 +65,14 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
6965
pblocktree = new CBlockTreeDB(1 << 20, true);
7066
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
7167
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
72-
BOOST_REQUIRE(InitBlockIndex(chainparams));
68+
if (!InitBlockIndex(chainparams)) {
69+
throw std::runtime_error("InitBlockIndex failed.");
70+
}
7371
{
7472
CValidationState state;
75-
bool ok = ActivateBestChain(state, chainparams);
76-
BOOST_REQUIRE(ok);
73+
if (!ActivateBestChain(state, chainparams)) {
74+
throw std::runtime_error("ActivateBestChain failed.");
75+
}
7776
}
7877
nScriptCheckThreads = 3;
7978
for (int i=0; i < nScriptCheckThreads-1; i++)
@@ -150,18 +149,3 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn) {
150149
return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight,
151150
spendsCoinbase, sigOpCost, lp);
152151
}
153-
154-
void Shutdown(void* parg)
155-
{
156-
exit(EXIT_SUCCESS);
157-
}
158-
159-
void StartShutdown()
160-
{
161-
exit(EXIT_SUCCESS);
162-
}
163-
164-
bool ShutdownRequested()
165-
{
166-
return false;
167-
}

src/test/test_bitcoin_main.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2011-2016 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#define BOOST_TEST_MODULE Bitcoin Test Suite
6+
7+
#include "net.h"
8+
9+
#include <boost/test/unit_test.hpp>
10+
11+
std::unique_ptr<CConnman> g_connman;
12+
13+
void Shutdown(void* parg)
14+
{
15+
exit(EXIT_SUCCESS);
16+
}
17+
18+
void StartShutdown()
19+
{
20+
exit(EXIT_SUCCESS);
21+
}
22+
23+
bool ShutdownRequested()
24+
{
25+
return false;
26+
}

0 commit comments

Comments
 (0)