diff --git a/.gitignore b/.gitignore index 93decc0f..1f5f8c99 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ tests/testthat/connection_to_datasets/local_settings.csv tests/docker/armadillo/standard/logs/ tests/docker/armadillo/standard/data/ lintr_results.sarif +tests/testthat/Rplots.pdf diff --git a/R/ds.colnames.R b/R/ds.colnames.R index da842ec0..06e64728 100644 --- a/R/ds.colnames.R +++ b/R/ds.colnames.R @@ -52,30 +52,8 @@ #' ds.colnames <- function(x=NULL, datasources=NULL) { - # look for DS connections - if(is.null(datasources)){ - datasources <- datashield.connections_find() - } - - # ensure datasources is a list of DSConnection-class - if(!(is.list(datasources) && all(unlist(lapply(datasources, function(d) {methods::is(d,"DSConnection")}))))){ - stop("The 'datasources' were expected to be a list of DSConnection-class objects", call.=FALSE) - } - - if(is.null(x)){ - stop("Please provide the name of a data.frame or matrix!", call.=FALSE) - } - - # check if the input object(s) is(are) defined in all the studies - defined <- isDefined(datasources, x) - - # call the internal function that checks the input object is of the same class in all studies. - typ <- checkClass(datasources, x) - - # if the input object is not a matrix or a dataframe stop - if(!('data.frame' %in% typ) & !('matrix' %in% typ)){ - stop("The input vector must be of type 'data.frame' or a 'matrix'!", call.=FALSE) - } + datasources <- .set_datasources(datasources) + .check_df_name_provided(x) cally <- call("colnamesDS", x) column_names <- DSI::datashield.aggregate(datasources, cally) diff --git a/R/ds.contourPlot.R b/R/ds.contourPlot.R index 0adb44fa..42084006 100644 --- a/R/ds.contourPlot.R +++ b/R/ds.contourPlot.R @@ -181,9 +181,9 @@ ds.contourPlot <- function(x=NULL, y=NULL, type='combine', show='all', numints=2 if(method=='smallCellsRule'){ # get the range from each study and produce the 'global' range - x.ranges <- datashield.aggregate(datasources, as.symbol(paste0("rangeDS(", x, ")"))) + x.ranges <- datashield.aggregate(datasources, call("rangeDS", x)) - y.ranges <- datashield.aggregate(datasources, as.symbol(paste0("rangeDS(", y, ")"))) + y.ranges <- datashield.aggregate(datasources, call("rangeDS", y)) x.minrs <- c() x.maxrs <- c() diff --git a/R/ds.densityGrid.R b/R/ds.densityGrid.R index c2aa8ffc..d617dd73 100644 --- a/R/ds.densityGrid.R +++ b/R/ds.densityGrid.R @@ -104,9 +104,9 @@ ds.densityGrid <- function(x=NULL, y=NULL, numints=20, type='combine', datasourc if(type=="combine"){ # get the range from each study and produce the 'global' range - x.ranges <- datashield.aggregate(datasources, as.symbol(paste0("rangeDS(", x, ")"))) + x.ranges <- datashield.aggregate(datasources, call("rangeDS", x)) - y.ranges <- datashield.aggregate(datasources, as.symbol(paste0("rangeDS(", y, ")"))) + y.ranges <- datashield.aggregate(datasources, call("rangeDS", y)) x.minrs <- c() x.maxrs <- c() diff --git a/R/ds.getWGSR.R b/R/ds.getWGSR.R index 9cc87851..80306811 100644 --- a/R/ds.getWGSR.R +++ b/R/ds.getWGSR.R @@ -139,5 +139,4 @@ ds.getWGSR <- function(sex=NULL, firstPart=NULL, secondPart=NULL, index=NULL, st cally <- call("getWGSRDS", sex, firstPart, secondPart, index, standing, thirdPart) DSI::datashield.assign(datasources, newobj, cally) - -} +} diff --git a/R/ds.heatmapPlot.R b/R/ds.heatmapPlot.R index 95232157..48312460 100644 --- a/R/ds.heatmapPlot.R +++ b/R/ds.heatmapPlot.R @@ -229,9 +229,9 @@ ds.heatmapPlot <- function(x=NULL, y=NULL, type="combine", show="all", numints=2 if (method=="smallCellsRule"){ # get the range from each study and produce the 'global' range - x.ranges <- datashield.aggregate(datasources, as.symbol(paste0("rangeDS(", x, ")"))) + x.ranges <- datashield.aggregate(datasources, call("rangeDS", x)) - y.ranges <- datashield.aggregate(datasources, as.symbol(paste0("rangeDS(", y, ")"))) + y.ranges <- datashield.aggregate(datasources, call("rangeDS", y)) x.minrs <- c() x.maxrs <- c() diff --git a/R/ds.isValid.R b/R/ds.isValid.R index e43b61b1..266dbca2 100644 --- a/R/ds.isValid.R +++ b/R/ds.isValid.R @@ -13,8 +13,10 @@ #' @param datasources a list of \code{\link[DSI]{DSConnection-class}} #' objects obtained after login. If the \code{datasources} argument is not specified #' the default set of connections will be used: see \code{\link[DSI]{datashield.connections_default}}. +#' @template classConsistencyCheckTrue #' @return \code{ds.isValid} returns a boolean. If it is TRUE input object is valid, FALSE otherwise. #' @author DataSHIELD Development Team +#' @author Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands #' @export #' @examples #' \dontrun{ @@ -55,36 +57,21 @@ #' #' } #' -ds.isValid <- function(x=NULL, datasources=NULL){ +ds.isValid <- function(x=NULL, datasources=NULL, classConsistencyCheck=TRUE){ - # look for DS connections - if(is.null(datasources)){ - datasources <- datashield.connections_find() - } - - # ensure datasources is a list of DSConnection-class - if(!(is.list(datasources) && all(unlist(lapply(datasources, function(d) {methods::is(d,"DSConnection")}))))){ - stop("The 'datasources' were expected to be a list of DSConnection-class objects", call.=FALSE) - } + datasources <- .set_datasources(datasources) if(is.null(x)){ stop("Please provide the name of the input vector!", call.=FALSE) } - # check if the input object is defined in all the studies - isDefined(datasources, x) - - # call the internal function that checks the input object is of the same class in all studies. - typ <- checkClass(datasources, x) + # call the server side function that does the job and return its output + cally <- call("isValidDS", x) + results <- DSI::datashield.aggregate(datasources, cally) - # the input object must be a vector - if(!('character' %in% typ) & !('factor' %in% typ) & !('integer' %in% typ) & !('logical' %in% typ) & !('numeric' %in% typ) & !('data.frame' %in% typ) & !('matrix' %in% typ)){ - stop("The input object must be a character, factor, integer, logical or numeric vector or a dataframe or a matrix", call.=FALSE) + if(classConsistencyCheck){ + .checkClassConsistency(results) } - # call the server side function that does the job and return its output - cally <- paste0('isValidDS(', x, ')') - output <- DSI::datashield.aggregate(datasources, as.symbol(cally)) - - return(output) + return(lapply(results, function(r) r$valid)) } diff --git a/R/ds.make.R b/R/ds.make.R index 1def3dcf..044c727a 100644 --- a/R/ds.make.R +++ b/R/ds.make.R @@ -134,7 +134,6 @@ #' ds.make<-function(toAssign=NULL, newobj=NULL, datasources=NULL){ - # look for DS connections datasources <- .set_datasources(datasources) if(is.null(toAssign)){ diff --git a/R/ds.rowColCalc.R b/R/ds.rowColCalc.R index cf133c27..8d0ec804 100644 --- a/R/ds.rowColCalc.R +++ b/R/ds.rowColCalc.R @@ -74,33 +74,6 @@ ds.rowColCalc <- function(x=NULL, operation=NULL, newobj=NULL, datasources=NULL) stop("Please provide the name of a data.frame or matrix!", call.=FALSE) } - # number of studies and their names - numsources <- length(datasources) - stdnames <- names(datasources) - - # we want to deal only with two dimensional tables - dim2 <- c() - for(i in 1:numsources){ - dims <- DSI::datashield.aggregate(datasources[i], call("dimDS", x)) - if(length(dims[[1]]$dim) != 2){ - stop("The input table in ", stdnames[i]," has more than two dimensions. Only strutures of two dimensions are allowed", call.=FALSE) - } - dim2 <- append(dim2, dims[[1]]$dim[2]) - } - - # check that, for each study, all the columns of the input table are of 'numeric' type - dtname <- x - for(i in 1:numsources){ - cols <- DSI::datashield.aggregate(datasources[i], call("colnamesDS", x)) - for(j in 1:dim2[i]){ - cally <- call("classDS", paste0(dtname, "$", cols[[1]][j])) - res <- DSI::datashield.aggregate(datasources[i], cally) - if(res[[1]] != 'numeric' & res[[1]] != 'integer'){ - stop("One or more columns of ", dtname, " are not of numeric type, in ", stdnames[i], ".", call.=FALSE) - } - } - } - ops <- c("rowSums","colSums","rowMeans","colMeans") if(is.null(operation)){ message(" ALERT!") diff --git a/R/ds.summary.R b/R/ds.summary.R index 82f04f93..3174023a 100644 --- a/R/ds.summary.R +++ b/R/ds.summary.R @@ -89,7 +89,7 @@ ds.summary <- function(x=NULL, datasources=NULL){ # now get the summary depending on the type of the input variable if(("data.frame" %in% typ) | ("matrix" %in% typ)){ for(i in 1:numsources){ - validity <- DSI::datashield.aggregate(datasources[i], as.symbol(paste0('isValidDS(', x, ')')))[[1]] + validity <- DSI::datashield.aggregate(datasources[i], call('isValidDS', x))[[1]]$valid if(validity){ dims <- DSI::datashield.aggregate(datasources[i], call('dimDS', x)) r <- dims[[1]]$dim[1] @@ -106,7 +106,7 @@ ds.summary <- function(x=NULL, datasources=NULL){ if("character" %in% typ){ for(i in 1:numsources){ - validity <- DSI::datashield.aggregate(datasources[i], as.symbol(paste0('isValidDS(', x, ')')))[[1]] + validity <- DSI::datashield.aggregate(datasources[i], call('isValidDS', x))[[1]]$valid if(validity){ l <- DSI::datashield.aggregate(datasources[i], call('lengthDS', x))[[1]]$length stdsummary <- list('class'=typ, 'length'=l) @@ -120,7 +120,7 @@ ds.summary <- function(x=NULL, datasources=NULL){ if("factor" %in% typ){ for(i in 1:numsources){ - validity <- DSI::datashield.aggregate(datasources[i], as.symbol(paste0('isValidDS(', x, ')')))[[1]] + validity <- DSI::datashield.aggregate(datasources[i], call('isValidDS', x))[[1]]$valid if(validity){ l <- DSI::datashield.aggregate(datasources[i], call('lengthDS', x))[[1]]$length levels.resp <- DSI::datashield.aggregate(datasources[i], call('levelsDS', x))[[1]] @@ -141,7 +141,7 @@ ds.summary <- function(x=NULL, datasources=NULL){ if(("integer" %in% typ) | ("numeric" %in% typ)){ for(i in 1:numsources){ - validity <- DSI::datashield.aggregate(datasources[i], as.symbol(paste0('isValidDS(', x, ')')))[[1]] + validity <- DSI::datashield.aggregate(datasources[i], call('isValidDS', x))[[1]]$valid if(validity){ l <- DSI::datashield.aggregate(datasources[i], call('lengthDS', x))[[1]]$length q <- (DSI::datashield.aggregate(datasources[i], call('quantileMeanDS', x)))[[1]]$quantiles @@ -176,7 +176,7 @@ ds.summary <- function(x=NULL, datasources=NULL){ if("logical" %in% typ){ for(i in 1:numsources){ - validity <- DSI::datashield.aggregate(datasources[i], as.symbol(paste0('isValidDS(', x, ')')))[[1]] + validity <- DSI::datashield.aggregate(datasources[i], call('isValidDS', x))[[1]]$valid if(validity){ l <- DSI::datashield.aggregate(datasources[i], call('lengthDS', x))[[1]]$length freq <- DSI::datashield.aggregate(datasources[i], as.symbol(paste0('table1DDS(', x, ')' )))[[1]][1] diff --git a/dsBase_7.0.0-permissive.tar.gz b/dsBase_7.0.0-permissive.tar.gz index 285d780d..137855e3 100644 Binary files a/dsBase_7.0.0-permissive.tar.gz and b/dsBase_7.0.0-permissive.tar.gz differ diff --git a/man/ds.isValid.Rd b/man/ds.isValid.Rd index 2f927ae2..eb4f4cd9 100644 --- a/man/ds.isValid.Rd +++ b/man/ds.isValid.Rd @@ -4,7 +4,7 @@ \alias{ds.isValid} \title{Checks if a server-side object is valid} \usage{ -ds.isValid(x = NULL, datasources = NULL) +ds.isValid(x = NULL, datasources = NULL, classConsistencyCheck = TRUE) } \arguments{ \item{x}{a character string specifying the name of a vector, dataframe or matrix.} @@ -12,6 +12,9 @@ ds.isValid(x = NULL, datasources = NULL) \item{datasources}{a list of \code{\link[DSI]{DSConnection-class}} objects obtained after login. If the \code{datasources} argument is not specified the default set of connections will be used: see \code{\link[DSI]{datashield.connections_default}}.} + +\item{classConsistencyCheck}{logical. If TRUE, checks that the input object has the same +class across all studies. Default TRUE.} } \value{ \code{ds.isValid} returns a boolean. If it is TRUE input object is valid, FALSE otherwise. @@ -71,4 +74,6 @@ Server function called: \code{isValidDS} } \author{ DataSHIELD Development Team + +Tim Cadman, Genomics Coordination Centre, UMCG, Netherlands } diff --git a/tests/testthat/Rplots.pdf b/tests/testthat/Rplots.pdf deleted file mode 100644 index 3439ff7d..00000000 Binary files a/tests/testthat/Rplots.pdf and /dev/null differ diff --git a/tests/testthat/test-arg-ds.isValid.R b/tests/testthat/test-arg-ds.isValid.R index 37fbf21a..4d97f1fa 100644 --- a/tests/testthat/test-arg-ds.isValid.R +++ b/tests/testthat/test-arg-ds.isValid.R @@ -22,7 +22,6 @@ connect.studies.dataset.cnsim(list("LAB_HDL")) # context("ds.isValid::arg::errors") test_that("isValid errors", { expect_error(ds.isValid(), "Please provide the name of the input vector!", fixed=TRUE) - expect_error(ds.isValid("D$NOT_THERE"), "The input object D$NOT_THERE is not defined in sim1, sim2, sim3!", fixed=TRUE) }) # diff --git a/tests/testthat/test-arg-ds.metadata.R b/tests/testthat/test-arg-ds.metadata.R index a80b40cc..5bcabe43 100644 --- a/tests/testthat/test-arg-ds.metadata.R +++ b/tests/testthat/test-arg-ds.metadata.R @@ -26,9 +26,6 @@ test_that("setup", { # # context("ds.metadata::arg") -# "missing variable" / "missing column" moved to test-smk-ds.metadata.R: -# these are now server-side existence checks (via .loadServersideObject), not -# client-side argument validation, so they belong in the smk suite. # # Tear down diff --git a/tests/testthat/test-perf-ds.hetcor.R b/tests/testthat/test-perf-ds.hetcor.R index 69a3a79f..23da1a95 100644 --- a/tests/testthat/test-perf-ds.hetcor.R +++ b/tests/testthat/test-perf-ds.hetcor.R @@ -6,6 +6,8 @@ # context("ds.hetcor::perf::setup") connect.studies.dataset.cnsim(list("LAB_TSC", "LAB_TRIG", "LAB_HDL", "LAB_GLUC_ADJUSTED", "PM_BMI_CONTINUOUS", "DIS_CVA", "MEDI_LPD", "DIS_DIAB", "DIS_AMI", "GENDER", "PM_BMI_CATEGORICAL")) +ds.dataFrame(c("D$LAB_TSC", "D$LAB_TRIG", "D$LAB_HDL", "D$LAB_GLUC_ADJUSTED", "D$PM_BMI_CONTINUOUS", "D$DIS_CVA", "D$MEDI_LPD", "D$DIS_DIAB", "D$DIS_AMI", "D$GENDER", "D$PM_BMI_CATEGORICAL"), newobj="df") + # # Tests # @@ -18,7 +20,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.hetcor(data="D") + ds.hetcor(data="df", ML=TRUE, std.err=TRUE, bins=4, pd=TRUE, use="complete.obs") .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.isValid.R b/tests/testthat/test-perf-ds.isValid.R new file mode 100644 index 00000000..83cde48b --- /dev/null +++ b/tests/testthat/test-perf-ds.isValid.R @@ -0,0 +1,50 @@ + +# +# Set up +# + +# context("ds.isValid::perf::setup") +connect.studies.dataset.cnsim(list("LAB_TSC", "LAB_TRIG")) + +# +# Tests +# + +# context("ds.isValid::perf::0") +test_that("performance", { + .durationSec <- 30 # seconds + .count <- 0 + .start.time <- Sys.time() + .current.time <- .start.time + + while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { + ds.isValid(x='D$LAB_TSC') + + .count <- .count + 1 + .current.time <- Sys.time() + } + + .current.rate <- .count / (difftime(.current.time, .start.time, units = "secs")[[1]]) + .reference.rate <- perf.reference.rate("ds.isValid::perf::0") + if (any(length(.reference.rate) == 0) || any(is.null(.reference.rate))) { + print(paste("ds.isValid::perf::0 ", .current.rate, 0.5, 2.0)) + perf.reference.save("ds.isValid::perf::0", .current.rate, 0.5, 2.0) + } else { + print(paste("ds.isValid::perf::0 ", format(.current.rate, digits = 8), ", ", format(100.0 * .current.rate / .reference.rate, digits = 4), "%", sep = '')) + } + + .reference.rate <- perf.reference.rate("ds.isValid::perf::0") + .reference.tolerance.lower <- perf.reference.tolerance.lower("ds.isValid::perf::0") + .reference.tolerance.upper <- perf.reference.tolerance.upper("ds.isValid::perf::0") + + expect_gt(.current.rate, .reference.rate * .reference.tolerance.lower, label = "Observed rate", expected.label = "lower threshold on rate") + expect_lt(.current.rate, .reference.rate * .reference.tolerance.upper, label = "Observed rate", expected.label = "upper threshold on rate") +}) + +# +# Done +# + +# context("ds.isValid::perf::shutdown") +disconnect.studies.dataset.cnsim() +# context("ds.isValid::perf::done") diff --git a/tests/testthat/test-perf-ds.make.R b/tests/testthat/test-perf-ds.make.R index 2b23a48f..1101ccd1 100644 --- a/tests/testthat/test-perf-ds.make.R +++ b/tests/testthat/test-perf-ds.make.R @@ -18,7 +18,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.make(toAssign="D$LAB_TSC + D$LAB_TRIG", newobj="make.newobj") + ds.make("(D$LAB_TSC*D$LAB_TRIG*D$LAB_HDL)", "make.newobj") .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.metadata.R b/tests/testthat/test-perf-ds.metadata.R index ee17ac41..56b1e130 100644 --- a/tests/testthat/test-perf-ds.metadata.R +++ b/tests/testthat/test-perf-ds.metadata.R @@ -18,7 +18,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.metadata(x="D$LAB_TSC") + ds.metadata(x='D') .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.ns.R b/tests/testthat/test-perf-ds.ns.R index 3d8811e7..074da997 100644 --- a/tests/testthat/test-perf-ds.ns.R +++ b/tests/testthat/test-perf-ds.ns.R @@ -18,7 +18,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.ns("D$PM_BMI_CONTINUOUS", df=3, newobj="ns.newobj") + ds.ns(x="D$PM_BMI_CONTINUOUS", knots=c(15,25,35), newobj="ns.newobj") .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.qlspline.R b/tests/testthat/test-perf-ds.qlspline.R index 99aa6dce..9e624339 100644 --- a/tests/testthat/test-perf-ds.qlspline.R +++ b/tests/testthat/test-perf-ds.qlspline.R @@ -18,7 +18,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.qlspline("D$PM_BMI_CONTINUOUS", q=3, newobj="qlspline.newobj") + ds.qlspline(x="D$PM_BMI_CONTINUOUS", q=4, na.rm=TRUE, newobj="qlspline.newobj") .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.rowColCalc.R b/tests/testthat/test-perf-ds.rowColCalc.R index 21e5736d..54b1755e 100644 --- a/tests/testthat/test-perf-ds.rowColCalc.R +++ b/tests/testthat/test-perf-ds.rowColCalc.R @@ -18,7 +18,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.rowColCalc(x="D", operation="colMeans", newobj="rowcol.newobj") + ds.rowColCalc(x="D", operation="rowSums", newobj="rowcol.newobj") .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.table.R b/tests/testthat/test-perf-ds.table.R index 5511710b..0888fa08 100644 --- a/tests/testthat/test-perf-ds.table.R +++ b/tests/testthat/test-perf-ds.table.R @@ -5,7 +5,13 @@ # context("ds.table::perf::setup") -connect.studies.dataset.cnsim(list("GENDER")) +connect.all.datasets() + +ds.asFactor(input.var.name="D$FACTOR_CHARACTER", newobj.name="factorCharacter") +ds.asFactor(input.var.name="D$FACTOR_INTEGER", newobj.name="factorInteger") +ds.asFactor(input.var.name="D$CATEGORY", newobj.name="factorCategory") +ds.dataFrame(x=c("factorInteger", "factorCharacter", "factorCategory"), newobj="tablesource") +ds.dataFrameSubset(df.name="tablesource", V1.name="factorInteger", V2.name='6', Boolean.operator="!=", newobj="tablesource_subset") # # Tests @@ -19,7 +25,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.table(rvar="D$GENDER") + ds.table(rvar='tablesource_subset$factorCharacter') .count <- .count + 1 .current.time <- Sys.time() @@ -47,5 +53,5 @@ test_that("performance", { # # context("ds.table::perf::shutdown") -disconnect.studies.dataset.cnsim() +disconnect.all.datasets() # context("ds.table::perf::done") diff --git a/tests/testthat/test-perf-ds.tapply.R b/tests/testthat/test-perf-ds.tapply.R index 8ad28a46..a1bc1b65 100644 --- a/tests/testthat/test-perf-ds.tapply.R +++ b/tests/testthat/test-perf-ds.tapply.R @@ -6,6 +6,9 @@ # context("ds.tapply::perf::setup") connect.studies.dataset.cnsim(list("LAB_TSC", "GENDER")) +ds.assign('D$LAB_TSC', 'LAB_TSC') +ds.assign('D$GENDER', 'GENDER') + # # Tests # @@ -18,7 +21,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.tapply(X.name="D$LAB_TSC", INDEX.names="D$GENDER", FUN.name="mean") + ds.tapply('LAB_TSC', INDEX.names=c('GENDER'), FUN.name='mean') .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-perf-ds.tapply.assign.R b/tests/testthat/test-perf-ds.tapply.assign.R index f3bedfe1..453ef1b4 100644 --- a/tests/testthat/test-perf-ds.tapply.assign.R +++ b/tests/testthat/test-perf-ds.tapply.assign.R @@ -6,6 +6,9 @@ # context("ds.tapply.assign::perf::setup") connect.studies.dataset.cnsim(list("LAB_TSC", "GENDER")) +ds.assign('D$LAB_TSC', 'LAB_TSC') +ds.assign('D$GENDER', 'GENDER') + # # Tests # @@ -18,7 +21,7 @@ test_that("performance", { .current.time <- .start.time while (difftime(.current.time, .start.time, units = "secs")[[1]] < .durationSec) { - ds.tapply.assign(X.name="D$LAB_TSC", INDEX.names="D$GENDER", FUN.name="mean", newobj="tapply.newobj") + ds.tapply.assign('LAB_TSC', INDEX.names=c('GENDER'), FUN.name='mean', newobj="tapply.newobj") .count <- .count + 1 .current.time <- Sys.time() diff --git a/tests/testthat/test-smk-ds.colnames.R b/tests/testthat/test-smk-ds.colnames.R index b7d289ac..40d9e1c2 100644 --- a/tests/testthat/test-smk-ds.colnames.R +++ b/tests/testthat/test-smk-ds.colnames.R @@ -47,21 +47,28 @@ test_that("simple colnames", { test_that("fails if the object does not exist", { expect_error( ds.colnames("non_existing_df"), - regexp = "The input object non_existing_df is not defined in sim1, sim2, sim3!", - ignore.case = TRUE + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'non_existing_df' does not exist") + } }) -########################################### -### Remote checks not performed ### -########################################### -# test_that("fails if object is not a data frame or matrix", { -# expect_error( -# ds.colnames("D$LAB_TSC"), -# regexp = "must be of type data.frame or matrix", -# ignore.case = TRUE -# ) -# }) +test_that("fails if object is not a data frame or matrix", { + expect_error( + ds.colnames("D$LAB_TSC"), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "must be of type data.frame or matrix") + } +}) # # Done diff --git a/tests/testthat/test-smk-ds.contourPlot.R b/tests/testthat/test-smk-ds.contourPlot.R index 944b192c..ff03ff8f 100644 --- a/tests/testthat/test-smk-ds.contourPlot.R +++ b/tests/testthat/test-smk-ds.contourPlot.R @@ -40,6 +40,15 @@ test_that("contour plot with wrong input class fails", { # Done # +test_that("contour plot with nonexistent object fails in the default combine path", { + expect_error(ds.contourPlot(x="nonexistent_obj", y="D$LAB_TRIG"), "There are some DataSHIELD errors", fixed=TRUE) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_obj' does not exist", fixed = TRUE) + } +}) + # context("ds.contourPlot::smk::shutdown") test_that("shutdown", { diff --git a/tests/testthat/test-smk-ds.densityGrid.R b/tests/testthat/test-smk-ds.densityGrid.R index 2c01ae0f..61195b32 100644 --- a/tests/testthat/test-smk-ds.densityGrid.R +++ b/tests/testthat/test-smk-ds.densityGrid.R @@ -49,6 +49,15 @@ test_that("density grid with wrong input class fails", { # Done # +test_that("density grid with nonexistent object fails in the default combine path", { + expect_error(ds.densityGrid(x="nonexistent_obj", y="D$LAB_TRIG"), "There are some DataSHIELD errors", fixed=TRUE) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_obj' does not exist", fixed = TRUE) + } +}) + # context("ds.densityGrid::smk::shutdown") test_that("shutdown", { diff --git a/tests/testthat/test-smk-ds.elspline.R b/tests/testthat/test-smk-ds.elspline.R index 9b859808..7f356fef 100644 --- a/tests/testthat/test-smk-ds.elspline.R +++ b/tests/testthat/test-smk-ds.elspline.R @@ -132,8 +132,14 @@ test_that("elspline", { test_that("fails if the object does not exist", { expect_error( ds.elspline(x = "nonexistent_object", n = 3), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # diff --git a/tests/testthat/test-smk-ds.getWGSR.R b/tests/testthat/test-smk-ds.getWGSR.R index 7aaf391e..7c6a2a53 100644 --- a/tests/testthat/test-smk-ds.getWGSR.R +++ b/tests/testthat/test-smk-ds.getWGSR.R @@ -59,14 +59,35 @@ test_that("simple getWGSR", { test_that("fails if the object does not exist", { expect_error( ds.getWGSR(sex = "D$sex", firstPart = "nonexistent_object", secondPart = "D$height", index = "hfa"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } +}) + +test_that("fails if firstPart is not numeric", { + ds.asFactor(input.var.name = "D$sex", newobj.name = "sex_factor") + + expect_error( + ds.getWGSR(sex = "D$sex", firstPart = "sex_factor", secondPart = "D$height", index = "hfa"), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object must be of type numeric") + } }) # context("ds.getWGSR::smk::shutdown") test_that("shutdown", { - ds_expect_variables(c("D", "newobj.getwgsr")) + ds_expect_variables(c("D", "newobj.getwgsr", "sex_factor")) }) disconnect.studies.dataset.cnsim() diff --git a/tests/testthat/test-smk-ds.heatmapPlot.R b/tests/testthat/test-smk-ds.heatmapPlot.R index ed50c15f..3f1112b3 100644 --- a/tests/testthat/test-smk-ds.heatmapPlot.R +++ b/tests/testthat/test-smk-ds.heatmapPlot.R @@ -40,6 +40,15 @@ test_that("heatmap plot with wrong input class fails", { # Done # +test_that("heatmap plot with nonexistent object fails in the default combine path", { + expect_error(ds.heatmapPlot(x="nonexistent_obj", y="D$LAB_TRIG"), "There are some DataSHIELD errors", fixed=TRUE) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_obj' does not exist", fixed = TRUE) + } +}) + # context("ds.heatmapPlot::smk::shutdown") test_that("shutdown", { diff --git a/tests/testthat/test-smk-ds.hetcor.R b/tests/testthat/test-smk-ds.hetcor.R index 026cf051..5c8c2abd 100644 --- a/tests/testthat/test-smk-ds.hetcor.R +++ b/tests/testthat/test-smk-ds.hetcor.R @@ -181,8 +181,14 @@ test_that("hetcor", { test_that("fails if the object does not exist", { expect_error( ds.hetcor(data = "nonexistent_object"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.hetcor::smk::shutdown") diff --git a/tests/testthat/test-smk-ds.isValid.R b/tests/testthat/test-smk-ds.isValid.R index 59b72dcc..34d2f730 100644 --- a/tests/testthat/test-smk-ds.isValid.R +++ b/tests/testthat/test-smk-ds.isValid.R @@ -37,6 +37,13 @@ test_that("isValid", { expect_length(res1$sim3, 1) expect_true(res1$sim3) + res2 <- ds.isValid(x='D') + + expect_length(res2, 3) + expect_true(res2$sim1) + expect_true(res2$sim2) + expect_true(res2$sim3) + # myvectors <- c("D$LAB_TSC", "D$LAB_TRIG") # ds.dataFrame(x=myvectors, newobj="unsubset_df") # ds.dataFrameSubset(df.name="unsubset_df", V1.name="D$LAB_TSC", V2.name="D$LAB_TRIG", Boolean.operator=">", newobj="subset_df") @@ -52,6 +59,34 @@ test_that("isValid", { # expect_false(res2$sim3) }) +test_that("fails if the object does not exist", { + expect_error( + ds.isValid(x='nonexistent_object'), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } +}) + +test_that("fails if the object is of a type that cannot be checked", { + ds.asList(x.name='D', newobj='D_list') + + expect_error( + ds.isValid(x='D_list'), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object must be of type") + } +}) + # # Tear down # @@ -59,7 +94,7 @@ test_that("isValid", { # context("ds.isValid::smk::shutdown") test_that("shutdown", { - ds_expect_variables(c("D")) + ds_expect_variables(c("D", "D_list")) }) disconnect.studies.dataset.cnsim() diff --git a/tests/testthat/test-smk-ds.lexis.R b/tests/testthat/test-smk-ds.lexis.R index 13708d58..e9c99b4f 100644 --- a/tests/testthat/test-smk-ds.lexis.R +++ b/tests/testthat/test-smk-ds.lexis.R @@ -51,6 +51,12 @@ test_that("simple lexis", { expect_equal(res.message$survival3, "ALL OK: there are no studysideMessage(s) on this datasource") }) +test_that("lexis without entryCol defaults entry times to 0", { + ds.lexis(data='D', intervalWidth = c(1.0, 1.5, 2.5), idCol = 'D$id', exitCol = 'D$endtime', statusCol = 'D$cens', expandDF = 'EM.noentry') + + ds_expect_variables(c("D", "EM.new", "messageobj", "EM.noentry")) +}) + # # Done # @@ -58,14 +64,20 @@ test_that("simple lexis", { test_that("fails if the object does not exist", { expect_error( ds.lexis(data = "D", intervalWidth = c(1.0, 1.5, 2.5), idCol = "D$id", entryCol = "D$starttime", exitCol = "nonexistent_object", statusCol = "D$cens"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.lexis::smk::shutdown") test_that("shutdown", { - ds_expect_variables(c("D", "EM.new", "messageobj")) + ds_expect_variables(c("D", "EM.new", "messageobj", "EM.noentry")) }) disconnect.studies.dataset.survival() diff --git a/tests/testthat/test-smk-ds.lspline.R b/tests/testthat/test-smk-ds.lspline.R index 7f79cadf..2e46ac45 100644 --- a/tests/testthat/test-smk-ds.lspline.R +++ b/tests/testthat/test-smk-ds.lspline.R @@ -85,8 +85,14 @@ test_that("lspline", { test_that("fails if the object does not exist", { expect_error( ds.lspline(x = "nonexistent_object", knots = c(1, 2)), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.lspline::smk::shutdown") diff --git a/tests/testthat/test-smk-ds.ns.R b/tests/testthat/test-smk-ds.ns.R index b805a9f8..d7aed55b 100644 --- a/tests/testthat/test-smk-ds.ns.R +++ b/tests/testthat/test-smk-ds.ns.R @@ -89,8 +89,14 @@ test_that("ns", { test_that("fails if the object does not exist", { expect_error( ds.ns(x = "nonexistent_object", df = 3), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.ns::smk::shutdown") diff --git a/tests/testthat/test-smk-ds.qlspline.R b/tests/testthat/test-smk-ds.qlspline.R index 2a169d9e..7cbc7a7a 100644 --- a/tests/testthat/test-smk-ds.qlspline.R +++ b/tests/testthat/test-smk-ds.qlspline.R @@ -134,8 +134,14 @@ test_that("qlspline", { test_that("fails if the object does not exist", { expect_error( ds.qlspline(x = "nonexistent_object", q = 3), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.qlspline::smk::shutdown") diff --git a/tests/testthat/test-smk-ds.rowColCalc.R b/tests/testthat/test-smk-ds.rowColCalc.R index 6b8a50fb..bebcce20 100644 --- a/tests/testthat/test-smk-ds.rowColCalc.R +++ b/tests/testthat/test-smk-ds.rowColCalc.R @@ -52,14 +52,49 @@ test_that("rowColCalc_out_exists", { test_that("fails if the object does not exist", { expect_error( ds.rowColCalc(x = "nonexistent_object", operation = "rowSums"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } +}) + +test_that("fails if the object is not a data.frame or matrix", { + expect_error( + ds.rowColCalc(x = "D$LAB_TSC", operation = "rowSums"), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object must be of type data.frame or matrix") + } +}) + +test_that("fails if a column is not numeric", { + ds.asCharacter(x.name = "D$LAB_TSC", newobj = "tsc_chr") + ds.dataFrame(x = c("D$LAB_HDL", "tsc_chr"), newobj = "mixed_df") + + expect_error( + ds.rowColCalc(x = "mixed_df", operation = "rowSums"), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "are not of numeric type") + } }) # context("ds.rowColCalc::smk::shutdown") test_that("shutdown", { - ds_expect_variables(c("D", "rsum_hdl_tsc", "rowcolcalc.newobj")) + ds_expect_variables(c("D", "rsum_hdl_tsc", "rowcolcalc.newobj", "tsc_chr", "mixed_df")) }) disconnect.studies.dataset.cnsim() diff --git a/tests/testthat/test-smk-ds.table.R b/tests/testthat/test-smk-ds.table.R index 4290c338..f944e1e5 100644 --- a/tests/testthat/test-smk-ds.table.R +++ b/tests/testthat/test-smk-ds.table.R @@ -153,8 +153,14 @@ test_that("simple table 3D, with assign", { test_that("fails if the object does not exist", { expect_error( ds.table(rvar = "nonexistent_object"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) test_that("fails if rvar column does not exist", { @@ -196,6 +202,23 @@ test_that("fails if stvar column does not exist", { expect_match(res.errors$study3, "Column 'nonexistent_column' not found in 'tablesource_subset'") }) +test_that("simple table 1D, with forced nfilter", { + expect_no_error(ds.table(rvar='tablesource_subset$factorCharacter', force.nfilter="5")) +}) + +test_that("fails if forced nfilter is below nfilter.tab", { + expect_error( + ds.table(rvar='tablesource_subset$factorCharacter', force.nfilter="1"), + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE + ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "force.nfilter is non-null it must be >= to nfilter.tab") + } +}) + # context("ds.table::smk::shutdown") test_that("shutdown", { diff --git a/tests/testthat/test-smk-ds.tapply.R b/tests/testthat/test-smk-ds.tapply.R index bec4e50c..dfbc5f29 100644 --- a/tests/testthat/test-smk-ds.tapply.R +++ b/tests/testthat/test-smk-ds.tapply.R @@ -136,8 +136,14 @@ test_that("simplest 'ds.tapply', fun=quantile", { test_that("fails if the object does not exist", { expect_error( ds.tapply("nonexistent_object", INDEX.names = c("GENDER"), FUN.name = "mean"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.tapply::smk::shutdown") diff --git a/tests/testthat/test-smk-ds.tapply.assign.R b/tests/testthat/test-smk-ds.tapply.assign.R index b3214d79..5c8cc5dc 100644 --- a/tests/testthat/test-smk-ds.tapply.assign.R +++ b/tests/testthat/test-smk-ds.tapply.assign.R @@ -92,8 +92,14 @@ test_that("simplest 'ds.tapply.assign', fun=quantile", { test_that("fails if the object does not exist", { expect_error( ds.tapply.assign("nonexistent_object", INDEX.names = c("GENDER"), FUN.name = "mean"), - regexp = "DataSHIELD errors" + "There are some DataSHIELD errors, list them with datashield.errors()", + fixed = TRUE ) + + res.errors <- DSI::datashield.errors() + for (study.errors in res.errors) { + expect_match(study.errors, "The server-side object 'nonexistent_object' does not exist") + } }) # context("ds.tapply.assign::smk::shutdown")