diff options
author | Russell Yanofsky <russ@yanofsky.org> | 2017-11-06 20:11:43 -0500 |
---|---|---|
committer | Russell Yanofsky <russ@yanofsky.org> | 2019-01-04 06:31:07 -0500 |
commit | 7e4bd19785ff9120b7242ff9f15231868aaf7db4 (patch) | |
tree | 6a08b07a7be3233661b9a1bf973d77fa81a31109 /src/qt/test | |
parent | ca20b65cc04825bb317f1a59d02c77912f6bf097 (diff) |
Add BitcoinApplication & RPCConsole tests
Add test coverage for Qt initialization code & basic RPC console functionality.
Diffstat (limited to 'src/qt/test')
-rw-r--r-- | src/qt/test/apptests.cpp | 117 | ||||
-rw-r--r-- | src/qt/test/apptests.h | 50 | ||||
-rw-r--r-- | src/qt/test/rpcnestedtests.cpp | 2 | ||||
-rw-r--r-- | src/qt/test/test_main.cpp | 12 |
4 files changed, 178 insertions, 3 deletions
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp new file mode 100644 index 0000000000..2c477a2e98 --- /dev/null +++ b/src/qt/test/apptests.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <qt/test/apptests.h> + +#include <chainparams.h> +#include <init.h> +#include <qt/bitcoin.h> +#include <qt/bitcoingui.h> +#include <qt/networkstyle.h> +#include <qt/rpcconsole.h> +#include <shutdown.h> +#include <validation.h> + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif +#ifdef ENABLE_WALLET +#include <wallet/db.h> +#endif + +#include <QAction> +#include <QEventLoop> +#include <QLineEdit> +#include <QScopedPointer> +#include <QTest> +#include <QTextEdit> +#include <QtGlobal> +#if QT_VERSION >= 0x050000 +#include <QtTest/QtTestWidgets> +#endif +#include <QtTest/QtTestGui> +#include <new> +#include <string> +#include <univalue.h> + +namespace { +//! Call getblockchaininfo RPC and check first field of JSON output. +void TestRpcCommand(RPCConsole* console) +{ + QEventLoop loop; + QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget"); + QObject::connect(messagesWidget, &QTextEdit::textChanged, &loop, &QEventLoop::quit); + QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit"); + QTest::keyClicks(lineEdit, "getblockchaininfo"); + QTest::keyClick(lineEdit, Qt::Key_Return); + loop.exec(); + QString output = messagesWidget->toPlainText(); + UniValue value; + value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString()); + QCOMPARE(value["chain"].get_str(), std::string("regtest")); +} +} // namespace + +//! Entry point for BitcoinApplication tests. +void AppTests::appTests() +{ +#ifdef Q_OS_MAC + if (QApplication::platformName() == "minimal") { + // Disable for mac on "minimal" platform to avoid crashes inside the Qt + // framework when it tries to look up unimplemented cocoa functions, + // and fails to handle returned nulls + // (https://bugreports.qt.io/browse/QTBUG-49686). + QWARN("Skipping AppTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke " + "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build."); + return; + } +#endif + + m_app.parameterSetup(); + m_app.createOptionsModel(true /* reset settings */); + QScopedPointer<const NetworkStyle> style( + NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString()))); + m_app.setupPlatformStyle(); + m_app.createWindow(style.data()); + connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests); + expectCallback("guiTests"); + m_app.baseInitialize(); + m_app.requestInitialize(); + m_app.exec(); + m_app.requestShutdown(); + m_app.exec(); + + // Reset global state to avoid interfering with later tests. + AbortShutdown(); + UnloadBlockIndex(); +} + +//! Entry point for BitcoinGUI tests. +void AppTests::guiTests(BitcoinGUI* window) +{ + HandleCallback callback{"guiTests", *this}; + connect(window, &BitcoinGUI::consoleShown, this, &AppTests::consoleTests); + expectCallback("consoleTests"); + QAction* action = window->findChild<QAction*>("openRPCConsoleAction"); + action->activate(QAction::Trigger); +} + +//! Entry point for RPCConsole tests. +void AppTests::consoleTests(RPCConsole* console) +{ + HandleCallback callback{"consoleTests", *this}; + TestRpcCommand(console); +} + +//! Destructor to shut down after the last expected callback completes. +AppTests::HandleCallback::~HandleCallback() +{ + auto& callbacks = m_app_tests.m_callbacks; + auto it = callbacks.find(m_callback); + assert(it != callbacks.end()); + callbacks.erase(it); + if (callbacks.empty()) { + m_app_tests.m_app.quit(); + } +} diff --git a/src/qt/test/apptests.h b/src/qt/test/apptests.h new file mode 100644 index 0000000000..83bf56f1e4 --- /dev/null +++ b/src/qt/test/apptests.h @@ -0,0 +1,50 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_TEST_APPTESTS_H +#define BITCOIN_QT_TEST_APPTESTS_H + +#include <QObject> +#include <set> +#include <string> +#include <utility> + +class BitcoinApplication; +class BitcoinGUI; +class RPCConsole; + +class AppTests : public QObject +{ + Q_OBJECT +public: + explicit AppTests(BitcoinApplication& app) : m_app(app) {} + +private Q_SLOTS: + void appTests(); + void guiTests(BitcoinGUI* window); + void consoleTests(RPCConsole* console); + +private: + //! Add expected callback name to list of pending callbacks. + void expectCallback(std::string callback) { m_callbacks.emplace(std::move(callback)); } + + //! RAII helper to remove no-longer-pending callback. + struct HandleCallback + { + std::string m_callback; + AppTests& m_app_tests; + ~HandleCallback(); + }; + + //! Bitcoin application. + BitcoinApplication& m_app; + + //! Set of pending callback names. Used to track expected callbacks and shut + //! down the app after the last callback has been handled and all tests have + //! either run or thrown exceptions. This could be a simple int counter + //! instead of a set of names, but the names might be useful for debugging. + std::multiset<std::string> m_callbacks; +}; + +#endif // BITCOIN_QT_TEST_APPTESTS_H diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index ed453336da..173c814f1e 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -41,7 +41,7 @@ void RPCNestedTests::rpcNestedTests() TestingSetup test; - SetRPCWarmupFinished(); + if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); std::string result; std::string result2; diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index b6523604fd..a2bf53973b 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -7,6 +7,9 @@ #endif #include <chainparams.h> +#include <interfaces/node.h> +#include <qt/bitcoin.h> +#include <qt/test/apptests.h> #include <qt/test/rpcnestedtests.h> #include <util/system.h> #include <qt/test/uritests.h> @@ -47,12 +50,13 @@ int main(int argc, char *argv[]) { SetupEnvironment(); SetupNetworking(); - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::REGTEST); noui_connect(); ClearDatadirCache(); fs::path pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin-qt_%lu_%i", (unsigned long)GetTime(), (int)GetRand(100000)); fs::create_directories(pathTemp); gArgs.ForceSetArg("-datadir", pathTemp.string()); + auto node = interfaces::MakeNode(); bool fInvalid = false; @@ -67,11 +71,15 @@ int main(int argc, char *argv[]) // Don't remove this, it's needed to access // QApplication:: and QCoreApplication:: in the tests - QApplication app(argc, argv); + BitcoinApplication app(*node, argc, argv); app.setApplicationName("Bitcoin-Qt-test"); SSL_library_init(); + AppTests app_tests(app); + if (QTest::qExec(&app_tests) != 0) { + fInvalid = true; + } URITests test1; if (QTest::qExec(&test1) != 0) { fInvalid = true; |