apptests.cpp raw

   1  // Copyright (c) 2018-2022 The Limenka 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 <common/args.h>
   9  #include <key.h>
  10  #include <logging.h>
  11  #include <qt/limenka.h>
  12  #include <qt/limenkagui.h>
  13  #include <qt/networkstyle.h>
  14  #include <qt/rpcconsole.h>
  15  #include <test/util/setup_common.h>
  16  #include <validation.h>
  17  
  18  #include <QAction>
  19  #include <QLineEdit>
  20  #include <QRegularExpression>
  21  #include <QScopedPointer>
  22  #include <QSignalSpy>
  23  #include <QString>
  24  #include <QTest>
  25  #include <QTextEdit>
  26  #include <QtGlobal>
  27  #include <QtTest/QtTestWidgets>
  28  #include <QtTest/QtTestGui>
  29  
  30  namespace {
  31  //! Regex find a string group inside of the console output
  32  QString FindInConsole(const QString& output, const QString& pattern)
  33  {
  34      const QRegularExpression re(pattern);
  35      return re.match(output).captured(1);
  36  }
  37  
  38  //! Call getblockchaininfo RPC and check first field of JSON output.
  39  void TestRpcCommand(RPCConsole* console)
  40  {
  41      QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget");
  42      QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit");
  43      QSignalSpy mw_spy(messagesWidget, &QTextEdit::textChanged);
  44      QVERIFY(mw_spy.isValid());
  45      QTest::keyClicks(lineEdit, "getblockchaininfo");
  46      QTest::keyClick(lineEdit, Qt::Key_Return);
  47      QVERIFY(mw_spy.wait(1000));
  48      QCOMPARE(mw_spy.count(), 4);
  49      const QString output = messagesWidget->toPlainText();
  50      const QString pattern = QStringLiteral("\"chain\": \"(\\w+)\"");
  51      QCOMPARE(FindInConsole(output, pattern), QString("regtest"));
  52  }
  53  } // namespace
  54  
  55  //! Entry point for LimenkaApplication tests.
  56  void AppTests::appTests()
  57  {
  58  #ifdef Q_OS_MACOS
  59      if (QApplication::platformName() == "minimal") {
  60          // Disable for mac on "minimal" platform to avoid crashes inside the Qt
  61          // framework when it tries to look up unimplemented cocoa functions,
  62          // and fails to handle returned nulls
  63          // (https://bugreports.qt.io/browse/QTBUG-49686).
  64          qWarning() << "Skipping AppTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
  65                        "with 'QT_QPA_PLATFORM=cocoa test_limenka-qt' on mac, or else use a linux or windows build.";
  66          return;
  67      }
  68  #endif
  69  
  70      {
  71          // Need to ensure datadir is setup so resetting settings can delete the non-existent limenka_rw.conf
  72          std::string error;
  73          if (!gArgs.ReadConfigFiles(error, true)) {
  74              qWarning() << "Error in readConfigFiles";
  75          }
  76      }
  77  
  78      qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
  79      m_app.parameterSetup();
  80      QVERIFY(m_app.createOptionsModel(/*resetSettings=*/true));
  81      QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().GetChainType()));
  82      m_app.setupPlatformStyle();
  83      m_app.createWindow(style.data());
  84      connect(&m_app, &LimenkaApplication::windowShown, this, &AppTests::guiTests);
  85      expectCallback("guiTests");
  86      m_app.baseInitialize();
  87      m_app.requestInitialize();
  88      m_app.exec();
  89      m_app.requestShutdown();
  90      m_app.exec();
  91  
  92      // Reset global state to avoid interfering with later tests.
  93      LogInstance().DisconnectTestLogger();
  94  }
  95  
  96  //! Entry point for LimenkaGUI tests.
  97  void AppTests::guiTests(LimenkaGUI* window)
  98  {
  99      HandleCallback callback{"guiTests", *this};
 100      connect(window, &LimenkaGUI::consoleShown, this, &AppTests::consoleTests);
 101      expectCallback("consoleTests");
 102      QAction* action = window->findChild<QAction*>("openRPCConsoleAction");
 103      action->activate(QAction::Trigger);
 104  }
 105  
 106  //! Entry point for RPCConsole tests.
 107  void AppTests::consoleTests(RPCConsole* console)
 108  {
 109      HandleCallback callback{"consoleTests", *this};
 110      TestRpcCommand(console);
 111  }
 112  
 113  //! Destructor to shut down after the last expected callback completes.
 114  AppTests::HandleCallback::~HandleCallback()
 115  {
 116      auto& callbacks = m_app_tests.m_callbacks;
 117      auto it = callbacks.find(m_callback);
 118      assert(it != callbacks.end());
 119      callbacks.erase(it);
 120      if (callbacks.empty()) {
 121          m_app_tests.m_app.exit(0);
 122      }
 123  }
 124