[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