diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -14,11 +14,13 @@ if ENABLE_WALLET TEST_QT_MOC_CPP += \ + qt/test/moc_addressbooktests.cpp \ qt/test/moc_paymentservertests.cpp \ qt/test/moc_wallettests.cpp endif TEST_QT_H = \ + qt/test/addressbooktests.h \ qt/test/bitcoinaddressvalidatortests.h \ qt/test/compattests.h \ qt/test/guiutiltests.h \ @@ -51,6 +53,7 @@ $(TEST_BITCOIN_H) if ENABLE_WALLET qt_test_test_bitcoin_qt_SOURCES += \ + qt/test/addressbooktests.cpp \ qt/test/paymentservertests.cpp \ qt/test/wallettests.cpp \ wallet/test/wallet_test_fixture.cpp diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -34,7 +34,7 @@ }; explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, - Tabs tab, QWidget *parent); + Tabs tab, QWidget *parent = nullptr); ~AddressBookPage(); void setModel(AddressTableModel *model); diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h --- a/src/qt/editaddressdialog.h +++ b/src/qt/editaddressdialog.h @@ -31,7 +31,7 @@ EditSendingAddress }; - explicit EditAddressDialog(Mode mode, QWidget *parent); + explicit EditAddressDialog(Mode mode, QWidget *parent = nullptr); ~EditAddressDialog(); void setModel(AddressTableModel *model); diff --git a/src/qt/test/CMakeLists.txt b/src/qt/test/CMakeLists.txt --- a/src/qt/test/CMakeLists.txt +++ b/src/qt/test/CMakeLists.txt @@ -7,6 +7,7 @@ add_dependencies(check check-bitcoin-qt) add_test_to_suite(bitcoin-qt test_bitcoin-qt + addressbooktests.cpp bitcoinaddressvalidatortests.cpp compattests.cpp guiutiltests.cpp diff --git a/src/qt/test/addressbooktests.h b/src/qt/test/addressbooktests.h new file mode 100644 --- /dev/null +++ b/src/qt/test/addressbooktests.h @@ -0,0 +1,14 @@ +#ifndef BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H +#define BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H + +#include +#include + +class AddressBookTests : public QObject { + Q_OBJECT + +private Q_SLOTS: + void addressBookTests(); +}; + +#endif // BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp new file mode 100644 --- /dev/null +++ b/src/qt/test/addressbooktests.cpp @@ -0,0 +1,146 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace { + +/** + * Fill the edit address dialog box with data, submit it, and ensure that + * the resulting message meets expectations. + */ +void EditAddressAndSubmit(EditAddressDialog *dialog, const QString &label, + const QString &address, QString expected_msg) { + QString warning_text; + + dialog->findChild("labelEdit")->setText(label); + dialog->findChild("addressEdit")->setText(address); + + ConfirmMessage(&warning_text, 5); + dialog->accept(); + QCOMPARE(warning_text, expected_msg); +} + +/** + * Test adding various send addresses to the address book. + * + * There are three cases tested: + * + * - new_address: a new address which should add as a send address + * successfully. + * - existing_s_address: an existing sending address which won't add + * successfully. + * - existing_r_address: an existing receiving address which won't add + * successfully. + * + * In each case, verify the resulting state of the address book and optionally + * the warning message presented to the user. + */ +void TestAddAddressesToSendBook() { + TestChain100Setup test; + CWallet wallet(Params(), "mock", WalletDatabase::CreateMock()); + bool firstRun; + wallet.LoadWallet(firstRun); + + auto build_address = [&wallet]() { + CKey key; + key.MakeNewKey(true); + CTxDestination dest(GetDestinationForKey( + key.GetPubKey(), wallet.m_default_address_type)); + + return std::make_pair( + dest, QString::fromStdString(EncodeCashAddr(dest, Params()))); + }; + + CTxDestination r_key_dest, s_key_dest; + + // Add a preexisting "receive" entry in the address book. + QString preexisting_r_address; + QString r_label("already here (r)"); + + // Add a preexisting "send" entry in the address book. + QString preexisting_s_address; + QString s_label("already here (s)"); + + // Define a new address (which should add to the address book successfully). + QString new_address; + + std::tie(r_key_dest, preexisting_r_address) = build_address(); + std::tie(s_key_dest, preexisting_s_address) = build_address(); + std::tie(std::ignore, new_address) = build_address(); + + { + LOCK(wallet.cs_wallet); + wallet.SetAddressBook(r_key_dest, r_label.toStdString(), "receive"); + wallet.SetAddressBook(s_key_dest, s_label.toStdString(), "send"); + } + + auto check_addbook_size = [&wallet](int expected_size) { + QCOMPARE(static_cast(wallet.mapAddressBook.size()), expected_size); + }; + + // We should start with the two addresses we added earlier and nothing else. + check_addbook_size(2); + + // Initialize relevant QT models. + std::unique_ptr platformStyle( + PlatformStyle::instantiate("other")); + auto node = interfaces::MakeNode(); + OptionsModel optionsModel(*node); + AddWallet(&wallet); + WalletModel walletModel(std::move(node->getWallets()[0]), *node, + platformStyle.get(), &optionsModel); + RemoveWallet(&wallet); + EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); + editAddressDialog.setModel(walletModel.getAddressTableModel()); + + EditAddressAndSubmit( + &editAddressDialog, QString("uhoh"), preexisting_r_address, + QString( + "Address \"%1\" already exists as a receiving address with label " + "\"%2\" and so cannot be added as a sending address.") + .arg(preexisting_r_address) + .arg(r_label)); + + check_addbook_size(2); + + EditAddressAndSubmit( + &editAddressDialog, QString("uhoh, different"), preexisting_s_address, + QString( + "The entered address \"%1\" is already in the address book with " + "label \"%2\".") + .arg(preexisting_s_address) + .arg(s_label)); + + check_addbook_size(2); + + // Submit a new address which should add successfully - we expect the + // warning message to be blank. + EditAddressAndSubmit(&editAddressDialog, QString("new"), new_address, + QString("")); + + check_addbook_size(3); +} + +} // namespace + +void AddressBookTests::addressBookTests() { + TestAddAddressesToSendBook(); +} diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -17,6 +17,7 @@ #include #include #ifdef ENABLE_WALLET +#include #include #include #endif @@ -104,6 +105,10 @@ if (QTest::qExec(&test7) != 0) { fInvalid = true; } + AddressBookTests test8; + if (QTest::qExec(&test8) != 0) { + fInvalid = true; + } #endif fs::remove_all(pathTemp); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -218,6 +218,10 @@ bool isMultiwallet(); + AddressTableModel *getAddressTableModel() const { + return addressTableModel; + } + private: std::unique_ptr m_wallet; std::unique_ptr m_handler_status_changed;