[education/rkward/devel/workspace_output] /: Add auto-tests for output directories (and fix some bugs that surfaced on the way.)
Thomas Friedrichsmeier
null at kde.org
Sat Nov 7 16:35:12 GMT 2020
Git commit ea66c8979ec5ea4a1b9c3af1e1f234486afac5b9 by Thomas Friedrichsmeier.
Committed on 07/11/2020 at 16:34.
Pushed by tfry into branch 'devel/workspace_output'.
Add auto-tests for output directories (and fix some bugs that surfaced on the way.)
M +10 -8 rkward/misc/rkoutputdirectory.cpp
M +3 -1 rkward/rbackend/rpackages/rkward/R/rk.output.R
M +63 -0 tests/rkward_application_tests.R
A +6 -0 tests/rkward_application_tests/rk_output_test.messages.txt
https://invent.kde.org/education/rkward/commit/ea66c8979ec5ea4a1b9c3af1e1f234486afac5b9
diff --git a/rkward/misc/rkoutputdirectory.cpp b/rkward/misc/rkoutputdirectory.cpp
index 21919626..4cd5ae56 100644
--- a/rkward/misc/rkoutputdirectory.cpp
+++ b/rkward/misc/rkoutputdirectory.cpp
@@ -83,8 +83,7 @@ RKOutputDirectory* RKOutputDirectory::getOutputBySaveUrl(const QString& _dest) {
RK_TRACE (APP);
QString dest = QFileInfo(_dest).canonicalFilePath();
- auto it = outputs.constBegin();
- while (it != outputs.constEnd()) {
+ for (auto it = outputs.constBegin(); it != outputs.constEnd(); ++it) {
if (it.value()->save_filename == dest) {
return(it.value());
}
@@ -212,9 +211,9 @@ GenericRRequestResult RKOutputDirectory::revert(OverwriteBehavior discard) {
RK_TRACE (APP);
if (save_filename.isEmpty()) {
- return GenericRRequestResult::makeError(i18n("Output directory %1 has not previously been saved. Cannot revert.", id));
+ return GenericRRequestResult::makeError(i18n("Output has not previously been saved. Cannot revert."));
}
- if (!isModified()) return GenericRRequestResult(id, i18n("Output directory %1 had no modifications. Nothing reverted.", id));
+ if (!isModified()) return GenericRRequestResult(id, i18n("Output had no modifications. Nothing reverted."));
if (discard == Ask) {
if (KMessageBox::warningContinueCancel(RKWardMainWindow::getMain(), i18n("Reverting will destroy any changes, since the last time you saved (%1). Are you sure you want to proceed?", save_timestamp.toString())) == KMessageBox::Continue) {
discard = Force;
@@ -271,9 +270,9 @@ GenericRRequestResult RKOutputDirectory::clear(OverwriteBehavior discard) {
if (KMessageBox::warningContinueCancel(RKWardMainWindow::getMain(), i18n("Clearing will destroy any unsaved changes, and - upon saving - also saved changes. Are you sure you want to proceed?")) == KMessageBox::Continue) {
discard = Force;
}
- if (discard != Force) {
- return GenericRRequestResult::makeError(i18n("Output is not empty. Not clearing it."));
- }
+ }
+ if (discard != Force) {
+ return GenericRRequestResult::makeError(i18n("Output is not empty. Not clearing it."));
}
}
@@ -465,7 +464,10 @@ GenericRRequestResult RKOutputDirectory::handleRCall(const QStringList& params,
out = createOutputDirectoryInternal();
return (out->import(filename));
} else {
- if (!out) return (out->import(filename));
+ if (!out) {
+ out = createOutputDirectoryInternal();
+ return (out->import(filename));
+ }
}
}
return GenericRRequestResult(out->getId());
diff --git a/rkward/rbackend/rpackages/rkward/R/rk.output.R b/rkward/rbackend/rpackages/rkward/R/rk.output.R
index b6c40d13..66abf2cf 100644
--- a/rkward/rbackend/rpackages/rkward/R/rk.output.R
+++ b/rkward/rbackend/rpackages/rkward/R/rk.output.R
@@ -103,5 +103,7 @@ Do not write anything to the target filename, directly! This is purely for infor
"rk.output" <- function(filename=NULL, create=FALSE, all=FALSE) {
if(all && (!is.null(filename) || create)) stop("'all' cannot be combined with 'create' or 'filename'")
id <- .rk.do.call("output", c ("get", if(isTRUE(all)) "all" else "one", if(isTRUE(create)) "create" else "", if(is.null(filename)) "" else as.character(filename)))
- RK.Output(id=id)
+ ret <- lapply(id, function(id) RK.Output(id=id))
+ if (all) ret
+ else ret[[1]]
}
diff --git a/tests/rkward_application_tests.R b/tests/rkward_application_tests.R
index 1085f7b7..df6d2331 100644
--- a/tests/rkward_application_tests.R
+++ b/tests/rkward_application_tests.R
@@ -268,6 +268,69 @@ suite <- new ("RKTestSuite", id="rkward_application_tests",
}
', submit.mode="submit")
}),
+ new ("RKTest", id="rk_output_test", call=function () {
+ sync_outfile <- function() {
+ # Manually notify frontend of current output file. This is usually suppressed for auto-texting, but important, here, since
+ # the frontend uses this to detect, which output is active.
+ rkward:::.rk.do.plain.call ("set.output.file", c (rk.get.output.html.file()), synchronous=FALSE)
+ }
+
+ x <- rk.output() # get active output
+
+ l1 <- length(rk.output(all=TRUE))
+
+ y <- rk.output(create=TRUE) # create new output
+ l2 <- length(rk.output(all=TRUE))
+ stopifnot(l1 == l2-1)
+ stopifnot(x$id != y$id)
+ stopifnot(!y$isModified())
+ y$activate()
+ sync_outfile()
+ stopifnot(!y$isModified()) # initialization shall not count as modification
+ stopifnot(y$isEmpty())
+
+ rk.print("y")
+ stopifnot(y$isModified())
+ stopifnot(!y$isEmpty())
+
+ z <- rk.output() # rk.output() without parameters shall return active output
+ stopifnot(y$id == z$id)
+ rktest.expectError(z$close(discard=FALSE))
+ rktest.expectError(z$revert(discard=FALSE))
+ rktest.expectError(z$clear(discard=FALSE))
+
+ f <- tempfile() # saving shall mark the output as non-modified
+ y$save(f)
+ stopifnot(!y$isModified())
+ stopifnot(!y$isEmpty())
+ y$close(discard=FALSE)
+
+ z <- rk.output(f) # a freshly loaded output shall not count as modified
+ stopifnot(!z$isModified())
+ stopifnot(!z$isEmpty())
+
+ z$activate() # exporting shall not mark the output as non-modified
+ sync_outfile()
+ rk.print("z")
+ g <- tempfile()
+ z$export(g)
+ stopifnot(z$isModified())
+
+ z$revert(discard=TRUE) # revert shall mark output as non-modified
+ stopifnot(!z$isModified())
+
+ rk.print("z2") # dicard=TRUE shall allow closing modified output
+ z$close(discard=TRUE)
+
+ rktest.expectError(z$view(), silent=TRUE) # closed output shall be invalid; silent, because error message will contain id
+
+ sync_outfile()
+ a <- rk.output() # When closing, the previous output shall be re-activated
+ stopifnot(a$id == x$id)
+
+ unlink(f)
+ unlink(g)
+ }, ignore=c("code")),
new ("RKTest", id="run_again_links", call=function () {
# usually, commands to generate run-again-links are not included in the command recording, since these can sometimes change at a large scale (e.g. if the plot-options plugin gains a new option), and this is rarely of interest. Here, we do include a test to catch any grave problems. For this purpose, we simply call some complex plugins.
rk.call.plugin ("rkward::plot_beta_clt", a.real="2.00", b.real="2.00", drawnorm.state="1", function.string="hist", histogram_opt.addtoplot.state="", histogram_opt.barlabels.state="1", histogram_opt.density.real="-1.00", histogram_opt.doborder.state="1", histogram_opt.freq.state="0", histogram_opt.histbordercol.color.string="", histogram_opt.histbreaksFunction.string="Sturges", histogram_opt.histfillcol.color.string="azure", histogram_opt.histlinetype.string="solid", histogram_opt.rightclosed.state="1", histogram_opt.usefillcol.state="1", nAvg.real="10.00", nDist.real="1000.00", normlinecol.color.string="red", normpointtype.string="l", plotoptions.add_grid.state="0", plotoptions.asp.real="0.00", plotoptions.main.text="", plotoptions.pointcolor.color.string="", plotoptions.pointtype.string="", plotoptions.sub.text="", plotoptions.xaxt.state="", plotoptions.xlab.text="", plotoptions.xlog.state="", plotoptions.xmaxvalue.text="", plotoptions.xminvalue.text="", plotoptions.yaxt.state="", plotoptions.ylab.text="", plotoptions.ylog.state="", plotoptions.ymaxvalue.text="", plotoptions.yminvalue.text="", scalenorm.state="0", submit.mode="submit")
diff --git a/tests/rkward_application_tests/rk_output_test.messages.txt b/tests/rkward_application_tests/rk_output_test.messages.txt
new file mode 100644
index 00000000..cf64cafa
--- /dev/null
+++ b/tests/rkward_application_tests/rk_output_test.messages.txt
@@ -0,0 +1,6 @@
+Error in .rk.do.call("output", c("close", .checkId(), if (is.null(discard)) "ask" else if (isTRUE(discard)) "force" else "fail")) :
+ Output has been modified. Not closing it.
+Error in .rk.do.call("output", c("revert", .checkId(), if (is.null(discard)) "ask" else if (isTRUE(discard)) "force" else "fail")) :
+ Output has not previously been saved. Cannot revert.
+Error in .rk.do.call("output", c("clear", .checkId(), if (is.null(discard)) "ask" else if (isTRUE(discard)) "force" else "fail")) :
+ Output is not empty. Not clearing it.
More information about the rkward-tracker
mailing list