Skip to content

Commit 9bfbdd8

Browse files
committed
Add qt tests for wallet spends & bumpfee
1 parent 731ca5c commit 9bfbdd8

File tree

9 files changed

+225
-30
lines changed

9 files changed

+225
-30
lines changed

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
@@ -125,6 +125,7 @@ BITCOIN_TESTS =\
125125
test/streams_tests.cpp \
126126
test/test_bitcoin.cpp \
127127
test/test_bitcoin.h \
128+
test/test_bitcoin_main.cpp \
128129
test/test_random.h \
129130
test/testutil.cpp \
130131
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: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
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

@@ -36,7 +36,6 @@ extern void noui_connect();
3636
// This is all you need to run all the tests
3737
int main(int argc, char *argv[])
3838
{
39-
ECC_Start();
4039
SetupEnvironment();
4140
SetupNetworking();
4241
SelectParams(CBaseChainParams::MAIN);
@@ -46,7 +45,7 @@ int main(int argc, char *argv[])
4645

4746
// Don't remove this, it's needed to access
4847
// QCoreApplication:: in the tests
49-
QCoreApplication app(argc, argv);
48+
QApplication app(argc, argv);
5049
app.setApplicationName("Bitcoin-Qt-test");
5150

5251
SSL_library_init();
@@ -65,7 +64,11 @@ int main(int argc, char *argv[])
6564
CompatTests test4;
6665
if (QTest::qExec(&test4) != 0)
6766
fInvalid = true;
67+
#ifdef ENABLE_WALLET
68+
WalletTests test5;
69+
if (QTest::qExec(&test5) != 0)
70+
fInvalid = true;
71+
#endif
6872

69-
ECC_Stop();
7073
return fInvalid;
7174
}

src/qt/test/wallettests.cpp

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include "wallettests.h"
2+
3+
#include "qt/optionsmodel.h"
4+
#include "qt/platformstyle.h"
5+
#include "qt/sendcoinsdialog.h"
6+
#include "qt/sendcoinsentry.h"
7+
#include "qt/transactiontablemodel.h"
8+
#include "qt/transactionview.h"
9+
#include "qt/walletmodel.h"
10+
#include "test/test_bitcoin.h"
11+
#include "validation.h"
12+
#include "wallet/wallet.h"
13+
#include "qt/bitcoinamountfield.h"
14+
#include "qt/qvalidatedlineedit.h"
15+
16+
#include <QAbstractButton>
17+
#include <QAction>
18+
#include <QApplication>
19+
#include <QPushButton>
20+
#include <QTimer>
21+
#include <QVBoxLayout>
22+
#include <QDebug>
23+
24+
namespace
25+
{
26+
27+
void ConfirmMessage(QString* text = nullptr)
28+
{
29+
QTimer::singleShot(0, Qt::PreciseTimer, [&]() {
30+
for (QWidget* widget : QApplication::topLevelWidgets()) {
31+
if (widget->inherits("QMessageBox")) {
32+
QMessageBox* messageBox = qobject_cast<QMessageBox*>(widget);
33+
if (text) *text = messageBox->text();
34+
messageBox->defaultButton()->click();
35+
}
36+
}
37+
});
38+
}
39+
40+
void ConfirmSend(QString* text = nullptr, bool cancel = false)
41+
{
42+
QTimer::singleShot(0, Qt::PreciseTimer, [&]() {
43+
for (QWidget* widget : QApplication::topLevelWidgets()) {
44+
if (widget->inherits("SendConfirmationDialog")) {
45+
SendConfirmationDialog* dialog = qobject_cast<SendConfirmationDialog*>(widget);
46+
if (text) *text = dialog->text();
47+
QAbstractButton* button = dialog->button(cancel ? QMessageBox::Cancel : QMessageBox::Yes);
48+
button->setEnabled(true);
49+
button->click();
50+
}
51+
} });
52+
}
53+
54+
uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CBitcoinAddress& address, CAmount amount)
55+
{
56+
uint256 txid;
57+
auto notify = [&txid](CWallet*, const uint256& hash, ChangeType status) {
58+
if (status == CT_NEW) txid = hash;
59+
};
60+
QVBoxLayout* entries = sendCoinsDialog.findChild<QVBoxLayout*>("entries");
61+
SendCoinsEntry* entry = qobject_cast<SendCoinsEntry*>(entries->itemAt(0)->widget());
62+
entry->findChild<QValidatedLineEdit*>("payTo")->setText(QString::fromStdString(address.ToString()));
63+
entry->findChild<BitcoinAmountField*>("payAmount")->setValue(5 * COIN);
64+
boost::signals2::scoped_connection c = wallet.NotifyTransactionChanged.connect(notify);
65+
ConfirmSend();
66+
QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked");
67+
return txid;
68+
}
69+
70+
QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
71+
{
72+
QString hash = QString::fromStdString(txid.ToString());
73+
int rows = model.rowCount({});
74+
for (int row = 0; row < rows; ++row) {
75+
QModelIndex index = model.index(row, 0, {});
76+
if (model.data(index, TransactionTableModel::TxHashRole) == hash) {
77+
return index;
78+
}
79+
}
80+
return {};
81+
}
82+
83+
void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, std::string expectError, bool cancel)
84+
{
85+
QTableView* table = view.findChild<QTableView*>("transactionView");
86+
QModelIndex index = FindTx(*table->selectionModel()->model(), txid);
87+
QVERIFY2(index.isValid(), "Could not find BumpFee txid");
88+
89+
// Select row in table, invoke context menu, and make sure bumpfee action is
90+
// enabled or disabled as expected.
91+
QAction* action = view.findChild<QAction*>("bumpFeeAction");
92+
table->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
93+
action->setEnabled(expectDisabled);
94+
table->customContextMenuRequested({});
95+
QCOMPARE(action->isEnabled(), !expectDisabled);
96+
97+
action->setEnabled(true);
98+
QString text;
99+
if (expectError.empty()) {
100+
ConfirmSend(&text, cancel);
101+
} else {
102+
ConfirmMessage(&text);
103+
}
104+
action->trigger();
105+
printf("FIXME compare '%s'\n", text.toStdString().c_str());
106+
}
107+
108+
}
109+
110+
void WalletTests::walletTests()
111+
{
112+
// Set up wallet and chain with 105 blocks (5 mature blocks for spending).
113+
TestChain100Setup test;
114+
for (int i = 0; i < 5; ++i) {
115+
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
116+
}
117+
bitdb.MakeMock();
118+
CWallet wallet("wallet_test.dat");
119+
bool firstRun;
120+
wallet.LoadWallet(firstRun);
121+
wallet.SetAddressBook(test.coinbaseKey.GetPubKey().GetID(), "", "receive");
122+
wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
123+
wallet.ScanForWalletTransactions(chainActive.Genesis(), true);
124+
wallet.SetBroadcastTransactions(true);
125+
126+
// Create widgets for sending coins and listing transactions.
127+
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
128+
SendCoinsDialog sendCoinsDialog(platformStyle.get());
129+
TransactionView transactionView(platformStyle.get());
130+
OptionsModel optionsModel;
131+
WalletModel walletModel(platformStyle.get(), &wallet, &optionsModel);
132+
sendCoinsDialog.setModel(&walletModel);
133+
transactionView.setModel(&walletModel);
134+
135+
// Send two transactions.
136+
fWalletRbf = false;
137+
uint256 txid = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(test.coinbaseKey.GetPubKey().GetID()), 5 * COIN);
138+
fWalletRbf = true;
139+
uint256 rbftxid = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(test.coinbaseKey.GetPubKey().GetID()), 10 * COIN);
140+
141+
// Call bumpfee. FIXME describe.
142+
BumpFee(transactionView, txid, true /* expect disabled */, "lala" /* expected error */, false /* cancel */);
143+
BumpFee(transactionView, rbftxid, false /* expect disabled */, {} /* expected error */, false /* cancel */);
144+
BumpFee(transactionView, rbftxid, false /* expect disabled */, "lala" /* expected error */, true /* cancel */);
145+
146+
bitdb.Flush(true);
147+
bitdb.Reset();
148+
}

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/qt/transactionview.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,12 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
136136
view->installEventFilter(this);
137137

138138
transactionView = view;
139+
transactionView->setObjectName("transactionView");
139140

140141
// Actions
141142
abandonAction = new QAction(tr("Abandon transaction"), this);
142143
bumpFeeAction = new QAction(tr("Increase transaction fee"), this);
144+
bumpFeeAction->setObjectName("bumpFeeAction");
143145
QAction *copyAddressAction = new QAction(tr("Copy address"), this);
144146
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
145147
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
@@ -150,6 +152,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
150152
QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
151153

152154
contextMenu = new QMenu(this);
155+
contextMenu->setObjectName("contextMenu");
153156
contextMenu->addAction(copyAddressAction);
154157
contextMenu->addAction(copyLabelAction);
155158
contextMenu->addAction(copyAmountAction);
@@ -380,7 +383,7 @@ void TransactionView::contextualMenu(const QPoint &point)
380383

381384
if(index.isValid())
382385
{
383-
contextMenu->exec(QCursor::pos());
386+
contextMenu->popup(transactionView->viewport()->mapToGlobal(point));
384387
}
385388
}
386389

src/test/test_bitcoin.cpp

Lines changed: 1 addition & 20 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;
@@ -73,7 +69,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
7369
{
7470
CValidationState state;
7571
bool ok = ActivateBestChain(state, chainparams);
76-
BOOST_CHECK(ok);
72+
assert(ok);
7773
}
7874
nScriptCheckThreads = 3;
7975
for (int i=0; i < nScriptCheckThreads-1; i++)
@@ -153,18 +149,3 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPo
153149
return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, dPriority, nHeight,
154150
inChainValue, spendsCoinbase, sigOpCost, lp);
155151
}
156-
157-
void Shutdown(void* parg)
158-
{
159-
exit(0);
160-
}
161-
162-
void StartShutdown()
163-
{
164-
exit(0);
165-
}
166-
167-
bool ShutdownRequested()
168-
{
169-
return false;
170-
}

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(0);
16+
}
17+
18+
void StartShutdown()
19+
{
20+
exit(0);
21+
}
22+
23+
bool ShutdownRequested()
24+
{
25+
return false;
26+
}

0 commit comments

Comments
 (0)