apptests.cpp raw
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 }
115