diff --git a/R/test.data.table.R b/R/test.data.table.R
index 7d6bc58e1..c26450e25 100644
--- a/R/test.data.table.R
+++ b/R/test.data.table.R
@@ -130,6 +130,7 @@ test.data.table = function(script="tests.Rraw", verbose=FALSE, pkg=".", silent=F
}
assign("foreign", foreign, envir=env)
assign("nfail", 0L, envir=env)
+ assign("nskip", 0L, envir=env)
assign("ntest", 0L, envir=env)
assign("prevtest", -1L, envir=env)
assign("whichfail", NULL, envir=env)
@@ -282,6 +283,7 @@ test.data.table = function(script="tests.Rraw", verbose=FALSE, pkg=".", silent=F
nfail = env$nfail
ntest = env$ntest
+ nskip = env$nskip
if (nfail > 0L) {
# nocov start
stopf(
@@ -331,6 +333,7 @@ test.data.table = function(script="tests.Rraw", verbose=FALSE, pkg=".", silent=F
get("mtext")(lastRSS, side=4L, at=lastRSS, las=1L, font=2L)
}
+ if (foreign && nskip > 0L) catf("Skipped %d tests for translated messages. ", nskip) # nocov
catf("All %d tests (last %.8g) in %s completed ok in %s\n", ntest, env$prevtest, names(fn), timetaken(env$started.at))
ans = nfail==0L
attr(ans, "timings") = timings # as attr to not upset callers who expect a TRUE/FALSE result
@@ -409,6 +412,7 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
memtest.id = get("memtest.id", parent.frame())
filename = get("filename", parent.frame())
foreign = get("foreign", parent.frame())
+ nskip = get("nskip", parent.frame())
showProgress = get("showProgress", parent.frame())
time = nTest = RSS = NULL # to avoid 'no visible binding' note
# TODO(R>=4.0.2): Use add=TRUE up-front in on.exit() once non-positional arguments are supported.
@@ -451,6 +455,11 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
length(grep(x, y, fixed=TRUE)) || # try treating x as literal first; useful for most messages containing ()[]+ characters
length(tryCatch(grep(x, y, ignore.case=ignore.case), error=function(e)NULL)) # otherwise try x as regexp
}
+ if (foreign && .test.data.table && (
+ length(error) || length(warning) || length(message) || length(output) ||
+ length(notOutput) || length(ignore.warning)
+ ))
+ assign("nskip", nskip+1L, parent.frame(), inherits=TRUE) # nocov
xsub = substitute(x)
ysub = substitute(y)
@@ -478,7 +487,11 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
# save the overhead of capture.output() since there are a lot of tests, often called in loops
# Thanks to tryCatch2 by Jan here : https://github.com/jangorecki/logR/blob/master/R/logR.R#L21
} else {
- out = capture.output(print(x <- suppressMessages(withCallingHandlers(tryCatch(x, error=eHandler), warning=wHandler, message=mHandler))))
+ out = if (xsub %iscall% "print") {
+ capture.output(x <- suppressMessages(withCallingHandlers(tryCatch(x, error=eHandler), warning=wHandler, message=mHandler)))
+ } else {
+ capture.output(print(x <- suppressMessages(withCallingHandlers(tryCatch(x, error=eHandler), warning=wHandler, message=mHandler))))
+ }
}
if (!is.null(options)) {
# some of the options passed to test() may break internal data.table use below (e.g. invalid datatable.alloccol), so undo them ASAP
diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw
index 91efa4e72..c948f34f0 100644
--- a/inst/tests/tests.Rraw
+++ b/inst/tests/tests.Rraw
@@ -2031,8 +2031,8 @@ options(datatable.optimize = 2L)
test(658.1, DT[ , mean(x), by=grp1, verbose=TRUE], output="GForce optimized j to.*gmean")
test(658.2, DT[ , list(mean(x)), by=grp1, verbose=TRUE], output="GForce optimized j to.*gmean")
test(658.3, DT[ , list(mean(x), mean(y)), by=grp1, verbose=TRUE], output="GForce optimized j to.*gmean")
-tt = capture.output(DT[,list(mean(x),mean(y)),by=list(grp1,grp2),verbose=TRUE])
-test(659, !length(grep("Wrote less rows", tt))) # first group is one row with this seed. Ensure we treat this as aggregate case rather than allocate too many rows.
+# first group is one row with this seed. Ensure we treat this as aggregate case rather than allocate too many rows.
+test(659, DT[,list(mean(x),mean(y)),by=list(grp1,grp2),verbose=TRUE], notOutput = "Wrote less rows")
# Test .N for logical i subset
DT = data.table(a=1:10, b=rnorm(10))
@@ -2040,8 +2040,10 @@ test(660, DT[a==8L, .N], 1L)
# Test that growing is sensible in worst case
DT = data.table(a=rep(1:10,1:10),b=rnorm(55))
-tt = capture.output(DT[,sum(b)*b,by=a,verbose=TRUE])
-test(661, length(grep("growing from",tt))<3) # was 6 when we simply grew enough for latest result
+test(661, DT[,sum(b)*b,by=a,verbose=TRUE],
+ notOutput = paste(rep("growing from", 3), collapse = ".*"))
+# Need to test that "growing from" is printed less than three times.
+# The number was previously 6 when we simply grew enough for latest result
# Test that adding a new logical column is supported, #2094
DT=data.table(a=1:3)
@@ -8286,8 +8288,8 @@ test(1579.03, dt[, lapply(.SD, median), keyby=x],
dt[, lapply(.SD, function(x) median(as.numeric(x))), keyby=x])
test(1579.04, dt[, lapply(.SD, median, na.rm=TRUE), keyby=x],
dt[, lapply(.SD, function(x) median(as.numeric(x), na.rm=TRUE)), keyby=x])
-ans = capture.output(dt[, lapply(.SD, median), by=x, verbose=TRUE])
-test(1579.05, any(grepl("GForce optimized", ans)), TRUE)
+test(1579.05, dt[, lapply(.SD, median), by=x, verbose=TRUE],
+ output = "GForce optimized")
# testing gforce::ghead and gforce::gtail
# head(.SD, 1) and tail(.SD, 1) optimisation
@@ -8539,8 +8541,8 @@ if (x1==x2) {
# NB: x1==x2 is a condition in base R, independent of data.table
test(1590.12, forderv( c(x2,x1,x1,x2)), integer())
# don't test base ... test(1590.13, base::order(c(x2,x1,x1,x2)), 1:4)
-} else {
- # Windows-1252, #2856
+} else if (identical(l10n_info()$codepage, 1252L)) {
+ # US English ANSI codepage on Windows is CP1252, #2856
test(1590.14, forderv( c(x2,x1,x1,x2)), INT(1,4,2,3))
# don't test base ... test(1590.15, base::order(c(x2,x1,x1,x2)), INT(1,4,2,3))
}
@@ -9280,11 +9282,9 @@ test(1633.4, dt[, .SD, by=1:nrow(dt)], data.table(nrow=1:nrow(dt), dt)) # make s
# reuse secondary indices
dt = data.table(x=sample(3, 10, TRUE), y=1:10)
-v1 = capture.output(ans1 <- dt[.(3:2), on="x", verbose=TRUE])
+test(1634.1, dt[.(3:2), on="x", verbose=TRUE], output = "ad hoc")
setindex(dt, x)
-v2 = capture.output(ans2 <- dt[.(3:2), on="x", verbose=TRUE])
-test(1634.1, any(grepl("ad hoc", v1)), TRUE)
-test(1634.2, any(grepl("existing index", v2)), TRUE)
+test(1634.2, dt[.(3:2), on="x", verbose=TRUE], output = "existing index")
# fread's fill argument detects separator better in complex cases as well, #1573
# if pasted to the console, these tests won't work. But do work when sourced as these are tabs not spaces in text
@@ -10248,13 +10248,13 @@ options("datatable.use.index"=TRUE, "datatable.auto.index"=TRUE)
test(1666.01, d[k==1L, verbose=TRUE], d[3L], output="Creating new index 'k'")
d = data.table(k=3:1)
options("datatable.use.index"=TRUE, "datatable.auto.index"=FALSE)
-test(1666.02, grep("Creating new index", capture.output(d[k==1L, verbose=TRUE])), integer(0)) # do not create index
+test(1666.02, d[k==1L, verbose=TRUE], notOutput="Creating new index") # do not create index
d = data.table(k=3:1)
options("datatable.use.index"=FALSE, "datatable.auto.index"=FALSE)
-test(1666.03, grep("Creating new index", capture.output(d[k==1L, verbose=TRUE])), integer(0))
+test(1666.03, d[k==1L, verbose=TRUE], notOutput="Creating new index")
d = data.table(k=3:1)
options("datatable.use.index"=FALSE, "datatable.auto.index"=TRUE)
-test(1666.04, grep("Creating new index", capture.output(d[k==1L, verbose=TRUE])), integer(0))
+test(1666.04, d[k==1L, verbose=TRUE], notOutput="Creating new index")
d = data.table(k=3:1) # subset - index
setindex(d, k)
options("datatable.use.index"=TRUE, "datatable.auto.index"=TRUE)
@@ -10262,9 +10262,9 @@ test(1666.05, d[k==1L, verbose=TRUE], d[3L], output="Optimized subsetting with i
options("datatable.use.index"=TRUE, "datatable.auto.index"=FALSE)
test(1666.06, d[k==1L, verbose=TRUE], d[3L], output="Optimized subsetting with index 'k'")
options("datatable.use.index"=FALSE, "datatable.auto.index"=FALSE)
-test(1666.07, grep("Using existing index", capture.output(d[k==1L, verbose=TRUE])), integer(0)) # not using existing index
+test(1666.07, d[k==1L, verbose=TRUE], notOutput="Using existing index") # not using existing index
options("datatable.use.index"=FALSE, "datatable.auto.index"=TRUE)
-test(1666.08, grep("Using existing index", capture.output(d[k==1L, verbose=TRUE])), integer(0))
+test(1666.08, d[k==1L, verbose=TRUE], notOutput="Using existing index")
d1 = data.table(k=3:1) # join - no index
d2 = data.table(k=2:4)
options("datatable.use.index"=TRUE, "datatable.auto.index"=TRUE)
@@ -10272,9 +10272,9 @@ test(1666.09, d1[d2, on="k", verbose=TRUE], d1[d2, on="k"], output="ad hoc")
options("datatable.use.index"=TRUE, "datatable.auto.index"=FALSE)
test(1666.10, d1[d2, on="k", verbose=TRUE], d1[d2, on="k"], output="ad hoc")
options("datatable.use.index"=FALSE, "datatable.auto.index"=FALSE)
-test(1666.11, grep("Looking for existing (secondary) index", capture.output(d1[d2, on="k", verbose=TRUE])), integer(0)) # not looking for index
+test(1666.11, d1[d2, on="k", verbose=TRUE], notOutput="Looking for existing (secondary) index") # not looking for index
options("datatable.use.index"=FALSE, "datatable.auto.index"=TRUE)
-test(1666.12, grep("Looking for existing (secondary) index", capture.output(d1[d2, on="k", verbose=TRUE])), integer(0))
+test(1666.12, d1[d2, on="k", verbose=TRUE], notOutput="Looking for existing (secondary) index")
d1 = data.table(k=3:1,v1=10:12) # join - index
d2 = data.table(k=2:4,v2=20:22)
setindex(d1, k)
@@ -11653,8 +11653,7 @@ test(1765.4, {warning("foobar1"); warning("foobar2"); warning("FOO"); 4L}, 4L, i
test(1765.5, {warning("foobar1"); warning("foobar2"); warning("FOO"); 4L}, 4L, ignore.warning="2", warning=c("foobar1","FOO"))
# print(null.data.table()) should not output NULL as well, #1852
-# use capture.output() in this case rather than output= to ensure NULL is not output
-test(1766, capture.output(print(data.table(NULL))), "Null data.table (0 rows and 0 cols)")
+test(1766, data.table(NULL), notOutput = "NULL$")
# Bug on subset of 1-row data.table when expr returns a named logical vector #2152
options(datatable.auto.index=FALSE)
@@ -11888,8 +11887,8 @@ test(1774.17, as.data.table(x, na.rm='a'), error="'na.rm' must be scalar")
# verify print.keys works
DT1 <- data.table(a = 1:3, key = "a")
-test(1775.1, capture.output(print(DT1, print.keys = TRUE)),
- c("Key: ", " a", "1: 1", "2: 2", "3: 3"))
+test(1775.1, print(DT1, print.keys = TRUE),
+ output = c("Key: ", " a", "1: 1", "2: 2", "3: 3"))
DT2 <- data.table(a = 1:3, b = 4:6)
setindexv(DT2, c("b","a"))
test(1775.2, print(DT2, print.keys = TRUE),
@@ -13675,7 +13674,7 @@ test(1962.034, setkeyv(DT, c('a', '')),
setkey(DT, a)
test(1962.035, {setkeyv(DT, character(0L)); key(DT)}, NULL,
warning = 'cols is a character vector of zero length')
-test(1962.036, any(grepl('already ordered', capture.output(setkey(DT, a, verbose = TRUE)))))
+test(1962.036, setkey(DT, a, verbose = TRUE), output = 'already ordered')
setnames(DT, '.xi')
setkey(DT, NULL)
test(1962.037, setkey(DT, .xi),
@@ -16321,7 +16320,7 @@ test(2094.02, X$TAG, rep(names(x), each = 2))
# use arbitrary column without message when fun.aggregate=length, #2980
DT = data.table(a=c(3L, 3L, 2L, 9L, 5L, 10L, 3L, 2L, 9L, 8L), b=rep(1:5, 2))
-test(2095, any(grepl('override', capture.output(dcast(DT, a~b, fun.aggregate=length)), fixed=TRUE)), FALSE)
+test(2095, dcast(DT, a~b, fun.aggregate=length), notOutput='override')
# gmean intermediate can overflow integers without warning, #986
test(2096, data.table(a=c(1L,1L), v=c(2e9L, 2e9L))[, mean(v), a], data.table(a=1L, V1=2e9))
@@ -16705,10 +16704,10 @@ test(2125.05, print(DT, trunc.cols=TRUE, class=TRUE, row.names=FALSE),
"1 variable not shown: \\[d \\]"))
test(2125.06, print(DT, trunc.cols=TRUE, col.names="none"),
output=c("^ 1: 0 bbbbbbbbbbbbb ccccccccccccc", ".*",
- "1 variable not shown: \\[d\\]", ""))
+ "1 variable not shown: \\[d\\]$"))
test(2125.07, print(DT, trunc.cols=TRUE, class=TRUE, col.names="none"),
output=c("^ 1: 0 bbbbbbbbbbbbb", ".*",
- "2 variables not shown: \\[c, d\\]", ""),
+ "2 variables not shown: \\[c, d\\]$"),
warning = "Column classes will be suppressed when col.names is 'none'")
options("width" = 20)
DT = data.table(a = vector("integer", 2),
@@ -21491,11 +21490,11 @@ test(2328.2, droplevels(DT), data.table(f=factor(), i=integer(), f2=factor()))
#6882 print() output with col.names="none"
dt = data.table(short = 1:3, verylongcolumnname = 4:6)
-test(2329.1, print(dt, col.names = "none"), output = "1: 1 4\n2: 2 5\n3: 3 6\n")
+test(2329.1, print(dt, col.names = "none"), output = "1: 1 4\n2: 2 5\n3: 3 6$")
dt = data.table(x = 123456, y = "wide_string")
-test(2329.2, print(dt, col.names = "none"), output = "1: 123456 wide_string\n")
+test(2329.2, print(dt, col.names = "none"), output = "1: 123456 wide_string$")
dt = data.table(a = NA_integer_, b = NaN)
-test(2329.3, print(dt, col.names = "none"), output = "1: NA NaN\n")
+test(2329.3, print(dt, col.names = "none"), output = "1: NA NaN$")
# Row name extraction from multiple vectors, #7136
x <- 1:3