Skip to content

Commit 5ca5daa

Browse files
authored
Merge branch 'master' into issue6626
2 parents 7789d2a + c29e313 commit 5ca5daa

File tree

2 files changed

+87
-104
lines changed

2 files changed

+87
-104
lines changed

R/test.data.table.R

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,6 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
336336
Sys.unsetenv(names(old)[!is_preset])
337337
}, add=TRUE)
338338
}
339-
if (!is.null(options)) {
340-
old_options <- do.call(base::options, as.list(options)) # as.list(): allow passing named character vector for convenience
341-
on.exit(base::options(old_options), add=TRUE)
342-
}
343339
# Usage:
344340
# i) tests that x equals y when both x and y are supplied, the most common usage
345341
# ii) tests that x is TRUE when y isn't supplied
@@ -428,13 +424,23 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
428424
actual$message <- c(actual$message, conditionMessage(m))
429425
m
430426
}
427+
if (!is.null(options)) {
428+
old_options <- do.call(base::options, as.list(options)) # as.list(): allow passing named character vector for convenience
429+
on.exit(base::options(old_options), add=TRUE)
430+
}
431431
if (is.null(output) && is.null(notOutput)) {
432432
x = suppressMessages(withCallingHandlers(tryCatch(x, error=eHandler), warning=wHandler, message=mHandler))
433433
# save the overhead of capture.output() since there are a lot of tests, often called in loops
434434
# Thanks to tryCatch2 by Jan here : https://github.com/jangorecki/logR/blob/master/R/logR.R#L21
435435
} else {
436436
out = capture.output(print(x <- suppressMessages(withCallingHandlers(tryCatch(x, error=eHandler), warning=wHandler, message=mHandler))))
437437
}
438+
if (!is.null(options)) {
439+
# some of the options passed to test() may break internal data.table use below (e.g. invalid datatable.alloccol), so undo them ASAP
440+
base::options(old_options)
441+
# this is still registered for on.exit(), keep empty
442+
old_options <- list()
443+
}
438444
fail = FALSE
439445
if (.test.data.table && num>0.0) {
440446
if (num<prevtest+0.0000005) {
@@ -454,15 +460,15 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
454460
stopifnot(is.character(ignore.warning), !anyNA(ignore.warning), nchar(ignore.warning)>=1L)
455461
for (msg in ignore.warning) observed = grep(msg, observed, value=TRUE, invert=TRUE) # allow multiple for translated messages rather than relying on '|' to always work
456462
}
457-
if (length(expected) != length(observed)) {
463+
if (length(expected) != length(observed) && (!foreign || is.null(ignore.warning))) {
458464
# nocov start
459465
catf("Test %s produced %d %ss but expected %d\n%s\n%s\n", numStr, length(observed), type, length(expected), paste("Expected:", expected), paste("Observed:", observed, collapse = "\n"))
460466
fail = TRUE
461467
# nocov end
462-
} else {
468+
} else if (!foreign) {
463469
# the expected type occurred and, if more than 1 of that type, in the expected order
464470
for (i in seq_along(expected)) {
465-
if (!foreign && !string_match(expected[i], observed[i])) {
471+
if (!string_match(expected[i], observed[i])) {
466472
# nocov start
467473
catf("Test %s didn't produce the correct %s:\nExpected: %s\nObserved: %s\n", numStr, type, expected[i], observed[i])
468474
fail = TRUE
@@ -481,7 +487,8 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
481487
if (out[length(out)] == "NULL") out = out[-length(out)]
482488
out = paste(out, collapse="\n")
483489
output = paste(output, collapse="\n") # so that output= can be either a \n separated string, or a vector of strings.
484-
if (length(output) && !string_match(output, out)) {
490+
# it also happens to turn off the 'y' checking branch below
491+
if (length(output) && !foreign && !string_match(output, out)) {
485492
# nocov start
486493
catf("Test %s did not produce correct output:\n", numStr)
487494
catf("Expected: <<%s>>\n", encodeString(output)) # \n printed as '\\n' so the two lines of output can be compared vertically
@@ -493,7 +500,7 @@ test = function(num,x,y=TRUE,error=NULL,warning=NULL,message=NULL,output=NULL,no
493500
fail = TRUE
494501
# nocov end
495502
}
496-
if (length(notOutput) && string_match(notOutput, out, ignore.case=TRUE)) {
503+
if (length(notOutput) && !foreign && string_match(notOutput, out, ignore.case=TRUE)) {
497504
# nocov start
498505
catf("Test %s produced output but should not have:\n", numStr)
499506
catf("Expected absent (case insensitive): <<%s>>\n", encodeString(notOutput))

inst/tests/tests.Rraw

Lines changed: 71 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,43 +1361,20 @@ if (test_bit64) {
13611361
test(431.5, DT[5,1:=as.integer64(NA)], data.table(a=factor(c(NA,NA,NA,NA,NA), levels=LETTERS[1:3]), b=1:5))
13621362
}
13631363

1364-
old = getOption("datatable.alloccol") # Test that unsetting datatable.alloccol is caught, #2014
1365-
options(datatable.alloccol=NULL) # In this =NULL case, options() in R 3.0.0 returned TRUE rather than the old value. This R bug was fixed in R 3.1.1.
1366-
# This is why getOption is called first rather than just using the result of option() like elsewhere in this test file.
1367-
# TODO: simplify this test if/when R dependency >= 3.1.1
1368-
err1 = try(data.table(a=1:3), silent=TRUE)
1369-
options(datatable.alloccol="1024")
1370-
err2 = try(data.table(a=1:3), silent=TRUE)
1371-
options(datatable.alloccol=c(10L,20L))
1372-
err3 = try(data.table(a=1:3), silent=TRUE)
1373-
options(datatable.alloccol=NA_integer_)
1374-
err4 = try(data.table(a=1:3), silent=TRUE)
1375-
options(datatable.alloccol=-1)
1376-
err5 = try(data.table(a=1:3), silent=TRUE)
1377-
options(datatable.alloccol=1024L) # otherwise test() itself fails in its internals with the alloc.col error
1378-
test(432.1, inherits(err1,"try-error") && grep("Has getOption[(]'datatable.alloccol'[)] somehow become unset?", err1))
1379-
test(432.2, inherits(err2,"try-error") && grep("getOption[(]'datatable.alloccol'[)] should be a number, by default 1024. But its type is 'character'.", err2))
1380-
test(432.3, inherits(err3,"try-error") && grep("is a numeric vector ok but its length is 2. Its length should be 1.", err3))
1381-
test(432.4, inherits(err4,"try-error") && grep("It must be >=0 and not NA.", err4))
1382-
test(432.5, inherits(err5,"try-error") && grep("It must be >=0 and not NA.", err5))
1364+
# Test that unsetting datatable.alloccol is caught, #2014
1365+
test(432.1, data.table(a=1:3), options=list(datatable.alloccol=NULL), error="Has getOption('datatable.alloccol') somehow become unset?")
1366+
test(432.2, data.table(a=1:3), options=c(datatable.alloccol="1024"), error="getOption('datatable.alloccol') should be a number, by default 1024. But its type is 'character'.")
1367+
test(432.3, data.table(a=1:3), options=list(datatable.alloccol=c(10L,20L)), error="is a numeric vector ok but its length is 2. Its length should be 1.")
1368+
test(432.4, data.table(a=1:3), options=c(datatable.alloccol=NA_integer_), error="It must be >=0 and not NA.")
1369+
test(432.5, data.table(a=1:3), options=c(datatable.alloccol=-1), error="It must be >=0 and not NA.")
1370+
13831371
# Repeat the tests but this time with subsetting, to ensure the validity check on option happens for those too
13841372
DT = data.table(a=1:3, b=4:6)
1385-
options(datatable.alloccol=NULL)
1386-
err1 = try(DT[2,], silent=TRUE)
1387-
options(datatable.alloccol="1024")
1388-
err2 = try(DT[,2], silent=TRUE)
1389-
options(datatable.alloccol=c(10L,20L))
1390-
err3 = try(DT[a>1], silent=TRUE)
1391-
options(datatable.alloccol=NA_integer_)
1392-
err4 = try(DT[,"b"], silent=TRUE)
1393-
options(datatable.alloccol=-1)
1394-
err5 = try(DT[2,"b"], silent=TRUE)
1395-
options(datatable.alloccol=1024L) # otherwise test() itself fails in its internals with the alloc.col error
1396-
test(433.1, inherits(err1,"try-error") && grep("Has getOption[(]'datatable.alloccol'[)] somehow become unset?", err1))
1397-
test(433.2, inherits(err2,"try-error") && grep("getOption[(]'datatable.alloccol'[)] should be a number, by default 1024. But its type is 'character'.", err2))
1398-
test(433.3, inherits(err3,"try-error") && grep("is a numeric vector ok but its length is 2. Its length should be 1.", err3))
1399-
test(433.4, inherits(err4,"try-error") && grep("It must be >=0 and not NA.", err4))
1400-
test(433.5, inherits(err5,"try-error") && grep("It must be >=0 and not NA.", err5))
1373+
test(433.1, DT[2,], options=list(datatable.alloccol=NULL), error="Has getOption('datatable.alloccol') somehow become unset?")
1374+
test(433.2, DT[,2], options=c(datatable.alloccol="1024"), error="getOption('datatable.alloccol') should be a number, by default 1024. But its type is 'character'.")
1375+
test(433.3, DT[a>1], options=list(datatable.alloccol=c(10L,20L)), error="is a numeric vector ok but its length is 2. Its length should be 1.")
1376+
test(433.4, DT[,"b"], options=c(datatable.alloccol=NA_integer_), error="It must be >=0 and not NA.")
1377+
test(433.5, DT[2,"b"], options=c(datatable.alloccol=-1), error="It must be >=0 and not NA.")
14011378

14021379
# simple realloc test
14031380
DT = data.table(a=1:3,b=4:6)
@@ -8712,17 +8689,17 @@ test(1613.21, all.equal(DT2, DT1, ignore.row.order = TRUE), "Dataset 'current' h
87128689
# test attributes: key
87138690
DT1 <- data.table(a = 1:4, b = letters[1:4], key = "a")
87148691
DT2 <- data.table(a = 1:4, b = letters[1:4])
8715-
test(1613.22, all.equal(DT1, DT2), "Datasets have different keys. 'target': [a]. 'current': has no key.")
8692+
test(1613.22, all.equal(DT1, DT2), output="Datasets have different keys. 'target': [a]. 'current': has no key.")
87168693
test(1613.23, all.equal(DT1, DT2, check.attributes = FALSE), TRUE)
87178694
test(1613.24, all.equal(DT1, setkeyv(DT2, "a"), check.attributes = TRUE), TRUE)
87188695
# test attributes: index
87198696
DT1 <- data.table(a = 1:4, b = letters[1:4])
87208697
DT2 <- data.table(a = 1:4, b = letters[1:4])
87218698
setindexv(DT1, "b")
8722-
test(1613.25, all.equal(DT1, DT2), "Datasets have different indices. 'target': [b]. 'current': has no index.")
8699+
test(1613.25, all.equal(DT1, DT2), output="Datasets have different indices. 'target': [b]. 'current': has no index.")
87238700
test(1613.26, all.equal(DT1, DT2, check.attributes = FALSE), TRUE)
8724-
test(1613.27, all.equal(DT1, setindexv(DT2, "a")), "Datasets have different indices. 'target': [b]. 'current': [a].")
8725-
test(1613.28, all.equal(DT1, setindexv(DT2, "b")), "Datasets have different indices. 'target': [b]. 'current': [a, b].")
8701+
test(1613.27, all.equal(DT1, setindexv(DT2, "a")), output="Datasets have different indices. 'target': [b]. 'current': [a].")
8702+
test(1613.28, all.equal(DT1, setindexv(DT2, "b")), output="Datasets have different indices. 'target': [b]. 'current': [a, b].")
87268703
test(1613.29, all.equal(DT1, setindexv(setindexv(DT2, NULL), "b")), TRUE)
87278704
# test custom attribute
87288705
DT1 <- data.table(a = 1:4, b = letters[1:4])
@@ -11810,15 +11787,15 @@ test(1775.1, capture.output(print(DT1, print.keys = TRUE)),
1181011787
c("Key: <a>", " a", "1: 1", "2: 2", "3: 3"))
1181111788
DT2 <- data.table(a = 1:3, b = 4:6)
1181211789
setindexv(DT2, c("b","a"))
11813-
test(1775.2, capture.output(print(DT2, print.keys = TRUE)),
11814-
c("Index: <b__a>", " a b", "1: 1 4", "2: 2 5", "3: 3 6"))
11790+
test(1775.2, print(DT2, print.keys = TRUE),
11791+
output=c("Index: <b__a>", " a b", "1: 1 4", "2: 2 5", "3: 3 6"))
1181511792
setindexv(DT2, "b")
11816-
test(1775.3, capture.output(print(DT2, print.keys = TRUE)),
11817-
c("Indices: <b__a>, <b>", " a b", "1: 1 4", "2: 2 5", "3: 3 6"))
11793+
test(1775.3, print(DT2, print.keys = TRUE),
11794+
output=c("Indices: <b__a>, <b>", " a b", "1: 1 4", "2: 2 5", "3: 3 6"))
1181811795
setkey(DT2, a)
1181911796
setindexv(DT2, c("b","a"))
11820-
test(1775.4, capture.output(print(DT2, print.keys = TRUE)),
11821-
c("Key: <a>", "Indices: <b__a>, <b>", " a b", "1: 1 4", "2: 2 5", "3: 3 6")) ## index 'b' is still good, so we keep it
11797+
test(1775.4, print(DT2, print.keys = TRUE),
11798+
output=c("Key: <a>", "Indices: <b__a>, <b>", " a b", "1: 1 4", "2: 2 5", "3: 3 6")) ## index 'b' is still good, so we keep it
1182211799

1182311800
# dev regression #2285
1182411801
cat("A B C\n1 2 3\n4 5 6", file=f<-tempfile())
@@ -12142,8 +12119,7 @@ test(1831.4, fread(paste0("A\n", "1.", src2)), data.table(A=1.1234567890098766))
1214212119
DT = as.data.table(matrix(5L, nrow=10, ncol=10))
1214312120
test(1832.1, fwrite(DT, f<-tempfile(), verbose=TRUE), output="Column writers")
1214412121
DT = as.data.table(matrix(5L, nrow=10, ncol=60))
12145-
# Using capture.output directly to look for the "..." because test(,output=) intercepts [] for convenience elsewhere
12146-
test(1832.2, any(grepl("^Column writers.* [.][.][.] ", capture.output(fwrite(DT, f, verbose=TRUE)))))
12122+
test(1832.2, fwrite(DT, f, verbose=TRUE), output = "\nColumn writers.* [.][.][.] ")
1214712123
unlink(f)
1214812124

1214912125
# ensure explicitly setting select to default value doesn't error, #2007
@@ -16568,69 +16544,69 @@ DT = data.table(a = vector("integer", 102L),
1656816544
b = "bbbbbbbbbbbbb",
1656916545
c = "ccccccccccccc",
1657016546
d = c("ddddddddddddd", "d"))
16571-
test(2125.02, capture.output(print(DT, trunc.cols=TRUE)),
16572-
c(" a b c",
16573-
" 1: 0 bbbbbbbbbbbbb ccccccccccccc",
16574-
" 2: 0 bbbbbbbbbbbbb ccccccccccccc",
16575-
" 3: 0 bbbbbbbbbbbbb ccccccccccccc",
16576-
" 4: 0 bbbbbbbbbbbbb ccccccccccccc",
16577-
" 5: 0 bbbbbbbbbbbbb ccccccccccccc",
16578-
" --- ",
16579-
" 98: 0 bbbbbbbbbbbbb ccccccccccccc",
16580-
" 99: 0 bbbbbbbbbbbbb ccccccccccccc",
16581-
"100: 0 bbbbbbbbbbbbb ccccccccccccc",
16582-
"101: 0 bbbbbbbbbbbbb ccccccccccccc",
16583-
"102: 0 bbbbbbbbbbbbb ccccccccccccc",
16584-
"1 variable not shown: [d]"))
16585-
test(2125.03, capture.output(print(DT, trunc.cols=TRUE, row.names=FALSE)),
16586-
c(" a b c",
16587-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16588-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16589-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16590-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16591-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16592-
" --- --- ---",
16593-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16594-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16595-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16596-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16597-
" 0 bbbbbbbbbbbbb ccccccccccccc",
16598-
"1 variable not shown: [d]" ))
16547+
test(2125.02, print(DT, trunc.cols=TRUE),
16548+
output=c(" a b c",
16549+
" 1: 0 bbbbbbbbbbbbb ccccccccccccc",
16550+
" 2: 0 bbbbbbbbbbbbb ccccccccccccc",
16551+
" 3: 0 bbbbbbbbbbbbb ccccccccccccc",
16552+
" 4: 0 bbbbbbbbbbbbb ccccccccccccc",
16553+
" 5: 0 bbbbbbbbbbbbb ccccccccccccc",
16554+
" --- ",
16555+
" 98: 0 bbbbbbbbbbbbb ccccccccccccc",
16556+
" 99: 0 bbbbbbbbbbbbb ccccccccccccc",
16557+
"100: 0 bbbbbbbbbbbbb ccccccccccccc",
16558+
"101: 0 bbbbbbbbbbbbb ccccccccccccc",
16559+
"102: 0 bbbbbbbbbbbbb ccccccccccccc",
16560+
"1 variable not shown: [d]"))
16561+
test(2125.03, print(DT, trunc.cols=TRUE, row.names=FALSE),
16562+
output=c(" a b c",
16563+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16564+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16565+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16566+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16567+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16568+
" --- --- ---",
16569+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16570+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16571+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16572+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16573+
" 0 bbbbbbbbbbbbb ccccccccccccc",
16574+
"1 variable not shown: [d]" ))
1659916575
# also testing #4266 -- getting width of row #s register right
1660016576
# TODO: understand why 2 variables truncated here. a,b,c combined have width
1660116577
# _exactly_ 40, but still wraps. If we set options(width=41) it won't truncate.
1660216578
# seems to be an issue with print.default.
16603-
test(2125.04, capture.output(print(DT, trunc.cols=TRUE, class=TRUE))[14L],
16604-
"2 variables not shown: [c <char>, d <char>]")
16605-
test(2125.05, capture.output(print(DT, trunc.cols=TRUE, class=TRUE, row.names=FALSE))[c(1,14)],
16606-
c(" a b c",
16607-
"1 variable not shown: [d <char>]" ))
16608-
test(2125.06, capture.output(print(DT, trunc.cols=TRUE, col.names="none"))[c(1,12)],
16609-
c(" 1: 0 bbbbbbbbbbbbb ccccccccccccc",
16610-
"1 variable not shown: [d]" ))
16611-
test(2125.07, capture.output(print(DT, trunc.cols=TRUE, class=TRUE, col.names="none"))[c(1,13)],
16612-
c(" 1: 0 bbbbbbbbbbbbb",
16613-
"2 variables not shown: [c, d]" ),
16579+
test(2125.04, print(DT, trunc.cols=TRUE, class=TRUE),
16580+
output="2 variables not shown: [c <char>, d <char>]")
16581+
test(2125.05, print(DT, trunc.cols=TRUE, class=TRUE, row.names=FALSE),
16582+
output=c("^ a b c", ".*",
16583+
"1 variable not shown: \\[d <char>\\]"))
16584+
test(2125.06, print(DT, trunc.cols=TRUE, col.names="none"),
16585+
output=c("^ 1: 0 bbbbbbbbbbbbb ccccccccccccc", ".*",
16586+
"1 variable not shown: \\[d\\]", ""))
16587+
test(2125.07, print(DT, trunc.cols=TRUE, class=TRUE, col.names="none"),
16588+
output=c("^ 1: 0 bbbbbbbbbbbbb", ".*",
16589+
"2 variables not shown: \\[c, d\\]", ""),
1661416590
warning = "Column classes will be suppressed when col.names is 'none'")
1661516591
options("width" = 20)
1661616592
DT = data.table(a = vector("integer", 2),
1661716593
b = "bbbbbbbbbbbbb",
1661816594
c = "ccccccccccccc",
1661916595
d = "ddddddddddddd")
16620-
test(2125.08, capture.output(print(DT, trunc.cols=TRUE)),
16621-
c(" a b",
16622-
"1: 0 bbbbbbbbbbbbb",
16623-
"2: 0 bbbbbbbbbbbbb",
16624-
"2 variables not shown: [c, d]"))
16596+
test(2125.08, print(DT, trunc.cols=TRUE),
16597+
output=c(" a b",
16598+
"1: 0 bbbbbbbbbbbbb",
16599+
"2: 0 bbbbbbbbbbbbb",
16600+
"2 variables not shown: [c, d]"))
1662516601
options("width" = 10)
1662616602
DT = data.table(a = "aaaaaaaaaaaaa",
1662716603
b = "bbbbbbbbbbbbb",
1662816604
c = "ccccccccccccc",
1662916605
d = "ddddddddddddd")
16630-
test(2125.09, capture.output(print(DT, trunc.cols=TRUE)),
16631-
"4 variables not shown: [a, b, c, d]")
16632-
test(2125.10, capture.output(print(DT, trunc.cols=TRUE, class=TRUE)),
16633-
"4 variables not shown: [a <char>, b <char>, c <char>, d <char>]")
16606+
test(2125.09, print(DT, trunc.cols=TRUE),
16607+
output="4 variables not shown: [a, b, c, d]")
16608+
test(2125.10, print(DT, trunc.cols=TRUE, class=TRUE),
16609+
output="4 variables not shown: [a <char>, b <char>, c <char>, d <char>]")
1663416610
options(old_width)
1663516611

1663616612
# segfault when i is NULL or zero-column, #4060

0 commit comments

Comments
 (0)