Add test coverage for Qt initialization code & basic RPC console functionality.pull/643/head
parent
ca20b65cc0
commit
7e4bd19785
@ -0,0 +1,17 @@
|
|||||||
|
// 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/bitcoin.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/** Translate string to current locale using Qt. */
|
||||||
|
extern const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) {
|
||||||
|
return QCoreApplication::translate("bitcoin-core", psz).toStdString();
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) { return GuiMain(argc, argv); }
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
Loading…
Reference in new issue