Files
bitcoin/src/qt/test/apptests.cpp
Hennadii Stepanov be37037e8e Merge bitcoin-core/gui#337: test: Use Regex Search in Apptests
6969b2bb98 qt, test: use regex search in apptests (Jarol Rodriguez)
d09d1cf1a2 qt, test: introduce FindInConsole function (Jarol Rodriguez)

Pull request description:

  This PR refactors our GUI `apptests` so that it uses regex search to find values in our console/qtextedit output regardless if it is in `plaintext`, `html`, or `markdown`.

  This introduces a new function `FindInConsole` which uses [QRegularExpression](https://doc.qt.io/qt-5/qregularexpression.html) to search the output of the console. The function must be provided with a [perl compatible regex](https://www.debuggex.com/cheatsheet/regex/pcre) pattern which wants to match a single group. The function then returns the matched group. If no match is found, an empty `QString` is returned.

  We then use this new function in `TestRpcCommand` to find the current `chain` value instead of reading with univalue.

  This approach can apply to a wider variety of testing scenarios as we can reuse this function to search for values when the console output is exported in a different format than `plaintext`. As an example, A follow up PR will add tests for console resizing and needs to look for the size in `html` tags after exporting the console text with `toHtml()`.

ACKs for top commit:
  hebasto:
    ACK 6969b2bb98
  ShaMan239:
    ACK 6969b2bb98

Tree-SHA512: 4db8bcd4a1acc4539ca64bbd7de572fe7dd6afc3e95108235abfc2891585bc4db3a56a33928fa38e8d44ac87023ce0dee3abcfadfbcd4440e3a21a52fef02536
2021-08-05 08:53:03 +03:00

125 lines
4.1 KiB
C++

// Copyright (c) 2018-2020 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 <key.h>
#include <qt/bitcoin.h>
#include <qt/bitcoingui.h>
#include <qt/networkstyle.h>
#include <qt/rpcconsole.h>
#include <shutdown.h>
#include <test/util/setup_common.h>
#include <validation.h>
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
#include <QAction>
#include <QLineEdit>
#include <QRegularExpression>
#include <QScopedPointer>
#include <QSignalSpy>
#include <QString>
#include <QTest>
#include <QTextEdit>
#include <QtGlobal>
#include <QtTest/QtTestWidgets>
#include <QtTest/QtTestGui>
namespace {
//! Regex find a string group inside of the console output
QString FindInConsole(const QString& output, const QString& pattern)
{
const QRegularExpression re(pattern);
return re.match(output).captured(1);
}
//! Call getblockchaininfo RPC and check first field of JSON output.
void TestRpcCommand(RPCConsole* console)
{
QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget");
QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit");
QSignalSpy mw_spy(messagesWidget, &QTextEdit::textChanged);
QVERIFY(mw_spy.isValid());
QTest::keyClicks(lineEdit, "getblockchaininfo");
QTest::keyClick(lineEdit, Qt::Key_Return);
QVERIFY(mw_spy.wait(1000));
QCOMPARE(mw_spy.count(), 4);
const QString output = messagesWidget->toPlainText();
const QString pattern = QStringLiteral("\"chain\": \"(\\w+)\"");
QCOMPARE(FindInConsole(output, pattern), QString("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 'QT_QPA_PLATFORM=cocoa test_bitcoin-qt' on mac, or else use a linux or windows build.");
return;
}
#endif
fs::create_directories([] {
BasicTestingSetup test{CBaseChainParams::REGTEST}; // Create a temp data directory to backup the gui settings to
return gArgs.GetDataDirNet() / "blocks";
}());
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
m_app.parameterSetup();
m_app.createOptionsModel(true /* reset settings */);
QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(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.
LogInstance().DisconnectTestLogger();
AbortShutdown();
}
//! 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();
}
}