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