Line data Source code
1 : // Copyright (c) 2017-2020 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 : #include <qt/test/addressbooktests.h> 6 : #include <qt/test/util.h> 7 : #include <test/util/setup_common.h> 8 : 9 : #include <interfaces/chain.h> 10 : #include <interfaces/node.h> 11 : #include <qt/clientmodel.h> 12 : #include <qt/editaddressdialog.h> 13 : #include <qt/optionsmodel.h> 14 : #include <qt/platformstyle.h> 15 : #include <qt/qvalidatedlineedit.h> 16 : #include <qt/walletmodel.h> 17 : 18 : #include <key.h> 19 : #include <key_io.h> 20 : #include <wallet/wallet.h> 21 : #include <walletinitinterface.h> 22 : 23 : #include <QApplication> 24 : #include <QTimer> 25 : #include <QMessageBox> 26 : 27 : namespace 28 : { 29 : 30 : /** 31 : * Fill the edit address dialog box with data, submit it, and ensure that 32 : * the resulting message meets expectations. 33 : */ 34 0 : void EditAddressAndSubmit( 35 : EditAddressDialog* dialog, 36 : const QString& label, const QString& address, QString expected_msg) 37 : { 38 0 : QString warning_text; 39 : 40 0 : dialog->findChild<QLineEdit*>("labelEdit")->setText(label); 41 0 : dialog->findChild<QValidatedLineEdit*>("addressEdit")->setText(address); 42 : 43 0 : ConfirmMessage(&warning_text, 5); 44 0 : dialog->accept(); 45 0 : QCOMPARE(warning_text, expected_msg); 46 0 : } 47 : 48 : /** 49 : * Test adding various send addresses to the address book. 50 : * 51 : * There are three cases tested: 52 : * 53 : * - new_address: a new address which should add as a send address successfully. 54 : * - existing_s_address: an existing sending address which won't add successfully. 55 : * - existing_r_address: an existing receiving address which won't add successfully. 56 : * 57 : * In each case, verify the resulting state of the address book and optionally 58 : * the warning message presented to the user. 59 : */ 60 0 : void TestAddAddressesToSendBook(interfaces::Node& node) 61 : { 62 0 : TestChain100Setup test; 63 0 : node.setContext(&test.m_node); 64 0 : std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), "", CreateMockWalletDatabase()); 65 0 : wallet->SetupLegacyScriptPubKeyMan(); 66 0 : bool firstRun; 67 0 : wallet->LoadWallet(firstRun); 68 : 69 0 : auto build_address = [&wallet]() { 70 0 : CKey key; 71 0 : key.MakeNewKey(true); 72 0 : CTxDestination dest(GetDestinationForKey( 73 0 : key.GetPubKey(), wallet->m_default_address_type)); 74 : 75 0 : return std::make_pair(dest, QString::fromStdString(EncodeDestination(dest))); 76 0 : }; 77 : 78 0 : CTxDestination r_key_dest, s_key_dest; 79 : 80 : // Add a preexisting "receive" entry in the address book. 81 0 : QString preexisting_r_address; 82 0 : QString r_label("already here (r)"); 83 : 84 : // Add a preexisting "send" entry in the address book. 85 0 : QString preexisting_s_address; 86 0 : QString s_label("already here (s)"); 87 : 88 : // Define a new address (which should add to the address book successfully). 89 0 : QString new_address; 90 : 91 0 : std::tie(r_key_dest, preexisting_r_address) = build_address(); 92 0 : std::tie(s_key_dest, preexisting_s_address) = build_address(); 93 0 : std::tie(std::ignore, new_address) = build_address(); 94 : 95 : { 96 0 : LOCK(wallet->cs_wallet); 97 0 : wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive"); 98 0 : wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send"); 99 0 : } 100 : 101 0 : auto check_addbook_size = [&wallet](int expected_size) { 102 0 : LOCK(wallet->cs_wallet); 103 0 : QCOMPARE(static_cast<int>(wallet->m_address_book.size()), expected_size); 104 0 : }; 105 : 106 : // We should start with the two addresses we added earlier and nothing else. 107 0 : check_addbook_size(2); 108 : 109 : // Initialize relevant QT models. 110 0 : std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); 111 0 : OptionsModel optionsModel; 112 0 : ClientModel clientModel(node, &optionsModel); 113 0 : AddWallet(wallet); 114 0 : WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); 115 0 : RemoveWallet(wallet, nullopt); 116 0 : EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); 117 0 : editAddressDialog.setModel(walletModel.getAddressTableModel()); 118 : 119 0 : EditAddressAndSubmit( 120 0 : &editAddressDialog, QString("uhoh"), preexisting_r_address, 121 0 : QString( 122 : "Address \"%1\" already exists as a receiving address with label " 123 : "\"%2\" and so cannot be added as a sending address." 124 0 : ).arg(preexisting_r_address).arg(r_label)); 125 : 126 0 : check_addbook_size(2); 127 : 128 0 : EditAddressAndSubmit( 129 0 : &editAddressDialog, QString("uhoh, different"), preexisting_s_address, 130 0 : QString( 131 : "The entered address \"%1\" is already in the address book with " 132 : "label \"%2\"." 133 0 : ).arg(preexisting_s_address).arg(s_label)); 134 : 135 0 : check_addbook_size(2); 136 : 137 : // Submit a new address which should add successfully - we expect the 138 : // warning message to be blank. 139 0 : EditAddressAndSubmit( 140 0 : &editAddressDialog, QString("new"), new_address, QString("")); 141 : 142 0 : check_addbook_size(3); 143 0 : } 144 : 145 : } // namespace 146 : 147 1 : void AddressBookTests::addressBookTests() 148 : { 149 : #ifdef Q_OS_MAC 150 1 : if (QApplication::platformName() == "minimal") { 151 : // Disable for mac on "minimal" platform to avoid crashes inside the Qt 152 : // framework when it tries to look up unimplemented cocoa functions, 153 : // and fails to handle returned nulls 154 : // (https://bugreports.qt.io/browse/QTBUG-49686). 155 1 : QWARN("Skipping AddressBookTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke " 156 : "with 'QT_QPA_PLATFORM=cocoa test_bitcoin-qt' on mac, or else use a linux or windows build."); 157 1 : return; 158 : } 159 : #endif 160 0 : TestAddAddressesToSendBook(m_node); 161 1 : }