apptests.cpp
1 // Copyright (c) 2018-present 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/apptests.h> 6 7 #include <chainparams.h> 8 #include <key.h> 9 #include <logging.h> 10 #include <qt/bitcoin.h> 11 #include <qt/bitcoingui.h> 12 #include <qt/networkstyle.h> 13 #include <qt/rpcconsole.h> 14 #include <test/util/setup_common.h> 15 #include <validation.h> 16 17 #include <QAction> 18 #include <QLineEdit> 19 #include <QRegularExpression> 20 #include <QScopedPointer> 21 #include <QSignalSpy> 22 #include <QString> 23 #include <QTest> 24 #include <QTextEdit> 25 #include <QtGlobal> 26 #include <QtTest/QtTestWidgets> 27 #include <QtTest/QtTestGui> 28 29 namespace { 30 //! Regex find a string group inside of the console output 31 QString FindInConsole(const QString& output, const QString& pattern) 32 { 33 const QRegularExpression re(pattern); 34 return re.match(output).captured(1); 35 } 36 37 //! Call getblockchaininfo RPC and check first field of JSON output. 38 void TestRpcCommand(RPCConsole* console) 39 { 40 QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget"); 41 QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit"); 42 QSignalSpy mw_spy(messagesWidget, &QTextEdit::textChanged); 43 QVERIFY(mw_spy.isValid()); 44 QTest::keyClicks(lineEdit, "getblockchaininfo"); 45 QTest::keyClick(lineEdit, Qt::Key_Return); 46 QVERIFY(mw_spy.wait(1000)); 47 QCOMPARE(mw_spy.count(), 4); 48 const QString output = messagesWidget->toPlainText(); 49 const QString pattern = QStringLiteral("\"chain\": \"(\\w+)\""); 50 QCOMPARE(FindInConsole(output, pattern), QString("regtest")); 51 } 52 } // namespace 53 54 //! Entry point for BitcoinApplication tests. 55 void AppTests::appTests() 56 { 57 #ifdef Q_OS_MACOS 58 if (QApplication::platformName() == "minimal") { 59 // Disable for mac on "minimal" platform to avoid crashes inside the Qt 60 // framework when it tries to look up unimplemented cocoa functions, 61 // and fails to handle returned nulls 62 // (https://bugreports.qt.io/browse/QTBUG-49686). 63 qWarning() << "Skipping AppTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke " 64 "with 'QT_QPA_PLATFORM=cocoa test_bitcoin-qt' on mac, or else use a linux or windows build."; 65 return; 66 } 67 #endif 68 69 qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo"); 70 m_app.parameterSetup(); 71 QVERIFY(m_app.createOptionsModel(/*resetSettings=*/true)); 72 QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().GetChainType())); 73 m_app.setupPlatformStyle(); 74 m_app.createWindow(style.data()); 75 connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests); 76 expectCallback("guiTests"); 77 m_app.baseInitialize(); 78 m_app.requestInitialize(); 79 m_app.exec(); 80 m_app.requestShutdown(); 81 m_app.exec(); 82 83 // Reset global state to avoid interfering with later tests. 84 LogInstance().DisconnectTestLogger(); 85 } 86 87 //! Entry point for BitcoinGUI tests. 88 void AppTests::guiTests(BitcoinGUI* window) 89 { 90 HandleCallback callback{"guiTests", *this}; 91 connect(window, &BitcoinGUI::consoleShown, this, &AppTests::consoleTests); 92 expectCallback("consoleTests"); 93 QAction* action = window->findChild<QAction*>("openRPCConsoleAction"); 94 action->activate(QAction::Trigger); 95 } 96 97 //! Entry point for RPCConsole tests. 98 void AppTests::consoleTests(RPCConsole* console) 99 { 100 HandleCallback callback{"consoleTests", *this}; 101 TestRpcCommand(console); 102 } 103 104 //! Destructor to shut down after the last expected callback completes. 105 AppTests::HandleCallback::~HandleCallback() 106 { 107 auto& callbacks = m_app_tests.m_callbacks; 108 auto it = callbacks.find(m_callback); 109 assert(it != callbacks.end()); 110 callbacks.erase(it); 111 if (callbacks.empty()) { 112 m_app_tests.m_app.exit(0); 113 } 114 }