1## Regression tests for R >= 3.4.0
2
3pdf("reg-tests-1d.pdf", encoding = "ISOLatin1.enc")
4.pt <- proc.time()
5tryCid <- function(expr) tryCatch(expr, error = identity)
6tryCmsg<- function(expr) tryCatch(expr, error = conditionMessage) # typically == *$message
7identCO <- function(x,y, ...) identical(capture.output(x), capture.output(y), ...)
8assertErrV <- function(...) tools::assertError(..., verbose=TRUE)
9onWindows <- .Platform$OS.type == "windows"
10.M <- .Machine
11str(.M[grep("^sizeof", names(.M))]) ## also differentiate long-double..
12b64 <- .M$sizeof.pointer == 8
13options(nwarnings = 10000) # (rather than just 50)
14
15
16## body() / formals() notably the replacement versions
17x <- NULL; tools::assertWarning(   body(x) <-    body(mean))	# to be error
18x <- NULL; tools::assertWarning(formals(x) <- formals(mean))	# to be error
19x <- NULL; tools::assertWarning(f <-    body(x)); stopifnot(is.null(f))
20x <- NULL; tools::assertWarning(f <- formals(x)); stopifnot(is.null(f))
21## these all silently coerced NULL to a function in R <= 3.2.x
22
23## A good guess if we have _not_ translated error/warning/.. messages:
24## (should something like this be part of package tools ?)
25englishMsgs <- {
26    ## 1. LANGUAGE takes precedence over locale settings:
27    if(nzchar(lang <- Sys.getenv("LANGUAGE")))
28        lang == "en"
29    else { ## 2. Query the  locale
30        if(!onWindows) {
31            ## sub() :
32            lc.msgs <- sub("\\..*", "", print(Sys.getlocale("LC_MESSAGES")))
33            lc.msgs == "C" || substr(lc.msgs, 1,2) == "en"
34        } else { ## Windows
35            lc.type <- sub("\\..*", "", sub("_.*", "", print(Sys.getlocale("LC_CTYPE"))))
36            lc.type == "English" || lc.type == "C"
37        }
38    }
39}
40cat(sprintf("English messages: %s\n", englishMsgs))
41
42
43## match(x, t): fast algorithm for length-1 'x' -- PR#16885
44## a) string 'x'  when only encoding differs
45tmp <- "年付"
46tmp2 <- "\u5e74\u4ed8" ; Encoding(tmp2) <- "UTF-8"
47for(ex in list(c(tmp, tmp2), c("foo","foo"))) {
48    cat(sprintf("\n|%s|%s| :\n----------\n", ex[1], ex[2]))
49    for(enc in c("latin1", "UTF-8", "unknown")) { # , "MAC", "WINDOWS-1251"
50	cat(sprintf("%9s: ", enc))
51	tt <- ex[1]; Encoding(tt) <- enc; t2 <- ex[2]
52	if(identical(i1 <- (  tt       %in% t2),
53		     i2 <- (c(tt, "a") %in% t2)[1]))
54	    cat(i1,"\n")
55	else
56	    stop("differing: ", i1, ", ", i2)
57    }
58}
59##
60outerID <- function(x,y, ...) outer(x,y, Vectorize(identical,c("x","y")), ...)
61## b) complex 'x' with different kinds of NaN
62x0 <- c(0,1, NA_real_, NaN)
63z <- outer(x0,x0, complex, length.out=1L)
64z <- c(z[is.na(z)], # <- of length 4 * 4 - 2*2 = 12
65       as.complex(NaN), as.complex(0/0), # <- typically these two differ in bits
66       complex(real = NaN), complex(imaginary = NaN),
67       NA_complex_, complex(real = NA), complex(imaginary = NA))
68## 1..12 all differ, then
69symnum(outerID(z,z, FALSE,FALSE,FALSE,FALSE))# [14] differing from all on low level
70symnum(outerID(z,z))                         # [14] matches 2, 13,15
71(mz <- match(z, z)) # (checked with m1z below)
72zRI <- rbind(Re=Re(z), Im=Im(z)) # and see the pattern :
73print(cbind(format = format(z), t(zRI), mz), quote=FALSE)
74stopifnot(apply(zRI, 2, anyNA)) # NA *or* NaN: all TRUE
75is.NA <- function(.) is.na(.) & !is.nan(.)
76(iNaN <- apply(zRI, 2, function(.) any(is.nan(.))))
77(iNA <-  apply(zRI, 2, function(.) any(is.NA (.)))) # has non-NaN NA's
78## use iNA for consistency check once FIXME happened
79m1z <- sapply(z, match, table = z)
80stopifnot(exprs = {
81    identical(m1z, mz)
82    identical(m1z == 1L,             iNA)
83    identical(match(z, NA, 0) == 1L, iNA)
84    identical(mz[mz != 1L], c(2L, 4L, 9L, 10L, 12L, 2L, 2L, 2L, 9L))
85})
86## m1z uses match(x, *) with length(x) == 1 and failed in R 3.3.0
87set.seed(17)
88for(. in 1:20) {
89    zz <- sample(z)
90    stopifnot(identical(match(zz,zz), vapply(zz, match, -1L, table = zz)))
91}
92##
93## PR#16909 - a consequence of the match() bug; check here too:
94dvn <- paste0("var\xe9", 1:2); Encoding(dvn) <- "latin1"
95dv <- data.frame(1:3, 3); names(dv) <- dvn; dv[,"var\u00e92"] <- 2
96stopifnot(ncol(dv) == 2, dv[,2] == 2, identical(names(dv), dvn))
97## in R 3.3.0, got a 3rd column
98
99
100## deparse(<complex>,  "digits17")
101fz <- format(z <- c(outer(-1:2, 1i*(-1:1), `+`)))
102(fz0 <- sub("^ +","",z))
103r <- c(-1:1,100, 1e20); z2 <- c(outer(pi*r, 1i*r, `+`)); z2
104dz2 <- deparse(z2, control="digits17")
105stopifnot(exprs = {
106    identical(deparse(z, 200, control = "digits17"),
107              paste0("c(", paste(fz0, collapse=", "), ")"))
108    print((sum(nchar(dz2)) - 2) / length(z2)) < 22 # much larger in <= 3.3.0
109    ## deparse <-> parse equivalence, 17 digits should be perfect:
110    all.equal(z2, eval(parse(text = dz2)), tolerance = 3e-16) # seen 2.2e-35 on 32b
111})
112## deparse() for these was "ugly" in R <= 3.3.x
113
114## deparse of formals of a function
115fun <- function(a=1,b){}
116frmls <- tryCid(eval(parse(text=deparse(formals(fun)))))
117stopifnot(identical(frmls, formals(fun)))
118
119
120## length(environment(.)) == #{objects}
121stopifnot(identical(length(      baseenv()),
122                    length(names(baseenv()))))
123## was 0 in R <= 3.3.0
124
125
126## "srcref"s of closures
127op <- options(keep.source = TRUE)# as in interactive use
128getOption("keep.source")
129stopifnot(exprs = {
130    identical(function(){}, function(){})
131    identical(function(x){x+1},
132              function(x){x+1})
133}); options(op)
134## where all FALSE in 2.14.0 <= R <= 3.3.x because of "srcref"s etc
135
136
137## PR#16925, radix sorting INT_MAX w/ decreasing=TRUE and na.last=TRUE
138## failed ASAN check and segfaulted on some systems.
139data <- c(2147483645L, 2147483646L, 2147483647L, 2147483644L)
140stopifnot(identical(sort(data, decreasing = TRUE, method = "radix"),
141                    c(2147483647L, 2147483646L, 2147483645L, 2147483644L)))
142
143
144## as.factor(<named integer>)
145ni <- 1:2; Nni <- names(ni) <- c("A","B")
146stopifnot(exprs = {
147    identical(Nni, names(as.factor(ni)))
148    identical(Nni, names(   factor(ni)))
149    identical(Nni, names(   factor(ni+0))) # +0 : "double"
150    identical(Nni, names(as.factor(ni+0)))
151})
152## The first one lost names in  3.1.0 <= R <= 3.3.0
153
154
155## strtrim(<empty>, *) should work as substr(<empty>, *) does
156c0 <- character(0)
157stopifnot(identical(c0, strtrim(c0, integer(0))))
158## failed in R <= 3.3.0
159
160
161## Factors with duplicated levels {created via low-level code}:
162set.seed(11)
163f0 <- factor(sample.int(9, 20, replace=TRUE))
164(f <- structure(f0, "levels" = as.character(c(2:7, 2:4))))
165tools::assertWarning(print(f))
166tools::assertError(validObject(f))
167## no warning in print() for R <= 3.3.x
168
169
170## R <= 3.3.0 returned integer(0L) from unlist() in this case:
171stopifnot(identical(levels(unlist(list(factor(levels="a")))), "a"))
172
173
174## diff(<difftime>)
175d <- as.POSIXct("2016-06-08 14:21", tz="UTC") + as.difftime(2^(-2:8), units="mins")
176dd  <- diff(d)
177ddd <- diff(dd)
178d3d <- diff(ddd)
179d7d <- diff(d, differences = 7)
180(ldd <- list(dd=dd, ddd=ddd, d3d=d3d, d7d=d7d))
181stopifnot(exprs = {
182    identical(ddd, diff(d, differences = 2))
183    identical(d3d, diff(d, differences = 3))
184    vapply(ldd, units, "") == "secs"
185    vapply(ldd, class, "") == "difftime"
186    lengths(c(list(d), ldd)) == c(11:8, 11-7)
187})
188## was losing time units in R <= 3.3.0
189
190
191## sample(NA_real_) etc
192for(xx in list(NA, NA_integer_, NA_real_, NA_character_, NA_complex_, "NA", 1i))
193    stopifnot(identical(xx, sample(xx)))
194## error in R <= 3.3.1
195
196
197## merge.data.frame with names matching order()'s arguments (PR#17119)
198nf <- names(formals(order))
199nf <- nf[nf != "..."]
200v1 <- c(1,3,2)
201v2 <- c(4,2,3)
202for(nm in nf)  {
203    cat(nm,":\n")
204    mdf <- merge(
205        as.data.frame(setNames(list(v1), nm=nm)),
206        as.data.frame(setNames(list(v2), nm=nm)), all = TRUE)
207    stopifnot(identical(mdf,
208                        as.data.frame(setNames(list(0+ 1:4), nm=nm))))
209}
210## some were wrong, others gave an error in R <= 3.3.1
211
212
213## PR#16936: table() dropping "NaN" level & 'exclude' sometimes failing
214op <- options(warn = 2)# no warnings allowed
215(fN1 <- factor(c("NA", NA, "NbN", "NaN")))
216(tN1 <- table(fN1)) ##--> was missing 'NaN'
217(fN <- factor(c(rep(c("A","B"), 2), NA), exclude = NULL))
218(tN  <- table(fN, exclude = "B"))       ## had extraneous "B"
219(tN. <- table(fN, exclude = c("B",NA))) ## had extraneous "B" and NA
220stopifnot(exprs = {
221    identical(c(tN1), c(`NA`=1L, `NaN`=1L, NbN=1L))
222    identical(c(tN),  structure(2:1, .Names = c("A", NA)))
223    identical(c(tN.), structure(2L,  .Names = "A"))
224})
225## both failed in R <= 3.3.1
226stopifnot(identical(names(dimnames(table(data.frame(Titanic[2,2,,])))),
227		    c("Age", "Survived", "Freq"))) # was wrong for ~ 32 hours
228##
229## Part II:
230x <- factor(c(1, 2, NA, NA), exclude = NULL) ; is.na(x)[2] <- TRUE
231x # << two "different" NA's (in codes | w/ level) looking the same in print()
232stopifnot(identical(x, structure(as.integer(c(1, NA, 3, 3)),
233				 .Label = c("1", "2", NA), class = "factor")))
234(txx <- table(x, exclude = NULL))
235stopifnot(identical(txx, table(x, useNA = "ifany")),
236	  identical(as.vector(txx), c(1:0, 3L)))
237## wrongly gave  1 0 2  for R versions  2.8.0 <= Rver <= 3.3.1
238u.opt <- list(no="no", ifa = "ifany", alw = "always")
239l0 <- c(list(`_` = table(x)),
240           lapply(u.opt, function(use) table(x, useNA=use)))
241xcl <- list(NULL=NULL, none=""[0], "NA"=NA, NANaN = c(NA,NaN))
242options(op) # warnings ok:
243lt <- lapply(xcl, function(X)
244    c(list(`_` = table(x, exclude=X)), #--> 4 warnings from (exclude, useNA):
245      lapply(u.opt, function(use) table(x, exclude=X, useNA=use))))
246(y <- factor(c(4,5,6:5)))
247ly <-  lapply(xcl, function(X)
248    c(list(`_` = table(y, exclude=X)), #--> 4 warnings ...
249      lapply(u.opt, function(use) table(y, exclude=X, useNA=use))))
250lxy <-  lapply(xcl, function(X)
251    c(list(`_` = table(x, y, exclude=X)), #--> 4 warnings ...
252      lapply(u.opt, function(use) table(x, y, exclude=X, useNA=use))))
253op <- options(warn = 2)# no warnings allowed
254
255stopifnot(exprs = {
256    vapply(lt, function(i) all(vapply(i, class, "") == "table"), NA)
257    vapply(ly, function(i) all(vapply(i, class, "") == "table"), NA)
258    vapply(lxy,function(i) all(vapply(i, class, "") == "table"), NA)
259    identical((ltNA  <- lt [["NA"  ]]), lt [["NANaN"]])
260    identical((ltNl  <- lt [["NULL"]]), lt [["none" ]])
261    identical((lyNA  <- ly [["NA"  ]]), ly [["NANaN"]])
262    identical((lyNl  <- ly [["NULL"]]), ly [["none" ]])
263    identical((lxyNA <- lxy[["NA"  ]]), lxy[["NANaN"]])
264    identical((lxyNl <- lxy[["NULL"]]), lxy[["none" ]])
265})
266## 'NULL' behaved special (2.8.0 <= R <= 3.3.1)  and
267##  *all* tables in l0 and lt were == (1 0 2) !
268ltN1 <- ltNA[[1]]; lyN1 <- lyNA[[1]]; lxyN1 <- lxyNA[[1]]
269lNl1 <- ltNl[[1]]; lyl1 <- lyNl[[1]]; lxyl1 <- lxyNl[[1]]
270
271stopifnot(exprs = {
272    vapply(names(ltNA) [-1], function(n) identical(ltNA [[n]], ltN1 ), NA)
273    vapply(names(lyNA) [-1], function(n) identical(lyNA [[n]], lyN1 ), NA)
274    vapply(names(lxyNA)[-1], function(n) identical(lxyNA[[n]], lxyN1), NA)
275    identical(lyN1, lyl1)
276    identical(2L, dim(ltN1)); identical(3L, dim(lyN1))
277    identical(3L, dim(lNl1))
278    identical(dimnames(ltN1), list(x = c("1","2")))
279    identical(dimnames(lNl1), list(x = c("1","2", NA)))
280    identical(dimnames(lyN1), list(y = paste(4:6)))
281    identical(  1:0    , as.vector(ltN1))
282    identical(c(1:0,3L), as.vector(lNl1))
283    identical(c(1:2,1L), as.vector(lyN1))
284    identical(c(1L, rep(0L, 5)), as.vector(lxyN1))
285    identical(dimnames(lxyN1), c(dimnames(ltN1), dimnames(lyN1)))
286    identical(c(1L,1:0), as.vector(table(3:1, exclude=1, useNA = "always")))
287    identical(c(1L,1L ), as.vector(table(3:1, exclude=1)))
288})
289
290x3N <- c(1:3,NA)
291(tt <- table(x3N, exclude=NaN))
292stopifnot(exprs = {
293    tt == 1
294    length(nt <- names(tt)) == 4
295    is.na(nt[4])
296    identical(tt, table(x3N, useNA = "ifany"))
297    identical(tt, table(x3N, exclude = integer(0)))
298    identical(t3N <- table(x3N), table(x3N, useNA="no"))
299    identical(c(t3N), setNames(rep(1L, 3), as.character(1:3)))
300    ##
301    identical(c("2" = 1L), c(table(1:2, exclude=1) -> t12.1))
302    identical(t12.1, table(1:2, exclude=1, useNA= "no"))
303    identical(t12.1, table(1:2, exclude=1, useNA= "ifany"))
304    identical(structure(1:0, .Names = c("2", NA)),
305              c(     table(1:2, exclude=1, useNA= "always")))
306})
307options(op) # (revert to default)
308
309
310## contour() did not check args sufficiently
311tryCmsg(contour(matrix(rnorm(100), 10, 10), levels = 0, labels = numeric()))
312## caused segfault in R 3.3.1 and earlier
313
314
315## unique.warnings() needs better duplicated():
316invisible(warnings())
317.tmp <- lapply(list(0, 1, 0:1, 1:2, c(1,1), -1:1), function(x) wilcox.test(x))
318if(!interactive())
319stopifnot(length(print(uw <- unique(warnings()))) == 2)
320## unique() gave only one warning in  R <= 3.3.1
321
322
323options(warn = 2)# no warnings allowed
324
325## findInterval(x, vec)  when 'vec' is of length zero
326n0 <- numeric(); TF <- c(TRUE, FALSE)
327stopifnot(0 == unlist(lapply(TF, function(L1)
328    lapply(TF, function(L2) lapply(TF, function(L3)
329        findInterval(x=8:9, vec=n0, L1, L2, L3))))))
330## did return -1's for all.inside=TRUE  in R <= 3.3.1
331
332
333## droplevels(<factor with NA-level>)
334L3 <- c("A","B","C")
335f <- d <- factor(rep(L3, 2), levels = c(L3, "XX")); is.na(d) <- 3:4
336(dn <- addNA(d)) ## levels: A B C XX <NA>
337stopifnot(exprs = {
338    identical(levels(print(droplevels(dn))), c(L3, NA))
339    ## only XX must be dropped; R <= 3.3.1 also dropped <NA>
340    identical(levels(droplevels(f)), L3)
341    identical(levels(droplevels(d)), L3) # do *not* add <NA> here
342    identical(droplevels(d ), d [, drop=TRUE])
343    identical(droplevels(f ), f [, drop=TRUE])
344    identical(droplevels(dn), dn[, drop=TRUE])
345})
346
347
348## summary.default() no longer rounds (just its print() method does):
349set.seed(0)
350replicate(256, { x <- rnorm(1); stopifnot(summary(x) == x)}) -> .t
351replicate(256, { x <- rnorm(2+rpois(1,pi))
352    stopifnot(min(x) <= (sx <- summary(x)), sx <= max(x))}) -> .t
353## was almost always wrong in R <= 3.3.x
354
355
356## NULL in integer arithmetic
357i0 <- integer(0)
358stopifnot(exprs = {
359    identical(1L + NULL, 1L + integer())
360    identical(2L * NULL, i0)
361    identical(3L - NULL, i0)
362})
363## gave double() in R <= 3.3.x
364
365
366## factor(x, exclude)  when  'x' or 'exclude' are  character -------
367stopifnot(identical(factor(c(1:2, NA), exclude = ""),
368		    factor(c(1:2, NA), exclude = NULL) -> f12N))
369fab <- factor(factor(c("a","b","c")), exclude = "c")
370stopifnot(identical(levels(fab), c("a","b")))
371faN <- factor(c("a", NA), exclude=NULL)
372stopifnot(identical(faN, factor(faN, exclude="c")))
373## differently with NA coercion warnings in R <= 3.3.x
374
375## factor(x, exclude = X) - coercing 'exclude' or not
376## From r-help/2005-April/069053.html :
377fNA <- factor(as.integer(c(1,2,3,3,NA)), exclude = NaN)
378stopifnot(identical(levels(fNA), c("1", "2", "3", NA)))
379## did exclude NA wrongly in R <= 3.3.x
380## Now when 'exclude' is a factor,
381cc <- c("x", "y", "NA")
382ff <- factor(cc)
383f2 <- factor(ff, exclude = ff[3]) # it *is* used
384stopifnot(identical(levels(f2), cc[1:2]))
385## levels(f2) still contained NA in R <= 3.3.x
386
387
388## arithmetic, logic, and comparison (relop) for 0-extent arrays
389(m <- cbind(a=1[0], b=2[0]))
390Lm <- m; storage.mode(Lm) <- "logical"
391Im <- m; storage.mode(Im) <- "integer"
392stopifnot(exprs = {
393    identical( m, m + 1 ); identical( m,  m + 1 [0]); identical( m,  m + NULL)
394    identical(Im, Im+ 1L); identical(Im, Im + 1L[0]); identical(Im, Im + NULL)
395    identical(m, m + 2:3); identical(Im, Im + 2:3)
396    identical(Lm, m & 1);  identical(Lm,  m | 2:3)
397    identical(Lm,  m & TRUE [0])
398    identical(Lm, Lm | FALSE[0])
399    identical(Lm, m & NULL) # gave Error (*only* place where NULL was not allowed)
400    identical(Lm, m > 1)
401    identical(Lm, m > .1[0]); identical(Lm, m > NULL)
402    identical(Lm, m <= 2:3)
403})
404mm <- m[,c(1:2,2:1,2)]
405tools::assertError(m + mm) # ... non-conformable arrays
406tools::assertError(m | mm) # ... non-conformable arrays
407tools::assertError(m == mm)# ... non-conformable arrays
408## in R <= 3.3.x, relop returned logical(0) and  m + 2:3  returned numeric(0)
409
410## arithmetic, logic, and comparison (relop) -- inconsistency for 1x1 array o <vector >= 2>:
411(m1 <- matrix(1,1,1, dimnames=list("Ro","col")))
412(m2 <- matrix(1,2,1, dimnames=list(c("A","B"),"col")))
413if(FALSE) { # in the future (~ 2018):
414tools::assertError(m1  + 1:2) ## was [1] 2 3  even w/o warning in R <= 3.3.x
415} else tools::assertWarning(m1v <- m1 + 1:2); stopifnot(identical(m1v, 1+1:2))
416tools::assertError(m1  & 1:2) # ERR: dims [product 1] do not match the length of object [2]
417tools::assertError(m1 <= 1:2) # ERR:                  (ditto)
418##
419## non-0-length arrays combined with {NULL or double() or ...} *fail*
420n0 <- numeric(0)
421l0 <- logical(0)
422stopifnot(exprs = {
423    identical(m1 + NULL, n0) # as "always"
424    identical(m1 +  n0 , n0) # as "always"
425    identical(m1 & NULL, l0) # ERROR in R <= 3.3.x
426    identical(m1 &  l0,  l0) # ERROR in R <= 3.3.x
427    identical(m1 > NULL, l0) # as "always"
428    identical(m1 >  n0 , l0) # as "always"
429    ## m2 was slightly different:
430    identical(m2 + NULL, n0) # ERROR in R <= 3.3.x
431    identical(m2 +  n0 , n0) # ERROR in R <= 3.3.x
432    identical(m2 & NULL, l0) # ERROR in R <= 3.3.x
433    identical(m2 &  l0 , l0) # ERROR in R <= 3.3.x
434    identical(m2 == NULL, l0) # as "always"
435    identical(m2 ==  n0 , l0) # as "always"
436})
437
438## strcapture()
439stopifnot(identical(strcapture("(.+) (.+)",
440                               c("One 1", "noSpaceInLine", "Three 3"),
441                               proto=data.frame(Name="", Number=0)),
442                    data.frame(Name=c("One", NA, "Three"),
443                               Number=c(1, NA, 3))))
444
445
446## PR#17160: min() / max()  arg.list starting with empty character
447TFT <- 1:3 %% 2 == 1
448stopifnot(exprs = {
449    identical(min(character(), TFT), "0")
450    identical(max(character(), TFT), "1")
451    identical(max(character(), 3:2, 5:7, 3:0), "7")
452    identical(min(character(), 3:2, 5:7), "2")
453    identical(min(character(), 3.3, -1:2), "-1")
454    identical(max(character(), 3.3, 4:0), "4")
455})
456## all gave NA in R <= 3.3.0
457
458
459## PR#17147: xtabs(~ exclude) fails in R <= 3.3.1
460exc <- exclude <- c(TRUE, FALSE)
461xt1 <- xtabs(~ exclude) # failed : The name 'exclude' was special
462xt2 <- xtabs(~ exc)
463xt3 <- xtabs(rep(1, length(exclude)) ~ exclude)
464noCall  <- function(x) structure(x, call = NULL)
465stripXT <- function(x) structure(x, call = NULL, dimnames = unname(dimnames(x)))
466stopifnot(exprs = {
467    identical(dimnames(xt1), list(exclude = c("FALSE", "TRUE")))
468    identical(names(dimnames(xt2)), "exc")
469    all.equal(stripXT(xt1), stripXT(xt2))
470    all.equal(noCall (xt1), noCall (xt3))
471})
472## [fix was to call table() directly instead of via do.call(.)]
473
474
475## str(xtabs( ~ <var>)):
476stopifnot(grepl("'xtabs' int", capture.output(str(xt2))[1]))
477## did not mention "xtabs" in R <= 3.3.1
478
479
480## findInterval(x_with_ties, vec, left.open=TRUE)
481stopifnot(identical(
482    findInterval(c(6,1,1), c(0,1,3,5,7), left.open=TRUE), c(4L, 1L, 1L)))
483set.seed(4)
484invisible(replicate(100, {
485 vec <- cumsum(1 + rpois(6, 2))
486 x <- rpois(50, 3) + 0.5 * rbinom(50, 1, 1/4)
487 i <- findInterval(x, vec, left.open = TRUE)
488 .v. <- c(-Inf, vec, Inf)
489 isIn <-  .v.[i+1] < x  &  x <= .v.[i+2]
490 if(! all(isIn)) {
491     dump(c("x", "vec"), file=stdout())
492     stop("not ok at ", paste(which(!isIn), collapse=", "))
493 }
494}))
495## failed in R <= 3.3.1
496
497
498## PR#17132 -- grepRaw(*, fixed = TRUE)
499stopifnot(
500    identical(1L,        grepRaw("abcd",     "abcd",           fixed = TRUE)),
501    identical(integer(), grepRaw("abcdefghi", "a", all = TRUE, fixed = TRUE)))
502## length 0 and seg.faulted in R <= 3.3.2
503
504
505## format()ing invalid hand-constructed  POSIXlt  objects
506if(hasTZ <- nzchar(.TZ <- Sys.getenv("TZ"))) cat(sprintf("env.var. TZ='%s'\n",.TZ))
507d <- as.POSIXlt("2016-12-06", tz = "Europe/Vienna")
508hasGMTOFF <- !is.null(d$gmtoff)
509op <- options(warn = 1)# ==> assert*() will match behavior
510if(is.null(d$zone)) cat("Skipping timezone-dependent POSIXlt formatting\n") else
511for(EX in expression({}, Sys.setenv(TZ = "UTC"), Sys.unsetenv("TZ"))) {
512    cat(format(EX),":\n---------\n")
513    eval(EX)
514    dz <- d$zone
515    d$zone <- 1
516    tools::assertError(format(d))
517    if (hasGMTOFF) {
518        d$zone <- NULL # now has 'gmtoff' but no 'zone' --> warning:
519        tools::assertWarning(stopifnot(identical(format(d),"2016-12-06")))
520        d$zone <- dz # = previous, but 'zone' now is last
521        tools::assertError(format(d))
522    } else
523      cat("Skipping timezone amd gmtoff dependent POSIXlt formatting\n")
524}
525if(hasTZ) Sys.setenv(TZ = .TZ); options(op)# revert
526
527dlt <- structure(
528    list(sec = 52, min = 59L, hour = 18L, mday = 6L, mon = 11L, year = 116L,
529         wday = 2L, yday = 340L, isdst = 0L, zone = "CET", gmtoff = 3600L),
530    class = c("POSIXlt", "POSIXt"), tzone = "CET")
531dlt$sec <- 10000 + 1:10 # almost three hours & uses re-cycling ..
532fd <- format(dlt)
533stopifnot(length(fd) == 10, identical(fd, format(dct <- as.POSIXct(dlt))))
534dlt2 <- as.POSIXlt(dct)
535stopifnot(identical(format(dlt2), fd))
536## The two assertError()s gave a seg.fault in  R <= 3.3.2
537
538
539stopifnot(inherits(methods("("), "MethodsFunction"),
540          inherits(methods("{"), "MethodsFunction"))
541## methods("(") and ..("{")  failed in R <= 3.3.2
542
543
544## moved after commit in r71778
545f <- eval(parse(text = "function() { x <- 1 ; for(i in 1:10) { i <- i }}",
546                keep.source = TRUE))
547g <- removeSource(f)
548stopifnot(is.null(attributes(body(g)[[3L]][[4L]])))
549
550## pmin/pmax of ordered factors -- broken in R 3.3.2  [PR #17195]
551of <- ordered(c(1,5,6))
552asI <- as.integer # < shorter code
553set.seed(6); rof <- sample(of, 12, replace=TRUE)
554stopifnot(exprs = {
555    identical(pmax(rof, of), ordered(pmax(asI(rof), asI(of)), labels=levels(rof)) -> pmar)
556    identical(pmax(of, rof), pmar)
557    identical(pmin(rof, of), ordered(pmin(asI(rof), asI(of)), labels=levels(rof)) -> pmir)
558    identical(pmin(of, rof), pmir)
559    identical(pmin(rof, 5), ordered(pmin(asI(rof), 2), levels=1:3, labels=levels(rof)))
560    identical(pmax(rof, 6), ordered(pmax(asI(rof), 3), levels=1:3, labels=levels(rof)))
561    identical(pmax(rof, 1), rof)
562    identical(pmin(rof, 6), rof)
563    identical(pmax(of, 5, rof), ordered(pmax(asI(of),2L,asI(rof)), levels=1:3,
564                                        labels=levels(of)))
565})
566## these were "always" true .. but may change (FIXME ?)
567stopifnot(exprs = {
568    identical(of,   pmin(of, 3)) # what? error? at least warning?
569    identical(pmar, pmax(of, 3, rof))
570})
571## pmin/pmax() of 0-length S3 classed  [PR #17200]
572for(ob0 in list(I(character()), I(0[0]), I(0L[0]),
573                structure(logical(), class="L"),
574                structure(character(), class="CH"))) {
575    stopifnot(exprs = {
576        identical(ob0, pmax(ob0, ob0))
577        identical(ob0, pmin(ob0, ob0))
578        identical(ob0, pmin(ob0, FALSE))
579        identical(ob0, pmax(ob0, FALSE))
580    })
581}
582## pmin()/pmax() of matching numeric data frames
583mUSJ <- data.matrix(dUSJ <- USJudgeRatings)
584stopifnot(exprs = {
585    identical(              pmin(dUSJ, 10 - dUSJ),
586              as.data.frame(pmin(mUSJ, 10 - mUSJ)))
587    identical(              pmax(dUSJ, 10 - dUSJ),
588              as.data.frame(pmax(mUSJ, 10 - mUSJ)))
589})
590## had failed for a while.   Note however :
591d1 <- data.frame(y0 = 0:3 +1/2) ; (d1.2 <- d1[1:2, , drop=FALSE])
592stopifnot(exprs = {  ## FIXME: The 'NA's really are wrong
593    identical(pmax(d1,2),     data.frame(y0 = c(2, NA, 2.5, 3.5)))
594    identical(pmax(d1, 3-d1), data.frame(y0 = .5+c(2, 1:3)))
595    identical(pmax(d1.2, 2),  data.frame(y0 = c(2, NA)))
596    identical(pmax(d1.2, 2-d1.2),data.frame(y0=c(1.5,1.5)))
597    identical(pmin(d1, 2),    data.frame(y0 = c(.5+0:1, NA,NA)))
598    identical(pmin(d1, 3-d1), data.frame(y0 = .5+c(0, 1:-1)))
599    identical(pmin(d1.2, 2),  data.frame(y0 = c(.5, 1.5)))
600    identical(pmin(d1.2, 2-d1.2),data.frame(y0 = c(.5,.5)))
601})
602## some CRAN pkgs have been relying that these at least "worked somehow"
603
604
605## quantile(x, prob) monotonicity in prob[] - PR#16672
606sortedQ <- function(x, prob, ...)
607    vapply(1:9, function(type)
608        !is.unsorted(quantile(x, prob, type=type, names=FALSE, ...)), NA)
609xN <- c(NA, 10.5999999999999996, NA, NA, NA, 10.5999999999999996,
610        NA, NA, NA, NA, NA, 11.3000000000000007, NA, NA,
611        NA, NA, NA, NA, NA, 5.2000000000000002)
612sQ.xN <- sortedQ(xN, probs = seq(0,1,1/10), na.rm = TRUE)
613x2 <- rep(-0.00090419678460984, 602)
614stopifnot(sQ.xN, sortedQ(x2, (0:5)/5))
615## both not fulfilled in R < 3.4.0
616
617
618## seq.int() anomalies in border cases, partly from Mick Jordan (on R-devel):
619stopifnot(exprs = {
620    identical(1,         seq.int(to=1,  by=1 ))
621    identical(1:2,       seq.int(to=2L, by=1L))
622    identical(c(1L, 3L), seq.int(1L, 3L, length.out=2))
623})
624## the first was missing(.), the others "double" in R < 3.4.0
625assertErrV(seq(1,7, by = 1:2))# gave warnings in R < 3.4.0
626## seq() for <complex> / <integer>
627stopifnot(exprs = {
628    all.equal(seq(1+1i, 9+2i, length.out = 9) -> sCplx,
629              1:9 + 1i*seq(1,2, by=1/8))
630    identical(seq(1+1i, 9+2i, along.with = 1:9), sCplx)
631    identical(seq(1L, 3L, by=1L), 1:3)
632})
633## had failed in R-devel for a few days
634D1 <- as.Date("2017-01-06")
635D2 <- as.Date("2017-01-12")
636seqD1 <- seq.Date(D1, D2, by = "1 day")
637stopifnot(exprs = {
638    identical(seqD1, seq(D1, D2, by = "1 days"))
639    ## These two work "accidentally" via seq -> seq.default + "Date"-arithmetic
640    identical(seqD1, seq(by = 1, from = D1, length.out = 7))
641    identical(seqD1, seq(by = 1,   to = D2, length.out = 7))
642    ## swap order of (by, to) ==> *FAILS* because directly calls seq.Date() - FIXME?
643    TRUE ||
644    identical(seqD1, seq(to = D2,  by = 1, length.out = 7))
645    ## above had failed in R-devel for a couple of days
646    identical(seq(9L, by = -1L, length.out = 4L), 9:6)
647    identical(seq(9L, by = -1L, length.out = 4 ), 9:6)
648})
649## for consistency, new in R >= 3.4.0
650
651
652## Underflow happened when parsing small hex constants PR#17199
653stopifnot(exprs = {
654    as.double("0x1.00000000d0000p-987") > 0   # should be 7.645296e-298
655    as.double("0x1.0000000000000p-1022") > 0  # should be 2.225074e-308
656    as.double("0x1.f89fc1a6f6613p-974") > 0   # should be 1.23456e-293
657})
658##
659
660
661## format.POSIX[cl]t() after print.POSIXct()
662dt <- "2012-12-12 12:12:12"
663x <- as.POSIXct(dt, tz = "GMT")
664stopifnot(identical(format(x), dt))
665op <- options(warn=1)# allow
666(Sys.t <- Sys.timezone()) # may occasionally warn (and work)
667options(op)
668someCET <- paste("Europe", c("Berlin", "Brussels", "Copenhagen", "Madrid",
669                             "Paris", "Rome", "Vienna", "Zurich"), sep="/")
670if(Sys.t %in% someCET)
671    stopifnot(print(TRUE), identical(format(x, tz = ""), "2012-12-12 13:12:12"))
672## had failed for almost a month in R-devel & R-patched
673
674
675## xtabs() , notably with NA's :
676asArr <- function(x) {
677    attributes(x) <- list(dim=dim(x), dimnames=dimnames(x)); x }
678as_A <- function(x, A) array(x, dim=dim(A), dimnames=dimnames(A))
679eq_A <- function(a,b) ## equality of arrays, notably sparseMatrix vs dense
680    identical(dim(a),dim(b)) && identical(dimnames(a),dimnames(b)) &&
681        identical(as.vector(a), as.vector(b))
682esoph2 <- droplevels(subset(esoph, subset = tobgp > "10-19" & alcgp >= "40-79"))
683(xt <- xtabs(~ agegp + alcgp + tobgp, esoph2))
684stopifnot(identical(dim(xt), c(6L, 3L, 2L)), # of the 6 x 3 x 2 = 36 entries,
685          identical(which(xt == 0), c(7L, 12L, 18L, 23L, 30L, 32L, 36L)),
686          ## the above 8 are zeros and the rest is 1 :
687          all(xt[xt != 0] == 1))
688xtC <- xtabs(ncontrols ~ agegp + alcgp + tobgp, data = esoph2)
689stopifnot(# no NA's in data, hence result should have none, just 0's:
690    identical(asArr(unname(xtC)),
691 	      array(c(4, 13, 10, 13, 4, 3,   0, 2, 4, 3, 1, 0,	 1, 2, 1, 1, 0, 0,
692 		      7,  8,  2,  3, 0, 0,   2, 1, 2, 0, 0, 0,	 2, 0, 0, 1, 0, 0),
693 		    dim = dim(xt))))
694
695DF <- as.data.frame(UCBAdmissions)
696xt <- xtabs(Freq ~ Gender + Admit, DF)
697stopifnot(identical(asArr(xt),
698		    array(c(1198, 557, 1493, 1278), dim = c(2L, 2L),
699			  dimnames = list(Gender = c("Male", "Female"),
700					  Admit = c("Admitted", "Rejected")))))
701op <- options(na.action = "na.omit")
702DN <- DF; DN[cbind(6:9, c(1:2,4,1))] <- NA; DN
703
704tools::assertError(# 'na.fail' should fail :
705	   xtabs(Freq ~ Gender + Admit, DN, na.action = na.fail))
706xt. <- xtabs(Freq ~ Gender + Admit, DN)
707xtp <- xtabs(Freq ~ Gender + Admit, DN, na.action = na.pass)
708xtN <- xtabs(Freq ~ Gender + Admit, DN, addNA = TRUE)
709stopifnot(exprs = {
710    identical(asArr(xt - xt.), as_A(c(120,17, 207, 8 ), xt))
711    identical(asArr(xt - xtp), as_A(c(120,17, 207, NA), xt)) # not ok in R <= 3.3.2
712    identical(asArr(-xtN + rbind(cbind(xt, 0), 0)),
713              as_A(c(120, 17, -17, 207, NA, 0, -327, 0, 0), xtN))
714})
715## 'sparse = TRUE requires recommended package Matrix
716if(requireNamespace('Matrix', lib.loc=.Library, quietly = TRUE)) {
717    xtS <- xtabs(Freq ~ Gender + Admit, DN, na.action = na.pass, sparse = TRUE)# error in R <= 3.3.2
718    xtNS <- xtabs(Freq ~ Gender + Admit, DN, addNA = TRUE, sparse = TRUE)
719    stopifnot(
720        eq_A(xt., xtabs(Freq ~ Gender + Admit, DN, sparse = TRUE)),
721        eq_A(xtp, xtS),
722        eq_A(xtN, xtNS)
723   )
724}
725## NA treatment partly wrong in R < 3.4.0; new option 'addNA'
726ee <- esoph[esoph[,"ncases"] > 0, c(1:2,4)]
727ee[,"ncases"] <- as.integer(ee[,"ncases"])
728(tt <- xtabs(ncases ~ ., ee)); options(op)
729stopifnot(identical(as.vector(tt[1:2,]), # *integer* + first value
730		    c(0L, 1L, 0L, 4L, 0L, 0L, 1L, 4L)))
731## keeping integer in sum()mation of integers
732
733
734## tapply() with FUN returning raw  |  with factor -> returning integer
735stopifnot(identical(tapply(1:3, 1:3, as.raw),
736                    array(as.raw(1:3), 3L, dimnames=list(1:3))), ## failed in R < 3.4.0
737          identical(3:1, as.vector(tapply(1:3, 1:3, factor, levels=3:1))))
738x <- 1:2 ; (txx <- tapply(x, list(x, x), function(x) "a"))
739##   1   2
740## 1 "a" NA
741## 2 NA  "a"
742stopifnot(identical(txx,
743  matrix(c("a", NA, NA, "a"), 2, dimnames = rep(list(as.character(x)),2L))))
744## Failed in R 3.4.[01]
745
746
747## str(<list of list>, max.level = 1)
748LoL <- function(lenC, FUN = identity)
749    lapply(seq_along(lenC), function(i) lapply(seq_len(lenC[i]), FUN))
750xx <- LoL(c(7,3,17,798,3))
751str(xx, list.len = 7, max.level = 1)
752str2 <- capture.output(
753 str(xx, list.len = 7, max.level = 2))
754stopifnot(exprs = {
755    grepl("List of ", capture.output(str(xx, list.len = 7, max.level = 1)))
756    length(str2) == 35
757    sum(grepl("list output truncated", str2)) == 2
758    vapply(paste("List of", lengths(xx)), function(pat) any(grepl(pat, str2)), NA)
759})
760## wrongly showed '[list output truncated]'  in R < 3.4.0
761
762
763## stopifnot(all.equal(.)) message abbreviation
764msg <- tryCmsg(stopifnot(all.equal(rep(list(pi),4), list(3.1, 3.14, 3.141, 3.1415))))
765writeLines(msg)
766stopifnot(length(strsplit(msg,"\n")[[1]]) == 1+3+1)
767## was wrong for months in R-devel only
768
769
770## available.packages() (not) caching in case of errors
771tools::assertWarning(ap1 <- available.packages(repos = "http://foo.bar"))
772tools::assertWarning(ap2 <- available.packages(repos = "http://foo.bar"))
773stopifnot(nrow(ap1) == 0, identical(ap1, ap2))
774## had failed for a while in R-devel (left empty *.rds file)
775
776
777## rep()/rep.int() : when 'times' is a list
778stopifnot(exprs = {
779    identical(rep    (4,   list(3)), c(4,4,4))
780    identical(rep.int(4,   list(3)), c(4,4,4))
781    identical(rep.int(4:5, list(2,1)), c(4L,4:5))
782    identical(rep    (4:5, list(2,1)), c(4L,4:5))
783})
784## partly failed in R 3.3.{2,3}
785
786
787## quantile(ordered(.)) - error message more directly useful
788OL <- ordered(sample(LETTERS, 20, replace=TRUE))
789(e <- tryCmsg(quantile(OL)))
790stopifnot(exprs = {
791    grepl("type.*1.*3", e) # typically works in several locales
792    is.ordered(quantile(OL, type = 1))
793    is.ordered(quantile(OL, type = 3))
794})
795## gave  "factors are not allowed" in R <= 3.3.x
796
797## terms() ignored arg names (PR#17235)
798a1 <- attr(terms(y ~ f(x, a = z) + f(x, a = z)),
799           "term.labels")
800a2 <- attr(terms(y ~ f(x, a = z) + f(x, b = z)),
801           "term.labels")
802stopifnot(length(a1) == 1, length(a2) == 2)
803## both gave length 1
804
805
806## by.data.frame() called not from toplevel w different arg names
807dby <- function(dat, ind, F) by(dat, ind, FUN=F)
808dby(warpbreaks, warpbreaks[,"tension"], summary)
809if(!interactive())
810stopifnot(is.list(r <- .Last.value), inherits(r, "by"))
811## failed after r72531
812
813
814## status returned by 'R CMD Sweave'
815fil <- "Sweave-test-1.Rnw"
816file.copy(system.file("Sweave", fil, package="utils"), tempdir())
817owd <- setwd(tempdir())
818(o <- capture.output(utils:::.Sweave(fil, no.q = TRUE), type = "message"))
819stopifnot(grepl("exit status 0", tail(o, 1)))
820setwd(owd)
821## R CMD Sweave gave status 1 and hence an error in R 3.4.0 (only)
822
823
824## print.noquote(*,  right = *)
825nq <- noquote(LETTERS[1:9]); stopifnot(identical(nq, print(nq, right = TRUE)))
826## print() failed a few days end in R-devel ca. May 1, 2017; non-identical for longer
827tt <- table(c(rep(1, 7), 2,2,2))
828stopifnot(identical(tt, print.noquote(tt)))
829## print.noquote(<table>) failed for 6 weeks after r72638
830
831
832## accessing  ..1  when ... is empty and using ..0, etc.
833t0 <- function(...) ..0
834t1 <- function(...) ..1
835t2 <- function(...) ..2
836stopifnot(identical(t1(pi, 2), pi), identical(t1(t1), t1),
837	  identical(t2(pi, 2), 2))
838et1 <- tryCid(t1())
839if(englishMsgs)
840    stopifnot(identical("the ... list contains fewer than 1 element",
841			conditionMessage(et1)))
842## previously gave   "'nthcdr' needs a list to CDR down"
843et0   <- tryCid(t0()) ; (mt0   <- conditionMessage(et0))
844et2.0 <- tryCid(t2()) ; (mt2.0 <- conditionMessage(et2.0))
845et2.1 <- tryCid(t2(1)); (mt2.1 <- conditionMessage(et2.1))
846if(englishMsgs)
847    stopifnot(grepl("indexing '...' with .* index 0", mt0),
848	      identical("the ... list contains fewer than 2 elements", mt2.0),
849	      identical(mt2.0, mt2.1))
850assertErrV(t0(1))
851assertErrV(t0(1, 2))
852## the first gave a different error msg, the next gave no error in R < 3.5.0
853
854
855## stopifnot(e1, e2, ...) .. evaluating expressions sequentially
856one <- 1
857try(stopifnot(3 < 4:5, 5:6 >= 5, 6:8 <= 7, one <<- 2))
858stopifnot(identical(one, 1)) # i.e., 'one <<- 2' was *not* evaluated
859## all the expressions were evaluated in R <= 3.4.x
860(et <- tryCid(stopifnot(0 < 1:10, is.numeric(..vaporware..), stop("FOO!"))))
861stopifnot(exprs = {
862    inherits(et, "simpleError")
863    ## condition call now *does* contain 'stopifnot':
864    ## !grepl("^stopifnot", deparse(conditionCall(et), width.cutoff=500))
865    grepl("'..vaporware..'", conditionMessage(et))
866})
867## call was the full 'stopifnot(..)' in R < 3.5.0 .. and again in R > 3.6.x
868## (don't afford tryCatch()ing everything)
869
870
871## path.expand shouldn't translate to local encoding PR#17120
872## This has been fixed on Windows, but not yet on Unix non-UTF8 systems
873if(onWindows) {
874    filename <- "\U9b3c.R"
875    stopifnot(identical(path.expand(paste0("~/", filename)),
876		 	      paste0(path.expand("~/"), filename)))
877}
878## Chinese character was changed to hex code
879
880
881## aggregate.data.frame(*, drop=FALSE)  {new feature in R 3.3.0}
882## PR#16918 : problem with near-eq. factor() levels "not quite matching"
883group <- c(2 + 2^-51, 2)
884d1 <- data.frame(n = seq(group))
885b1 <- list(group = group)
886stopifnot(
887    identical(aggregate(d1, b1, length, drop = TRUE),
888              aggregate(d1, b1, length, drop = FALSE)))
889## drop=FALSE gave two rows + deprec. warning in R 3.3.x, and an error in 3.4.0
890
891
892## line() [Tukey's resistant line]
893cfs <- t(sapply(2:50, function(k) {x <- 1:k; line(x, 2+x)$coefficients }))
894set.seed(7)
895cf2 <- t(sapply(2:50, function(k) {
896    x <- sample.int(k)
897    line(x, 1-2*x)$coefficients }))
898stopifnot(all.equal(cfs, matrix(c(2,  1), 49, 2, byrow=TRUE), tol = 1e-14), # typically exact
899          all.equal(cf2, matrix(c(1, -2), 49, 2, byrow=TRUE), tol = 1e-14))
900## had incorrect medians of the left/right third of the data (x_L, x_R), in R < 3.5.0
901
902
903## 0-length Date and POSIX[cl]t:  PR#71290
904D <- structure(17337, class = "Date") # Sys.Date() of "now"
905D; D[0]; D[c(1,2,1)] # test printing of NA too
906stopifnot(identical(capture.output(D[0]), "Date of length 0"))
907D <- structure(1497973313.62798, class = c("POSIXct", "POSIXt")) # Sys.time()
908D; D[0]; D[c(1,2,1)] # test printing of NA too
909stopifnot(identical(capture.output(D[0]), "POSIXct of length 0"))
910D <- as.POSIXlt(D)
911D; D[0]; D[c(1,2,1)] # test printing of NA too
912stopifnot(identical(capture.output(D[0]), "POSIXlt of length 0"))
913## They printed as   '[1] "Date of length 0"'  etc in R < 3.5.0
914
915
916## aggregate.data.frame() producing spurious names  PR#17283
917dP <- state.x77[,"Population", drop=FALSE]
918by <- list(Region = state.region, Cold = state.x77[,"Frost"] > 130)
919a1 <- aggregate(dP, by=by, FUN=mean, simplify=TRUE)
920a2 <- aggregate(dP, by=by, FUN=mean, simplify=FALSE)
921stopifnot(exprs = {
922    is.null(names(a1$Population))
923    is.null(names(a2$Population))
924    identical(unlist(a2$Population), a1$Population)
925    all.equal(unlist(a2$Population),
926              c(8802.8, 4208.12, 7233.83, 4582.57, 1360.5, 2372.17, 970.167),
927              tol = 1e-6)
928})
929## in R <= 3.4.x, a2$Population had spurious names
930
931
932## factor() with duplicated labels allowing to "merge levels"
933x <- c("Male", "Man", "male", "Man", "Female")
934## The pre-3.5.0 way {two function calls, nicely aligned}:
935xf1 <- factor(x, levels = c("Male", "Man",  "male", "Female"))
936           levels(xf1) <- c("Male", "Male", "Male", "Female")
937## the new "direct" way:
938xf <- factor(x, levels = c("Male", "Man",  "male", "Female"),
939                labels = c("Male", "Male", "Male", "Female"))
940stopifnot(identical(xf1, xf),
941          identical(xf, factor(c(rep(1,4),2), labels = c("Male", "Female"))))
942## Before R 3.5.0, the 2nd factor() call gave an error
943aN <- c("a",NA)
944stopifnot(identical(levels(factor(1:2, labels = aN)), aN))
945## the NA-level had been dropped for a few days in R-devel(3.5.0)
946##
947
948## Factor behavior -- these have been unchanged, also in R >= 3.5.0 :
949ff <- factor(c(NA,2,3), levels = c(2, NA), labels = c("my", NA), exclude = NULL)
950stopifnot(exprs = { ## all these have been TRUE "forever" :
951    identical(as.vector(ff), as.character(ff))
952    identical(as.vector(ff), c(NA, "my", NA))
953    identical(capture.output(ff), c("[1] <NA> my   <NA>",
954				    "Levels: my <NA>"))
955    identical(factor(ff),
956	      structure(c(NA, 1L, NA), .Label = "my", class = "factor"))
957    identical(factor(ff, exclude=NULL),
958	      structure(c(2L, 1L, 2L), .Label = c("my", NA), class = "factor"))
959    identical(as.integer(       ff),                c(2:1,NA))
960    identical(as.integer(factor(ff, exclude=NULL)), c(2:1,2L))
961})
962
963
964## within.list({ .. rm( >=2 entries ) }) :
965L <- list(x = 1, y = 2, z = 3)
966stopifnot(identical(within(L, rm(x,y)), list(z = 3)))
967## has failed since R 2.7.2 patched (Aug. 2008) without any noticeable effect
968sortN <- function(x) x[sort(names(x))]
969LN <- list(y = 2, N = NULL, z = 5)
970stopifnot(exprs = {
971    identical(within(LN, { z2 <- z^2 ; rm(y,z,N) }),
972              list(z2 = 5^2)) ## failed since Aug. 2008
973    identical(within(LN, { z2 <- z^2 ; rm(y,z) }),
974              list(N = NULL, z2 = 5^2)) ## failed for a few days in R-devel
975    ## within.list() fast version
976    identical(sortN(within(LN, { z2 <- z^2 ; rm(y,z) }, keepAttrs=FALSE)),
977              sortN(list(N = NULL, z2 = 5^2)))
978})
979
980
981## write.csv did not signal an error if the disk was full PR#17243
982if (file.access("/dev/full", mode = 2) == 0) { # Not on all systems...
983    cat("Using  /dev/full  checking write errors... ")
984    # Large writes should fail mid-write
985    tools::assertError(write.table(data.frame(x=1:1000000), file = "/dev/full"))
986    # Small writes should fail on closing
987    tools::assertWarning(write.table(data.frame(x=1), file = "/dev/full"))
988    cat("[Ok]\n")
989}
990## Silently failed up to 3.4.1
991
992
993## model.matrix() with "empty RHS" -- PR#14992 re-opened
994row.names(trees) <- 42 + seq_len(nrow(trees))
995.RN <- row.names(mf <- model.frame(log(Volume) ~ log(Height) + log(Girth), trees))
996stopifnot(identical(.RN, row.names(model.matrix(~ 1, mf))),
997	  identical(.RN, row.names(model.matrix(~ 0, mf))))
998## had 1:nrow()  up to 3.4.x
999
1000
1001## "\n" etc in calls and function definitions
1002(qq <- quote(-"\n"))
1003stopifnot(exprs = {
1004    identical('-"\\n"', cq <- capture.output(qq))
1005    identical(5L, nchar(cq))
1006    identical(6L, nchar(capture.output(quote(("\t")))))
1007})
1008## backslashes in language objects accidentally duplicated in R 3.4.1
1009
1010
1011## length(<pairlist>) <- N
1012pl <- pairlist(a=1, b=2); length(pl) <- 1
1013al <- formals(ls);        length(al) <- 2
1014stopifnot(identical(pl, pairlist(a = 1)),
1015	  identical(al, as.pairlist(alist(name = , pos = -1L))))
1016## both `length<-` failed in R <= 3.4.1; the 2nd one for the wrong reason
1017
1018
1019## dist(*, "canberra") :
1020x <- cbind(c(-1,-5,10), c(-2,7,8)); (dc <- dist(x, method="canberra"))
1021##          1        2
1022## 2 1.666667
1023## 3 2.000000 1.066667
1024stopifnot(all.equal(as.vector(dc), c(25, 30, 16)/15))
1025## R's definition wrongly assumed x[] entries all of the same sign
1026
1027
1028## sigma( <rank-deficient model> ), PR#17313
1029dd <- data.frame(x1 = LETTERS[c(1,2,3, 1,2,3, 1,2,3)],
1030                 x2 = letters[c(1,2,1, 2,1,1, 1,2,1)], y = 1:9)
1031(sf <- summary(fit <- lm(y ~ x1*x2, data = dd))) ## last coef is NA
1032stopifnot(all.equal(sigma(fit)^2,  27/2,  tol = 1e-14),
1033	  all.equal(sigma(fit), sf$sigma, tol = 1e-14))
1034## was too large because of wrong denom. d.f. in R <= 3.4.1
1035
1036
1037## nclass.FD() and nclass.scott() for "extreme" data, PR#17274
1038NC <- function(x) c(Sturges = nclass.Sturges(x),
1039                    Scott = nclass.scott(x), FD = nclass.FD(x))
1040xE <- function(eps, n = 5) {
1041    stopifnot(n >= 2, is.numeric(eps), eps >= 0)
1042    c(rep.int(1, n-2), 1+eps, 2)
1043}
1044ncE <- c(Sturges = 4, Scott = 2, FD = 3)
1045stopifnot(exprs = {
1046    sapply(-5:-16, function(E) identical(NC(xE(10^E)), ncE))
1047    identical(NC(xE(1e-4)), c(Sturges = 4, Scott = 2, FD = 8550))
1048    identical(NC(xE(1e-3)), c(Sturges = 4, Scott = 2, FD =  855))
1049})
1050## for these, nclass.FD() had "exploded" in R <= 3.4.1
1051## Extremely large diff(range(.)) : NB: this gives a UBSAN warning
1052XXL <- c(1:9, c(-1,1)*1e300)
1053stopifnot(nclass.scott(XXL) == 1)
1054## gave 0 in R <= 3.4.1
1055tools::assertWarning(hh <- hist(XXL, "FD", plot=FALSE))
1056stopifnot(sum(hh$counts) == length(XXL))
1057## gave error from pretty.default + NA coercion warning in R <= 3.4.1
1058
1059
1060## methods:::rbind / cbind no longer deeply recursive also fixes bug:
1061library(methods)
1062myM <- setClass("myMatrix", contains="matrix")
1063T <- rbind(1:2, c=2, "a+"=10, myM(4:1,2), deparse.level=0)
1064stopifnot(identical(rownames(T), c("", "c", "a+", "", "")))
1065## rownames(.) wrongly were NULL in R <= 3.4.1
1066proc.time() - .pt; .pt <- proc.time()
1067
1068
1069## qr.coef(qr(X, LAPACK=TRUE)) when X has column names, etc
1070X <- cbind(int = 1,
1071           c2 = c(2, 8, 3, 10),
1072           c3 = c(2, 5, 2, 2)); rownames(X) <- paste0("r", 1:4)
1073y <- c(2,3,5,7); yc <- as.complex(y)
1074q.Li <- qr(X);              cfLi <- qr.coef(q.Li, y)
1075q.LA <- qr(X, LAPACK=TRUE); cfLA <- qr.coef(q.LA, y)
1076q.Cx <- qr(X + 0i);         cfCx <- qr.coef(q.Cx, y)
1077e1 <- tryCid(qr.coef(q.Li, y[-4])); e1
1078e2 <- tryCid(qr.coef(q.LA, y[-4]))
1079stopifnot(exprs = {
1080    all.equal(cfLi,    cfLA , tol = 1e-14)# 6.376e-16 (64b Lx)
1081    all.equal(cfLi, Re(cfCx), tol = 1e-14)#  (ditto)
1082    identical(conditionMessage(e1), conditionMessage(e2))
1083})
1084## 1) cfLA & cfCx had no names in R <= 3.4.1
1085## 2) error messages were not consistent
1086
1087
1088## invalid user device function  options(device = *) -- PR#15883
1089graphics.off() # just in case
1090op <- options(device=function(...){}) # non-sense device
1091assertErrV(plot.new())
1092if(no.grid <- !("grid" %in% loadedNamespaces())) requireNamespace("grid")
1093assertErrV(grid::grid.newpage())
1094if(no.grid) unloadNamespace("grid") ; options(op)
1095## both errors gave segfaults in R <= 3.4.1
1096
1097
1098## readRDS(textConnection())
1099abc <- c("a", "b", "c"); tmpC <- ""
1100zz <- textConnection('tmpC', 'wb')
1101saveRDS(abc, zz, ascii = TRUE)
1102sObj <- paste(textConnectionValue(zz), collapse='\n')
1103close(zz); rm(zz)
1104stopifnot(exprs = {
1105    identical(abc, readRDS(textConnection(tmpC)))
1106    identical(abc, readRDS(textConnection(sObj)))
1107})
1108## failed in R 3.4.1 only
1109
1110
1111## Ops (including arithmetic) with 0-column data frames:
1112d0 <- USArrests[, FALSE]
1113stopifnot(exprs = {
1114    identical(d0, sin(d0))
1115    identical(d0, d0 + 1); identical(d0, 2 / d0) # failed
1116    all.equal(sqrt(USArrests), USArrests ^ (1/2)) # now both data frames
1117    is.matrix(m0 <- 0 < d0)
1118    identical(dim(m0), dim(d0))
1119    identical(dimnames(m0)[1], dimnames(d0)[1])
1120    identical(d0 & d0, m0)
1121})
1122## all but the first failed in R < 3.5.0
1123
1124
1125## pretty(x, n) for n = <large> or  large diff(range(x)) gave overflow in C code
1126(fLrg <- Filter(function(.) . < 9e307, c(outer(1:8, 10^(0:2))*1e306)))
1127pL  <- vapply(fLrg, function(f)length(pretty(c(-f,f), n = 100,  min.n = 1)), 1L)
1128pL
1129pL3 <- vapply(fLrg, function(f)length(pretty(c(-f,f), n = 10^3, min.n = 1)), 1L)
1130pL3
1131stopifnot(71 <= pL, pL <= 141, # 81 <= pL[-7], # not on Win-64: pL[-15] <= 121,
1132          701 <= pL3, pL3 <= 1401) # <= 1201 usually
1133## in R < 3.5.0, both had values as low as 17
1134## without long doubles, min(pl[-7]) is 71.
1135
1136
1137### Several returnValue() fixes (r 73111) --------------------------
1138##          =============
1139## returnValue() corner case 1: return 'default' on error
1140hret <- NULL
1141fret <- NULL
1142h <- function() {
1143  on.exit(hret <<- returnValue(27))
1144  stop("h fails")
1145}
1146f <- function() {
1147    on.exit(fret <<- returnValue(27))
1148    h()
1149    1
1150}
1151res <- tryCatch(f(), error=function(e) 21)
1152stopifnot(exprs = {
1153    identical(fret, 27)
1154    identical(hret, 27)
1155    identical(res, 21)
1156})
1157##
1158## returnValue corner case 2: return 'default' on non-local return
1159fret <- NULL
1160gret <- NULL
1161f <- function(expr) {
1162  on.exit(fret <<- returnValue(28))
1163  expr
1164  1
1165}
1166g <- function() {
1167  on.exit(gret <<- returnValue(28))
1168  f(return(2))
1169  3
1170}
1171res <- g()
1172stopifnot(exprs = {
1173    identical(fret, 28)
1174    identical(gret, 2)
1175    identical(res, 2)
1176})
1177##
1178## returnValue corner case 3: return 'default' on restart
1179mret <- NULL
1180hret <- NULL
1181lret <- NULL
1182uvarg <- NULL
1183uvret <- NULL
1184h <- function(x) {
1185  on.exit(hret <<- returnValue(29))
1186  withCallingHandlers(
1187    myerror = function(e) invokeRestart("use_value", 1),
1188    m(x)
1189  )
1190}
1191m <- function(x) {
1192  on.exit(mret <<- returnValue(29))
1193  res <- withRestarts(
1194    l(x),
1195    use_value = function(x) {
1196      on.exit(uvret <<- returnValue(29))
1197      uvarg <<- x
1198      3
1199    }
1200  )
1201  res
1202}
1203l <- function(x) {
1204  on.exit(lret <<- returnValue(29))
1205  if (x > 1) {
1206    res <- x+1
1207    return(res)
1208  }
1209  cond <- structure(
1210    class = c("myerror", "error", "condition"),
1211    list(message = c("This is not an error", call = sys.call()))
1212  )
1213  stop(cond)
1214}
1215res <- h(1)
1216stopifnot(exprs = {
1217    identical(res, 3)
1218    identical(mret, 3)
1219    identical(hret, 3)
1220    identical(lret, 29)
1221    identical(uvarg, 1)
1222    identical(uvret, 3)
1223})
1224##
1225## returnValue: callCC
1226fret <- NULL
1227f <- function(exitfun) {
1228  on.exit(fret <<- returnValue(30))
1229  exitfun(3)
1230  4
1231}
1232res <- callCC(f)
1233stopifnot(identical(res, 3), identical(fret, 30))
1234##
1235## returnValue: instrumented callCC
1236fret <- NULL
1237mycallCCret <- NULL
1238funret <- NULL
1239mycallCC <- function(fun) {
1240  value <- NULL
1241  on.exit(mycallCCret <<- returnValue(31))
1242  delayedAssign("throw", return(value))
1243  fun(function(v) {
1244    on.exit(funret <<- returnValue(31))
1245    value <<- v
1246    throw
1247  })
1248}
1249f <- function(exitfun) {
1250  on.exit(fret <<- returnValue(31))
1251  exitfun(3)
1252  4
1253}
1254res <- mycallCC(f)
1255stopifnot(exprs = {
1256    identical(res, 3)
1257    identical(fret, 31)
1258    identical(mycallCCret, 3)
1259    identical(funret, 31)
1260})
1261## end{ returnValue() section}
1262
1263
1264## array(<empty>, *)  should create (corresponding) NAs for non-raw atomic:
1265a <- array(character(), 1:2)
1266stopifnot(identical(a, matrix(character(), 1,2)), is.na(a))
1267## had "" instead of NA in R < 3.5.0
1268
1269
1270## chaining on.exit handlers with return statements
1271x <- 0
1272fret1 <- NULL
1273fret2 <- NULL
1274f <- function() {
1275  on.exit(return(4))
1276  on.exit({fret1 <<- returnValue(); return(5)}, add = T)
1277  on.exit({fret2 <<- returnValue(); x <<- 2}, add = T)
1278  3
1279}
1280res <- f()
1281stopifnot(exprs = {
1282    identical(res, 5)
1283    identical(x, 2)
1284    identical(fret1, 4)
1285    identical(fret2, 5)
1286})
1287
1288
1289## splineDesign(*, derivs = <too large>):
1290if(no.splines <- !("splines" %in% loadedNamespaces())) requireNamespace("splines")
1291x <- (0:8)/8
1292aKnots <- c(rep(0, 4), c(0.3, 0.5, 0.6), rep(1, 4))
1293assertErrV(splines::splineDesign(aKnots, x, derivs = 4))
1294## gave seg.fault in R <= 3.4.1
1295
1296
1297## allow on.exit handlers to be added in LIFO order
1298x <- character(0)
1299f <- function() {
1300    on.exit(x <<- c(x, "first"))
1301    on.exit(x <<- c(x, "last"), add = TRUE, after = FALSE)
1302}
1303f()
1304stopifnot(identical(x, c("last", "first")))
1305##
1306x <- character(0)
1307f <- function() {
1308    on.exit(x <<- c(x, "last"), add = TRUE, after = FALSE)
1309}
1310f()
1311stopifnot(identical(x, "last"))
1312
1313
1314## deparse(<symbol>)
1315##_reverted_for_now
1316##_ brc <- quote(`{`)
1317##_ stopifnot(identical(brc, eval(parse(text = deparse(brc, control="all")))))
1318## default was to set  backtick=FALSE  so parse() failed in R <= 3.4.x
1319
1320
1321## sys.on.exit() is called in the correct frame
1322fn <- function() {
1323    on.exit("foo")
1324    identity(sys.on.exit())
1325}
1326stopifnot(identical(fn(), "foo"))
1327
1328
1329## rep.POSIXt(*, by="n  DSTdays") - PR#17342
1330x <- seq(as.POSIXct("1982-04-15 05:00", tz="US/Central"),
1331         as.POSIXct("1994-10-15",       tz="US/Central"), by="360 DSTdays")
1332stopifnot(length(x) == 13, diff((as.numeric(x) - 39600)/86400) == 360)
1333## length(x) was 1802 and ended in many NA's in R <= 3.4.2
1334
1335
1336## 0-length logic with raw()
1337r0 <- raw(0)
1338stopifnot(exprs = {
1339    identical(r0 & r0, r0)
1340    identical(r0 | r0, r0)
1341})
1342## gave logical(0) in R 3.4.[012]
1343
1344
1345## `[[`  and  `[[<-`  indexing with <symbol>
1346x <- c(a=2, b=3)
1347x[[quote(b)]] <- pi
1348stopifnot(exprs = {
1349    identical(2, x[[quote(a)]])
1350    identical(x, c(a=2, b=pi))
1351})
1352## `[[` only worked after fixing PR#17314, i.e., not in R <= 3.4.x
1353
1354
1355## range(<non-numeric>, finite = TRUE)
1356stopifnot(identical(0:1, range(c(NA,TRUE,FALSE), finite=TRUE)))
1357## gave NA's in R <= 3.4.2
1358
1359
1360## `[<-` : coercion should happen also in 0-length case:
1361x1 <- x0 <- x <- n0 <- numeric(); x0[] <- character(); x1[1[0]] <- character()
1362x[] <- numeric()
1363stopifnot(identical(x0, character()), identical(x1, x0), identical(x, n0))
1364## x0, x1 had remained 'numeric()' in  R <= 3.4.x
1365x[1] <- numeric(); stopifnot(identical(x, n0))
1366## had always worked; just checking
1367NUL <- NULL
1368NUL[3] <- integer(0); NUL[,2] <- character() ; NUL[3,4,5] <- list()
1369stopifnot(is.null(NUL))
1370## above had failed for one day in R-devel; next one always worked
1371NUL <- NULL; NUL[character()] <- "A"
1372stopifnot(identical(NUL, character()))
1373## 0-0-length subassignment should not change atomic to list:
1374ec <- e0 <- matrix(, 0, 4) # a  0 x 4  matrix
1375ec[,1:2] <- list()
1376x <- 1[0]; x[1:2] <- list()
1377a <- a0 <- array("", 0:2); a[,1,] <- expression()
1378stopifnot(exprs = {
1379    identical(ec, e0)
1380    identical(x, 1[0])
1381    identical(a, a0)
1382})## failed for a couple of days in R-devel
1383
1384
1385## as.character(<list>) should keep names in some nested cases
1386cl <-     'list(list(a = 1, "B", ch = "CH", L = list(f = 7)))'
1387E <- expression(list(a = 1, "B", ch = "CH", L = list(f = 7)))
1388str(ll <- eval(parse(text = cl)))
1389stopifnot(exprs = {
1390    identical(eval(E), ll[[1]])
1391    identical(as.character(E), as.character(ll) -> cll)
1392    grepl(cll, cl, fixed=TRUE) # currently, cl == paste0("list(", cll, ")")
1393    ## the last two have failed in R-devel for a while
1394    identical(as.character(list(list(one = 1))), "list(one = 1)")
1395    identical(as.character(list(  c (one = 1))),    "c(one = 1)")
1396})## the last gave "1" in all previous versions of R
1397
1398
1399## as.matrix( <data.frame in d.fr.> ) -- prompted by Patrick Perry, R-devel 2017-11-30
1400dm <- dd <- d1 <- data.frame(n = 1:3)
1401dd[[1]] <- d1            # -> 'dd' has "n" twice
1402dm[[1]] <- as.matrix(d1) #    (ditto)
1403d. <- structure(list(d1), class = "data.frame", row.names = c(NA, -3L))
1404d2. <- data.frame(ch = c("A","b"), m = 10:11)
1405d2  <- data.frame(V = 1:2); d2$V <- d2.; d2
1406d3 <- structure(list(A = 1:2, HH = cbind(c(.5, 1))),
1407                class = "data.frame", row.names=c(NA,-2L))
1408d3.2 <- d3; d3.2 $HH <- diag(2)
1409d3.2.<- d3; d3.2.$HH <- matrix(1:4, 2,2, dimnames=list(NULL,c("x","y")))
1410d0 <- as.data.frame(m0 <- matrix(,2,0))
1411d3.0 <- d3; d3.0 $HH <- m0
1412d3.d0<- d3; d3.d0$HH <- d0
1413stopifnot(exprs = {
1414    identical(unname(as.matrix(d0)), m0)
1415    identCO  (dd, d.)
1416    identical(as.matrix(d3.0 ), array(1:2, dim = 2:1, dimnames = list(NULL, "A")) -> m21)
1417    identical(as.matrix(d3.d0), m21)
1418    identical(as.matrix(dd), (cbind(n = 1:3) -> m.))
1419    identical(as.matrix(d.), m.)
1420    identical(as.matrix(d2), array(c("A", "b", "10", "11"), c(2L, 2L),
1421                                   dimnames = list(NULL, c("V.ch", "V.m"))))
1422    identical(as.matrix(dm), m.)
1423    identical(as.matrix(d1), m.)
1424    identical(colnames(m2 <- as.matrix(d2)), c("V.ch", "V.m"))
1425    identical(colnames(as.matrix(d3   )), colnames(d3   )) # failed a few days
1426    identical(colnames(as.matrix(d3.2 )), colnames(format(d3.2 )))
1427    identical(colnames(as.matrix(d3.2 )), c("A", paste("HH",1:2,sep=".")))
1428    identical(colnames(as.matrix(d3.2.)), colnames(format(d3.2.)))
1429    identical(colnames(as.matrix(d3.2.)), c("A", "HH.x", "HH.y"))
1430})
1431## the first  5  as.matrix() have failed at least since R-1.9.1, 2004
1432
1433
1434## Impossible conditions should at least give a warning - PR#17345
1435tools::assertWarning(
1436           power.prop.test(n=30, p1=0.90, p2=NULL, power=0.8)
1437       ) ## may give error in future
1438## silently gave p2 = 1.03 > 1 in R versions v, 3.1.3 <= v <= 3.4.3
1439
1440
1441## 1) removeSource() [for a function w/ body containing NULL]:
1442op <- options(keep.source=TRUE)
1443bod <- quote( foo(x, NULL) )
1444testf  <- function(x) { }; body(testf)[[2]] <- bod
1445testf
1446testfN <- removeSource(testf)
1447stopifnot(identical(body(testf )[[2]], bod)
1448        , identical(body(testfN)[[2]], bod)
1449)
1450## erronously changed  '(x, NULL)'  to  '(x)'  in R version <= 3.4.3
1451##
1452## 2) source *should* be kept:
1453f <- function(x=1) { # 'x' not really needed
1454    x+x + 2*x+1 # (note spaces)
1455}
1456stopifnot(exprs = {
1457    identical(capture.output(f) -> fsrc,
1458              capture.output(print(f)))
1459    length(fsrc) == 3
1460    grepl("(x=1)",             fsrc[1], fixed=TRUE)
1461    grepl("really needed",     fsrc[1], fixed=TRUE)
1462    grepl("x + 2*x+1 # (note", fsrc[2], fixed=TRUE)
1463})
1464options(op)
1465## (was fine, but not tested in R <= 3.5.0)
1466
1467
1468## ar.yw(x) with missing values in x, PR#17366
1469which(is.na(presidents)) # in 6 places
1470arp <- ar(presidents, na.action = na.pass)
1471## check "some" consistency with cheap imputation:
1472prF <- presidents
1473prF[is.na(presidents)] <- c(90, 37, 40, 32, 63, 66) # phantasy
1474arF <- ar(prF)
1475stopifnot(exprs = {
1476    all.equal(arp[c("order", "ar", "var.pred", "x.mean")],
1477              list(order = 3, ar = c(0.6665119, 0.2800927, -0.1716641),
1478                   var.pred = 96.69082, x.mean = 56.30702), tol = 7e-7)
1479    all.equal(arp$ar, arF$ar,                     tol = 0.14)
1480    all.equal(arp$var.pred, arF$var.pred,         tol = 0.005)
1481    all.equal(arp$asy.var.coef, arF$asy.var.coef, tol = 0.09)
1482})
1483## Multivariate
1484set.seed(42)
1485n <- 1e5
1486(i <- sample(n, 12))
1487u <- matrix(rnorm(2*n), n, 2)
1488y <- filter(u, filter=0.8, "recursive")
1489y. <- y; y.[i,] <- NA
1490est  <- ar(        y  , aic = FALSE, order.max = 2) ## Estimate VAR(2)
1491es.  <- ar(        y. , aic = FALSE, order.max = 2, na.action=na.pass)
1492## checking ar.yw.default() multivariate case
1493estd <- ar(unclass(y) , aic = FALSE, order.max = 2) ## Estimate VAR(2)
1494es.d <- ar(unclass(y.), aic = FALSE, order.max = 2, na.action=na.pass)
1495stopifnot(exprs = {
1496    all.equal(est$ar[1,,], diag(0.8, 2), tol = 0.08)# seen 0.0038
1497    all.equal(est[1:6], es.[1:6], tol = 5e-3)
1498    all.equal(estd$x.mean, es.d$x.mean, tol = 0.01) # seen 0.0023
1499    all.equal(estd[c(1:3,5:6)],
1500              es.d[c(1:3,5:6)], tol = 1e-3)## seen {1,3,8}e-4
1501    all.equal(lapply(estd[1:6],unname),
1502              lapply(est [1:6],unname), tol = 2e-12)# almost identical
1503    all.equal(lapply(es.d[1:6],unname),
1504              lapply(es. [1:6],unname), tol = 1e-11)
1505})
1506## NA's in x gave an error, in R versions <= 3.4.3
1507
1508
1509## as.list(<Date>) method:
1510toD <- Sys.Date(); stopifnot(identical(as.list(toD)[[1]], toD))
1511## was wrong for 20 hours
1512
1513options(warn = 2)# no warnings allowed
1514
1515## PR#17372: sum(<ints whose sum overflows>, <higher type>)
1516iL <- rep(1073741824L, 2) # 2^30 + 2^30 = 2^31 integer overflows to NA
1517r1 <- tryCmsg(sum("foo", iL))
1518r2 <- tryCmsg(sum(iL, "foo"))
1519stopifnot(exprs = {
1520    identical(r1, r2)
1521    grepl("invalid 'type' (character) ", r1, fixed=TRUE)
1522    ## each _gave_ an overflow warning + NA
1523    identical(sum(3.14, iL), sum(iL, 3.14))
1524    identical(sum(1+2i, iL), sum(iL, 1+2i))
1525    if(identical(.Machine$sizeof.longlong, 8L))
1526        TRUE # no longer overflows early when we have LONG_INT :
1527    else { # no LONG_INT [very rare in 2018-02 !]
1528        identical(sum(3.14, iL), NA_real_) &&
1529        identical(sum(1+2i, iL), NA_complex_)
1530    }
1531})
1532## r2 was no error and sum(iL, 1+2i) gave NA_real_ in R <= 3.4.x
1533## Was PR#1408 Inconsistencies in sum() {in ./reg-tests-2.R}
1534x <- as.integer(2^31 - 1)## = 2147483647L = .Machine$integer.max ("everywhere")
1535x24 <- rep.int(x, 2^24) # sum = 2^55 - 2^24
1536stopifnot(exprs = {
1537    sum(x, x)   == 2^32-2 # did not warn in 1.4.1 -- no longer overflows in 3.5.0
1538    sum(c(x,x)) ==(2^32-2 -> sx2) # did warn -- no longer overflows
1539    (z <- sum(x, x, 0.0)) == sx2 # was NA in 1.4.1
1540    typeof(z) == "double"
1541    is.integer(x24)
1542    sum(x24) == 2^55 - 2^24 # was NA (+ warning) in R <= 3.4.x
1543})
1544
1545
1546## aggregate.data.frame(*, drop=FALSE)  wishlist PR#17280
1547## [continued from above]
1548aF <- aggregate(dP, by=by, FUN=mean,   drop=FALSE)
1549lF <- aggregate(dP, by=by, FUN=length, drop=FALSE)
1550stopifnot(exprs = {
1551    identical(dim(aF), c(8L, 3L))
1552    identical(aF[6,3], NA_real_)
1553    identical(lF[6,3], NA_integer_)
1554})
1555DF <- data.frame(a=rep(1:3,4), b=factor(rep(1:2,6), levels=1:3))
1556aT <- aggregate(DF["a"], DF["b"], length)# drop=TRUE
1557aF <- aggregate(DF["a"], DF["b"], length,  drop=FALSE)
1558stopifnot(exprs = {
1559    identical(dim(aT), c(2L,2L))
1560    identical(dim(aF), c(3L,2L))
1561    identical(aT, aF[1:2,])
1562    identical(aF[3,"a"], NA_integer_)
1563    })
1564## In R <= 3.4.x, the function (FUN) was called on empty sets, above,
1565## giving NaN (and 0) or <nothing>;  now the result is NA.
1566
1567
1568## PR#16107  is.na(NULL) throws warning (contrary to all other such calls)
1569stopifnot(identical(is.na(NULL), logical(0)))
1570## gave a warning in R <= 3.4.x
1571
1572
1573## subtle [[<- , e.g.,  <nestedList>[[ c(i,j,k) ]]  <-  val :
1574xx0 <-
1575xx <- list(id = 1L,
1576           split = list(varid = 1L, breaks = NULL,
1577                        index = 1:3, right = TRUE, info = "s"),
1578           kids = list(id = 2L,
1579                       split = list(varid = 3L, breaks = 75,
1580                                    right = TRUE, info = "KS"),
1581                       kids = list(list(id = 3L, info = "yes"),
1582                                   list(id = 4L, info = "no")),
1583                       info = NULL),
1584           list(id = 5L,
1585                split = list(varid = 3L, breaks = 20,
1586                             right = TRUE, info = "4s"),
1587                kids = list(list(id = 6L, info = "no"),
1588                            list(id = 7L, info = "yes")),
1589                info = NULL),
1590           info = NULL)
1591
1592## no-ops:
1593xx[[1]] <- xx0[[1]]
1594xx[["kids"]] <- xx0[["kids"]]
1595xx[[2:1]] <- xx0[[2:1]] ; stopifnot(identical(xx, xx0))
1596xx[[3:1]] <- xx0[[3:1]] ; stopifnot(identical(xx, xx0)) # (err)
1597## replacements
1598              xx[[c(2,3)]]   <- 5:3
1599              xx[[c(4,2,4)]] <- c(4,2,c=4) # (err: wrong xx)
1600              xx[[c(4,2,3)]] <- c(ch="423")# (err)
1601              xx[[c(3,2,2)]] <- 47         # (err)
1602stopifnot(exprs = {
1603    identical(xx[[c(2,3)]],     5:3)
1604    identical(xx[[c(4,2,4)]],   c(4,2,c=4))
1605    identical(xx[[c(4,2,3)]],   c(ch="423"))
1606    identical(xx[[c(3,2,2)]],   47)
1607    identical(lengths(xx), lengths(xx0))
1608    identical(  names(xx),   names(xx0))
1609    identical(lapply(xx, lengths),
1610              lapply(xx0,lengths))
1611    identical(lapply(xx, names),
1612              lapply(xx0,names))
1613})
1614## several of these failed for a bit more than a day in R-devel
1615
1616
1617## PR#17369 and PR#17381 -- duplicated() & unique() data frame methods:
1618d22 <- data.frame(x = c(.3 + .6, .9), y = 1)
1619d21 <- d22[,"x", drop=FALSE]
1620dRT <- data.frame(x = c("\r", "\r\r"), y = c("\r\r", "\r"))
1621stopifnot(exprs = {
1622    identical(unique(d22), d22) # err
1623    is.data.frame(d21)
1624    identical(dim(d21), 2:1)
1625    identical(unique(d21), d21)
1626    identical(unique(dRT), dRT) # err
1627    })
1628## with a POSIXct column (with tz during Daylight Saving change):
1629Sys.setenv("TZ" = "Australia/Melbourne") # <== crucial (for most)!
1630x <- as.POSIXct(paste0("2013-04-06 ", 13:17, ":00:00"), tz = "UTC")
1631attr(x, "tzone") <- ""
1632(xMelb <- as.POSIXct(x, tz = "Australia/Melbourne"))# shows both AEDT & AEST
1633dMb <- data.frame(x = xMelb, y = 1)
1634stopifnot(exprs = {
1635    identical(unique(dMb), dMb)
1636    identical(anyDuplicated(dMb), 0L)
1637}) # both differing in R <= 3.4.x
1638
1639
1640## when sep is given, an opening quote may be preceded by non-space
1641stopifnot(  ncol(read.table(              text="=\"Total\t\"\t1\n",sep="\t")) == 2)
1642stopifnot(length(scan(what=list("foo",1), text="=\"Total\t\"\t1\n",sep="\t")) == 2)
1643##
1644## in 3.4.x, read.table failed on this
1645stopifnot(  ncol(read.table(              text="=\"CJ01 \"\t550\n",sep="\t")) == 2)
1646stopifnot(length(scan(what=list("foo",1), text="=\"CJ01 \"\t550\n",sep="\t")) == 2)
1647##
1648## when no sep is given, quotes preceded by non-space have no special
1649## meaning and are retained (related to PR#15245)
1650stopifnot(read.table(                 text="HO5\'\'\tH")[1,1] == "HO5\'\'")
1651stopifnot(read.table(                 text="HO5\'\tH")[1,1]   == "HO5\'")
1652stopifnot(scan(what=list("foo","foo"),text="HO5\'\'\tH")[[1]] == "HO5\'\'")
1653stopifnot(scan(what=list("foo","foo"),text="HO5\'\tH")[[1]]   == "HO5\'")
1654##
1655## when no sep is given, there does not have to be a separator between
1656## quoted entries; testing here to ensure read.table and scan agree,
1657## but without claiming this particular behavior is needed
1658stopifnot(read.table(                 text="\"A\"\" B \"")$V2   == " B ")
1659stopifnot(scan(what=list("foo","foo"),text="\"A\"\" B \"")[[2]] == " B ")
1660
1661
1662## merge() names when by.y
1663parents <- data.frame(name = c("Sarah", "Max", "Qin", "Lex"),
1664                      sex = c("F", "M", "F", "M"), age = c(41, 43, 36, 51))
1665children <- data.frame(parent = c("Sarah", "Max", "Qin"),
1666                       name = c("Oliver", "Sebastian", "Kai-lee"),
1667                       sex = c("M", "M", "F"), age = c(5,8,7))
1668# merge.data.frame() no longer creating a duplicated col.names
1669(m   <- merge(parents, children, by.x = "name", by.y = "parent"))
1670 m._ <- merge(parents, children, by.x = "name", by.y = "parent", all.x=TRUE)
1671(m_. <- merge(parents, children, by.x = "name", by.y = "parent", all.y=TRUE))
1672 m__ <- merge(parents, children, by.x = "name", by.y = "parent", all = TRUE)
1673## all four gave duplicate column 'name' with a warning in R <= 3.4.x
1674stopifnot(exprs = {
1675    identical(m,   m_.)
1676    identical(m._, m__)
1677    ## not identical(m, m__[-1,]) : row.names differ
1678    identical(names(m), names(m__))
1679    all(m == m__[-1,])
1680    identical(dim(m),   c(3L, 6L))
1681    identical(dim(m__), c(4L, 6L))
1682})
1683
1684
1685## scale(*, <non-numeric>)
1686if(requireNamespace('Matrix', lib.loc=.Library, quietly = TRUE)) {
1687    de <- data.frame(Type = structure(c(1L, 1L, 4L, 1L, 4L, 2L, 2L, 2L, 4L, 1L),
1688				      .Label = paste0("T", 1:4), class = "factor"),
1689		     Subj = structure(c(9L, 5L, 8L, 3L, 3L, 4L, 3L, 6L, 6L, 1L),
1690				      .Label = as.character(1:9), class = "factor"))
1691    show(SM <- xtabs(~ Type + Subj, data = de, sparse=TRUE))
1692    stopifnot(exprs = {
1693	inherits(SM, "sparseMatrix")
1694	all.equal(scale(SM, Matrix::colMeans(SM)),
1695		  scale(SM, Matrix::colMeans(SM, sparse=TRUE)),
1696		  check.attributes=FALSE)
1697    })
1698}
1699## 2nd scale() gave wrong error "length of 'center' must equal [..] columns of 'x'"
1700## in R <= 3.4.x
1701
1702
1703## as.data.frame.matrix() method not eliminating duplicated rownames
1704(m <- rbind(x = 1:3, x = 2:4, z = 0)) # matrix with duplicated rownams
1705rownames(d <- as.data.frame(m)) # --> fixed up to  "x" "x.1" "z"
1706## new feature -- 'make.names = *'  with '*' in non-defaults :
1707dN <- as.data.frame(m, make.names=NA)
1708tools::assertError( dF <- as.data.frame(m, make.names=FALSE) )
1709stopifnot(exprs = {
1710    !anyDuplicated(rownames(d))
1711    identical(colnames(d), paste0("V", 1:3))
1712    ## dN has correct automatic row names:
1713    identical(.row_names_info(dN, 0), .set_row_names(3L))
1714})
1715## as.data.frame(m)  kept the duplicated row names in R 3.4.x
1716
1717
1718## check that sorting preserves names and no other attributes
1719v <- sort(c(1,2,3))
1720names(v) <- letters[1:3]
1721stopifnot(identical(sort(v), v))
1722vv <- sort(c(1,2,3))
1723names(vv) <- names(v)
1724attr(vv, "foo") <- "bar"
1725stopifnot(identical(sort(vv), v))
1726## failed initially in ALTREP
1727
1728
1729## check that "TRUE", "FALSE" work in order, sort.int
1730order(1:3, decreasing = "TRUE")
1731order(1:3, decreasing = "FALSE")
1732sort.int(1:3, decreasing = "TRUE")
1733sort.int(1:3, decreasing = "FALSE")
1734## failed initially in ALTREP
1735
1736## this failed until 3.5.x
1737c1 <- c(1,1,2,2)
1738c2 <- as.Date(c("2010-1-1", "2011-1-1", "2013-1-1", "2012-1-1"))
1739order(c1, c2, decreasing = c(TRUE, FALSE), method="radix")
1740
1741
1742## check sort argument combinations
1743sort(1:3, decreasing = TRUE, na.last = NA)
1744sort(1:3, decreasing = TRUE, na.last = TRUE)
1745sort(1:3, decreasing = TRUE, na.last = FALSE)
1746sort(1:3, decreasing = FALSE, na.last = NA)
1747sort(1:3, decreasing = FALSE, na.last = TRUE)
1748sort(1:3, decreasing = FALSE, na.last = FALSE)
1749
1750## match.arg()s 'choices' evaluation, PR#17401
1751f <- function(x = y) {
1752    y <- c("a", "b")
1753    match.arg(x)
1754}
1755stopifnot(identical(f(), "a"))
1756## failed in R <= 3.4.x
1757
1758
1759## getOption(op, def) -- where 'def' is missing (passed down):
1760getO <- function(op, def) getOption(op, def)
1761stopifnot(is.null(getO("foobar")))
1762## failed for a few days in R-devel, when using MD's proposal of PR#17394,
1763## notably "killing"  parallelMap::getParallelOptions()
1764
1765
1766## Mantel-Haenszel test in "large" case, PR#17383:
1767set.seed(101); n <- 500000
1768aTab <- table(
1769    educ = factor(sample(1:3, replace=TRUE, size=n)),
1770    score= factor(sample(1:5, replace=TRUE, size=n)),
1771    sex  = sample(c("M","F"), replace=TRUE, size=n))
1772(MT <- mantelhaen.test(aTab))
1773stopifnot(all.equal(
1774    lapply(MT[1:3], unname),
1775    list(statistic = 9.285642, parameter = 8, p.value = 0.3187756), tol = 6e-6))
1776## gave integer overflow and error in R <= 3.4.x
1777
1778
1779## check for incorect inlining of named logicals
1780foo <- compiler::cmpfun(function() c("bar" = TRUE),
1781                        options = list(optimize = 3))
1782stopifnot(identical(names(foo()), "bar"))
1783foo <- compiler::cmpfun(function() c("bar" = FALSE),
1784                        options = list(optimize = 3))
1785stopifnot(identical(names(foo()), "bar"))
1786## Failed after changes to use isTRUE/isFALSE instead of identical in r74403.
1787
1788
1789## check that reverse sort is stable
1790x <- sort(c(1, 1, 3))
1791stopifnot(identical(sort.list(x, decreasing=TRUE), as.integer(c(3, 1, 2))))
1792stopifnot(identical(order(x, decreasing=TRUE), as.integer(c(3, 1, 2))))
1793## was incorrect with wrapper optimization (reported by Suharto Anggono)
1794
1795
1796## dump() & dput() where influenced by  "deparse.max.lines" option
1797op <- options(deparse.max.lines=NULL) # here
1798oNam <- "simplify2array" # (base function which is not very small)
1799fn <- get(oNam)
1800ffn <- format(fn)
1801dp.1 <- capture.output(dput(fn))
1802dump(oNam, textConnection("du.1", "w"))
1803stopifnot(length(ffn) > 3, identical(dp.1, ffn), identical(du.1[-1], dp.1))
1804options(deparse.max.lines = 2) ## "truncate heavily"
1805dp.2 <- capture.output(dput(fn))
1806dump(oNam, textConnection("du.2", "w"))
1807stopifnot(identical(dp.2, dp.1),
1808          identical(du.2, du.1))
1809options(op); rm(du.1, du.2) # connections
1810writeLines(tail(dp.2))
1811## dp.2 and du.2  where heavily truncated in R <= 3.4.4, ending  "  ..."
1812
1813
1814## optim() with "trivial bounds"
1815flb <- function(x) { p <- length(x); sum(c(1, rep(4, p-1)) * (x - c(1, x[-p])^2)^2) }
1816o1 <- optim(rep(3, 5), flb)
1817o2 <- optim(rep(3, 5), flb, lower = rep(-Inf, 5))
1818stopifnot(all.equal(o1,o2))
1819## the 2nd optim() call gave a warning and switched to "L-BFGS-B" in R <= 3.5.0
1820
1821
1822## Check that call matching doesn't mutate input
1823cl <- as.call(list(quote(x[0])))
1824cl[[1]][[3]] <- 1
1825v <- .Internal(match.call(function(x) NULL, cl, TRUE, .GlobalEnv))
1826cl[[1]][[3]] <- 2
1827stopifnot(v[[1]][[3]] == 1)
1828## initial patch proposal to reduce duplicating failed on this
1829
1830
1831## simulate.lm(<glm gaussian, non-default-link>), PR#17415
1832set.seed(7); y <- rnorm(n = 1000, mean = 10, sd = sqrt(10))
1833fmglm <- glm(y ~ 1, family = gaussian(link = "log"))
1834dv <- apply(s <- simulate(fmglm, 99, seed=1), 2, var) - var(y)
1835stopifnot(abs(dv) < 1.14, abs(mean(dv)) < .07)
1836## failed in R <= 3.5.0 (had simulated variances ~ 0.1)
1837
1838
1839## unlist() failed for nested lists of empty lists:
1840isLF <- function(x) .Internal(islistfactor(x, recursive=TRUE))
1841ex <- list(x0 = list()
1842         , x1 = list(list())
1843         , x12 = list(list(), list())
1844         , x12. = list(list(), expression(list()))
1845         , x2 = list(list(list(), list())) # <-- Steven Nydick's example
1846         , x212 = list(list(list(), list(list())))
1847         , x222 = list(list(list(list()), list(list())))
1848)
1849(exis <- vapply(ex, isLF, NA))
1850ue <- lapply(ex, unlist)# gave errors in R <= 3.3.x  but not 3.{4.x,5.0}
1851stopifnot(exprs = {
1852    !any(exis)
1853    identical(names(ue), names(ex))
1854    vapply(ue[names(ue) != "x12."], is.null, NA)
1855})
1856
1857
1858## qr.coef(qr(<all 0, w/ colnames>))
1859qx <- qr(x <- matrix(0, 10, 2, dimnames = list(NULL, paste0("x", 1:2))))
1860qc <- qr.coef(qx, x[,1])
1861stopifnot(identical(qc, c(x1 = NA_real_, x2 = NA_real_)))
1862## qr.coef() gave  Error ...: object 'pivotted' not found | in R <= 3.5.0
1863
1864
1865## unlist(<factor-leaves>)
1866x <- list(list(v=factor("a")))
1867y <- list(data.frame(v=factor("a")))
1868x. <- list(list(factor("a")), list(factor(LETTERS[2:4])), factor("lol"))
1869fN <- factor(LETTERS[c(2:4,30)])
1870xN <- list(list(factor("a")), list(list(fN)), L=factor("lol"))
1871stopifnot(exprs = {
1872    .valid.factor(ux <- unlist(x))
1873    identical(ux, unlist(y))
1874    identical(ux, as.factor(c(v="a")))
1875    .valid.factor(ux. <- unlist(x.))
1876    .valid.factor(uxN <- unlist(xN))
1877    identical(levels(ux.), c("a", "B", "C", "D", "lol"))
1878    identical(levels      (uxN), levels(ux.))
1879    identical(as.character(uxN), levels(ux.)[c(1:4,11L,5L)])
1880})
1881## gave invalid factor()s [if at all]
1882
1883
1884## printCoefMat()  w/ unusual arguments
1885cm <- matrix(c(9.2, 2.5, 3.6, 0.00031), 1, 4,
1886            dimnames = list("beta", c("Estimate", "Std.Err", "Z value", "Pr(>z)")))
1887cc <- capture.output(printCoefmat(cm))
1888stopifnot(grepl(" [*]{3}$", cc[2]),
1889          identical(cc, capture.output(
1890                     printCoefmat(cm, right=TRUE))))
1891## gave Error: 'formal argument "right" matched by multiple actual arguments'
1892
1893
1894## print.noquote() w/ unusual argument -- inspite of user error, be forgiving:
1895print(structure("foo bar", class="noquote"), quote=FALSE)
1896## gave Error: 'formal argument "quote" matched by multiple actual arguments'
1897
1898
1899## agrep(".|.", ch, fixed=FALSE)
1900chvec <- c(".BCD", "yz", "AB", "wyz")
1901patt <- "ABC|xyz"
1902stopifnot(identical(c(list(0L[0]), rep(list(1:4), 2)),
1903    lapply(0:2, function(m) agrep(patt, chvec, max.distance=m, fixed=FALSE))
1904))
1905## all three were empty in R <= 3.5.0
1906
1907
1908## str(<invalid>)
1909typeof(nn <- c(0xc4, 0x88, 0xa9, 0x02))
1910cc <- ch <- rawToChar(as.raw(nn))
1911str(ch)# worked already
1912nchar(cc, type="bytes")# 4, but  nchar(cc)  gives  "invalid multibyte string"
1913Encoding(cc) <- "UTF-8" # << makes it invalid for strtrim(.)!
1914as.octmode(as.integer(nn))
1915str(cc)
1916## In R <= 3.5.0, [strtrim() & nchar()] gave invalid multibyte string at '<a9>\002"'
1917
1918
1919## multivariate <empty model> lm():
1920y <- matrix(cos(1:(7*5)), 7,5) # <- multivariate y
1921lms <- list(m0 = lm(y ~ 0), m1 = lm(y ~ 1), m2 = lm(y ~ exp(y[,1]^2)))
1922dcf <- sapply(lms, function(fm) dim(coef(fm)))
1923stopifnot(dcf[1,] == 0:2, dcf[2,] == 5)
1924## coef(lm(y ~ 0)) had 3 instead of 5 columns in R <= 3.5.1
1925proc.time() - .pt; .pt <- proc.time()
1926
1927
1928## confint(<mlm>)
1929n <- 20
1930set.seed(1234)
1931datf <- local({
1932    x1 <- rnorm(n)
1933    x2 <- x1^2 + rnorm(n)
1934    y1 <- 100*x1 + 20*x2 + rnorm(n)
1935    data.frame(x1=x1, x2=x2, y1=y1, y2 = y1 + 10*x1 + 50*x2 + rnorm(n))
1936})
1937fitm <- lm(cbind(y1,y2) ~ x1 + x2, data=datf)
1938zapsmall(CI <- confint(fitm))
1939ciT <- cbind(c(-0.98031,  99.2304, 19.6859, -0.72741, 109.354, 69.4632),
1940             c( 0.00984, 100.179,  20.1709,  0.60374, 110.63,  70.1152))
1941dimnames(ciT) <- dimnames(CI)
1942## also checking confint(*, parm=*) :
1943pL <- list(c(1,3:4), rownames(CI)[c(6,2)], 1)
1944ciL  <- lapply(pL, function(ii) confint(fitm, parm=ii))
1945ciTL <- lapply(pL, function(ii) ciT[ii, , drop=FALSE])
1946stopifnot(exprs = {
1947    all.equal(ciT, CI,  tolerance = 4e-6)
1948    all.equal(ciL, ciTL,tolerance = 8e-6)
1949})
1950## confint(<mlm>) gave an empty matrix in R <= 3.5.1
1951## For an *empty* mlm :
1952mlm0 <- lm(cbind(y1,y2) ~ 0, datf)
1953stopifnot(identical(confint(mlm0),
1954                    matrix(numeric(0), 0L, 2L, dimnames = list(NULL, c("2.5 %", "97.5 %")))))
1955## failed inside vcov.mlm() because summary.lm()$cov.unscaled was NULL
1956
1957## cooks.distance.(<mlm>), rstandard(<mlm>) :
1958fm1 <- lm(y1 ~ x1 + x2, data=datf)
1959fm2 <- lm(y2 ~ x1 + x2, data=datf)
1960stopifnot(exprs = {
1961    all.equal(cooks.distance(fitm),
1962              cbind(y1 = cooks.distance(fm1),
1963                    y2 = cooks.distance(fm2)))
1964    all.equal(rstandard(fitm),
1965              cbind(y1 = rstandard(fm1),
1966                    y2 = rstandard(fm2)))
1967    all.equal(rstudent(fitm),
1968              cbind(y1 = rstudent(fm1),
1969                    y2 = rstudent(fm2)))
1970})
1971## were silently wrong in R <= 3.5.1
1972
1973
1974## kruskal.test(<non-numeric g>), PR#16719
1975data(mtcars)
1976mtcars$type <- rep(letters[1:2], c(16, 16))
1977kruskal.test(mpg ~ type, mtcars)
1978## gave 'Error: all group levels must be finite'
1979
1980
1981## Multivariate lm() with matrix offset, PR#17407
1982ss <- list(s1 = summary(fm1 <- lm(cbind(mpg,qsec) ~ 1, data=mtcars, offset=cbind(wt,wt*2))),
1983           s2 = summary(fm2 <- lm(cbind(mpg,qsec) ~ offset(cbind(wt,wt*2)), data=mtcars)))
1984## drop "call" and "terms" parts which differ; rest must match:
1985ss[] <- lapply(ss, function(s) lapply(s, function(R) R[setdiff(names(R), c("call","terms"))]))
1986stopifnot(all.equal(ss[["s1"]], ss[["s2"]], tolerance = 1e-15))
1987## lm() calls gave error 'number of offsets is 64, should equal 32 ...' in R <= 3.5.1
1988
1989
1990## print.data.frame(<non-small>)
1991USJ   <- USJudgeRatings
1992USJe6 <- USJudgeRatings[rep_len(seq_len(nrow(USJ)), 1e6),]
1993op <- options(max.print=500)
1994system.time(r1 <- print(USJ))
1995system.time(r2 <- print(USJe6))# was > 12 sec in R <= 3.5.1, now typically 0.01
1996                               # because the whole data frame was formatted.
1997## Now the timing ratio between r1 & r2 print()ing is typically in [1,2]
1998system.time(r3 <- print(USJe6, row.names=FALSE))
1999out <- capture.output(print(USJe6, max = 600)) # max > getOption("max.print")
2000stopifnot(exprs = {
2001    identical(r1, USJ  )# print() must return its arg
2002    identical(r2, USJe6)
2003    identical(r3, USJe6)
2004    length(out) == 52
2005    grepl("CALLAHAN", out[51], fixed=TRUE)
2006    identical(2L, grep("omitted", out[51:52], fixed=TRUE))
2007})
2008options(op); rm(USJe6)# reset
2009
2010
2011## hist.default() in rare cases
2012hh <- hist(seq(1e6, 2e6, by=20), plot=FALSE)
2013hd <- hh$density*1e6
2014stopifnot(0.999 <= hd, hd <= 1.001)
2015## in R <= 3.5.1: warning 'In n * h : NAs produced by integer overflow' and then NA's
2016
2017
2018## some things broken by sort.int optimization for sorted integer vectors
2019sort.int(integer(0))  ## would segfault with barrier testing
2020stopifnot(identical(sort.int(NA_integer_), integer(0)))
2021
2022
2023## attribute handling in the fastpass was not quite right
2024x <- sort.int(c(1,2))
2025dim(x) <- 2
2026dimnames(x) <- list(c("a", "b"))
2027stopifnot(! is.null(names(sort.int(x))))
2028
2029## is.unsorted fastpass incorrectly returned TRUE when constant-valued x was sorted descending
2030x <- c(1, 1, 1)
2031xs <- sort(x, decreasing = TRUE)
2032stopifnot(!is.unsorted(xs, strictly = FALSE)) ## is.unsorted should be FALSE
2033y <- as.integer(x)
2034ys <- sort(x, decreasing = TRUE)
2035stopifnot(!is.unsorted(ys, strictly = FALSE))
2036
2037## match() with length one x and POSIXlt table (PR#17459):
2038d <- as.POSIXlt("2018-01-01")
2039match(0, d)
2040## Gave a segfault in R < 3.6.0.
2041proc.time() - .pt; .pt <- proc.time()
2042
2043
2044## as(1L, "double") - PR#17457
2045stopifnot(exprs = {
2046    identical(as(1L,   "double"), 1.) # new
2047    identical(new("double"), double())
2048  ## 1. "double" is quite the same as "numeric" :
2049    local({
2050        i1 <- 1L; as(i1, "numeric") <- pi
2051        i2 <- 1L; as(i2, "double" ) <- pi
2052        identical(i1, i2)
2053    })
2054    validObject(Dbl <- getClass("double"))
2055    validObject(Num <- getClass("numeric"))
2056    c("double", "numeric") %in% extends(Dbl)
2057    setdiff(names(Num@subclasses),
2058            names(Dbl@subclasses) -> dblSub) == "double"
2059    "integer" %in% dblSub
2060  ## 2. These all remain as they were in R <= 3.5.x , the first one important for back-compatibility:
2061    identical(1:2, local({
2062        myN <- setClass("myN", contains="numeric", slots = c(truly = "numeric"))
2063        myN(log(1:2), truly = 1:2) })@truly)
2064    removeClass("myN")
2065    identical(as(1L,  "numeric"), 1L) # << disputable, but hard to change w/o changing myN() behavior
2066    identical(as(TRUE, "double"), 1.)
2067    identical(as(TRUE,"numeric"), 1.)
2068    !is(TRUE, "numeric") # "logical" should _not_ be a subclass of "numeric"
2069    ## We agree these should not change :
2070    typeof(1.0) == "double"  &  typeof(1L) == "integer"
2071    class (1.0) == "numeric" &  class (1L) == "integer"
2072    mode  (1.0) == "numeric" &  mode  (1L) == "numeric"
2073})
2074## as(*, "double") now gives what was promised
2075
2076
2077## next(n) for largish n
2078stopifnot(exprs = {
2079    nextn(214e7 ) == 2^31
2080    nextn(2^32+1) == 4299816960
2081    identical(nextn(NULL), integer())
2082})
2083## nextn(214e7) hang in infinite loop; nextn(<large>) gave NA  in R <= 3.5.1
2084
2085
2086## More strictness in '&&' and '||' :
2087Sys.getenv("_R_CHECK_LENGTH_1_LOGIC2_", unset=NA) -> oEV
2088Sys.setenv("_R_CHECK_LENGTH_1_LOGIC2_" = "warn") # only warn
2089tools::assertWarning(1 && 0:1)
2090Sys.setenv("_R_CHECK_LENGTH_1_LOGIC2_" = TRUE) # => error (when triggered)
2091tools::assertError(0 || 0:1)
2092if(is.na(oEV)) { # (by default)
2093    Sys.unsetenv ("_R_CHECK_LENGTH_1_LOGIC2_")
2094    2 && 0:1 # should not even warn
2095} else Sys.setenv("_R_CHECK_LENGTH_1_LOGIC2_" = oEV)
2096
2097
2098## polym() in "vector" case PR#17474
2099fm <- lm(Petal.Length ~ poly(cbind(Petal.Width, Sepal.Length), 2),
2100         data = iris)
2101p1 <- predict(fm, newdata = data.frame(Petal.Width = 1, Sepal.Length = 1))
2102stopifnot(all.equal(p1, c("1" = 4.70107678)))
2103## predict() calling polym() failed in R <= 3.5.1
2104
2105
2106## sample.int(<fractional>, k, replace=TRUE) :
2107(tt <- table(sample.int(2.9, 1e6, replace=TRUE)))
2108stopifnot(length(tt) == 2)
2109## did "fractionally" sample '3' as well in 3.0.0 <= R <= 3.5.1
2110
2111
2112## lm.influence() for simple regression through 0:
2113x <- 1:7
2114y <- c(1.1, 1.9, 2.8, 4, 4.9, 6.1, 7)
2115f0 <- lm(y ~ 0+x)
2116mi <- lm.influence(f0)
2117stopifnot(identical(dim(cf <- mi$coefficients), c(7L, 1L)),
2118          all.equal(range(cf), c(-0.0042857143, 0.0072527473)))
2119## gave an error for a few days in R-devel
2120
2121
2122## cut(<constant 0>), PR#16802
2123c0 <- cut(rep(0L, 7), breaks = 3)
2124stopifnot(is.factor(c0), length(c0) == 7, length(unique(c0)) == 1)
2125## cut() gave error  _'breaks' are not unique_  in R <= 3.5.1
2126
2127
2128## need to record OutDec in deferred string conversions (reported by
2129## Michael Sannella).
2130op <- options(scipen=-5, OutDec=",")
2131xx <- as.character(123.456)
2132options(op)
2133stopifnot(identical(xx, "1,23456e+02"))
2134
2135
2136## parseRd() and Rd2HTML() with some \Sexpr{} in *.Rd:
2137x <- tools::Rd_db("base")
2138## Now check that \Sexpr{}  "installed" correctly:
2139of <- textConnection("DThtml", "w")
2140tools::Rd2HTML(x$DateTimeClasses.Rd, out = of, stages = "install"); close(of)
2141(iLeap <- grep("leap seconds", DThtml)[[1]])
2142stopifnot(exprs = {
2143        grepl("[0-9]+ days",     DThtml[iLeap+ 1])
2144    any(grepl("20[1-9][0-9]-01", DThtml[iLeap+ 2:4]))
2145})
2146
2147
2148
2149## if( "length > 1" )  buglet in plot.data.frame()
2150Sys.getenv("_R_CHECK_LENGTH_1_CONDITION_", unset=NA) -> oEV
2151Sys.setenv("_R_CHECK_LENGTH_1_CONDITION_" = "true")
2152plot(data.frame(.leap.seconds))
2153if(!is.na(oEV)) Sys.setenv("_R_CHECK_LENGTH_1_CONDITION_" = oEV)
2154## gave Error in ... the condition has length > 1,  in R <= 3.5.1
2155
2156
2157## duplicated(<dataframe with 'f' col>) -- PR#17485
2158d <- data.frame(f=gl(3,5), i=1:3)
2159stopifnot(exprs = {
2160    identical(which(duplicated(d)), c(4:5, 9:10, 14:15))
2161    identical(anyDuplicated(d), 4L)
2162    identical(anyDuplicated(d[1:3,]), 0L)
2163})
2164## gave error from do.call(Map, ..) as Map()'s first arg. is 'f'
2165
2166
2167## print.POSIX[cl]t() - not correctly obeying "max.print" option
2168op <- options(max.print = 50, width = 85)
2169cc <- capture.output(print(dt <- .POSIXct(154e7 + (0:200)*60)))
2170c2 <- capture.output(print(dt, max = 6))
2171writeLines(tail(cc, 4))
2172writeLines(c2)
2173stopifnot(expr = {
2174    grepl("omitted 151 entries", tail(cc, 1))
2175                  !anyDuplicated(tail(cc, 2))
2176    grepl("omitted 195 entries", tail(c2, 1))
2177}); options(op)
2178## the omission had been reported twice because of a typo in R <= 3.5.1
2179
2180
2181## <data.frame>[ <empty>, ] <- v                    should be a no-op and
2182## <data.frame>[ <empty>, <existing column>] <- v   a no-op, too
2183df <- d0 <- data.frame(i=1:6, p=pi)
2184n <- nrow(df)
2185as1NA <- function(x) `is.na<-`(rep_len(unlist(x), 1L), TRUE)
2186for(i in list(FALSE, integer(), -seq_len(n)))
2187  for(value in list(numeric(), 7, "foo", list(1))) {
2188    df[i ,  ] <- value
2189    df[i , 1] <- value # had failed after svn c75474
2190    stopifnot(identical(df, d0))
2191    ## "expand": new column created even for empty <i>; some packages rely on this
2192    df[i, "new"] <- value ## -> produces new column of .. NA
2193    stopifnot(identical(df[,"new"], rep(as1NA(value), n)))
2194    df <- d0
2195  }
2196## gave error in R <= 3.5.1
2197df[7:12,] <- d0 + 1L
2198stopifnot(exprs = {
2199    is.data.frame(df)
2200    identical(dim(df), c(12L, 2L))
2201    identical(df[1:6,], d0)
2202})
2203## had failed after svn c75474
2204
2205
2206## Check that active binding uses primitive quote() and doesn't pick
2207## up `quote` binding on the search path
2208quote <- function(...) stop("shouldn't be called")
2209if (exists("foo", inherits = FALSE)) rm(foo)
2210makeActiveBinding("foo", identity, environment())
2211x <- (foo <- "foo")
2212stopifnot(identical(x, "foo"))
2213rm(quote, foo, x)
2214
2215
2216## .format.zeros() when zero.print is "wide":
2217x <- c(outer(c(1,3,6),10^(-5:0)))
2218(fx <- formatC(x))
2219stopifnot(identical(nchar(fx), rep(c(5L, 6:3, 1L), each=3)))
2220x3 <- round(x, 3)
2221tools::assertWarning(
2222  fz1. <- formatC(x3,          zero.print="< 0.001",   replace.zero=FALSE))# old default
2223 (fz1  <- formatC(x3,          zero.print="< 0.001"))#,replace.zero=TRUE  :  new default
2224 (fzw7 <- formatC(x3, width=7, zero.print="< 0.001"))
2225for(fz in list(fz1, fz1., fzw7)) stopifnot(identical(grepl("<", fz), x3 == 0))
2226## fz1, fzw7 gave error (for 2 bugs) in R <= 3.5.x
2227
2228
2229## Attempting to modify an object in a locked binding could succeed
2230## before signaling an error:
2231foo <- function() {
2232    zero <- 0           ## to fool constant folding
2233    x <- 1 + zero       ## value of 'x' has one reference
2234    lockBinding("x", environment())
2235    tryCatch(x[1] <- 2, ## would modify the value, then signal an error
2236             error = function(e) NULL)
2237    stopifnot(identical(x, 1))
2238}
2239foo()
2240
2241
2242## formalArgs()  should conform to names(formals()) also in looking up fun: PR#17499
2243by <- function(a, b, c) "Bye!" # Overwrites base::by, as an example
2244foo <- function() {
2245  f1 <- function(a, ...) {}
2246  list(nf = names(formals("f1")),
2247       fA = formalArgs   ("f1"))
2248}
2249stopifnot(exprs = {
2250    identical(names(formals("by")), letters[1:3])
2251    identical(formalArgs   ("by") , letters[1:3])
2252    { r <- foo(); identical(r$nf, r$fA) }
2253})
2254## gave "wrong" result and error in R <= 3.5.x
2255
2256
2257
2258## Subassigning multiple new data.frame columns (with specified row), PR#15362, 17504
2259z0 <- z1 <- data.frame(a=1, s=1)
2260z0[2, c("a","r","e")] <- data.frame(a=1, r=8, e=9)
2261z1[2, "r"] <- data.frame(r=8)
2262x <- x0 <- data.frame(a=1:3, s=1:3)
2263x[2, 3:4] <- data.frame(r=8, e=9)
2264stopifnot(exprs = {
2265    identical(z0, data.frame(a = c(1, 1), s = c(1, NA), r = c(NA, 8), e = c(NA, 9)))
2266    identical(z1, data.frame(a = c(1,NA), s = c(1, NA), r = c(NA, 8)))
2267    identical(x, cbind(x0,
2268                       data.frame(r = c(NA, 8, NA), e = c(NA, 9, NA))))
2269})
2270d0 <- d1 <- d2 <- d3 <- d4 <- d5 <- d6 <- d7 <- data.frame(n=1:4)
2271##
2272d0[, 2] <- c2 <- 5:8
2273d0[, 3] <- c3 <- 9:12
2274d1[, 2:3] <- list(c2, c3)
2275d2[  2:3] <- list(c2, c3)
2276d3[TRUE, 2] <- c2 ; d3[TRUE, 3] <- c3
2277d4[TRUE, 2:3] <- list(c2, c3)
2278d5[1:4,  2:3] <- list(c2, c3)
2279d6[TRUE, 1:2] <- list(c2, c3)
2280d7[    , 1:2] <- list(c2, c3)
2281stopifnot(exprs = {
2282    identical(d0, d1)
2283    identical(d0, d2)
2284    identical(d0, d3)
2285    identical(d0, d4)
2286    identical(d0, d5)
2287    ##
2288    identical(d6, d7)
2289    identical(d6, structure(list(n = c2, V2 = c3),
2290                            row.names = c(NA, -4L), class = "data.frame"))
2291})
2292## d4, d5 --> 'Error in `*tmp*`[[j]] : subscript out of bounds'
2293## d6     --> 'Error in x[[j]] <- `*vtmp*` :
2294##				more elements supplied than there are to replace
2295## in R <= 3.5.1
2296
2297
2298## str() now even works with invalid S4  objects:
2299## this needs Matrix loaded to be an S4 generic
2300if(requireNamespace('Matrix', lib.loc = .Library, quietly = TRUE)) {
2301moS <- mo <- findMethods("isSymmetric")
2302attr(mo, "arguments") <- NULL
2303print(validObject(mo, TRUE)) # shows what's wrong
2304tools::assertError(capture.output( mo ))
2305op <- options(warn = 1)# warning:
2306str(mo, max.level = 2)
2307options(op)# revert
2308## in R <= 3.5.x, str() gave error instead of the warning
2309}
2310
2311
2312## seq.default() w/ integer overflow in border cases: -- PR#17497, Suharto Anggono
2313stopifnot(is.integer(iMax <- .Machine$integer.max), iMax == 2^31-1,
2314          is.integer(iM2 <- iMax-1L), # = 2^31 - 2
2315          (t30 <- 1073741824L) == 2^30 ,
2316          is.integer(i3t30 <- c(-t30, 0L, t30)))
2317for(seq in c(seq, seq.int)) # seq() -> seq.default() to behave as seq.int() :
2318  stopifnot(exprs = {
2319    seq(iM2, length=2L) == iM2:(iM2+1L) # overflow warning and NA
2320    seq(iM2, length=3L) == iM2:(iM2+2 ) # Error in if (from == to) ....
2321              seq(-t30, t30, length=3) == i3t30 # overflow warning and NA
2322    ## Next two ok for the "seq.cumsum-patch" (for "seq.double-patch", give "double"):
2323    identical(seq(-t30, t30, length=3L),  i3t30)# Error in if(is.integer(del <- to - from)
2324    identical(seq(-t30, t30, t30)      ,  i3t30)# Error .. invalid '(to-from)/by'+NA warn.
2325  })
2326## each of these gave integer overflows  errors  or  NA's + warning in  R <= 3.5.x
2327stopifnot(identical(7:10, seq.default(7L, along.with = 4:1) ))
2328## errored for almost a day after r76062
2329
2330
2331## seq.int(*, by=<int.>, length = n) for non-integer 'from' or 'to'
2332stopifnot(exprs = {
2333    identical(seq.int(from = 1.5, by = 2, length = 3),
2334              s <- seq(from = 1.5, by = 2, length = 3))
2335    s == c(1.5, 3.5, 5.5)
2336    identical(seq.int(to = -0.1, by = -2, length = 2),
2337              s <- seq(to = -0.1, by = -2, length = 2))
2338    all.equal(s, c(1.9, -0.1))
2339    identical(seq.int(to = pi, by = 0, length = 1), pi)
2340})
2341## returned integer sequences in all R versions <= 3.5.1
2342
2343
2344## Check for modififation of arguments
2345## Issue originally reported by Lukas Stadler
2346x <- 1+0
2347stopifnot(x + (x[] <- 2) == 3)
2348f <- compiler::cmpfun(function(x) { x <- x + 0; x + (x[] <- 2) })
2349stopifnot(f(1) == 3)
2350
2351x <- 1+0
2352stopifnot(log(x, x[] <- 2) == 0)
2353f <- compiler::cmpfun(function(x) { x <- x + 0; log(x, x[] <- 2)})
2354stopifnot(f(1) == 0)
2355
2356f <- function() x + (x[] <<- 2)
2357x <- 1 + 0; stopifnot(f() == 3)
2358fc <- compiler::cmpfun(f)
2359x <- 1 + 0; stopifnot(fc() == 3)
2360
2361f <- function() x[{x[2] <<- 3; 1}] <<- 2
2362fc <- compiler::cmpfun(f)
2363x <- c(1,2); f(); stopifnot(x[2] == 2)
2364x <- c(1,2); fc(); stopifnot(x[2] == 2)
2365
2366x <- 1+0
2367stopifnot(c(x, x[] <- 2)[[1]] == 1)
2368f <- compiler::cmpfun(function(x) { x <- x + 0; c(x, x[] <- 2)})
2369stopifnot(f(1)[[1]] == 1)
2370
2371x <- c(1,2)
2372x[{x[2] <- 3; 1}] <- 2
2373stopifnot(x[2] == 2)
2374f <- compiler::cmpfun(function(a,b) { x <- c(a, b); x[{x[2] <- 3; 1}] <- 2; x})
2375f(1, 2)
2376stopifnot(f(1, 2) == 2)
2377
2378m <- matrix(1:4, 2)
2379i <- (1:2) + 0
2380stopifnot(m[i, {i[] <- 2; 1}][1] == 1)
2381f <- compiler::cmpfun(function(i) { i <- i + 0; m[i, {i[] <- 2; 1}]})
2382stopifnot(f(1:2)[1] == 1)
2383
2384m <- matrix(1:4, 2)
2385eval(compiler::compile(quote(m[1,1])))
2386stopifnot(max(.Internal(named(m)), .Internal(refcnt(m))) == 1)
2387
2388ma <- .Internal(address(m))
2389eval(compiler::compile(quote(m[1,1] <- 2L)))
2390stopifnot(identical(.Internal(address(m)), ma))
2391
2392a <- array(1:8, rep(2, 3))
2393eval(compiler::compile(quote(a[1,1,1])))
2394stopifnot(max(.Internal(named(a)), .Internal(refcnt(a))) == 1)
2395
2396aa <- .Internal(address(a))
2397eval(compiler::compile(quote(a[1,1,1] <- 2L)))
2398stopifnot(identical(.Internal(address(a)), aa))
2399
2400m <- matrix(1:4, 2)
2401i <- (1:2) + 0
2402stopifnot(m[i, {i[] <- 2; 1}][1] == 1)
2403f <- compiler::cmpfun(function(i) { i <- i + 0; m[i, {i[] <- 2; 1}]})
2404stopifnot(f(1:2)[1] == 1)
2405
2406a <- array(1:8, rep(2, 3))
2407i <- (1:2) + 0
2408stopifnot(a[i, {i[] <- 2; 1}, 1][1] == 1)
2409f <- compiler::cmpfun(function(i) { i <- i + 0; a[i, {i[] <- 2; 1}, 1]})
2410stopifnot(f(1:2)[1] == 1)
2411
2412i <- (1:2) + 0
2413stopifnot(a[i, {i[] <- 2; 1}, 1][1] == 1)
2414f <- compiler::cmpfun(function(i) { i <- i + 0; a[1, i, {i[] <- 2; 1}]})
2415stopifnot(f(1:2)[1] == 1)
2416
2417x <- 1 + 0
2418stopifnot(identical(rep(x, {x[] <- 2; 2}), rep(1, 2)))
2419x <- 1 + 0
2420v <- eval(compiler::compile(quote(rep(x, {x[] <- 2; 2}))))
2421stopifnot(identical(v, rep(1, 2)))
2422
2423x <- 1 + 0
2424stopifnot(round(x, {x[] <- 2; 0}) == 1)
2425x <- 1 + 0
2426v <- eval(compiler::compile(quote(round(x, {x[] <- 2; 0}))))
2427stopifnot(v == 1)
2428
2429f <- function() {
2430    x <- numeric(1)
2431    y <- 0
2432    rm("y")
2433    makeActiveBinding("y", function() { x[] <<- 1; 0}, environment())
2434    x + y
2435}
2436stopifnot(f() == 0)
2437stopifnot(compiler::cmpfun(f)() == 0)
2438
2439f <- function(y = {x[] <- 1; 0}) { x <- numeric(1); x + y }
2440stopifnot(f() == 0)
2441stopifnot(compiler::cmpfun(f)() == 0)
2442
2443
2444## This failed under REFCNT:
2445for (i in 1:2) { if (i == 1) { x <- i; rm(i) }}
2446stopifnot(x == 1)
2447
2448
2449## gamma & lgamma should not warn for correct limit cases:
2450stopifnot(exprs = {
2451    lgamma(0:-10) == Inf
2452    gamma(-180.5) == 0
2453    gamma(c(200,Inf)) == Inf
2454    lgamma(c(10^(306:310), Inf)) == Inf
2455})
2456## had  "Warning message:  value out of range in 'lgamma' "  for ever
2457
2458
2459## sub() with non-ASCII replacement failed to set encodings (PR#17509):
2460x <- c("a", "b")
2461x <- sub("a", "\u00e4", x)
2462stopifnot(Encoding(x)[1L] == "UTF-8")
2463x <- sub("b", "\u00f6", x)
2464stopifnot(Encoding(x)[2L] == "UTF-8")
2465## [1] has been "unknown" in R <= 3.5.x
2466
2467
2468## formula(model.frame()) -- R-devel report by Bill Dunlap
2469d <- data.frame(A = log(1:6), B = LETTERS[1:6], C = 1/(1:6), D = letters[6:1], Y = 1:6)
2470m0 <- model.frame(Y ~ A*B, data=d)
2471stopifnot(exprs = {
2472    DF2formula(m0) == (Y ~ A+B) # the previous formula(.) behavior
2473       formula(m0) == (Y ~ A*B)
2474})
2475## formula(.)  gave  Y ~ A + B  in R <= 3.5.x
2476
2477
2478## These used to fail (PR17514) in a NAMED build but not with REFCNT:
2479L <- matrix(list( c(0) ), 2, 1)
2480L[[2]][1] <- 11
2481stopifnot(L[[1]] == 0)
2482L <- matrix(list( c(0) ), 2, 1, byrow = TRUE)
2483L[[2]][1] <- 11
2484stopifnot(L[[1]] == 0)
2485
2486
2487## ar.ols() - PR#17517
2488ar_ols <- ar.ols(lynx)
2489stopifnot(exprs = {
2490    is.list(pa <- predict(ar_ols, n.ahead = 2))# must *not* warn
2491    all.equal(ar_ols$var.pred, 592392.12774) # not a matrix
2492})
2493## .$var.pred had been a 1x1 matrix in R <= 3.5.2
2494
2495
2496## check that parse lines are properly initialized in the parser
2497d <- getParseData(parse(text="{;}", keep.source=TRUE))
2498l <- d[ d[,"token"] == "exprlist", "line1" ]
2499stopifnot(identical(l, 1L))
2500## failed in 3.5 and earlier
2501
2502
2503## check that NA is treated as non-existent file (not file named "NA")
2504tools::assertError  (normalizePath(c(NA_character_,getwd()), mustWork=TRUE))
2505tools::assertWarning(normalizePath(c(NA_character_,getwd()), mustWork=NA))
2506stopifnot(identical (normalizePath(c(NA_character_,getwd()), mustWork=FALSE)[1],
2507                     NA_character_))
2508stopifnot(identical(unname(file.access(NA_character_)), -1L))
2509## NA treated as error
2510tools::assertError(file.edit(NA_character_))
2511tools::assertError(file(NA_character_))
2512
2513
2514## strtoi("") :
2515stopifnot(is.na(strtoi("")),
2516          is.na(strtoi("", 2L)))
2517## was platform dependent [libC strtol()] in R <= 3.5.x
2518
2519
2520## formula.data.frame() thinko at modularization [r75911]:
2521f <- function(df) {
2522    stopifnot(is.data.frame(df))
2523    d <- 4
2524    f2(formula(df))
2525}
2526f2 <- function(form) eval(quote(d), envir = environment(form))
2527rf <- f(data.frame(x=1, f="b")) ## gave error inside f2() in R-devel
2528stopifnot(identical(rf, 4))
2529## as after 75911 a wrong parent.frame() was used.
2530
2531
2532## format(.) when there's no method gives better message:
2533ee <- tryCid(format(.Internal(bodyCode(ls))))
2534stopifnot(exprs = {
2535    conditionCall(ee)[[1]] == quote(format.default)
2536    grepl("no format() method", conditionMessage(ee), fixed=TRUE)
2537})
2538## signalled from long .Internal(...) call + "must be atomic" in R <= 3.5.x
2539
2540
2541## writeLines(readLines(F), F)  -- PR#17528
2542tf <- tempfile("writeL_test")
2543writeLines("1\n2\n3", tf)
2544c123 <- paste(1:3)
2545stopifnot(identical(readLines(tf), c123))
2546writeLines(readLines(tf), tf)
2547stopifnot(identical(readLines(tf), c123))
2548## writeLines had opened the output for writing before readLines() read it
2549
2550
2551## max.col(<empty>)
2552stopifnot(identical(NA_integer_, max.col(matrix(,1,0))))
2553## gave 1 in R <= 3.5.x
2554
2555
2556## model.matrix() should warn on invalid 'contrasts.arg'
2557## suggested by Ben Bolker on R-devel list, Feb 20, 2019
2558data(warpbreaks)
2559   mf1 <- model.matrix(~tension, data=warpbreaks) # default
2560tools::assertWarning(
2561   mf2 <- model.matrix(~tension, data=warpbreaks, contrasts.arg = "contr.sum") )# wrong
2562tools::assertWarning(
2563   mf3 <- model.matrix(~tension, data=warpbreaks, contrasts.arg = contr.sum) )  # wrong
2564   mf4 <- model.matrix(~tension, data=warpbreaks, contrasts.arg = list(tension=contr.sum))
2565stopifnot(exprs = {
2566    identical(mf1, mf2)
2567    identical(mf1, mf3)
2568    ## and mf4 has sum contrasts :
2569    is.matrix(C <- attr(mf4, "contrasts")$tension)
2570    identical(dim(C), 3:2)
2571    all.equal(unname(C), rbind(diag(2), -1))
2572})
2573## gave no warnings but same results in R <= 3.5.0
2574
2575
2576## axTicks() should zap "almost zero" to zero, PR#17534
2577## (caused by non-exact floating point arithmetic -- (platform dependently!)
2578plot(c(-0.1, 0.2), axes=FALSE, ann=FALSE)
2579(a2 <- axTicks(2)) # -0.10 -0.05  0.00  0.05  0.10  0.15  0.20
2580axis(2, at = a2) # was ugly
2581stopifnot(exprs = {
2582    a2[3] == 0 # exactly
2583    all.equal(a2, (-2:4)/20, tol=1e-14) # closely
2584})
2585## a2[3] was 1.38778e-17  on typical platforms in R <= 3.5.x
2586
2587
2588## isSymmetric(<1x1-matrix>) and <0x0 matrix>  with dimnames
2589stopifnot(exprs = {
2590    ! isSymmetric(matrix(0, dimnames = list("A","b"))) # *non*-symmetric dimnames
2591      isSymmetric(matrix(0, dimnames = list("A","b")), check.attributes=FALSE) # dimn. not checked
2592    ## isSymmetric() gave TRUE wrongly in R versions 3.4.0 -- 3.5.x
2593    ! isSymmetric(matrix(1, dimnames = list("A", NULL)))
2594    ! isSymmetric(matrix(1, dimnames = list(NULL, "A")))
2595      isSymmetric(matrix(1, dimnames = list(NULL, "A")), check.attributes=FALSE)
2596      isSymmetric(matrix(1))
2597      isSymmetric(matrix(1,  dimnames = list("a", "a")))
2598      isSymmetric(matrix(1,  dimnames = list(NULL, NULL)))
2599      isSymmetric(matrix(,0,0, dimnames=list(NULL, NULL)))
2600      isSymmetric(matrix(,0,0))
2601})
2602
2603
2604## bxp() did not signal anything about duplicate actual arguments:
2605set.seed(3); bx.p <- boxplot(split(rt(100, 4), gl(5, 20)), plot=FALSE)
2606tools::assertWarning(bxp(bx.p, ylab = "Y LAB", ylab = "two"), verbose=TRUE)
2607w <- tryCatch(bxp(bx.p, ylab = "Y LAB", ylab = "two", xlab = "i", xlab = "INDEX"),
2608              warning = conditionMessage)
2609stopifnot(is.character(w), grepl('ylab = "two"', w), grepl('xlab = "INDEX"', w))
2610
2611
2612## reformulate() bug  PR#17359
2613(form <- reformulate(c("u", "log(x)"), response = "log(y)"))
2614stopifnot(identical(form, log(y) ~ u + log(x)))
2615## had *symbol*  `log(y)`  instead of call in R <= 3.5.1
2616newf <- function(terms, resp)
2617    list(e   = environment(),
2618         form= reformulate(terms, resp))
2619ef <- newf("x", "log(y)")
2620stopifnot( identical(ef$e, environment(ef$form)),
2621	  !identical(ef$e, .GlobalEnv),
2622	  identical(format(ef$form), "log(y) ~ x"))
2623## Back compatibility + deprecation warning:
2624notC <- "Model[no 4]"
2625form <- `Model[no 4]` ~ .
2626f1 <- function(p) reformulate(".", notC)
2627f2 <- function(e) f1(e)
2628stopifnot(exprs = {
2629    identical(form, suppressWarnings(reformulate(".", notC))) # << will STOP working!
2630    identical(form, reformulate(".", as.name(notC)))
2631    identical(form, reformulate(".", paste0("`", notC, "`")))
2632    inherits(tt <- tryCatch(reformulate(".", notC), warning=identity),
2633             "deprecatedWarning")
2634    inherits(tt, "warning")
2635    conditionCall(tt)[[1]] == quote(reformulate)
2636    inherits(t1 <- tryCatch(f1(pi), warning=identity), "deprecatedWarning")
2637    inherits(t2 <- tryCatch(f2(27), warning=identity), "deprecatedWarning")
2638    all.equal(t1, tt) # including call 'reformulate(..)'
2639    all.equal(t2, tt)
2640})
2641writeLines(conditionMessage(tt))
2642
2643
2644## stopifnot() now works *nicely* with expression object (with 'exprs' name):
2645ee <- expression(xpr=all.equal(pi, 3.1415927), 2 < 2, stop("foo!"))
2646te <- tryCid(stopifnot(exprObject = ee))
2647stopifnot(conditionMessage(te) == "2 < 2 is not TRUE")
2648## conditionMessage(te) was  "ee are not all TRUE" in R 3.5.x
2649t2 <- tryCid(stopifnot(exprs = { T }, exprObject = ee))
2650t3 <- tryCid(stopifnot(TRUE, 2 < 3,   exprObject = ee))
2651f <- function(ex) stopifnot(exprObject = ex)
2652t4 <- tryCid(f(ee))
2653stopifnot(grepl("one of 'exprs', 'exprObject' ", conditionMessage(t2)),
2654          conditionMessage(t2) == conditionMessage(t3),
2655          conditionMessage(t4) == conditionMessage(te)
2656          )
2657(function(e) stopifnot(exprObject = e))(expression(1 < 2, 2 <= 2:4))
2658## the latter (with 'exprs = e') gave  Error in eval(exprs) : object 'e' not found
2659
2660
2661##
2662## Empty 'exprs' should work in almost all cases:
2663stopifnot()
2664stopifnot(exprs = {})
2665e0 <- expression()
2666stopifnot(exprObject = e0)
2667do.call(stopifnot, list(exprObject = expression()))
2668do.call(stopifnot, list(exprObject = e0))
2669## the last three (w 'exprs = ')  failed in R 3.5.x
2670
2671
2672## as.matrix.data.frame() w/ character result and logical column, PR#17548
2673cx <- as.character(x <- c(TRUE, NA, FALSE))
2674stopifnot(exprs = {
2675    identical(cx, as.matrix(data.frame(x, y="chr"))[,"x"])
2676    identical(x, as.logical(cx))
2677})
2678
2679
2680## Failed to work after r76382--8:
2681assertErrV(formula("3"))
2682stopifnot(exprs = {
2683    ## New formula(<character>) specs:
2684    ## These give deprecation warnings:
2685    is.list(op <- options(warn = 1))
2686    identical(formula("ran = ~ 1|G"), ~ 1 | G)
2687    identical(formula(c("~", "foo")), ~ foo )
2688    identical(formula("({y ~ x})"), y ~ x)
2689    identical(formula("{ ~ x }"),   ~ x)
2690  TRUE || { ## all these "bugs" not yet in R <= 3.6.0
2691    identical(formula(c("y", "~", "x +    (1 | G)")), y ~ x + (1 | G))
2692    identical(formula(c("y", "~", "x +", "(1 | G)")), y ~ x + (1 | G))
2693  }## not yet
2694    identical(formula(c("~",    "x","+    (1 | G)")), ~x) ## NOT YET:   ~ x + (1 | G))
2695    is.list(options(op))
2696})
2697tools::assertWarning(formula("ran= ~ 1|G"),"deprecatedWarning", verbose=TRUE)
2698tools::assertWarning(formula(c("~", "x")), "deprecatedWarning", verbose=TRUE)
2699tools::assertWarning(formula("({y ~ x})"), "deprecatedWarning", verbose=TRUE)
2700tools::assertWarning(formula("{ ~ x }"),   "deprecatedWarning", verbose=TRUE)
2701
2702
2703## str2expression(<empty>) :
2704stopifnot(identical(str2expression(character()), expression()))
2705
2706
2707## quasi(*, variance = list()) - should not deparse(); PR#17560
2708## like quasipoisson() :
2709devRes <- function(y, mu, wt) { 2 * wt * (y * log(ifelse(y == 0, 1, y/mu)) - (y-mu)) }
2710init <- expression({
2711    if(any(y < 0)) stop("y < 0")
2712    n <- rep.int(1, nobs)
2713    mustart <- y + 0.1
2714})
2715myquasi <- quasi(link = "log",
2716                 variance = list(name = "my quasi Poisson",
2717                     varfun  = function(mu) mu,
2718                     validmu = function(mu) all(is.finite(mu)) && all(mu > 0),
2719                     dev.resids = devRes,
2720                     initialize = init))
2721x  <- runif(100, min=0, max=1)
2722y  <- rpois(100, lambda=1)
2723fq1 <- glm(y ~ x, family = myquasi)
2724fqP <- glm(y ~ x, family = quasipoisson)
2725str(keep <- setdiff(names(fq1), c("family", "call")))
2726identNoE <- function(x,y, ...) identical(x,y, ignore.environment=TRUE, ...)
2727stopifnot(exprs = {
2728    all.equal(fq1[keep], fqP[keep])
2729    ## quasi() failed badly "switch(vtemp, ... EXPR must be a length 1 vector" in R <= 3.6.0
2730    identNoE(quasi(var = mu),        quasi(variance = "mu"))
2731    identNoE(quasi(var = mu(1-mu)),  quasi(variance = "mu(1- mu)"))# both failed in R <= 3.6.0
2732    identNoE(quasi(var = mu^3),      quasi(variance = "mu ^ 3"))   #  2nd failed in R <= 3.6.0
2733    is.character(msg <- tryCmsg(quasi(variance = "log(mu)"))) &&
2734        grepl("variance.*log\\(mu\\).* invalid", msg) ## R <= 3.6.0: 'variance' "NA" is invalid
2735})
2736
2737
2738## rbind.data.frame() should *not* drop NA level of factors -- PR#17562
2739fcts <- function(N=8, k=3) addNA(factor(sample.int(k, N, replace=TRUE), levels=1:k))
2740set.seed(7) # <- leads to some  "0 counts" [more interesting: they are kept]
2741dfa <- data.frame(x=fcts())
2742dfb <- data.frame(x=fcts()) ; rbind(table(dfa), table(dfb))
2743dfy <- data.frame(y=fcts())
2744yN <- c(1:3, NA_character_, 5:8)
2745dfay  <- cbind(dfa, dfy)
2746dfby  <- cbind(dfa, data.frame(y = yN, stringsAsFactors = TRUE))
2747dfcy  <- dfa; dfcy$y <- yN # y: a <char> column
2748## dNay := drop unused levels from dfay incl NA
2749dNay <- dfay; dNay[] <- lapply(dfay, factor)
2750str(dfay) # both (x, y) have NA level
2751str(dfby) # (x: yes / y: no) NA level
2752str(dNay) # both: no NA level
2753stopifnot(exprs = { ## "trivial" (non rbind-related) assertions :
2754    identical(levels(dfa$x), c(1:3, NA_character_) -> full_lev)
2755    identical(levels(dfb$x),  full_lev)
2756    identical(levels(dfay$x), full_lev) # cbind() does work
2757    identical(levels(dfay$y), full_lev)
2758    identical(levels(dfby$x), full_lev)
2759    is.character(dfcy$y)
2760	   anyNA(dfcy$y)
2761    identical(levels(dfby$y), as.character((1:8)[-4]) -> levN) # no NA levels
2762    identical(lapply(dNay, levels),
2763              list(x = c("2","3"), y = levN[1:3])) # no NA levels
2764})
2765dfaby <- rbind(dfay, dfby)
2766dNaby <- rbind(dNay, dfby)
2767dfacy <- rbind(dfay, dfcy)
2768dfcay <- rbind(dfcy, dfay) # 1st arg col. is char => rbind() keeps char
2769stopifnot(exprs = {
2770    identical(levels(rbind(dfa, dfb)$x), full_lev) # <== not in  R <= 3.6.0
2771    identical(levels(dfaby$x),           full_lev)
2772    identical(levels(dfaby$y),                 yN) # failed a while
2773    identical(levels(dNaby$y),               levN) #  (ditto)
2774    identical(dfacy, dfaby)
2775    is.character(dfcay$y)
2776	   anyNA(dfcay$y)
2777    identical(dfacy$x, dfcay$x)
2778    identical(lapply(rbind(dfby, dfay), levels),
2779              list(x = full_lev, y = c(levN, NA)))
2780    identical(lapply(rbind(dfay, dfby, factor.exclude = NA), levels),
2781              list(x = as.character(1:3), y = levN))
2782    identical(lapply(rbind(dfay, dfby, factor.exclude=NULL), levels),
2783	      list(x = full_lev, y = yN))
2784})
2785
2786## rbind.data.frame() should work in all cases with "matrix-columns":
2787m <- matrix(1:12, 3) ## m.N := [m]atrix with (row)[N]ames :
2788m.N <- m ; rownames(m.N) <- letters [1:3]
2789## data frames with these matrices as *column*s:
2790dfm   <- data.frame(c = 1:3, m = I(m))
2791dfm.N <- data.frame(c = 1:3, m = I(m.N))
2792(mNm <- rbind(m.N, m))
2793dfmmN <- rbind(dfm, dfm.N)
2794dfmNm <- rbind(dfm.N, dfm)
2795stopifnot(exprs = {
2796    identical(     dim(dfmNm), c(6L, 2L))
2797    identical(dimnames(dfmNm), list(c(letters[1:3],1:3), c("c","m")))
2798    is.matrix(m. <- dfmNm[,"m"])
2799    identical(dim(m.), c(6L, 4L))
2800    identical(dfmNm, dfmmN[c(4:6, 1:3), ])
2801    identical(unname(mNm), unname(m.))
2802})
2803## The last rbind() had failed since at least R 2.0.0
2804
2805
2806## as.data.frame.array(<1D array>) -- PR#17570
2807str(x2 <- as.data.frame(array(1:2)))
2808stopifnot(identical(x2[[1]], 1:2))
2809## still was "array" in R <= 3.6.0
2810
2811
2812## vcov(<quasi>, dispersion = *) -- PR#17571
2813counts <- c(18,17,15,20,10,20,25,13,12)
2814treatment <- gl(3,3)
2815outcome <- gl(3,1,9)
2816## Poisson and Quasipoisson
2817 poisfit <- glm(counts ~ outcome + treatment, family = poisson())
2818qpoisfit <- glm(counts ~ outcome + treatment, family = quasipoisson())
2819spois     <- summary( poisfit)
2820sqpois    <- summary(qpoisfit)
2821sqpois.d1 <- summary(qpoisfit, dispersion=1)
2822SE1 <- sqrt(diag(V <- vcov(poisfit)))
2823(noLdbl <- (.Machine$sizeof.longdouble <= 8)) ## TRUE when --disable-long-double
2824stopifnot(exprs = { ## Same variances and same as V
2825    all.equal(vcov(spois), V)
2826    all.equal(vcov(qpoisfit, dispersion=1), V) ## << was wrong
2827    all.equal(vcov(sqpois.d1), V)
2828    all.equal(spois    $coefficients[,"Std. Error"], SE1)
2829    all.equal(sqpois.d1$coefficients[,"Std. Error"], SE1)
2830    all.equal(sqpois   $coefficients[,"Std. Error"],
2831              sqrt(sqpois$dispersion) * SE1)
2832})
2833## vcov(. , dispersion=*) was wrong on R versions 3.5.0 -- 3.6.0
2834proc.time() - .pt; .pt <- proc.time()
2835
2836
2837## runmed(<x_with_NA>, "Turlach") still seg.faults in 3.6.0 {reported by Hilmar Berger}
2838dd1 <- c(rep(NaN,82), rep(-1, 144), rep(1, 74))
2839xT1 <-  runmed(dd1, 21, algorithm="T", print.level=1)# gave seg.fault
2840xS1 <-  runmed(dd1, 21, algorithm="S", print.level=1)
2841if(FALSE)
2842cbind(dd1, xT1, xS1)
2843nN <- !is.na(xT1)
2844stopifnot(xT1[nN] == c(rep(-1, 154), rep(1, 74)))
2845dd2 <- c(rep(-1, 144), rep(1, 74), rep(NaN,82))
2846xS2 <- runmed(dd2, 21, algorithm = "Stuetzle", print.level=1)
2847xT2 <- runmed(dd2, 21, algorithm = "Turlach" , print.level=1)
2848if(FALSE)
2849cbind(dd2, xS2, xT2) # here, "St" and "Tu" are "the same"
2850nN <- !is.na(xT2)
2851stopifnot(exprs = { ## both NA|NaN and non-NA are the same:
2852    identical(xT2[nN], xS2[nN])
2853    identical(is.na(xS2) , !nN)
2854    { i <- 1:(144+74); xT2[i] == dd2[i] }
2855})
2856## close to *minimal* repr.example:
2857x5 <- c(NA,NA, 1:3/4)
2858rS <- runmed(x5, k= 3, algorithm = "St", print.level=3)
2859rT <- runmed(x5, k= 3, algorithm = "Tu", print.level=3)
2860stopifnot(exprs = {
2861    identical(rS, rT)
2862    rT == c(1,1,1:3)/4
2863})
2864## a bit larger:
2865x14 <- c(NA,NA,NA,NA, 1:10/4)
2866rS14 <- runmed(x14, k = 7, algorithm="S", print.level=2)
2867rT14 <- runmed(x14, k = 7, algorithm="T", print.level=2)
2868## cbind(x14, rT14, rS14)
2869(naActs <- eval(formals(runmed)$na.action)); names(naActs) <- naActs
2870allT14 <- lapply(naActs, function(naA)
2871    tryCatch(runmed(x14, k = 7, algorithm="T", na.action=naA, print.level=2),
2872             error=identity, warning=identity))
2873rTo14 <- runmed(na.omit(x14), k=7, algorithm="T")
2874stopifnot(exprs = {
2875    identical(  rT14, rS14)
2876    identical(c(rT14), c(NaN,NaN, .5, .5, .5, .75, x14[-(1:6)]))
2877    identical(  rT14, allT14$"+Big_alternate")
2878    (allT14$"-Big_alternate" >= rT14)[-(1:2)] # slightly surprisingly
2879    identical(allT14$na.omit[-(1:4)], c(rTo14))
2880    inherits(Tfail <- allT14$fail, "error")
2881    !englishMsgs || grepl("^runmed\\(.*: .*NA.*x\\[1\\]", Tfail$message)
2882})
2883
2884
2885## conformMethod()  "&& logic" bug, by Henrik Bengtsson on R-devel list, 2019-06-22
2886setClass("tilingFSet", slots = c(x = "numeric"))
2887if(!is.null(getGeneric("oligoFn"))) removeGeneric("oligoFn")
2888setGeneric("oligoFn",
2889           function(object, subset, target, value) { standardGeneric("oligoFn") })
2890Sys.setenv("_R_CHECK_LENGTH_1_LOGIC2_" = "true")
2891if(getRversion() <= "3.6")## to run this with R 3.6.0, 3.5.3, ..
2892    Sys.unsetenv("_R_CHECK_LENGTH_1_LOGIC2_")
2893setMethod("oligoFn", signature(object = "tilingFSet", value="array"),	## Method _1_
2894          function(object, value) { list(object=object, value=value) })
2895setMethod("oligoFn", signature(object = "matrix", target="array"),	## Method _2_
2896          function(object, target) list(object=object, target=target))
2897setMethod("oligoFn", signature(object = "matrix", subset="integer"),	## Method _3_
2898          function(object, subset) list(object=object, subset=subset))	#   *no* Note
2899setMethod("oligoFn", signature(object = "matrix"),			## Method _4_
2900          function(object) list(object=object))				#   *no* Note
2901setMethod("oligoFn", signature(subset = "integer"),			## Method _5_
2902          function(subset) list(subset=subset))
2903setMethod("oligoFn", signature(target = "matrix"),			## Method _6_
2904          function(target) list(target=target))
2905setMethod("oligoFn", signature(value = "array"),			## Method _7_
2906          function(value) list(value=value))
2907setMethod("oligoFn", signature(subset = "integer", target = "matrix"),  ## Method _8_
2908          function(subset, target) list(subset=subset, target=target))
2909setMethod("oligoFn", signature(subset = "integer", value = "array"),	## Method _9_
2910          function(subset, value) list(subset=subset, value=value))
2911setMethod("oligoFn", signature(target = "matrix", value = "array"),	## Method _10_
2912          function(target, value) list(target=target, value=value))
2913##
2914showMethods("oligoFn", include=TRUE) # F.Y.I.:  in R 3.6.0 and earlier: contains "ANY" everywhere
2915##=========            ------------
2916stopifnot(exprs = {
2917    is.function(mm <- getMethod("oligoFn",
2918                                signature(object="tilingFSet",
2919                                          subset="missing", target="missing",
2920                                          value="array")))
2921    inherits(mm, "MethodDefinition")
2922    identical(
2923        sort(names(getMethodsForDispatch(oligoFn))) # sort(.) the same for "all" locales
2924        ## Now,  "ANY" only appear "at the end" .. otherwise have "missing"
2925      , c("matrix#ANY#ANY#ANY",
2926          "matrix#integer#ANY#ANY",
2927          "matrix#missing#array#ANY",
2928          "missing#integer#ANY#ANY",
2929          "missing#integer#matrix#ANY",
2930          "missing#integer#missing#array",
2931          "missing#missing#matrix#ANY",
2932          "missing#missing#matrix#array",
2933          "missing#missing#missing#array",
2934          "tilingFSet#missing#missing#array"))
2935})
2936## Testing all 10 methods:
2937r1 <- oligoFn(object=new("tilingFSet"), value=array(2))
2938r2 <- oligoFn(object=diag(2),          target=array(42))
2939## These 2 work fine in all versions of R: Here the "ANY" remain at the end:
2940r3 <- oligoFn(object=diag(2),          subset=1:3)
2941r4 <- oligoFn(object=diag(2))
2942## All these do *not* specify 'object' --> Error in R <= 3.6.x {argument ... is missing}
2943r5 <- oligoFn(subset = 1:5)
2944r6 <- oligoFn(target = cbind(7))
2945r7 <- oligoFn(value = array(47))
2946r8 <- oligoFn(subset = -1:1, target = diag(3))
2947r9 <- oligoFn(subset = 2:6,  value = array(7))
2948r10<- oligoFn(target = cbind(1,2), value = array(1,1:3))
2949## in R <= 3.6.0, e.g., the first  setMethod(..)  gave
2950## Error in omittedSig && (signature[omittedSig] != "missing") :
2951##   'length(x) = 4 > 1' in coercion to 'logical(1)'
2952
2953
2954## apply(., MARGIN) when MARGIN is outside length(dim(.)):
2955a <- tryCid(apply(diag(3), 2:3, mean))
2956stopifnot(exprs = {
2957    inherits(a, "error")
2958    conditionCall(a)[[1]] == quote(`apply`)
2959    !englishMsgs || !grepl("missing", (Msg <- conditionMessage(a)), fixed=TRUE)
2960    !englishMsgs || grepl("MARGIN", Msg, fixed=TRUE)
2961})
2962
2963
2964## cbind() of data frames with no columns lost names -- PR#17584
2965stopifnot(identical(names(cbind(data.frame())),
2966                    character()))
2967stopifnot(identical(names(cbind(data.frame(), data.frame())),
2968                    character()))
2969## names() came out as NULL instead of character().
2970
2971
2972## NUL inserted incorrectly in adist trafos attribute -- PR#17579
2973s <- c("kitten", "sitting", "hi")
2974ad <- adist(s, counts = TRUE)
2975adc <- attr(ad, "counts")
2976adt <- attr(ad, "trafos")
2977## Follow analysis in the bug report: in the diagonal, we should have
2978## only matches for each character in the given string.
2979stopifnot(exprs = {
2980    nchar(diag(adt)) == nchar(s)
2981    ## The del/ins/sub counts should agree with the numbers of D/I/S
2982    ## occurrences in the trafos.
2983    nchar(gsub("[^D]", "", adt)) == adc[, , "del"]
2984    nchar(gsub("[^I]", "", adt)) == adc[, , "ins"]
2985    nchar(gsub("[^S]", "", adt)) == adc[, , "sub"]
2986})
2987
2988## list2env preserves values semantics
2989v <- list(x=c(1)) # << subtlety!
2990e <- list2env(v)
2991with(e, x[[1]] <- 42)
2992v
2993stopifnot(identical(v$x,1))
2994
2995
2996## misleading error message when coercing language object to atomic, etc:
2997e <- tryCid(as.double(quote(foo(1))))
2998stopifnot(inherits(e, "error"), grepl("'language'", e$message, fixed=TRUE))
2999## had 'pairlist' in R <= 3.6.1
3000
3001
3002## print(ls.str(<environment with error object with "missing" in message text>))
3003msg <- "arguments in the signature are missing"
3004e1 <- new.env(hash=FALSE)
3005e1$Err <- structure(list(message = msg, call = quote(foo(bar))),
3006                    class = c("simpleError", "error", "condition"))
3007writeLines(prE <- capture.output(ls.str(e1)))
3008## was "Err: <missing>" in R <= 3.6.1
3009stopifnot(exprs = { length(prE) >= 3
3010    grepl("List of 2", prE[[1]], fixed=TRUE)
3011    grepl(msg,         prE[[2]], fixed=TRUE)
3012    grepl("call.* foo\\(bar\\)", prE[[3]])
3013})
3014
3015
3016## format(x, scientific = FALSE)  for large x
3017xMAX <- .Machine$double.xmax
3018ch <- format(xMAX, scientific = 400) # << scientific as 'scipen'
3019op <- options(digits=1, scipen = 303)
3020co <- capture.output(cat(xMAX))
3021options(op)# back to normal
3022stopifnot(exprs = {
3023    nchar(ch) == 309
3024    identical(ch, co)
3025    ch == format(xMAX, scientific=FALSE)
3026})## format(*, scientific=FALSE) was "not obeyed" in R < 4.0.0
3027
3028
3029## format(<symbol>) aka format(<name>) :
3030for(ch in c("foo", "bar", "1", "a:b", "B space A", "`ABC", "'CBA"))
3031    stopifnot(identical(ch, format(as.symbol(ch))))
3032## gave  'Found no format() method for class "name"' in R <= 3.6.x
3033
3034
3035## x %% +- Inf -- PR#17611  //  also  %/%  for "large" args
3036for(x in list(0:3, c(0, 0.5+0:2))) {
3037    xp <- x[x != 0] # x "positive"
3038    for(L in c(2^(2:9), 1000^(1:7), Inf))
3039        stopifnot(exprs = {
3040            ## ----------------- %% -------------
3041            ## same signs :
3042               x  %%  L ==  x
3043             (-x) %% -L == -x
3044            ## opposite signs, x > 0 :
3045            (-xp) %%  L == L-xp
3046              xp  %% -L == xp-L
3047            ## ----------------- %/% ------------
3048              x  %/%  L == pmin(0, sign(x))
3049            (-x) %/% -L == x  %/%  L
3050            (-x) %/%  L == pmin(0, sign(-x))
3051              x  %/% -L == (-x) %/% L
3052              ## L . x :
3053              L %/%  xp == (-L) %/% -xp
3054              L %/% -xp == (-L) %/%  xp
3055        })
3056    stopifnot(exprs = {
3057        Inf %/%   x == sign( x+(x==0))*Inf
3058        Inf %/% -xp == -Inf
3059    })
3060}
3061## these all returned  NaN  when L == Inf  in R <= 3.6.1
3062##
3063## Further - very basics and some large (working "since ever"):
3064L <- 1e111 * c(-1,1)
3065stopifnot(exprs = {
3066    L %%  L == 0  # failed for a few days in R-devel
3067    L %% -L == 0
3068    -6:17 %%  3L == 0:2
3069    -5:15 %% -3L == -2:0
3070    is.finite(x <- 2^(1:1022))
3071    x %% (x.2 <- x/2) == 0
3072    x %/% 2 == x.2
3073    x[1:52] %% 3 == 2:1
3074   -x[1:52] %% 3 == 1:2
3075}) # larger x suffer from cancellation (well, warning too early now):
3076(iCrit <- ## depends on the presence and version of "long double":
3077    if(noLdbl)
3078        50:55
3079    else if(is.integer(digLd <- .Machine$longdouble.digits) && digLd == 64)
3080        60:68
3081    else if(is.integer(digLd) && digLd == 113) ## aarch64 {PR#17718}
3082        110:118
3083    else 250:258 # "wild guess" should always work
3084)
3085tools::assertWarning(x[iCrit] %% 3, verbose=TRUE)
3086
3087
3088## Hilmar Berger's on R-devel list: 'data.frame() == NULL' etc
3089d0. <- data.frame(a = numeric(0)) # zero length data.frame [ 0 x 1 ]
3090d0  <- unname(d0.) # zero length data.frame __without names__
3091d3   <- data.frame(a=1:3) # non-empty data.frame
3092d30. <- d3[,FALSE] # <3 x 0>
3093d30  <- unname(d30.)
3094for(DF in list(d0., d0, d30., d30))
3095    for(R in list(1, NULL, logical(0)))
3096	stopifnot(exprs = {
3097	    is.logical(r <- DF == R)
3098	    is.matrix(r) ## ~~~~~~~
3099	    length(r) == 0
3100	    dim(r) <= dim(DF) # sometimes r is <0 x 0> when DF is not
3101	})
3102## many of these '==' calls failed in R <= 3.6.x
3103
3104
3105## Can selectively suppress warnings
3106w <- function(class) {
3107    w <- simpleWarning("warned")
3108    w <- structure(w, class = c(class, class(w)))
3109    warning(w)
3110}
3111catch <- function(expr) tryCatch({ expr; FALSE }, warning = function(...) TRUE)
3112stopifnot(! catch(suppressWarnings(w("foo"))))
3113stopifnot(! catch(suppressWarnings(w("foo"), classes = c("bar", "foo"))))
3114stopifnot(  catch(suppressWarnings(w("foo"), classes = c("bar", "baz"))))
3115rm(w, catch)
3116
3117
3118## Can selectively suppress messages
3119m <- function(class) {
3120    m <- simpleMessage("notified")
3121    m <- structure(m, class = c(class, class(m)))
3122    message(m)
3123}
3124catch <- function(expr) tryCatch({ expr; FALSE }, message = function(...) TRUE)
3125stopifnot(! catch(suppressMessages(m("foo"))))
3126stopifnot(! catch(suppressMessages(m("foo"), classes = c("bar", "foo"))))
3127stopifnot(  catch(suppressMessages(m("foo"), classes = c("bar", "baz"))))
3128rm(m, catch)
3129
3130
3131## grepl(<NA>, ...)
3132N <- grepl(NA_character_, "something")
3133stopifnot(is.na(N), is.logical(N))
3134## gave integer instead of logical in R <= 3.6.1
3135
3136
3137## options(warn=1e11) leading to infinite loop -> "C Stack ..." error
3138tools::assertError(options(warn = 1+.Machine$integer.max))
3139## "worked" and gave problems later in R <= 3.6.1
3140
3141
3142## PR#17628
3143df <- data.frame(x = 1, y = 2); class(df$y) <- "object_size"
3144df ## --> print.data.frame(*, digits=NULL)' -- error in R <= 3.6.1
3145format(object.size(pi), digits=NULL)
3146## error in R <= 3.6.1
3147
3148## PR#15522
3149pos <- barplot(1:2, space=c(9, 1),
3150    ylim=c(0, 21), xlim=c(0, 11), horiz=TRUE,
3151    plot=FALSE)
3152stopifnot(all.equal(pos, cbind(c(9.5, 11.5))))
3153## bar spacing was wrong in R <= 3.6.1
3154
3155## methods(class = <{length > 1}>)  giving many non-helpful warnings
3156tools::assertWarning(mc <- methods(class = class(ordered(4:1))), verbose=TRUE)
3157                                        # class = ".S3methods",
3158stopifnot(is.character(mc), inherits(mc, "MethodsFunction"),
3159          is.data.frame(attr(mc,"info")))
3160## warns once only, in R >= 3.6.2
3161
3162
3163## PR#17580 -- using max.lines, "truncated"
3164op <- options(error = expression(NULL)) # {careful! : errors do *NOT* stop}
3165is.t.back <- function(x) is.pairlist(x) && all(vapply(x, is.character, NA))
3166f <- function(...) stop(deparse(substitute(...)))
3167g <- function(...) f(...)
3168do.call(g, mtcars)
3169tb. <- .traceback()
3170traceback(tb1 <- .traceback(max.lines=1))# prints with '...' as it's truncated
3171stopifnot(exprs = {
3172    is.t.back(tb.)
3173    is.t.back(tb1)
3174    length(tb.) == length(tb1)
3175    vapply(tb1, length, 0L) == 1
3176    length(tb.[[3]]) > 20
3177})
3178f <- function() options(warn = 1+.Machine$integer.max)
3179do.call(g, mtcars)
3180tb0 <- .traceback()
3181traceback(tb3  <- .traceback(max.lines = 3))
3182traceback(tb00 <- .traceback(max.lines = 0))
3183options(op)# revert to normal
3184stopifnot(exprs = {
3185    is.t.back(tb0)
3186    is.t.back(tb3)
3187    is.t.back(tb00)
3188    vapply(tb0, function(.) is.null(attributes(.)), NA)
3189    length(tb0) == length(tb3)
3190    vapply(tb3 , length, 0L) <= 3
3191    vapply(tb00, length, 0L) == 0L
3192    identical(lapply(tb3, attributes),
3193              list(list(truncated = TRUE), NULL))
3194    identical(lapply(tb00, attributes),
3195              rep(list(list(truncated = TRUE)), 2))
3196})
3197f <- function(...) .traceback(2, max.lines=1)
3198g(
3199  'hello hello hello hello hello hello hello hello hello hello hello',
3200  'world world world world world world world world world world world'
3201) -> tb2n1
3202stopifnot(is.character(t1 <- tb2n1[[1]]), length(t1) == 1L, attr(t1, "truncated"))
3203## partly not possible in R < 4.0.0; always deparsed in full
3204
3205
3206## PR#13624 : get_all_vars(*, <matrix>):
3207ok_get_all_vars <- function(form,d) { ## get_all_vars() :<=> model_frame() apart from "terms"
3208    mf <- if(missing(d)) model.frame(form) else model.frame(form,d)
3209    attr(mf, "terms") <- NULL
3210    identical(mf,
3211              if(missing(d)) get_all_vars(form) else get_all_vars(form,d))
3212}
3213M <- .Date(matrix(1:15, 5,3)) # has class to be kept
3214n <- 26:30
3215T <- TRUE
3216m <- 2:7
3217stopifnot(exprs = { is.matrix(M) ; dim(M) == c(5,3)
3218    ok_get_all_vars(~ M)
3219    ok_get_all_vars(~M+n)
3220    ok_get_all_vars(~ X ,               list(X=  M))
3221    ok_get_all_vars(~z+X,               list(X=  M,  z=n))
3222    ok_get_all_vars(~z+X,               list(X=I(M), z=n))
3223    ok_get_all_vars(~z+X,    data.frame(     X=I(M), z=n))
3224    ok_get_all_vars(~z+X,    data.frame(list(X=I(M), z=n)))
3225    ok_get_all_vars(~z+X, as.data.frame(list(X=I(M), z=n)))
3226    lengths(d <- get_all_vars(~ n + T, "2n" = 2*n)) == 5L
3227    identical(d[,"T"], rep.int(TRUE, 5))
3228    ## recycling works when commensurate:
3229    lengths(d6 <- get_all_vars(~ m + T, one=1, "2 s"=1:2, "3's"=3:1, `f 3` = gl(3,2))) == 6
3230    identical(colnames(d6), c("m", "T", "one", "2 s", "3's", "f 3"))
3231})
3232## all but the first 4 cases worked already in R <= 3.6.1
3233
3234
3235## two-arg Rd macros (PR#17627)
3236parse_Rd_txt <- function(ch) tools::parse_Rd(textConnection(ch), fragment = TRUE)
3237rd1 <- parse_Rd_txt(t1 <- "\\if{html}{\\out{<hr>}}")
3238rd2 <- parse_Rd_txt(t2 <- "\\href{https://www.r-project.org}{some text}")
3239(tx1 <- paste(as.character(rd1), collapse = ""))
3240(tx2 <- paste(as.character(rd2), collapse = ""))
3241stopifnot(exprs = {
3242    identical(paste0(t1,"\n"), tx1)
3243    identical(paste0(t2,"\n"), tx2)
3244})
3245## had duplicated braces in R < 4.0.0
3246
3247
3248## power.t.test() failure for very small (unreasonable) n;  R-devel m.list Oct.4, 2019
3249(ptt0 <- power.t.test(delta=10,  sd=1,       power=0.9 , sig.level=0.05, tol = 1e-8))
3250(ptt1 <- power.t.test(delta=0.6, sd=0.00001, power=0.9 , sig.level=0.05))
3251(ptt2 <- power.t.test(delta=2,   sd = 1e-8,  power=0.99, sig.level=0.01))
3252stopifnot(exprs = {
3253    all.equal(0.9, power.t.test(delta=10, sd=1, n = ptt0 $ n)$power)
3254    all.equal(ptt1$n, 1.00428,   tol = 1e-5)
3255    all.equal(ptt2$n, 1.1215733, tol = 1e-5)
3256})
3257## when uniroot() was trying n < 1, the code failed previously (in 2nd and 3rd case)
3258
3259
3260## improved error message from contour():
3261tt <- tryCid(contour(volcano, levels = c(20*c(4:6, -Inf, 8:10))))
3262print(tt)
3263## The rest of this message is OS-dependent: gcc 5.x on Solaris has '= -Inf'
3264## others have " = -inf"
3265stopifnot(inherits(tt, "error"), grepl("non-finite level.*\\[4\\]", tt$message))
3266## had "invalid NA contour values"
3267
3268
3269## get_all_vars() when some variables are data frames - PR#14905
3270x <- (1:10)/10
3271Y <- data.frame(A = 2^x, B = pi*x)
3272gav <- get_all_vars(Y[,1] ~ x)
3273stopifnot(exprs = {
3274    is.data.frame(gav)
3275    ncol(gav) == 3
3276    identical(gav, cbind(Y, x))
3277    identical(get_all_vars(x ~ Y), cbind(x, Y))
3278})
3279## the last were wrong in R <= 3.6.1
3280
3281
3282## get all arguments from matched argument list; failed in R <= 4.0.0
3283y <- list()
3284stopifnot(identical(attr(`attr<-`(y, value = 1, "A"), "A"), 1))
3285y <- structure(list(), AA = 1)
3286stopifnot(is.null(attr(y, exact = TRUE, "A")))
3287
3288
3289## 1) A matrix is an array, too:
3290stopifnot( vapply(1:9, function(N) inherits(array(pi, dim = 1:N), "array"), NA) )
3291## was false for N=2 in R < 4.0.0
3292##
3293## 2) Matrix must dispatch for array methods, too :
3294foo <- function(x) UseMethod("foo")
3295foo.array <- function(x) "made in foo.array()"
3296stopifnot(
3297    vapply(1:9, function(N) foo(array(pi, dim = 1:N)), "chr") == foo.array())
3298## foo(array(*)) gave error for N=2 in R < 4.0.0
3299
3300
3301## PR#17659: Some *.colors() producers have appended (alpha=1) info even by default
3302fnms <- c(apropos("[.]colors$"), "rainbow") # 8 x "<foo>.colors" + rainbow
3303for(fn in fnms) {
3304    Fn <- get(fn, mode="function")
3305    cat(sprintf("%14s(n), n = 1,2,3 : ", fn))
3306    for(n in 1:3)
3307        stopifnot(length(cc <- Fn(n)) == n,
3308                  nchar(cc) == 1L+6L, # just RGB, no alpha
3309                  identical(cc, Fn(n, alpha=NULL)))
3310    cat("[Ok]\n")
3311}
3312## in R <= 3.6.x, four of these functions gave extra alpha=1 info (appended "FF")
3313
3314
3315## Generalized head(x, n) and tail() methods - for length(n) > 1 and arbitrary array x
3316## PR#17652
3317## -------- pkg glmmTMB uses head(.) on calls quite a bit
3318cForm <- quote(some ~ really + quite + longish + but:still:not:very:long *
3319                   (formula | reality / extreme:cases:you:never:think:of))
3320fL <- eval(cForm)
3321length(fRHS <- fL[[3]])
3322cLong <- quote(fun_with_many_args(1,2,3, 4,5,6, 7,8,9))
3323a1 <- structure(array(1:7,  7  ), class = "foo")
3324a3 <- structure(array(1:24, 2:4), class = "foo")
3325stopifnot(exprs = {
3326    ## these all work as previously
3327    head(cForm,1) == `~`()
3328    head(cForm,2) == ~some
3329    head(cForm) == cForm
3330    is.call(cl <- quote((Days|Subject)))
3331    is.call(fL)
3332    inherits(fL, "formula")
3333    head(fL) == fL
3334    ## == tail ===
3335    identical(tail(cForm,1), cForm[3])
3336    tail(cForm,2) == cForm[2:3]
3337    tail(cForm) == cForm
3338    tail(fL) == fL
3339    ##
3340    ## -------------failed from here -----------------------
3341    identical(head(cl), cl) ## for a few days, gave Error in do.call(..):  object 'Days' not found
3342    identical( head(fRHS), fRHS)
3343    identical(head(cLong), cLong[1:6])
3344    identical(head(cLong, 2), cLong[1:2])
3345    identical(head(cLong, 1), quote(fun_with_many_args()))
3346    ## == tail ===
3347    identical(tail(cl), cl) ## for a few days, gave Error ...:  object 'Days' not found
3348    identical( tail(fRHS), fRHS)
3349    identical(tail(cLong), cLong[tail(seq_along(cLong))])
3350    identical(tail(cLong, 2), cLong[9:10])
3351    identical(tail(cLong, 1), cLong[10])
3352    ## funny arrays
3353    identical(head(a1,1), a1[1,    drop=FALSE])
3354    identical(head(a3,1), a3[1, ,, drop=FALSE])
3355    identical(tail(a3,1), a3[2, ,, drop=FALSE])
3356})
3357##
3358## Ensure that the code does not access dimensions it does not need (pkg TraMineR):
3359`[.noCol` <- function(x, i, j, drop = FALSE) {
3360    if(!missing(j)) stop(" [!] Column subscripts not allowed", call. = FALSE)
3361    NextMethod("[")
3362}
3363noC <- structure(datasets::trees, class = c("noCol", "data.frame"))
3364assertErrV( noC[1,2]) # fails indeed
3365stopifnot(exprs = {
3366    identical(head(noC), noC[1:6,])
3367    identical(head(noC, 1), noC[1, ])
3368    identical(tail(noC, 1), noC[31,])
3369})
3370##
3371## For all arrays 'a',  head(a, 1)  should correspond to  a[1, {,}* , drop = FALSE]
3372## length(n) > length(dim(x)) (or 1L if dim(x) is NULL) is an error
3373str(Alis <- lapply(1:4, function(n) {d <- 1+(1:n); array(seq_len(prod(d)), d) }))
3374h2 <- lapply(Alis, head, 2)
3375t2 <- lapply(Alis, head, 2)
3376assertErrV( head(Alis[[1]], c(1, NA)))
3377assertErrV( tail(1:5, c(1, NA)))
3378h1 <- lapply(Alis, head, 1)
3379t1 <- lapply(Alis, tail, 1)
3380dh1 <- lapply(h1, dim)
3381## n =1L and n=c(1, NA) equivalent (only ones with 2+ dimensions)
3382Alis2p <- Alis[-1]
3383h1N <- lapply(Alis2p, head, c(1, NA))
3384t1N <- lapply(Alis2p, tail, c(1, NA))
3385Foolis <- lapply(Alis, `class<-`, "foo")
3386assertErrV( head(Foolis[[1]], c(1, NA)))
3387h1F  <- lapply(Foolis, head, 1)
3388h2F  <- lapply(Foolis, head, 2)
3389t1F  <- lapply(Foolis, tail, 1)
3390t2F  <- lapply(Foolis, tail, 2)
3391Foolis2p <- Foolis[-1]
3392h1FN <- lapply(Foolis2p, head, c(1, NA))
3393t1FN <- lapply(Foolis2p, tail, c(1, NA))
3394stopifnot(exprs = {
3395    identical(h2, Alis)
3396    identical(t2, Alis)
3397    vapply(h1, is.array, NA)
3398    vapply(t1, is.array, NA)
3399    identical(dh1, lapply(1:4, function(n) seq_len(n+1L)[-2L]))
3400    identical(dh1, lapply(t1, dim))
3401    identical(h1,  c(list(Alis  [[1]][1, drop=FALSE]), h1N))
3402    identical(t1,  c(list(Alis  [[1]][2, drop=FALSE]), t1N))
3403    identical(h1F, c(list(Foolis[[1]][1, drop=FALSE]), h1FN))
3404    identical(t1F, c(list(Foolis[[1]][2, drop=FALSE]), t1FN))
3405})
3406## This was *not the case for  1d arrays in R <= 3.6.x
3407##
3408tools::assertWarning(t3 <- tail(iris3[,1,], addrownums = FALSE), verbose=TRUE)
3409stopifnot( identical(t3,   tail(iris3[,1,],  keepnums  = FALSE)) )
3410##
3411## 4-dim array
3412## 4th dimension failed transiently when I using switch() in keepnums logic
3413adims <- c(11, 12, 4, 3)
3414arr <- array(seq_len(prod(adims)), adims)
3415headI4 <- function(M, n) {
3416    d <- dim(M)
3417    M[head(seq_len(d[1]), n[1]),
3418      head(seq_len(d[2]), n[2]),
3419      head(seq_len(d[3]), n[3]),
3420      head(seq_len(d[4]), n[4]),
3421      drop = FALSE]
3422}
3423tailI4 <- function(M, n) {
3424    d <- dim(M)
3425    M[tail(seq_len(d[1]), n[1]),
3426      tail(seq_len(d[2]), n[2]),
3427      tail(seq_len(d[3]), n[3]),
3428      tail(seq_len(d[4]), n[4]),
3429      drop = FALSE]
3430}
3431
3432n.set2 <- lapply(-2:2, rep, times = 4)
3433stopifnot(
3434    vapply(n.set2, function(n) identCO (head(arr, n), headI4(arr, n)), NA),
3435    vapply(n.set2, function(n) identCO (tail (arr, n, keepnums=FALSE),
3436                                        tailI4(arr, n)), NA),
3437    vapply(n.set2, function(n) all.equal(tail(arr, n), tailI4(arr, n),
3438                                         check.attributes=FALSE), NA))
3439
3440## full output
3441aco <- capture.output(arr)
3442## extract all dimnames from full output
3443## assumes no spaces in names
3444## assumes NO WRAPPING when printing rows!
3445getnames <- function(txt, ndim = 4) {
3446    el <- which(!nzchar(txt))
3447    ## first handled elsewhere, last is just trailing line
3448    el <- el[-c(1L, length(el))]
3449    hdln  <- c(1L, el[seq(2, length(el), by = 2)] - 1L)
3450    hdraw <- lapply(txt[hdln], function(tx) strsplit(tx, ", ")[[1L]])
3451
3452    ## line 1 is higher indices, 2 is blank, 3 is columns
3453    cnms <- strsplit(trimws(txt[3], which = "left"), split = "[[:space:]]+")[[1]]
3454    cnms <- cnms[nzchar(cnms)]
3455    matln <- 4:(el[1] - 1L)
3456    rnms <- gsub("^([[:space:]]*[^[:space:]]+)[[:space:]].*", "\\1", txt[matln])
3457    hdnms <- lapply(3:ndim, ## blank ones are left in so this is ok
3458                    function(i) unique(sapply(hdraw, `[`, i )))
3459    c(list(rnms, cnms),
3460      hdnms)
3461}
3462fpnms <- getnames(aco, length(adims))
3463## ensure all dimnames correct for keepnums = TRUE
3464stopifnot(
3465    vapply(n.set2, function(n) identical(dimnames(tail(arr, n)),
3466                                         mapply(function(x, ni) if(ni != 0) tail(x, ni),
3467                                                x = fpnms, ni = n, SIMPLIFY = FALSE)),
3468           NA)
3469)
3470## mix named and non-named dimensions to catch bug in initial keepnums patch
3471arr2 <- arr
3472adnms <- lapply(seq_along(adims),
3473                function(i) paste0("dim_", i, "_", seq(1L, adims[i])))
3474adnms[3L] <- list(NULL)
3475dimnames(arr2) <- adnms
3476ii <- seq_along(adnms)
3477stopifnot(
3478    vapply(n.set2, function(n)
3479        identical(dimnames(tail(arr2, n)),
3480                  mapply(function(i, ni) {
3481                            x <- adnms[[i]]
3482                            if(is.null(x))
3483                                x <- as.character(seq_len(adims[i]))
3484                            if(ni != 0L)
3485                                tail(x, ni)
3486                         },
3487                         i = ii, ni = n, SIMPLIFY = FALSE)),
3488        NA)
3489)
3490##
3491## matrix of "language" -- with expression()
3492is.arr.expr <- function(x) is.array(x) && is.expression(x)
3493e <- matrix(expression(foo(2), bar(x), r(foobar), foo(rbar)), 2)
3494str(h1 <- head(e, 1))
3495str(t1 <- tail(e, 1))
3496stopifnot(exprs = {
3497    is.arr.expr(e)  && identical(dim(e),  c(2L, 2L))
3498    is.arr.expr(h1) && identical(dim(h1), c(1L, 2L))
3499    is.arr.expr(t1) && identical(dim(t1), c(1L, 2L))
3500    is.arr.expr(ee <- e[rep(1:2, 3), rep(1:2, 2)]) && identical(dim(ee), c(6L, 4L))
3501    is.arr.expr(hee <- head(ee, n=c(2,-1))) && identical(dim(hee), 2:3)
3502    is.arr.expr(tee <- tail(ee, n=c(-3,1))) && identical(dim(tee), c(3L, 1L))
3503})
3504## (for length(n) == 1,  has worked the same "always")
3505
3506
3507## Forgotten 'drop=FALSE' in plot.formula()
3508df <- data.frame(x=1:3, grp=c("A","A","B"), stringsAsFactors = TRUE)
3509plot( ~grp, data=df, subset = x > 1)
3510## failed in R <= 3.6.1
3511
3512
3513## dnorm() etc border cases, notably sigma = -Inf
3514tools::assertWarning(v0Neg  <- dnorm(0:1, sd = -Inf))
3515tools::assertWarning(dlInf0 <- dlnorm(Inf,Inf, sd = 0))
3516stopifnot(is.nan(v0Neg), is.nan(dlInf0))
3517## in R <= 3.6.2, v0Neg was 0 w/o any warning; dlnorm(...) was +Inf
3518
3519
3520## Unusual frequency and start not supported by ts() and window()
3521x <- ts(x, start = 2.5, end = 107.5, frequency = 0.2)
3522(wx <- window(x, start = 20, end = 30, extend = TRUE))
3523stopifnot(exprs = {
3524    all.equal(attributes(x),         list(tsp = c(2.5, 107.5, 0.2), class = "ts"))
3525    all.equal(wx, structure(c(0.5, 0.6), .Tsp = c(22.5, 27.5, 0.2), class = "ts"))
3526})
3527assertErrV(cbind(ts(1:2, start = 0.5, end = 1.5),
3528                 ts(1:2, start = 0  , end = 1)))
3529## Wrong results in R < 4.0.0
3530## New checks needed tweaks :
3531## -- 1 --
3532frYr <- 365.25
3533tt <- (0:3652)/frYr
3534timeO <- structure(tt, .Tsp = c(1981, 1990.998631, frYr), class = "ts")
3535ttt <- time(timeO) # Error "'end' must be a whole number of cycles after 'start'"
3536## -- 2 --
3537set.seed(7); tt <- ts(rnorm(60), frequency=12)
3538dt2 <- diff(tt, differences = 2) # Error in .cbind.ts(..): not all series have the same phase
3539tsD <- ts(1:49, start=as.Date("2019-12-12"), frequency=12)
3540stopifnot(exprs = {
3541    all.equal(timeO, ttt - 1981, tol = 1e-8)
3542    inherits(ttt, "ts")
3543    inherits(dt2, "ts")
3544    length(dt2) == length(tt) - 2L
3545    all.equal(6*tsp(dt2), c(7, 35.5, 72))
3546    all.equal(dt2[1:2], c(3.986498, -0.22047961))
3547    all.equal(tsD, structure(1:49, .Tsp = c(18242, 18246, 12), class = "ts"))
3548})
3549## failed for a while in R-devel 2019-12-*
3550
3551
3552
3553## Using deparse1() fixing potential naming problems in many places, PR#17671
3554(acl <- do.call(acf, list(lynx, plot=FALSE)))
3555set.seed(7); t44 <- table(sample(LETTERS[1:4], size = 50, replace=TRUE),
3556                          sample(letters[1:4], size = 50, replace=TRUE))
3557ft44 <- do.call(fisher.test, list(t44))
3558stopifnot(length(acl$series) == 1,
3559          length(do.call(pacf, list(lynx, plot=FALSE))$series) == 1,
3560          identical(t44, eval(str2lang(ft44$data.name))))
3561## funny data names in R < 4.0.0
3562
3563
3564## wilcox.test(x,{y,} ..): when 'x' and/or 'y' contain +/- Inf
3565dfn <- c(shifted = function(L) 1/8 + c(9:4, L), # <- without, and
3566            ties = function(L)       c(9:4, L)) # <- with ties
3567oWarn <- getOption("warn")
3568for(nm in names(dfn)) {
3569    y7 <- dfn[[nm]]
3570    options(warn = if(nm == "ties") 1 else 2) ## "ties" : ==> 2 x 3 (different) warnings
3571    w2  <- lapply(c(1000, Inf), function(L) wilcox.test(1:7, y7(L)))
3572    w1  <- lapply(c(1000, Inf), function(L) wilcox.test( y7(L) ))
3573    w2p <- lapply(c(1000, Inf), function(L) wilcox.test(1:7, y7(L), paired= TRUE))
3574    w2n <- lapply(c(1000, Inf), function(L) wilcox.test(1:7, y7(L), exact = FALSE))
3575    w2pn<- lapply(c(1000, Inf), function(L) wilcox.test(1:7, y7(L), exact = FALSE, paired=TRUE))
3576    stopifnot(exprs = {
3577        identical(w2  [[1]], w2  [[2]]) # was FALSE in R <= 3.6.x
3578        identical(w1  [[1]], w1  [[2]]) # was FALSE ..
3579        identical(w2p [[1]], w2p [[2]])
3580        identical(w2n [[1]], w2n [[2]]) # was FALSE ..
3581        identical(w2pn[[1]], w2pn[[2]])
3582    })
3583}; options(warn = oWarn)
3584## non-paired cases treated 'Inf' non-robustly in R <= 3.6.x
3585wII <- wilcox.test(c(-Inf, 1:5, Inf), c(-Inf, 4*(0:4), Inf), paired=TRUE) # error in R <= 3.6.x
3586 w1 <- wilcox.test(c(      1:5, Inf), c(      4*(0:4), Inf), paired=TRUE) # ditto
3587(w0 <- wilcox.test(        1:5,               4*(0:4),       paired=TRUE))
3588sel <- names(w0) != "data.name"
3589stopifnot(identical(w0[sel], w1[sel]), identical(w0[sel], wII[sel]))
3590## Inf-Inf  etc broken in paired case in R <= 3.6.x
3591
3592
3593if(FALSE){ ## pro tem
3594## round(x, n) "to even" failed in some cases -- PR#17668
3595dd <- 0:12
3596x55 <- 55 + as.numeric(vapply(dd+1, function(k) paste0(".", strrep("5",k)), ""))
3597
3598rnd.x <- vapply(dd+1L, function(k) round(x55[k], dd[k]), 1.1)
3599noquote(formatC(cbind(x55, dd, rnd.x), w=1, digits=15))
3600signif (rnd.x - x55, 3) # look at .. but don't test (yet)
3601stopifnot(exprs = {
3602      all.equal(abs(rnd.x - x55), 5 * 10^-(dd+1), tol = 1e-11) # see diff. of 6e-13
3603})
3604## more than half of the above were rounded *down* in R <= 3.6.x
3605## Some "wrong" test cases from CRAN packages (partly relying on wrong R <= 3.6.x behavior)
3606stopifnot(exprs = {
3607    all.equal(round(10.7775, digits=3), 10.778, tolerance = 1e-12) # even tol=0, was 10.777
3608    all.equal(round(12345 / 1000,   2), 12.35 , tolerance = 1e-12) # even tol=0, was 12.34 in Rd
3609    all.equal(round(9.18665, 4),        9.1866, tolerance = 1e-12) # even tol=0, was  9.1867
3610})
3611## This must work, too, the range of 'e' depending on 'd'
3612EE <- c(-307, -300, -250, -200,-100,-50, -20, -10, -2:2,
3613        10, 20, 50, 100, 200, 250, 290:307)
3614for(d in 0:16) { cat("digits 'd' = ", d, ": ")
3615    for(e in EE[EE+d <= 308]) {
3616        f <- 10^e
3617        cat(".")
3618        stopifnot(all.equal(tolerance = if(d < 14) 1e-15
3619                                        else if(d == 14) 1e-14 else 1e-13,
3620                            round(pi/f, e + d) * f,
3621                            round(pi, d)))
3622    };cat("\n")
3623}
3624## (2nd part: continued working)
3625i <- c(-2^(33:10), -10:10, 2^(10:33))
3626for(digi in c(0:10, 500L, 1000L, 100000L, .Machine$integer.max))
3627    stopifnot(identical(i, round(i, digi)),
3628              identical(i+round(1/4, digi), round(i+1/4, digi)))
3629x <- 7e-304; rx <- round(x, digits=307:322); xx <- rep(x, length(rx))
3630print(cbind(rx), digits=16) # not really what ideally round() should do; but "ok"
3631          all.equal(rx, xx, tol = 0)# show "average relative difference" ("5.6856 e -16")
3632stopifnot(all.equal(rx, xx, tol = 1e-4)) # tol may change in future
3633## the round(i, *) failed, for ~ 2 days, in R-devel
3634e <- 5.555555555555555555555e-308
3635(e10 <- e * 1e298) # 5.555556e-10 -- much less extreme, for comparison
3636ds <- 20:1 ;   s.e <- signif(e, ds) ; names(s.e) <- paste0("d", ds)
3637
3638## currently, for round,  digits := pmin(308, digits) -- not going further than 310
3639d <- 310:305; r.e   <- round (e,   d) ; names(r.e)   <- paste0("d", d)
3640d <- d - 298; r.e10 <- round (e10, d) ; names(r.e10) <- paste0("d", d)
3641op <- options(digits=18)
3642cbind(signif = c(e, s.e)) ##-- this always rounds up (= to even)
3643cbind( round = c(e, r.e), round.10 = c(e10, r.e10))
3644iSub <- 6 : (18 + capabilities("long.double"))
3645stopifnot(exprs = {
3646    ## the regularity of signif()'s result is amazing:
3647    is.integer(d <- ds[iSub] - 1L)
3648    all.equal(log10(abs(1 -  diff(unname(s.e))[iSub] * 1e308*10^d / 4)),
3649              d - 16, tol = 0.08) # tol: seen 0.0294 / 0.02988 (Win 32b)
3650    all.equal(r.e * 1e298, r.e10,
3651              check.attributes = FALSE, countEQ=TRUE, tol=1e-14)
3652})
3653## was not true for digits = 309, 310 in R <= 3.6.x
3654##
3655## round(*, digits < 0)
3656M <- .Machine$double.xmax
3657rM <- round(M, -(1:400))
3658stopifnot(exprs = {
3659    rM[(1:400) > 308] == 0
3660### platform (compiler configuration) dependent:
3661    ## identical(which(rM == Inf),
3662    ##           c(if(!b64) 294L, 298L, 299L, 304:308) -> II)
3663    ## is.finite(rM[-II])
3664})
3665## had many Inf and NaN; now looks optimal: 'Inf' are "correct" rounding up
3666##
3667(mm <- 2^-(1022+52)) # denormalized smallest number
3668mm == 1.49*mm # yes, that's "denormal"
3669dr <- diff(rmm <- round(mm, 301:500))
3670(inz <- which(dr != 0))
3671stopifnot(length(inz) == 1, dr[inz] == mm, dr[-inz] == 0,
3672          rmm[-(1:23)] == mm)
3673options(op) ## in R <= 3.6.x, all(rmm == 0)
3674}
3675
3676## update.formula() triggering terms.formula() bug -- PR#16326
3677mkF <- function(nw) as.formula(paste("y ~ x + x1",
3678                                     paste0("- w", seq_len(nw), collapse="")),
3679                               env = .GlobalEnv)
3680fterms <- function(n, simplify=TRUE) formula(terms.formula(mkF(n), simplify=simplify))
3681if(interactive())
3682    for(n in 1:20) print(fterms(66)) # always correct now:  y ~ x + x1
3683## used to have a '-1'  (and much more, see below) in R <= 3.6.2
3684## NB: had memory / random behavior -- and sometimes ended in
3685##     malloc(): corrupted top size
3686##     Process R... aborted (core dumped)
3687set.seed(17)
3688N <- 1024
3689Ns <- sort(1 + rpois(N, 3)+ 16*rpois(N, 3))
3690FN <- lapply(Ns, fterms)
3691(UFN <- unique(FN))
3692stopifnot(identical(y ~ x + x1, UFN[[1]]))
3693## Ended in this error [which really comes from C code trying to set dimnames !] :
3694##   Error in terms.formula(mkF(n), simplify = simplify) :
3695##     'dimnames' applied to non-array
3696##
3697##--TODO: less severe now (no seg.fault / corrupt memory crashes), but still really bad ! ---
3698
3699
3700## Corner cases in choose(),
3701## misbehaved when n was _nearly_ int, and n - k < k
3702stopifnot(choose(4 - 1e-7, 4) == 1)
3703stopifnot(choose(4 + 1e-7, 4) == 1)
3704## These gave 0 and 4 in R <= 3.6.x
3705
3706
3707## correct error message:
3708tt <- tryCid(strptime(100, pi))
3709stopifnot(inherits(tt, "error"), grepl("'format'", tt$message))
3710## had 'x' instead of 'format'
3711
3712
3713## r<integer-RV>() now return double if integer would overflow:
3714set.seed(47)
3715Npi <- rpois(100, 0.9999 *2^31)
3716Npd <- rpois(100, 0.99999*2^31)# had 33 NA's
3717Nbi <- rbinom(100, 2^31, 1/2)
3718Nbd <- rbinom(100, 2^32, 1/2)# 51 NA's
3719Ngi <- rgeom(999, 1e-8)
3720Ngd <- rgeom(999, 1e-9) # 106 NA's
3721stopifnot(is.integer(Npi), is.double(Npd), !anyNA(Npi), !anyNA(Npd),
3722          is.integer(Nbi), is.double(Nbd), !anyNA(Nbi), !anyNA(Nbd),
3723          is.integer(Ngi), is.double(Ngd), !anyNA(Ngi), !anyNA(Ngd),
3724          TRUE)
3725## had many NA's in  3.0.0 <= R <= 3.6.x
3726
3727
3728## rhyper() for some large arguments, PR#17694
3729n <- 2e9 # => .Machine$integer.max ~= 1.07 * N
3730set.seed(6860); N <- rhyper(1, n,n,n)
3731x <- 1.99e9; Nhi <- rhyper(256, x,x,x)
3732stopifnot(#identical(N, 999994112L), # (wrong) implementation detail
3733          is.integer(Nhi),
3734          all.equal(mean(Nhi), x/2, tol = 6e-6)) # ==> also: no NAs
3735## NA's and warnings, incl "SHOULD NOT HAPPEN!" in R <= 3.6.2
3736
3737
3738## assertCondition(*, "error") etc triggered errors *twice* (accidentally)
3739stopifnot(identical(tools::assertError(sqrt("a")),
3740                    list(     tryCid(sqrt("a")))))
3741## The former contained the error object twice in R <= 3.6.2
3742
3743
3744## Overriding encoding in parse()
3745if (l10n_info()$"UTF-8" || l10n_info()$"Latin-1") {
3746    x8 <- "'\uf6'"
3747    x8.2 <- substr(x8, 2, 2)
3748    stopifnot(identical(Encoding(x8), "UTF-8"))
3749    f8 <- tempfile()
3750    writeLines(x8, f8, useBytes=TRUE) # save in UTF-8
3751    ##
3752    chk_x82 <- function(x) stopifnot(identical(Encoding(x), "UTF-8"),
3753                                     identical(x, x8.2))
3754    ## parse(*, encoding = "UTF-8", ..) :
3755    for(FF in c(function(.) parse(text=., encoding="UTF-8", keep.source=TRUE),
3756                function(.) parse(text=., encoding="UTF-8", keep.source=FALSE)
3757                )) {
3758        x <- eval(FF(x8))
3759        chk_x82(x)
3760    }
3761    for(K.S in c(TRUE, FALSE)) {
3762        x <- eval(parse(file=f8, encoding="UTF-8", keep.source = K.S))
3763        chk_x82(x)
3764    }
3765    ## latin1 <--> UTF-8
3766    xl <- iconv(x8, from="UTF-8", to="latin1")
3767    stopifnot(identical(Encoding(xl), "latin1"))
3768    stopifnot(identical(x8, iconv(xl, from="latin1", to="UTF-8")))
3769    unlist(l10n_info()) # to see ..
3770}
3771if (l10n_info()$"UTF-8") {
3772    for(x in c(eval(parse(text=x8)),
3773               eval(parse(text=xl, keep.source=TRUE)),
3774               eval(parse(text=xl, keep.source=FALSE)),
3775               eval(parse(file=f8)),
3776               str2lang(x8),
3777               str2expression(x8)))
3778        stopifnot(identical(x, x8.2))
3779}
3780if (l10n_info()$"Latin-1") {
3781    for(x in c(eval(parse(text=xl)),
3782               eval(parse(text=x8, keep.source=TRUE)),
3783               eval(parse(text=x8, keep.source=FALSE)),
3784               str2lang(x8),
3785               str2expression(x8)))
3786        stopifnot(identical(x, x8.2))
3787}
3788## parse(text=xl) had failed w/ "EOF whilst reading MBCS char at line 2"
3789
3790
3791## smoothEnds(<integer>, .) - PR#17693
3792y1 <- as.integer(c(8,5,4,1,1,1,1))
3793y2 <- y1; y2[3] <- 6L
3794s1 <- smoothEnds(y1); s1.5 <- smoothEnds(y1, 5)
3795s2 <- smoothEnds(y2); s2.5 <- smoothEnds(y2, 5)
3796stopifnot(is.integer(y1), is.integer(y2), y1[-3] == y2[-3],
3797          is.integer(s1), is.integer(s2),
3798          is.integer(s1.5), is.integer(s2.5),
3799          s1[1] == 7L, s1[-1] == y1[-1], identical(s1.5, s1),
3800          s2[1] == 5L, s2[-1] == y2[-1], identical(s2.5, rep(c(6L, 1L), 3:4)))
3801## s1, s1.5 were double in R <= 3.6.x
3802
3803
3804## stopifnot() custom message now via <named> args:
3805e <- assertErrV(stopifnot("ehmm, you must be kidding!" = 1 == 0))
3806stopifnot(grepl("must be kidding!", e[[1]]$message))
3807e2 <- assertErrV(stopifnot("2 is not approximately 2.1" = all.equal(2, 2.1)))
3808stopifnot(grepl("not approximately", e2[[1]]$message))
3809## did not work in original stopifnot(<named>) patch
3810CHK <- function(...) stopifnot(...)
3811e  <- tryCid(CHK(1 == 1, 1 == 0))
3812e2 <- tryCid(CHK(1 == 1, "not possible" = 1 == 0))
3813stopifnot(inherits(e , "error"), grepl("is not TRUE", e$message),
3814          inherits(e2, "error"), identical("not possible", e2$message))
3815## wrapping stopifnot() in this way did not work in some unreleased R-devel
3816
3817
3818## norm(<matrix-w-NA>, "2")
3819stopifnot(is.na( norm(diag(c(1, NA)), "2") ))
3820## gave error from svd() in R <= 3.6.x
3821
3822
3823## norm(<matrix-w-NA>, "F")
3824(m <- cbind(0, c(NA, 0), 0:-1))
3825nTypes <- eval(formals(base::norm)$type) # "O" "I" "F" "M" "2"
3826print( # stopifnot( -- for now, as Lapack is still broken in some OpenBLAS -- FIXME
3827    is.na( print(vapply(nTypes, norm, 0., x = m)) )) # print(): show NA *or* NaN
3828## "F" gave non-NA with LAPACK 3.9.0, before our patch in R-devel and R-patched
3829
3830
3831## dimnames(<matrix>)[[.]] <- v -- inconsistency when length(v) == 1 : PR#17719
3832aa <- matrix(1:2); dimnames(aa)[[1]] <- c("a", "b") # OK (always)
3833 a <- matrix(1)  ; dimnames(a )[[1]] <-   "a"       # gave error: 'dimnames' must be a list
3834stopifnot(exprs = {
3835    identical(dimnames(a ), list(  "a",      NULL))
3836    identical(dimnames(aa), list(c("a","b"), NULL))
3837})
3838## The above works, because now, `[[<-` is consistently returning a list:
3839N <- NULL; N[["a"]] <- 1:2; stopifnot(identical(N, list(a = 1:2)))
3840N <- NULL; N[["a"]] <- 1  ; stopifnot(identical(N, list(a = 1)))
3841## the latter gave c(a = 1) in earlier versions of R
3842
3843
3844## deparse(), dput(), etc :  "all" now includes "digits17"; new "exact"
3845x <- 1 - 2^-51 ; dput(x, , "all")
3846stopifnot(exprs = {
3847    identical(deparse(x), as.character(x))
3848    identical(deparse(x), "1") # default only uses 15 (= DBL_DIG) digits
3849    if(!capabilities("long.double")) TRUE else
3850        identical(x, as.numeric(deparse(x, control="all")))
3851    identical(x, as.numeric(deparse(x, control="exact") -> dx.x))
3852    identical(print(dx.x),  deparse(x, control="hexNumeric"))
3853    TRUE || ## maybe not on all platforms ?
3854        identical(dx.x, "0x1.ffffffffffffcp-1") # on 32-bit, too
3855})
3856## "all" gave "1" in R <= 3.6.z
3857
3858
3859## Can suppress warnings with missing restarts
3860cnd <- simpleWarning("foo")
3861out <- tryCatch(suppressWarnings(stop(cnd)), warning = identity)
3862stopifnot(identical(out, cnd))
3863## Can suppress messages with missing restarts
3864cnd <- simpleMessage("foo")
3865out <- tryCatch(suppressMessages(stop(cnd)), message = identity)
3866stopifnot(identical(out, cnd))
3867
3868
3869## PR#17730 -- data() should no longer "lie" and warn {already have getOption("warn") == 2
3870for(p in c("base", "stats")) {
3871    dd <- data(package=p)
3872    stopifnot(inherits(dd, "packageIQR"), is.list(dd),
3873              nrow(dd$results) == 0)
3874}
3875## gave all data from pkg 'datasets'  *and* warned in  R <= 3.6.3
3876
3877
3878## PR#17756: x[[Inf]] and also x[[ -i ]] ,  for i in (Inf, 1,2,...):
3879obj <- list(
3880    a = 1:3
3881  , L3 = as.list(1:3)
3882  , L  = list(a = 1:2)
3883  , L2 = list(a = 1:2, b = 3:5)
3884  , LL2 = list(a = list(a1=1:3, a2=letters[1:4]),
3885               b = list(b1=10, b2=-(1:3)))
3886    )
3887obj$ LL3 <- c(obj$ LL2, list(c = list(c1= 7, c2= -11)))
3888stopifnot( print(vapply(obj[-1], function(x) is.null(x[[Inf]]), NA)) )
3889t_mInf <- lapply(obj, function(x) tryCid(x[[-Inf]]))
3890getMsg <- function(tryClist) vapply(tryClist, conditionMessage, "..")
3891stopifnot(length(print(table(msg_Inf <- getMsg(t_mInf)))) == 1)
3892## in R <= 3.6.3:
3893## attempt to select less than one element in get1index <real> : 1 x
3894## attempt to select more than one element in get1index <real> : 5 x
3895
3896umInf <- unique(msg_Inf)
3897str(t_m1 <- lapply(obj, function(x) tryCid(x[[-1]]))) # L2, LL2 "work" - why?
3898    t_m2 <- lapply(obj, function(x) tryCid(x[[-2]]))  # L2, LL2 "work" - why?
3899    t_m3 <- lapply(obj, function(x) tryCid(x[[-3]]))
3900nonL2 <- grep("L2$", names(t_m1), value=TRUE, invert=TRUE)
3901stopifnot(exprs = {
3902    identical(getMsg(t_m3), msg_Inf)
3903    identical(t_m2$L2, 1:2)
3904    identical(t_m2$LL2, obj$LL2[[1]])
3905    identical(getMsg(t_m1[nonL2]), msg_Inf[nonL2])
3906    identical(getMsg(t_m2[nonL2]), msg_Inf[nonL2])
3907})
3908if(englishMsgs) { cat("checking (default = ) English error messages\n")
3909    stopifnot(grepl("negative subscript", umInf))
3910}
3911##
3912
3913
3914## paste(...,  recycle0=TRUE)  uses the "normal" 0-length recycling rule:
3915##                                "if one argument has length zero, the result has too."
3916ch0 <- character(0)
3917stopifnot(exprs = {
3918    ## a) when paste() has 0 '...' arguments :
3919    identical(paste (), ch0)               ## collapse = NULL -----------
3920    identical(paste0(), ch0)
3921    identical(paste (collapse= "A"  ), "")
3922    identical(paste0(collapse="foof"), "")
3923    identical(paste (collapse= "A"  , recycle0 = TRUE), "") # new!
3924    identical(paste0(collapse="foof", recycle0 = TRUE), "") # new!
3925    ##
3926    ## b) when all '...'  arguments have length 0 :
3927    ## ---- collapse = NULL -------------
3928    identical(paste({}),                  ch0)
3929    identical(paste({}, recycle0 = TRUE), ch0)
3930    identical(paste({}, NULL, ch0),                  ch0)
3931    identical(paste({}, NULL, ch0, recycle0 = TRUE), ch0)
3932    ## ---- collapse not NULL ---------
3933    identical(paste({}, collapse=""),                              "")
3934    identical(paste({}, collapse="", recycle0 = TRUE),             "") # new!
3935    identical(paste({}, NULL, ch0, collapse=""),                   "")
3936    identical(paste({}, NULL, ch0, collapse="", recycle0 = TRUE),  "") # new!
3937    ##
3938    ## c) when *one* of the ...-args has length 0 :
3939    identical(paste ("foo", character(0), "bar", recycle0 = FALSE), "foo  bar")
3940    identical(paste0("foo", character(0), "bar", recycle0 = FALSE), "foobar")
3941    identical(paste ("foo", character(0), "bar", recycle0 = TRUE), ch0)
3942    identical(paste0("foo", character(0), "bar", recycle0 = TRUE), ch0)
3943    identical(paste ("foo", character(0), "bar", recycle0 = TRUE, collapse="A"), "")
3944    identical(paste0("foo", character(0), "bar", recycle0 = TRUE, collapse="A"), "")
3945})
3946## 0-length recycling with default recycle0 = FALSE has always been "unusual"
3947## -----------------  with     recycle0 = TRUE      returns 0-length i.e. character(0)
3948
3949
3950## aov() formula deparsing  {Jan Hauffa, Apr 11, 2020, on R-devel}
3951mkAov <- function(nms, n = 50) {
3952    dflong <- as.data.frame(matrix(pi, n, length(nms),
3953                                   dimnames = list(NULL, nms)))
3954    forml <- as.formula(paste0("cbind(", paste(nms, collapse = ","), ") ~ 1 + Error(1)"))
3955    aov(forml, data=dflong)
3956}
3957nLng <- paste0("someReallyLongVariableName", 1:20)
3958cf1 <- coef(fm1 <- mkAov(vnms <- paste0("v", 1:20)))
3959cfL <- coef(fmL <- mkAov(nLng)); colnames(cfL[[1]]) <- vnms
3960stopifnot(all.equal(cf1, cfL))
3961## mkAov(nLng)  failed in R <= 4.0.0
3962
3963
3964## UTF8 validity checking internal in R (from PCRE, PR#17755)
3965## This is the byte representation of U+D800 (a part of a surrogate
3966## pair) in UTF-8, but do not rely on parser (which on some platforms
3967## has mis-parsed that)
3968stopifnot(identical(validUTF8("\xed\xa0\x80"), FALSE))
3969
3970## summary.warnings()  -- reported by Allison Meisner, jhmi.edu
3971testf <- function(x) {
3972    if(x > 30)
3973        warning("A big problem (should be 20 of these)")
3974    else
3975        warning("Bigger problem (should be 30 of these)")
3976}
3977op <- options(warn=0)
3978for(i in 1:50) testf(i) # -> 50 warnings ..
3979options(op)# reset
3980(sw <- summary(warnings()))
3981stopifnot(identical(unlist(lapply(names(sw), substr, 1, 6)), c("Bigger", "A big ")),
3982          identical(attr(sw, "counts"), c(30L, 20L)))
3983## was wrong (mis-sorted counts) in R <= 4.0.0
3984
3985
3986## plot.formula(..,  ylab = <call>)
3987dd <- list(x = -4:4, w = 1/(1+(-4:4)^2))
3988plot(w ~ x, data=dd, type = "h", xlab = quote(x[j]))                    # worked before
3989plot(w ~ x, data=dd, type = "h", xlab = quote(x[j]), ylab = quote(y[j]))# *now* works
3990## main, sub, xlab worked (PR#10525)  but ylab did not in R <= 4.0.0
3991
3992
3993## ...names()
3994F <- function(x, ...) ...names()
3995F(a, b="bla"/0, c=c, D=d, ..) # << does *not* evaluate arguments
3996# |->  c("b", "c", "D", NA)
3997stopifnot(exprs = {
3998    identical(F(pi), character(0))
3999    F(foo = "bar") == "foo"
4000    identical(F(., .., .not.ok. = "a"-b, 2, 3, last = LAST),
4001              c(  NA, ".not.ok.",      NA, NA,"last"))
4002})
4003# .. was wrong for a few days
4004
4005
4006## check raw string parse data
4007p <- parse(text = 'r"-(hello)-"', keep.source = TRUE)
4008stopifnot(identical(getParseData(p)$text, c("r\"-(hello)-\"", "")))
4009rm(p)
4010# (wrong in R 4.0.0; reported by Gabor Csardi)
4011
4012## check 0x...L parse data
4013p <- parse(text = '0x2L', keep.source = TRUE)
4014stopifnot(identical(getParseData(p)$text, c("0x2L", "")))
4015rm(p)
4016# (wrong in R 4.0.0; reported by Gabor Csardi)
4017
4018
4019## make sure there is n aliasing in assignments with partial matching
4020v <- list(misc = c(1))
4021v$mi[[1]] <- 2
4022stopifnot(v$misc == 1)
4023rm(v)
4024# defensive reference counts needed; missing in R 4.0.0
4025
4026
4027## round() & signif() with one / wrong (named) argument(s):
4028cat("Case 1 : round(1.12345):            ", round(  1.12345),"\n")
4029cat("Case 2 : round(x=1.12345,2):        ", round(x=1.12345, 2),"\n")
4030cat("Case 3 : round(x=1.12345,digits=2): ", round(x=1.12345, digits=2),"\n")
4031cat("Case 4 : round(digits=2,x=1.12345): ", round(digits=2, x=1.12345),"\n")
4032cat("Case 4b: round(digits=2,1.12345):   ", round(digits=2,1.12345),"\n")
4033## R <= 4.0.0 does not produce error in cases 5,6 but should :
4034cat("Case 5:    round(digits=x): \n")
4035assertErrV(cat("round(digits=99.23456): ", round(digits=99.23456)))
4036cat("Case 6:    round(banana=x): \n")
4037assertErrV(cat("round(banana=99.23456): ", round(banana=99.23456)))
4038## Cases 7,8 have been given an error already:
4039cat("Case 7: round(x=1.12345, digits=2, banana=3):\n")
4040assertErrV(  round(x=1.12345, digits=2, banana=3))
4041cat("Case 8 : round(x=1.12345, banana=3):\n")
4042assertErrV(  round(x=1.12345, banana=3))
4043## (by Shane Mueller, to the R-devel m.list)
4044
4045
4046## source(*, echo=TRUE) with srcref's and empty lines; PR#
4047exP <- parse(text=c("1;2+", "", "3"), keep.source=TRUE)
4048r <- source(exprs=exP, echo=TRUE)
4049stopifnot(identical(r, list(value = 5, visible = TRUE)))
4050## failed in R <= 4.0.1
4051
4052
4053## boxplot() with call (instead of expression) in labels; Marius Hofert on R-devel
4054rm(x,y,X,f)
4055boxplot(cbind(x = 1:10, y = c(16,9:1)), xlab = quote(x^{y[2]}), ylab = quote(X[t]),
4056        sub = quote(f^2 == f %*% f), main = quote(e^{-x^2/2}))
4057## failed in R <= 4.0.1
4058
4059
4060## on.exit() argument matching -- PR#17815
4061f <- function() { on.exit(add=FALSE, expr=cat('bar\n')) ; 'foo' }
4062stopifnot(identical(f(), 'foo')) # and write 'bar' line
4063g <- function() { on.exit(add=stop('boom'), expr={cat('bar\n'); FALSE}) ; "foo" }
4064assertErrV(g())
4065## f() :> "Error in on.exit(....): invalid 'add' argument"  and no error for g() in R <= 4.0.1
4066
4067
4068## multi-encodings in vector-case for duplicated/match -- PR#17809
4069c_latin1 <- "\xe4"
4070Encoding(c_latin1) <- "latin1"
4071c_utf8 <- enc2utf8(c_latin1)
4072x <- list(c_latin1, c_utf8, letters)
4073stopifnot(identical(duplicated(x)[2], TRUE))
4074## failed in R <= 4.0.1
4075
4076
4077## str(<S4 w/ extra attributes>)
4078mixW <- setClass("mixW", contains = "numeric")
4079Summ <- setClass("Summ", representation(call = "language", wts = "mixW"))
4080S <- Summ(call = quote(foo(x)), wts = structure(mixW(pi), CA="sunny"))
4081stopifnot(length(c.str <- capture.output(str(S))) >= 5,
4082          grepl(r"(\$ CA: chr "sunny")", c.str[5]))
4083deparse(S)# FIXME: is still wrong (no trace of "CA")
4084## "CA" was not shown in R <= 4.0.2
4085
4086
4087## sort(), order(), rank() for "raw - object":
4088int8 <- function(x) structure(x, class = c("int8", oldClass(x)))
4089`[.int8` <- function(x, ...) structure(NextMethod("["), class=class(x))
4090set.seed(2); si <- sample.int(37)
4091rI <- int8(as.raw(si))
4092stopifnot(exprs = {
4093    identical(rank (rI), rank (si))
4094    identical(order(rI), order(si))
4095    identical(sort (rI), int8(as.raw(1:37)))
4096})
4097## failed in  R <= 4.0.2
4098
4099
4100## PR#16814: r2dtable() and chisq.test(*, simulate.p.value=TRUE) for large numbers
4101rc <- c(63194L, 4787074L)
4102cc <- c(34677L, 4815591L)
4103set.seed(28); system.time(R2 <- simplify2array(r2dtable(1000, rc, cc)))
4104(c.t <- chisq.test(R2[,,1], simulate.p.value = TRUE))
4105set.seed(2*3); R2x3 <- r2dtable(5000, c(3,13), c(4,4,8))
4106stopifnot(exprs = {
4107    sum(!(dupR2 <- duplicated.array(R2, MARGIN=3))) == 109
4108    all.equal(c.t$p.value, 1929/2001)
4109    ## From here, true also in previous R versions:
4110    is.matrix(cR2 <- colSums(R2))
4111    cR2[1,] == cc[1]
4112    cR2[2,] == cc[2]
4113    identical(c(table(vapply(R2x3, function(m) 10*m[2,1]+m[2,3], 1))),
4114              c(`18` = 42L, `27` = 405L, `28` = 217L, `36` = 1021L, `37` = 1159L,
4115                `38` = 192L, `45` = 491L, `46` = 967L, `47` = 464L, `48` = 42L))
4116})
4117## The large tables and p-values were completely wrong in R <= 4.0.2
4118
4119
4120## PR#16877: glm()-internal refitting for the null deviance
4121y <- c(1, 1, 0, 0)
4122x <- c(5, 3, 2, 4)
4123fit <- glm(y ~ 1 + x + offset(log(x)), family = gaussian("log"), start = c(0,0))
4124## failed in R < 4.1.0 due to missing starting values for glm-internal 'fit2'
4125fit0 <- glm.fit(x = rep(1, length(y)), y = y, offset = log(x),
4126                family = gaussian("log"), start = 0)
4127stopifnot(all.equal(fit$null.deviance, fit0$deviance))
4128proc.time() - .pt; .pt <- proc.time()
4129
4130
4131## UTF-8 truncation tests
4132if (l10n_info()$"UTF-8") {
4133    ## These tests fail on R < 4.0
4134
4135    ## Use .Internal(seterrmessage(old.err)) to trigger truncation via
4136    ## Rsnprintf (mbcsTruncateToValid).
4137    trunc_string <- function(x) {
4138        old.err <- geterrmessage()
4139        on.exit(.Internal(seterrmessage(old.err)))
4140        unname(
4141            vapply(
4142                x,
4143                function(y) {
4144                    .Internal(seterrmessage(y))
4145                    geterrmessage()
4146                },
4147                ""
4148            )
4149        )
4150    }
4151    ## limits to detect the internal buffer size for truncation (now 8192)
4152    buff.min <- 8
4153    buff.max <- 7e4  # > buff.min
4154    buff.size <- nchar(
4155        trunc_string(paste0(rep(0:9, length.out = buff.max), collapse="")),
4156        type='bytes'
4157    )
4158    stopifnot(buff.size >= buff.min + 1)
4159    if(buff.size == buff.max)
4160        ## possibly, the buffer is no longer fixed size?
4161        warning('BUFSIZE too large for UTF-8 truncation test?')
4162    else {
4163        string.base <- paste0(
4164            rep(0:9, length.out = buff.size),
4165            collapse=""
4166        )
4167        ## Append UTF-8 sequences at the end of strings that are just
4168        ## a bit shorter than the buffer, each one byte longer than the
4169        ## previous.
4170        string.starts <- substr(
4171            rep(string.base, 6), 1,
4172            nchar(string.base) - seq(buff.min, 3, -1)
4173        )
4174        ## For each of the increasing length string, append 2, 3, and 4 byte
4175        ## (valid) UTF-8 characters.
4176        string.ends <- rep(
4177            c(
4178                '\u00A2',            # <C2><A2>           (cent symbol)
4179                '\u20AC',            # <E2><82><AC>       (euro symbol)
4180                '\U00010348',        # <F0><90><8D><88>   (circle with dot)
4181                NULL
4182            ),
4183            each=length(string.starts)
4184        )
4185        strings <- paste0(
4186            string.starts,
4187            '\U0001F600',  # 4 byte grinning face, extra padding char
4188            string.ends
4189        )
4190        output <- trunc_string(strings)
4191        stopifnot(validUTF8(strings)) # sanity check
4192        stopifnot(validUTF8(output))
4193    }
4194    ## These tests fail on R < 4.1
4195    ##
4196    ## Checking that truncation and `...` concatenation are working
4197    ## correctly in verrorcall_dflt.  Prior to 4.1 truncation detection did
4198    ## not work with call set, and multibyte characters could be mangled by
4199    ## the `...`.
4200    ##
4201    ## We assume getttext strings are not translated (or are translated
4202    ## to the same byte-length as the ones in source).
4203
4204    ## We cannot use `tryCatch` as we're testing the C-level error construction
4205    ## and that is not invoked when signalled errors are caught, hence:
4206    capt_err_msg <- function(expr) {
4207        tmp <- tempfile()
4208        on.exit(unlink(tmp))
4209        err.con <- getConnection(sink.number(type='message'))
4210        sink(file(tmp, 'w'), type='message')
4211        withRestarts(expr, abort=function() sink(err.con, type='message'))
4212        ## add back newlines consumed by readlines; we assume a trailing one
4213        ## exists, if it doesn't readLines will issue a warning
4214        paste0(c(readLines(tmp), ""), collapse="\n")
4215    }
4216    ## Generate errors with long messages (length buff.size + overflow), ending
4217    ## in `x`, to test truncation.  Will need to be updated if buff.size is
4218    ## increased.  Function names / etc. are all carefully counted.
4219    long_error <- function(x, overflow=0, buff.size=8192) {
4220        overflow <- as.integer(overflow)
4221        x <- paste0(as.character(x), collapse="")
4222
4223        ## Compute how many chars needed to fill buffer
4224        call.len <- 51   # nchar of a_really...(stop(x)) - see below
4225        extra.len <- 12  # "Error in  : "
4226        extra.ws <- 3    # +2 spaces +1 \n from `tail`
4227        chars.left <- buff.size - call.len - extra.len - extra.ws
4228        chars <- nchar(x, type = 'bytes')
4229        pad.chars <- chars.left - chars + as.integer(overflow)
4230        stopifnot(pad.chars >= 0)
4231        err.msg <- paste0(paste0(rev(rep_len(rev(LETTERS), pad.chars)),
4232                                 collapse = ""), x)
4233        ## force truncation despite 8170 warn length limit
4234        old.opt <- options(warning.length = 8170, warn=2)
4235        on.exit(options(old.opt))
4236        a_really_long_function_to_cause_truncation <- function(x) x
4237        f <- function(x)
4238            a_really_long_function_to_cause_truncation(stop(x))
4239        ## trigger error and capture std.err
4240        capt_err_msg(f(err.msg))
4241    }
4242    buff.size.2 <- buff.size + 1     # .Internal(seterrmessage) drops 1 byte
4243
4244    ## 2 byte and 4 byte utf-8 encoded chars, avoid code points between \u00a0
4245    ## and \u0100 as some iconv implementations will translate them into char
4246    ## values in those ranges instead of into "<U+...>" in C locales.
4247    utf8.test <- '\u0238\U00010348'
4248
4249    if(buff.size.2 != 8192) {
4250        warning('These tests assume BUFSIZE = 8192')
4251    } else {
4252        ## Mangled multibyte in R < 4.1
4253        stopifnot(validUTF8(long_error(utf8.test, overflow=-1)))
4254
4255        ## Truncation detection fails in R < 4.1, so newline isn't appended, so
4256        ## we get a "incomplete final line" warning (converted to error)
4257        long_error(utf8.test, overflow=0)
4258
4259        overflow <- c(
4260             -6,   # Buffer unambiguosly unfilled for MB_CUR_MAX=6
4261             -5,   # Buffer maybe filled for MB_CUR_MAX=6
4262             -4,   # Buffer full with '...\n\0'
4263             -3,   # Lose 4 byte UTF-8 char
4264             -2,
4265             -1,
4266              0,   # 4 byte UTF-8 char exactly replaced by '...\n', buffer full
4267              1,   # Lose 2 byte UTF-8 char
4268              2,
4269              3,   # Lose first non UTF-8
4270            # These will need to change if R_ConciseTraceback changes
4271            -87,   # Room for traceback; options(showErrorCalls=TRUE)
4272            -86    # No room for traceback.
4273        )
4274        le.res <- vapply(overflow, long_error, character(1),
4275                         buff.size = buff.size.2, x = utf8.test)
4276        stopifnot(validUTF8(utf8.test))  # sanity check
4277        stopifnot(validUTF8(le.res))
4278
4279        ## # For first one, before truncation test, we've used 8186 bytes, so we
4280        ## # know there was no truncation.  Code adds a trailing newline, which
4281        ## # is why we get 8187.  For the second, we add one byte to the
4282        ## # message, which puts us in maybe-truncated state, which adds 3 more
4283        ## # bytes via with "...", so total of 8187 + 1 + 3 == 8191.
4284        ## le.res.nc <- nchar(le.res)
4285        ## data.frame(overflow,
4286        ##            bytes=nchar(le.res, type='bytes'),
4287        ##            snippet=substr(le.res, le.res.nc - 5, le.res.nc))
4288        ##
4289        ##    overflow bytes snippet
4290        ## 1        -6  8187 XYZȸ��\n
4291        ## 2        -5  8191 ȸ��...\n
4292        ## 3        -4  8192 ȸ��...\n
4293        ## 4        -3  8189 Zȸ...\n
4294        ## 5        -2  8190 Zȸ...\n
4295        ## 6        -1  8191 Zȸ...\n
4296        ## 7         0  8192 Zȸ...\n
4297        ## 8         1  8191 YZ...\n
4298        ## 9         2  8192 YZ...\n
4299        ## 10        3  8192 XY...\n
4300        ## 11      -87  8192 ation\n
4301        ## 12      -86  8107 XYZȸ��\n
4302        ## test recursive errors in handler, Fails R < 4.0
4303
4304        handler_error <- function(x, overflow=0, buff.size=8192) {
4305            overflow <- as.integer(overflow)
4306            x <- paste0(as.character(x), collapse="")
4307            pad.chars <- buff.size - nchar(x, type='bytes') + overflow
4308            err.msg <- paste0(
4309                paste0(rev(rep_len(rev(LETTERS), pad.chars)), collapse=""), x
4310            )
4311            old.opt <- options(
4312                error=function(...) {
4313                    options(error=old.opt[['error']])
4314                    stop(err.msg)
4315                }
4316            )
4317            capt_err_msg(stop('initial error'))
4318        }
4319        handler.error.trunc <- vapply(
4320            c(0, 1, 5), handler_error, x=utf8.test, "", buff.size=buff.size.2
4321        )
4322        stopifnot(validUTF8(handler.error.trunc))
4323
4324        ## Test when warning.length is limiting
4325
4326        short_error <- function(call.=TRUE) {
4327            old.opt <- options(warning.length=100)
4328            on.exit(old.opt)
4329            f <- function()
4330                stop(paste0(rep_len(0:9, 110), collapse=""), call.=call.)
4331            capt_err_msg(f())
4332        }
4333        ## trailing newline adds 1
4334        stopifnot(nchar(short_error(call.=FALSE)) == 101L)
4335    }
4336    ## PrintGenericVector truncations
4337    ##
4338    ## New printing in r78508 needs to account for UTF-8 truncation
4339    grin <- "\U0001F600"
4340    lc1 <- paste0(c(rep(LETTERS, length.out=110), grin), collapse="")
4341    lc2 <- paste0(c(rep(LETTERS, length.out=111), grin), collapse="")
4342    list.mats <- list(matrix(list(structure(1:2, class=lc1))),
4343                      matrix(list(structure(1:2, class=lc2))))
4344
4345    ## Allowed UTF-8 truncation in R < 4.1
4346    ls1 <- paste0(c(rep(0:9, length.out=95), "\U0001F600"), collapse="")
4347    ls2 <- paste0(c(rep(0:9, length.out=96), "\U0001F600"), collapse="")
4348    long.strings <- list(matrix(list(ls1)), matrix(list(ls2)))
4349
4350    ## Invalid UTF-8 output as "\xf0\x9f..." so needs to be parsed to un-escape
4351    capt_parse <- function(x) {
4352        out <- capture.output(print(x))
4353        eval(parse(text=paste0(c('c(', sprintf("'%s',", out), 'NULL)'),
4354                               collapse=""))[[1]])
4355    }
4356    capt.parsed <- unlist(lapply(c(list.mats, long.strings), capt_parse))
4357    stopifnot(validUTF8(capt.parsed))
4358
4359    ## Allowed MBCS truncation in R < 4.1
4360    fmt <- paste0(c(rep_len("a", 253), "\U0001f600"), collapse="")
4361    stopifnot(validUTF8(format(as.POSIXlt('2020-01-01'), fmt)))
4362
4363    f <- file(paste0(c(rep_len("a", 992), "\U0001F600"), collapse=""))
4364    suppressWarnings(g <- gzcon(f))
4365    stopifnot(!grepl("xf0", capture.output(g)[2]))
4366}
4367
4368## c() generic removes all NULL elements --- *but* the first --- before dispatch
4369c.foobar <- function(...) list("ok", ...)
4370foobar <- structure(list(), class = "foobar")
4371stopifnot(exprs = {
4372    identical(c(foobar, NULL, one=1,NULL), list("ok", foobar, one=1))
4373    identical(c(a = foobar, pi, NULL, b="B",NULL), list("ok", a = foobar, pi, b="B"))
4374    identical(c(a = foobar, b = NULL),     list("ok", a = foobar))
4375    identical(c(foobar, b = foobar),       list("ok", foobar, b=foobar))
4376    ## Back compatibly, w/ initial NULL, using c()'s default method:
4377    ##  ==> result has list() for foobar
4378    identical(c(NULL,     foobar, NULL, NULL, 1), c(  list(), 1))
4379    identical(c(NULL, b = foobar, NULL, NULL, 1), c(b=list(), 1))
4380    identical(c(a = NULL, b = foobar),                 list())
4381    identical(c(a = NULL, b = foobar, c = NULL),       list())
4382    identical(c(NULL, a = NULL, b = foobar, c = NULL), list())
4383})
4384## the first three cases failed in R <= 4.0.x
4385
4386
4387## quantile(*, pr)  allows pr values very slightly outside [0,1] -- PR#17891
4388stopifnot( identical(quantile(0:1, 1+1e-14), c("100%" = 1)) )
4389## failed  in R <= 4.0.2
4390
4391
4392## quantile(*, pr, names=FALSE)  with NA's in 'pr' -- PR#17892
4393x <- (0:99)/64
4394prN <- c(0.1, 0.5, 1, 2, 5, 10, 50, NA)/100
4395qxN  <- quantile(x, probs = prN)
4396qxNN <- quantile(x, probs = prN, names = FALSE)
4397stopifnot(exprs = {
4398    is.null(names(qxNN))
4399    identical(qxNN, unname(qxN))
4400    identical(NA_real_, quantile(x, probs = NA, names = FALSE))
4401})
4402## qxNN gave "Error in names(o.pr)[p.ok] <- names(qs) : ..."  in R <= 4.0.2
4403
4404
4405## Vectorize() no longer keeps "garbage":
4406vrep <- Vectorize(rep.int, "times")
4407stopifnot(identical(sort(names(environment(vrep))),
4408                    c("FUN", "SIMPLIFY", "USE.NAMES", "vectorize.args")))
4409## names(..) was of length 7 in R <= 4.0.2
4410
4411
4412## as.Date( "" ) -- PR#17909
4413dd <- c("", "2001-09-11")
4414(D1 <- as.Date(    dd)) # failed in R <= 4.0.2
4415(D2 <- as.Date(rev(dd)))
4416stopifnot(is.na(D1[1]), identical(D1, rev(D2)))
4417## "" was not treated correctly when at [1] in R <= 4.0.2
4418
4419
4420## ..elt() propagates visibility consistently with ..n and other args, PR#17905
4421local({
4422    fn <- function(...) list(withVisible(...elt(1)), withVisible(..2))
4423    stopifnot(identical(
4424	fn(invisible(NULL), invisible(NULL)),
4425	rep(list(withVisible(invisible(NULL))), 2)
4426    ))
4427})
4428
4429
4430## PR#17913 -- numToBits() accidentally was destructive
4431n0 <- c(-7.7, 2.34e55)
4432b0 <- numToBits(n0)
4433stopifnot(sum(l0 <- as.logical(b0)) == 62L,
4434          identical(which(head(l0, 10)), c(1L, 3:4, 7:8)),
4435          identical(n0, c(-7.7, 2.34e55)))
4436## was '0 0' for almost a month in R-devel
4437
4438
4439## No longer assuming integer length()
4440if(.Machine$sizeof.pointer >= 8) {
4441  .Internal(inspect(-199900000:2e9))
4442}
4443## gave an error in R <= 4.0.2
4444
4445
4446## PR#17907 -- capture.output() now using standard evaluation (SE) :
4447## parent.frame() returns the correct environment in capture.output()
4448local({
4449    fn <- function(env = parent.frame()) {
4450	capture.output(env)
4451	list(
4452	    env,
4453	    parent.frame()
4454	)
4455    }
4456    env <- environment()
4457    out <- fn()
4458    stopifnot(
4459	identical(out[[1]], out[[2]]),
4460	identical(out[[1]], env)
4461    )
4462})
4463## capture.output() works with forwarded dots
4464local({
4465    wrapper <- function(...) {
4466	capture.output(..., type = "output")
4467    }
4468    out <- local({
4469	foo <- 1
4470	wrapper(foo)
4471    })
4472    stopifnot(identical(out, capture.output(1)))
4473})
4474## Failed when capture.output() was using NSE
4475
4476
4477## Inverse of numToBits() via
4478stopifnot(identical(packBits(b0, "double"), n0))
4479r <- c(pi, 1+ (0:8)/4); head(b <- numToBits(r), 25)
4480stopifnot(identical(packBits(b, "double"), r))
4481## thanks to PR#17914 by Bill Dunlap
4482
4483
4484## quantile(x, probs) when probs has NA's, PR#17899
4485stopifnot(identical(quantile(NULL), quantile(numeric())), # back-compatibility
4486	  identical(quantile(structure(numeric(), names = character()), names = FALSE),
4487		    rep(NA_real_, 5)))
4488L <- list(ordered(letters[1:11]), # class "ordered" "factor"
4489          seq(as.Date("2000-01-07"), as.Date("1997-12-17"), by="-1 month"))
4490ct <- seq(as.POSIXct("2020-01-01 12:13:14", tz="UTC"), by="1 hour", length.out = 47)
4491LL <- c(L, list(o0 = L[[1]][FALSE], D0 = L[[2]][FALSE],
4492                ct = ct, lt = as.POSIXlt(ct), num= as.numeric(ct)))
4493prb <- seq(0, 1, by=2^-8) # includes 0.25, 0.5, etc
4494for(x in LL) {
4495    cat("x : "); str(x, vec.len=3)
4496    clx <- class(if(inherits(x, "POSIXlt")) as.POSIXct(x) else x)
4497    ## for "ordered" *and* "Date", type must be 1 or 3
4498    for(typ in if(any(clx %in% c("ordered", "Date"))) c(1,3) else 1:7) {
4499        cat(typ, ": ")
4500        stopifnot(exprs = {
4501            identical(clx, class(q1 <- quantile(x, probs=  prb,     type=typ)))
4502            identical(clx, class(qN <- quantile(x, probs=c(prb,NA), type=typ))) # failed
4503            ## for "POSIXct", here q1 is integer, qN "double":
4504            { if(inherits(q1, "POSIXct")) storage.mode(qN) <- storage.mode(q1); TRUE }
4505            identical(qN[seq_along(q1)], q1)
4506            is.na(    qN[length(qN)])
4507        })
4508    }; cat("\n")
4509}
4510## qN often lost class() e.g. for "ordered" and "Date" in  R <= 4.0.2
4511
4512
4513## isS3stdGeneric() traced function:
4514trace(print)
4515stopifnot( isS3stdGeneric(print) )
4516untrace(print)
4517## was FALSE in R <= 4.0.2
4518
4519
4520## PR#17897: all.equal.factor() did not distinguish the two different NA in factors
4521labs <- c("a", "b", NA)
4522x <- factor(      3:1,                labels = labs)
4523y <- factor(c(NA, 2:1), levels = 1:3, labels = labs)
4524x
4525dput(x) ; dput(y) ## --> they are clearly different, but print the same:
4526stopifnot(exprs = {
4527    identCO(x,y)
4528    is.character(print(ae <- all.equal(x,y)))
4529    !englishMsgs || grepl("NA mismatch", ae, fixed=TRUE)
4530})
4531## all.equal() gave TRUE wrongly, from 2012 till R <= 4.0.2
4532
4533
4534## PR#17935:  `[.formula` for formulas with NULL:
4535forms <- list(f0 = (~ NULL)
4536            , f1 = (z ~ NULL)
4537            , f2 = (NULL ~ x)
4538            , f3 = (NULL ~ NULL)
4539              )
4540rr <- lapply(forms, function(f)
4541        lapply(seq_along(f), function(ii) f[ii]))
4542cN <- quote(NULL())
4543stopifnot(exprs = {
4544    identical( unique(lapply(rr , `[[`, 1)), list(`~`()))
4545    identical( lapply(unname(rr), `[[`, 2),  list(cN, quote(z()), cN,cN) )
4546})
4547## subsetting failed for all 4 formulas in R <= 4.0.3
4548(tm1 <- (~ "~")[-1])
4549(tq1 <- (~ `~`)[-1])
4550stopifnot(exprs = {
4551    identical((~ NA)[-1], quote(NA())) ## subsetting (~ NA) failed in R <= 4.0.3
4552    identical(tm1,        `[[<-`(call("T"), 1L, "~")) ;  is.call(tm1)
4553    identical(tq1,        structure(call("~"), class="formula", ".Environment" = globalenv()))
4554})
4555## zero-length formulas from subsetting are now equal to formula(NULL)
4556exps <- expression(
4557           (~ x)[FALSE]
4558         , (~ x)[rep(FALSE, 2)]
4559         , (y ~ x)[FALSE])
4560formL <- lapply(exps, eval)
4561stopifnot( length(unique(formL)) == 1,
4562          all.equal(formL[[1]], formula(NULL)) )
4563## Gave error  "attempt to set an attribute on NULL" in R <= 4,0.3
4564
4565
4566## Regression in .traceback()  PR#17930
4567op <- options(keep.source=TRUE)
4568f <- function() .traceback(1)
4569g <- function() f()
4570x <- g()
4571stopifnot(inherits(attr(x[[1]], 'srcref'), "srcref"))
4572options(op)
4573## had worked up to R 3.6.3, but not from 4.0.0 to 4.0.3
4574
4575
4576## Summary() and Math() data.frame methods with *logical* columns
4577a <- na.omit(airquality)
4578aF <- a[FALSE,] # 0-row version of it
4579dL0 <- data.frame(x=numeric(), L=logical()) # logical column
4580stopifnot(exprs = {
4581    ## "Summary" :
4582    sum(aF) == 0 # gave Error  "only defined on a data frame with all numeric variables"
4583    sum(subset(a, Ozone > 200)) == 0 # (ditto)
4584    suppressWarnings(range(dL0) == c(Inf, -Inf)) # (2 warnings)
4585    ## "Math" , gave Error..: non-numeric variable(s) in data frame :
4586    identical(exp(data.frame(L=TRUE)), data.frame(L=exp(TRUE)))
4587    identical(sinL0 <- sin(dL0), data.frame(x=numeric(), L=numeric()))
4588    identical(sinL0, log1p(dL0))
4589    identical(cumsum(dL0),       data.frame(x=numeric(), L=integer()))
4590})
4591## probably never worked in any R <= 4.0.3
4592
4593
4594## unlist(<pairlist w/ list>, recursive=FALSE), PR#17950
4595l.ex <- list(a = list(1:5, LETTERS[1:5]), b = "Z", c = NA)
4596stopifnot(identical(
4597    unlist(as.pairlist(l.ex), recursive = FALSE),
4598    unlist(            l.ex , recursive = FALSE)))
4599##
4600l2 <- list(a = "a", b = quote(b), c = pi+2i)# no list-entries
4601stopifnot(
4602    identical(
4603        unlist(as.pairlist(l2), recursive = FALSE) -> ul2,
4604        unlist(as.pairlist(l2))),
4605    identical(ul2, unlist(l2, recursive = FALSE)))
4606## lost content in R <= 4.0.3  ('FIXME' in source went lost in 2006)
4607
4608
4609## `class<-` was mutating outside of an assignment context
4610x <- c(1)
4611xx <- `class<-`(x, "foo")
4612stopifnot(identical(class(x), "numeric"))
4613
4614
4615## Can splice expression vectors with attributes -- PR#17869
4616local({
4617    exprs <- structure(expression(1, 2, 3), attr = TRUE)
4618    exprsSrcrefs <- parse(text = "1;2;3", keep.source = TRUE)
4619    stopifnot(
4620	identical(
4621	    bquote({ ..(exprs) }, splice = TRUE),
4622	    call("{", 1, 2, 3)
4623	),
4624	identical(
4625	    bquote({ ..(exprsSrcrefs) }, splice = TRUE),
4626	    call("{", 1, 2, 3)
4627	)
4628    )
4629})
4630
4631
4632## some issues with task callbacks:
4633## avoid adding a reference to the value:
4634x <- c(1)
4635old_xr <- .Internal(refcnt(x))
4636TCB <- addTaskCallback(function(...) TRUE)
4637x
4638stopifnot(.Internal(refcnt(x)) == old_xr)
4639removeTaskCallback(TCB)
4640
4641## these used to fail with "object 'foo' not found":
4642TCB <- addTaskCallback(function(e, v, ...) { v; TRUE})
4643quote(foo)
4644removeTaskCallback(TCB)
4645TCB <- addTaskCallback(function(...) { length(list(...)); TRUE},
4646                       data = quote(foo))
4647removeTaskCallback(TCB)
4648
4649
4650## all.equal(<functions>) should check.environment (Kevin Van Horn, R-devel)
4651f <- function(x) function(y) x+y
4652dif <- all.equal(f(5), f(0))
4653stopifnot(is.function(f(5)),
4654          is.character(dif), grepl("difference", dif))
4655## all.equal() gave TRUE in  R <= 4.0.x
4656
4657
4658## p.adjust(<empty>, n=0) - PR#18002
4659## (1st fix-proposal computed wrongly w/ NAs:
4660pp <- 2^-(40:1); pp[17:19] <- NA
4661ppa <- p.adjust(pp, "holm") # worked always but was not strictly tested
4662stopifnot(all.equal(c(3.365e-11, 6.548e-11, 1.273e-10, 2.474e-10, 4.802e-10,
4663                      9.313e-10, 1.804e-09), ppa[1:7]))
4664n0 <- numeric()
4665stopifnot(identical(n0, p.adjust(n0, n = length(n0))))
4666## errored in R <= 4.0.3
4667
4668
4669## show(<standardGeneric>) where it has package ".GlobalEnv"
4670f <- function(x) x
4671setGeneric("f")
4672f # failed for a while (in R-devel only)
4673
4674
4675## all.equal.function() in case the env contains '...' -- PR#18010
4676a <- (function(...) function() NULL)(1)
4677b <- (function(...) function() NULL)(1) # want "a .eq. b"
4678D <- (function(...) function() NULL)(1:2 < 3) # want "D .NE. b"
4679e.. <- (function(...) environment())(1)
4680##' General creator of "..."  (DOTSXP) objects (short form by Suharto Anggono):
4681...maker <- function(...) get("...") ## fails if called without argument
4682...maker <- function(...) (function(...) environment())(...)[["..."]]
4683str( ddd <- ...maker(1) )
4684str( Ddd <- environment(D)[["..."]] ) # length 1, mode "...":
4685str( D2  <- ...maker(TRUE,TRUE))      # length 2, mode "...":
4686str( D3n <- ...maker(ch = {cat("HOO!\n"); "arg1"}, 2, three=1+2) )
4687## These all worked "accidentally" in R <= 4.0.x
4688assertErrV(lD2 <- D2[]) #  type '...' is not subsettable
4689assertErrV(D3n[]) #   (ditto)
4690assertErrV(D3n[][["three"]]) #  (ditto)
4691assertErrV(D3n $ ch) #  (ditto)
4692str( D3n <- ...maker(ch = {cat("HOO!\n"); "arg1"}, 2, three=1+2) )
4693stopifnot(exprs = {
4694    identical(alist(a=)$a, ...maker())# "*the* missing", the empty symbol
4695    identical(ddd, ...maker(1))
4696    identical(Ddd, ...maker(1:2 < 3))
4697    is.character(aeLD <- all.equal(quote(x+1), ddd))
4698    grepl("Mode",    aeLD[1])
4699    grepl("deparse", aeLD[2])
4700    all.equal(a, b) # failed with "Component “...”: target is not list-like" since r79585 (2020-12-07)
4701    all.equal(e.., environment(a))
4702    ## all.equal() dispatch for "..." objects ('ddd') directly:
4703    typeof(ddd) == "..."
4704    typeof(D2) == "..."
4705    length(D2) == 2
4706    is.character(aeD <- all.equal(a, D) )
4707    grepl("same length", aeD)
4708    grepl("...", aeD, fixed=TRUE)
4709    grepl("not identical", aeD)
4710    ##
4711    ## names(<DOTSXP>):
4712    is.null(names(ddd))
4713    identical(c("ch", "", "three"), names(D3n))
4714})
4715##  for identical() ==> ./reg-tests-2.R  -- as it's about "output"
4716op <- options(keep.source = FALSE) # don't keep "srcref" etc
4717##
4718Qlis <- list(NULL
4719## Next 4 now must work as identical(X,X) is true:
4720, ddd = ddd
4721, Ddd = Ddd
4722, D2  = D2
4723, D3n = D3n
4724, Qass   = quote(x <- 1)
4725, Qbrc   = quote({1})
4726, Qparen = quote((1))
4727, Qif    = quote(if(1)2)
4728, Qif2   = quote(if(1)2 else 3)
4729, Qwhile = quote(while(1) 2)
4730)
4731##
4732sapply(Qlis, class)
4733stopifnot( sapply(Qlis, function(obj) all.equal(obj, obj)) )
4734## only the first failed in R <= 4.0.3
4735
4736
4737## See PR#18012 -- may well change
4738aS <- (function(x) function() NULL)(stop('hello'))
4739bS <- (function(x) function() NULL)(stop('hello'))
4740try( all.equal(aS, bS) ) ## now (check.environment=TRUE) triggers the promise ..
4741## Now have a way *not* to evaluate aka force the promise:
4742(aeS <- all.equal(aS, bS, evaluate=FALSE)) # no promises forced
4743stopifnot(grepl("same names.* not identical", aeS))
4744
4745
4746## PR#18032: identical(<DOTSXP>,*)
4747ddd <- ...maker(47)
4748DDD <- ...maker(ch = {cat("Hu hu!\n"); "arg1"}, two = 1+1, pi, ABC="A")
4749stopifnot(exprs = {
4750    identical(ddd,ddd)
4751    identical(DDD,DDD)
4752    identical  (ddd, ...maker(47))
4753    ! identical(ddd, ...maker(7 )) # these *are* different
4754    ! identical(ddd, DDD)
4755})
4756options(op)
4757
4758
4759## PR#18034 : explicit and implicit row.names=NULL for as.data.frame.list()
4760data(mtcars, package="datasets")
4761lmtcars <- as.list(mtcars)
4762names(lmtcars[[3]]) <- RN <- c(letters[1:26], LETTERS[1:6])
4763dfcars1 <- as.data.frame.list(lmtcars)# default: missing(row.names); uses RN
4764dfcarsN <- as.data.frame.list(lmtcars, row.names = NULL)# does *not* use  RN
4765stopifnot(identical(RN,    rownames      (dfcars1)) ,
4766          identical(-32L, .row_names_info(dfcarsN))) # now has "automatic" (integer) row names
4767## dfcarsN == dfcars1  in  R <= 4.0.3
4768
4769
4770## str(x) when x has "unusal" length() semantics such that lapply() / vapply() fails:
4771length.Strange4 <- function(x) 4
4772`[[.Strange4` <- function(x, i) {
4773    stopifnot(length(i) == 1)
4774    if(i %in% 1:4) paste(sprintf("content of  x[[%d]]", i))
4775    else stop("invalid [[-index, partly out of 1..4")
4776}
4777`[.Strange4` <- function(x, i) {
4778    isM <- length(i) > 1
4779    if(all(i %in% 1:4)) paste(sprintf("content of  x[%s]",
4780                                      if(isM) paste0("c(", i, collapse=", ", ")")
4781                                      else paste0(i, collapse=", ")))
4782    else stop("invalid indices, partly out of 1..4")
4783}
4784L <- structure(as.list(1:6), class="Strange4")
4785stopifnot(is.list(L), length(L) == 4, length(unclass(L)) == 6)
4786assertErrV(lapply(L, length))
4787assertErrV(vapply(L, typeof, ""))
4788lns <- capture.output(str(L)) # no longer fails
4789stopifnot(length(lns) == 1+6,  grepl("hidden list", lns[1]))
4790## str() failed for these and similar in R <= 4.0.x
4791
4792
4793## PR#18041:  checkRdaFiles(<more-than-1>) $ version
4794save(pi, file = rda2 <- tempfile(fileext = ".rda"), version = 2)
4795save(pi, file = rda3 <- tempfile(fileext = ".rda"), version = 3)
4796stopifnot(identical(2:3, tools::checkRdaFiles(c(rda2, rda3))$version))
4797## gave '3 3' in R <= 4.0.3
4798
4799
4800if (l10n_info()$"UTF-8") {
4801  x <- "d\xc3\xa9faut" # "défaut" flagged as native
4802  stopifnot(grepl("d.faut", x)) # incorrectly FALSE in in R < 4.1
4803}
4804
4805
4806## constructing the names() of quantile():
4807str(L <- lapply(c(2,3,5,7), function(dig) { options(digits = dig)
4808    names(quantile(lynx, probs = 1 - 10^(-1:-5))) }))
4809stopifnot(length(unique(L)) == 1)
4810## in R <= 4.0.x,  L contained 3 different results
4811
4812
4813## PR#18079:  sub() & gsub(patt, repl, x) -- when patt is NA
4814(x <- c(a="abc", b="bd", d=NA, foo="babar"))
4815stopifnot(exprs = {
4816    identical(names(x1  <-  sub("a", "_", x)), names(x)) ; x1[["foo"]] == "b_bar"
4817    identical(names(x2  <- gsub("a", "_", x)), names(x)) ; x2[["foo"]] == "b_b_r"
4818    identical(names(xN2 <- gsub(NA , "_", x)), names(x)) ; is.na(xN2)
4819    identical(names(xN1 <-  sub(NA , "_", x)), names(x)) ; is.na(xN1)
4820})
4821## NA-pattern did not keep any attributes in R <= 4.0
4822
4823
4824## svn c80082/80141's change to grep.R broke several of these -- the PR#18063 saga
4825check_regexetc <- function(txt, fx.ptn, s.ptn, gr.ptn, msg = stop) {
4826    stopifnot(is.character(txt))
4827    chkString <- function(ch) {
4828        if(!is.character(ch)) { str(ch); stop("is not a character") }
4829        if(length(ch) != 1)   { str(ch); stop("is not of length 1") }
4830    }
4831    chkString(fx.ptn)
4832    chkString( s.ptn)
4833    chkString(gr.ptn)
4834    ## ref: result using "character";
4835    ## x  : from as.character(.) w/ "lost" attributes
4836    identC <- function(x, ref) {
4837        attributes(ref) <- attributes(ref)[names(attributes(x))]
4838        identical(x, ref)
4839    }
4840
4841    a2_fns <- expression(grepl,  regexpr, gregexpr,  regexec) # plus possibly:
4842    if(getRversion() >= "4.1") a2_fns <- c(a2_fns, expression(gregexec))
4843
4844    exclude <- NA # (the default, used in  factor(.., exclude=*)
4845    ##
4846    for (txt_i in 1:3) {
4847        if (txt_i == 2) { # txt_i  \in {2, 3}  will have  NA in 'txt'
4848            txt <- c(NA_character_, txt, NA_character_)
4849        } else if (txt_i == 3) {
4850            exclude <- NULL
4851        }
4852        txt_fkt <- factor(txt, exclude = exclude)
4853        cat("txt_i = ", txt_i,"; str(<factor>):\n", sep="") ; str(txt_fkt)
4854        if(chkpre <- !is.null(names(txt_fkt)) && length(levels(txt_fkt)) < length(txt_fkt)) {
4855            txt_fkt_pre <- txt_fkt[seq(levels(txt_fkt))]
4856            cat("str(txt_fkt_pre):\n") ; str(txt_fkt_pre)
4857        }
4858
4859        for (ptn in c(fx.ptn, s.ptn, gr.ptn, NA_character_)) {
4860            fixed <- (!is.na(ptn) && ptn == fx.ptn)
4861            perl  <- (!is.na(ptn) && ptn == gr.ptn)
4862            ptn_ch <- if(is.na(ptn)) ptn else dQuote(ptn, q=NULL)
4863            cat(sprintf(" pattern=%16s, fixed=%s, perl=%s:  ", ptn_ch, fixed, perl))
4864            for (e_2 in a2_fns) {
4865                f_2 <- eval(e_2)
4866                f_2s <- as.character(e_2)
4867                ## when ptn ==  NA_character_  only test grep() & grepl() :
4868                if(is.na(ptn) && !(f_2s %in% c("grep", "grepl"))) next
4869                cat(f_2s,"")
4870                if(!identical(
4871                    f_2(ptn, txt_fkt, fixed = fixed, perl = perl),
4872                    f_2(ptn, txt,     fixed = fixed, perl = perl)
4873                    )) msg(sprintf(
4874                           "not identical: %s(%s, txt*, fixed=%s, perl=%s)",
4875                           f_2s, ptn_ch, fixed, perl))
4876            }
4877
4878            cat("\n\t grep(*, invert=F/T, value = F/T): ")
4879            for(iv in list(c(FALSE,FALSE), c(TRUE,FALSE), c(FALSE,TRUE), c(TRUE,TRUE)))
4880              if(!identical(
4881                grep(ptn, txt_fkt, fixed = fixed, perl = perl, invert=iv[1], value = iv[2]),
4882                grep(ptn, txt,     fixed = fixed, perl = perl, invert=iv[1], value = iv[2])
4883              )) msg(sprintf(
4884                    "not identical: grep(%s, txt*, fixed=%s, perl=%s, invert=%s, value=%s)",
4885                    ptn_ch, fixed, perl, iv[1], iv[2]))
4886            cat("f_3, i.e. *sub() :")
4887            for (e_3 in expression(sub, gsub)) {
4888                ##                 ---  -----
4889                f_3 <- eval(e_3)
4890                f_3s <- as.character(e_3)
4891                cat(f_3s,"")
4892                if(!identC(##identical(
4893                    res <-
4894                    f_3(ptn, "@@", txt_fkt, fixed = fixed, perl = perl),
4895                    f_3(ptn, "@@", txt,     fixed = fixed, perl = perl)
4896                )) msg(sprintf(
4897                    "not identical: %s(%s, \"@@\", txt*, fixed=%s, perl=%s)",
4898                    f_3s, ptn_ch, fixed, perl))
4899                if(chkpre &&
4900                   is.null(names(f_3(ptn, "@@", txt_fkt_pre, fixed = fixed, perl = perl))) !=
4901                   is.null(names(res))
4902                ) msg(sprintf(
4903                    "not identical pre: names(%s(%s, \"@@\", txt_fkt*, fixed=%s, perl=%s))",
4904                    f_3s, ptn_ch, fixed, perl))
4905            }
4906            cat("\n")
4907        }
4908        cat("--------- finished  txt_i = ", txt_i,"\n")
4909    }
4910} ## end{ check_regexetc }
4911
4912if(requireNamespace("codetools", quietly = TRUE))
4913    codetools::findGlobals(check_regexetc, merge=FALSE)
4914
4915## "default check"
4916txt <- c(
4917    "The", "licenses", "for", "most", "software", "are",  "designed", "to",
4918    "take", "away", "your", "freedom",  "to", "share", "and", "change", "it.",
4919    "", "By", "contrast,", "the", "GNU", "General", "Public", "License",
4920    "is", "intended", "to", "guarantee", "your", "freedom", "to", "share",
4921    "and", "change", "free", "software", "--", "to", "make", "sure", "the",
4922    "software", "is", "free", "for", "all", "its", "users")
4923names(txt) <- paste0("c", seq_along(txt))
4924if(FALSE)
4925 system.time(check_regexetc(txt, fx.ptn = "e", s.ptn = "e.", gr.ptn = "(?<a>e)(?<b>.)", msg=warning))
4926check_regexetc(txt, fx.ptn = "e", s.ptn = "e.", gr.ptn = "(?<a>e)(?<b>.)")
4927##============
4928
4929
4930x <- c("e", "\xe7")
4931Encoding(x) <- "UTF-8"
4932x <- factor(c(1, 1, 2), c(1, 2), x)
4933tools::assertWarning(grep("e", x, fixed = TRUE))
4934## broken by svn c80136
4935
4936
4937## "difftime" objects pmin() .. & modifications when "units" differ -- PR#18066
4938x_hr <- as.difftime(1:10, units = "hours")
4939y_hr <- as.difftime( 5,   units = "hours")
4940y_mi <- `units<-`(y_hr, "mins")
4941x_na <- `[<-`(x_hr, 2L, NA_real_)
4942stopifnot(exprs = { ## these all are FALSE in R <= 4.0.*
4943    inherits(rep(y_hr, 5L), "difftime")
4944    identical(`[<-`(x_hr, 1L, y_hr), `[<-`(x_hr, 1L, y_mi))
4945    identical(pmin(x_hr, y_hr), pmin(x_hr, y_mi))
4946    identical(pmin(x_na, y_hr, na.rm = TRUE),
4947              pmin(x_na, y_mi, na.rm = TRUE))
4948})
4949## objects became wrong without warning in R <= 4.0.x
4950
4951## Bytes Enc may be unset directly to unknown (impossible R <= 4.0.x)
4952x <- "fa\xE7ile"
4953Encoding(x) <- "bytes"
4954xu <- x
4955Encoding(xu) <- "unknown"
4956stopifnot(identical(Encoding(c(x, xu)), c("bytes", "unknown")))
4957
4958
4959## Correctness tests for sorted ALTREP handling of unique/duplicated (PR#17993)
4960
4961
4962altrep_dup_test <- function(vec, nalast, fromlast, s3class) {
4963    svec_ar <- sort(vec, na.last = nalast)
4964    svec_std <- svec_ar
4965    svec_std[1] <- svec_std[1] ## this clobbers ALTREP-ness
4966    if(!is.null(s3class)) {
4967        class(svec_ar) <- s3class
4968        class(svec_std) <- s3class
4969    }
4970    stopifnot(identical(duplicated(svec_ar, fromLast = fromlast),
4971                        duplicated(svec_std, fromLast = fromlast)),
4972              identical(unique(svec_ar, fromLast = fromlast),
4973                        unique(svec_std, fromLast = fromlast)),
4974              identical(anyDuplicated(svec_ar, fromLast = fromlast),
4975                        anyDuplicated(svec_std, fromLast = fromlast))
4976              )
4977}
4978
4979altint_dup_check <- function(vec, numna, nalast, fromlast, s3class = NULL) {
4980     if(length(vec) > 0 && numna > 0) {
4981         vec[1:numna] = NA_integer_
4982     }
4983     altrep_dup_test(vec, nalast = nalast, fromlast = fromlast, s3class = s3class)
4984}
4985
4986altint_dup_multicheck <- function(vec, numna, s3class = NULL) {
4987    altint_dup_check(ivec, numna, FALSE, FALSE, s3class = s3class)
4988    altint_dup_check(ivec, numna, FALSE, TRUE, s3class = s3class)
4989    altint_dup_check(ivec, numna, TRUE, FALSE, s3class = s3class)
4990    altint_dup_check(ivec, numna, TRUE, TRUE, s3class = s3class)
4991}
4992
4993altreal_dup_check <- function(vec, numna, numnan, numinf, nalast, fromlast,
4994                              s3class = NULL) {
4995    if(length(vec) > 0) {
4996        ## on Intel adding 0 changes the NA_real_ NaN from signaling
4997        ## to non-signaling
4998        if(numna > 0) {
4999            vec[1:numna] <- rep(c(NA_real_, NA_real_ + 0), length.out = numna)
5000        }
5001        if(numnan > 0) {
5002            vec[seq(1 + numna, numna + numnan)] <-
5003                rep(c(NaN, NaN + 0), length.out = numnan)
5004        }
5005        if(numinf > 0) {
5006            infstrt <- 1 + numna + numnan
5007            vec[seq(infstrt, infstrt + numinf - 1)] <-
5008                rep(c(Inf, -Inf), length.out = numinf)
5009        }
5010    } ## end length(vec) > 0
5011    altrep_dup_test(vec, nalast = nalast, fromlast = fromlast,
5012                    s3class = s3class)
5013}
5014
5015altreal_dup_multicheck <- function(vec, numna, numnan, numinf, s3class = NULL) {
5016    altreal_dup_check(ivec, numna, numnan, numinf, FALSE, FALSE,
5017                      s3class = s3class)
5018    altreal_dup_check(ivec, numna, numnan, numinf, FALSE, TRUE,
5019                      s3class = s3class)
5020    altreal_dup_check(ivec, numna, numnan, numinf, TRUE, FALSE,
5021                      s3class = s3class)
5022    altreal_dup_check(ivec, numna, numnan, numinf, TRUE, TRUE,
5023                      s3class = s3class)
5024}
5025
5026## NB buffer size used by ITERATE_BY_REGION macros is 512, so we need to test
5027## handling of NAs, NaNs, and Infs around/past that barrier.
5028
5029set.seed(83); dvec <- round(runif(2000, 1, 20), 1)
5030ivec <- ceiling(dvec)
5031
5032altint_dup_multicheck(ivec, 0)
5033## just before buffer break
5034altint_dup_multicheck(ivec, 512)
5035## just after buffer break
5036altint_dup_multicheck(ivec, 513)
5037## all nas
5038altint_dup_multicheck(ivec, 2000)
5039
5040altreal_dup_multicheck(dvec, 0, 0, 0)
5041## NA/NaN up to edge of 1 buffer
5042altreal_dup_multicheck(dvec, 256, 256, 0)
5043## NA/NaN  crossing buffer barrier
5044altreal_dup_multicheck(dvec, 256, 257, 0)
5045## all NA/NaN
5046altreal_dup_multicheck(dvec, 1000, 1000, 0)
5047## non-finite filling exactly one buffer on each side
5048altreal_dup_multicheck(dvec, 0, 0, 1024)
5049## non-finite  across more than one buffer on both sides
5050altreal_dup_multicheck(dvec, 0, 0, 1026)
5051## all non-finite
5052altreal_dup_multicheck(dvec, 0, 0, 2000)
5053
5054## sanity checks
5055## no breakage on length 0 vectors
5056altint_dup_multicheck(integer(0), 0)
5057altreal_dup_multicheck(numeric(0), 0, 0, 0)
5058## works on on length 1 vectors
5059altint_dup_multicheck(1L, 0)
5060altreal_dup_multicheck(1.0, 0, 0, 0)
5061
5062
5063## s3 methods take precedence over altrep methods
5064## these methods are (very) wrong on purpose so there can be
5065## no doubt they are hit rather than the altrep code even in the sorted case
5066duplicated.fake_class <-  function(x, incomparables = FALSE, ...) {
5067    rep(c(TRUE, FALSE), length.out = length(x))
5068}
5069
5070unique.fake_class <- function(x, incomparables = FALSE, ...) {
5071    x[c(1, 5, length(x))]
5072}
5073
5074altint_dup_multicheck(ivec, 0, s3class = "fake_class")
5075altreal_dup_multicheck(dvec, 0, 0, 0, s3class = "fake_class")
5076
5077
5078## Value stored in .Last.value needs to count at least one reference
5079c(1)
5080stopifnot(1 + .Last.value + .Last.value == 3)
5081
5082
5083## in 4.1.0, encodeString() below would return unflagged UTF-8
5084## representation of the string
5085if (l10n_info()$"Latin-1" && localeToCharset()=="ISO8859-1") {
5086  # checking localeToCharset() because on Windows, in C locale,
5087  # l10n_info() would report Latin-1 when that is the code page
5088  y <- "\xfc"
5089  stopifnot(y == encodeString(y))
5090}
5091
5092
5093
5094## keep at end
5095rbind(last =  proc.time() - .pt,
5096      total = proc.time())
5097