[education/rkward] rkward/autotests: Add tests regarding order of command execution
Thomas Friedrichsmeier
null at kde.org
Sun Jun 12 08:34:09 BST 2022
Git commit b4e86689de3606b860f4840cb16e6983b99526f3 by Thomas Friedrichsmeier.
Committed on 12/06/2022 at 07:33.
Pushed by tfry into branch 'master'.
Add tests regarding order of command execution
M +57 -2 rkward/autotests/core_test.cpp
https://invent.kde.org/education/rkward/commit/b4e86689de3606b860f4840cb16e6983b99526f3
diff --git a/rkward/autotests/core_test.cpp b/rkward/autotests/core_test.cpp
index 2c95fc28..3aee7d28 100644
--- a/rkward/autotests/core_test.cpp
+++ b/rkward/autotests/core_test.cpp
@@ -11,6 +11,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include <QFile>
#include <QDir>
#include <QLoggingCategory>
+#include <QRegularExpression>
#include <KAboutData>
@@ -31,8 +32,12 @@ void RKDebug (int, int, const char* fmt, ...) {
printf("\n");
}
+/** 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.
+ *
+ * Since starting can still take several seconds, the plan, for now, is to run most tests most individual tests inside this single test suite. */
class RKWardCoreTest: public QObject {
- Q_OBJECT
+ Q_OBJECT
void runCommandWithTimeout(RCommand *command, RCommandChain* chain, std::function<void(RCommand*)> callback, int timeoutms = 1000) {
QString ccopy = command->command();
@@ -51,8 +56,13 @@ class RKWardCoreTest: public QObject {
}
}
+ void runCommandAsync(RCommand *command, RCommandChain* chain, std::function<void(RCommand*)> callback) {
+ command->whenFinished(this, callback);
+ RInterface::issueCommand(command, chain);
+ }
+
void waitForAllFinished(int timeoutms = 1000) {
- runCommandWithTimeout(new RCommand(QString(), RCommand::App | RCommand::EmptyCommand), nullptr, [](RCommand* command){}, timeoutms);
+ runCommandWithTimeout(new RCommand(QString(), RCommand::App | RCommand::EmptyCommand), nullptr, [](RCommand*){}, timeoutms);
}
void cleanGlobalenv() {
@@ -163,10 +173,55 @@ private slots:
cleanGlobalenv();
}
+ void commandOrderAndOutputTest() {
+ // commands shall run in the order 1, 3, 2, 5, 4, but also, of course, all different types of output shall be captured
+ QStringList output;
+ QRegularExpression extractnumber("\\d\\d\\d");
+ auto callback = [&output, extractnumber](RCommand *command) {
+ auto res = extractnumber.match(command->fullOutput());
+ QVERIFY(res.hasMatch());
+ output.append(res.captured());
+ };
+
+ runCommandAsync(new RCommand("cat(\"111\\n\")", RCommand::User), nullptr, callback);
+ auto chain = RInterface::startChain();
+ auto chain2 = RInterface::startChain(chain);
+ runCommandAsync(new RCommand("message(\"222\\n\")", RCommand::App), chain, callback);
+ runCommandAsync(new RCommand("stop(\"333\\n\")", RCommand::App), chain2, callback);
+ runCommandAsync(new RCommand("warning(\"444\\n\")", RCommand::User), nullptr, callback);
+ runCommandAsync(new RCommand("system(\"echo 555\")", RCommand::App), chain, callback);
+ RInterface::closeChain(chain);
+ RInterface::closeChain(chain2);
+ waitForAllFinished();
+
+ QCOMPARE(output.size(), 5);
+ QCOMPARE(output.value(0), "111");
+ QCOMPARE(output.value(1), "333");
+ QCOMPARE(output.value(2), "222");
+ QCOMPARE(output.value(3), "555");
+ QCOMPARE(output.value(4), "444");
+ }
+
+ void priorityCommandTest() {
+ bool priority_command_done = false;
+ runCommandAsync(new RCommand("Sys.sleep(5)", RCommand::User), nullptr, [&priority_command_done](RCommand *command) {
+ QVERIFY(priority_command_done);
+ QVERIFY(command->failed());
+ QVERIFY(command->wasCanceled());
+ });
+ auto priority_command = new RCommand("cat(\"something\\n\")", RCommand::PriorityCommand | RCommand::App);
+ runCommandAsync(priority_command, nullptr, [&priority_command_done](RCommand *) {
+ priority_command_done = true;
+ RInterface::instance()->cancelAll();
+ });
+ waitForAllFinished(); // priority_command_done must remain in scope until done
+ }
+
void cleanupTestCase()
{
// at least the backend should exit properly, to avoid creating emergency save files
RInterface::issueCommand(new RCommand(QString(), RCommand::QuitCommand));
+ RKWardMainWindow::getMain()->slotCloseAllWindows();
while (!(RInterface::instance()->backendIsDead())) {
qApp->processEvents();
}
More information about the rkward-tracker
mailing list