[education/rkward] rkward: Add test for restarting R backend.
Thomas Friedrichsmeier
null at kde.org
Mon Jun 13 19:51:11 BST 2022
Git commit f22dd26c9db653da6f99b1071c31740923442f77 by Thomas Friedrichsmeier.
Committed on 13/06/2022 at 18:51.
Pushed by tfry into branch 'master'.
Add test for restarting R backend.
M +45 -19 rkward/autotests/core_test.cpp
M +1 -1 rkward/rkward.cpp
https://invent.kde.org/education/rkward/commit/f22dd26c9db653da6f99b1071c31740923442f77
diff --git a/rkward/autotests/core_test.cpp b/rkward/autotests/core_test.cpp
index bb8f7f3c..dec6a98a 100644
--- a/rkward/autotests/core_test.cpp
+++ b/rkward/autotests/core_test.cpp
@@ -14,6 +14,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include <QRegularExpression>
#include <KAboutData>
+#include <KActionCollection>
#include "../debug.h"
#include "../rkward.h"
@@ -34,9 +35,9 @@ void RKDebug (int, int, const char* fmt, ...) {
}
/** This test suite sets up a mostly complete application. That's a bit heavy, but arguably, a) modularity isn't ideal in RKWard, and b) many of the more interesting
- * test involve passing commands to the R backend, and then verifying the expected state in the frontend. That alone requires a fairly extensive setup in the first place.
+ * tests involve passing commands to the R backend, and then verifying the expected state in the frontend. That alone requires a fairly extensive setup, anyway.
*
- * Since starting can still take several seconds, the plan, for now, is to run most tests most individual tests inside this single test suite. */
+ * Since starting can still take several seconds, the plan, for now, is to run most individual tests inside this single test suite. */
class RKWardCoreTest: public QObject {
Q_OBJECT
@@ -69,8 +70,26 @@ class RKWardCoreTest: public QObject {
void cleanGlobalenv() {
RInterface::issueCommand(new RCommand("rm(list=ls(all.names=TRUE))", RCommand::User));
}
+
+ void waitForBackendStarted() {
+ QElapsedTimer t;
+ t.start();
+ while (!(RInterface::instance()->backendIsDead() || RInterface::instance()->backendIsIdle())) {
+ if (t.elapsed() > 20000) break;
+ qApp->sendPostedEvents();
+ }
+ if (RInterface::instance()->backendIsIdle()) {
+ qDebug("Backend startup completed");
+ } else {
+ qDebug("Backend startup failed. Listing contents of /tmp/rkward.rbackend");
+ QFile f(QDir::tempPath() + "/rkward.rbackend");
+ f.open(QIODevice::ReadOnly);
+ auto output = f.readAll();
+ qDebug("%s", output.data());
+ }
+ }
- QPointer<RKWardMainWindow> main_win;
+ QPointer<RKWardMainWindow> main_win;
private slots:
void init() {
}
@@ -87,22 +106,7 @@ private slots:
RKSessionVars::r_binary = R_EXECUTABLE;
main_win = new RKWardMainWindow();
main_win->testmode_suppress_dialogs = true;
-
- QElapsedTimer t;
- t.start();
- while (!(RInterface::instance()->backendIsDead() || RInterface::instance()->backendIsIdle())) {
- if (t.elapsed() > 20000) break;
- qApp->sendPostedEvents();
- }
- if (RInterface::instance()->backendIsIdle()) {
- qDebug("Startup completed");
- } else {
- qDebug("Startup failed. Listing contents of /tmp/rkward.rbackend");
- QFile f(QDir::tempPath() + "/rkward.rbackend");
- f.open(QIODevice::ReadOnly);
- auto output = f.readAll();
- qDebug("%s", output.data());
- }
+ waitForBackendStarted();
}
void getIntVector() {
@@ -218,6 +222,28 @@ private slots:
waitForAllFinished(); // priority_command_done must remain in scope until done
}
+ void restartRBackend() {
+ auto restart_action = RKWardMainWindow::getMain()->actionCollection()->action("restart_r");
+ QVERIFY(restart_action != nullptr);
+ RInterface::issueCommand(new RCommand("x <- 1", RCommand::User));
+ waitForAllFinished();
+ QVERIFY(RObjectList::getGlobalEnv()->findObject("x"));
+
+ auto oldiface = RInterface::instance();
+ restart_action->trigger();
+ while (RInterface::instance() == oldiface) { // action may be delayed until next event processing
+ qApp->processEvents();
+ }
+ waitForBackendStarted();
+
+ // backend should be clean after restart
+ QVERIFY(!RObjectList::getGlobalEnv()->findObject("x"));
+ // but of course it should also be functional...
+ RInterface::issueCommand(new RCommand("x <- 1", RCommand::User));
+ waitForAllFinished();
+ QVERIFY(RObjectList::getGlobalEnv()->findObject("x"));
+ }
+
void cleanupTestCase()
{
// at least the backend should exit properly, to avoid creating emergency save files
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index 414b0561..a0657ea8 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -619,7 +619,7 @@ void RKWardMainWindow::initActions() {
restart_r->setText(i18n("Restart R Backend"));
connect(restart_r, &QAction::triggered, this, [this]() {
QString message = i18n("<p>This feature is primarily targetted at advanced users working on scripts or packages. Please proceed with caution.</p><p><b>All unsaved data in this workspace will be lost!</b> All data editors, and graphics windows will be closed.</p><p>Are you sure you want to proceed?</p>");
- if (KMessageBox::warningContinueCancel(this, message, i18n("Restart R backend"), KGuiItem(i18n("Restart R backend"))) == KMessageBox::Continue) {
+ if (suppressModalDialogsForTesting() || (KMessageBox::warningContinueCancel(this, message, i18n("Restart R backend"), KGuiItem(i18n("Restart R backend"))) == KMessageBox::Continue)) {
bool forced = RInterface::instance()->backendIsDead();
while (!RInterface::instance()->backendIsDead() && !RInterface::instance()->backendIsIdle()) {
message = i18n("<p>One or more operations are pending.</p><p>If you have recently chosen to save your workspace, and you see this message, <b>your data may not be saved, yet!</b></p><p>How do you want to proceed?</p>");
More information about the rkward-tracker
mailing list