diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index b598e0e78..c4122a9f2 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -1,4 +1,5 @@ on: + push: schedule: - cron: '17 13 23 * *' # 23rd of month at 13:17 UTC workflow_dispatch: @@ -17,17 +18,42 @@ jobs: matrix: os: [macOS-latest, windows-latest, ubuntu-latest] r: ['devel', 'release', '3.5', '3.6', '4.0', '4.1', '4.2', '4.3', '4.4', '4.5'] - locale: ['en_US.utf8', 'zh_CN.utf8', 'lv_LV.utf8'] # Chinese for translations, Latvian for collate order (#3502) + locale: ['en_US.utf8', + # Multibyte characters: Mandarin + 'zh_CN.utf8', + # Collate order (#3502, see also #7837): Latvian, Azeri, Hungarian, Faroese, Albanian + 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8', + # Local time formatting (for R bug #19117) + 'vi_VN.utf8'] + # we're constrained by GHA inflexibility to do a tedious thing here with 'exclude' below. + # better would be for GHA to support multiple 'matrix' configs (one for ubuntu, one for other OS); + # an approach with multiple jobs would tediously require copy-pasting the _rest_ of the steps exclude: # only run non-English locale CI on Ubuntu - os: macOS-latest locale: 'zh_CN.utf8' - os: macOS-latest locale: 'lv_LV.utf8' + - os: macOS-latest + locale: 'az_AZ.utf8' + - os: macOS-latest + locale: 'hu_HU.utf8' + - os: macOS-latest + locale: 'fo_FO.utf8' + - os: macOS-latest + locale: 'sq_MK.utf8' - os: windows-latest locale: 'zh_CN.utf8' - os: windows-latest locale: 'lv_LV.utf8' + - os: windows-latest + locale: 'az_AZ.utf8' + - os: windows-latest + locale: 'hu_HU.utf8' + - os: windows-latest + locale: 'fo_FO.utf8' + - os: windows-latest + locale: 'sq_MK.utf8' # macOS/arm64 only available for R>=4.1.0 - os: macOS-latest r: '3.5' @@ -44,24 +70,11 @@ jobs: steps: - name: Set locale - if: matrix.os == 'ubuntu-latest' && matrix.locale == 'en_US.utf8' - run: | - sudo locale-gen en_US - echo "LC_ALL=en_US.utf8" >> $GITHUB_ENV - - - name: Set locale - if: matrix.locale == 'zh_CN.utf8' - run: | - sudo locale-gen 'zh_CN.utf8' - echo "LC_ALL=zh_CN.utf8" >> $GITHUB_ENV - echo "LANGUAGE=zh_CN" >> $GITHUB_ENV - - - name: Set locale - if: matrix.locale == 'lv_LV.utf8' + if: matrix.os == 'ubuntu-latest' run: | - sudo locale-gen 'lv_LV.utf8' - echo "LC_ALL=lv_LV.utf8" >> $GITHUB_ENV - echo "LANGUAGE=lv_LV" >> $GITHUB_ENV + sudo locale-gen "${{ matrix.locale }}" + echo "LC_ALL=${{ matrix.locale }}" >> $GITHUB_ENV + echo "LANGUAGE=$(echo '${{ matrix.locale }}' | cut -d'.' -f1)" >> $GITHUB_ENV - uses: actions/checkout@v7 @@ -118,7 +131,9 @@ jobs: other_deps_expr = parse('inst/tests/other.Rraw', n=1L) eval(other_deps_expr) - other_pkgs = get(as.character(other_deps_expr[[1L]][[2L]])) + other_pkgs = setdiff( + get(as.character(other_deps_expr[[1:2]])), + tools:::.get_standard_package_names()$base) # skip parallel # Many will not install on oldest R versions message("*** Installing fully optional packages ***") try(install.packages(c(other_pkgs, "rcmdcheck"))) @@ -133,10 +148,7 @@ jobs: } else { message(sprintf("Skipping other.Rraw since some required packages are not available: %s\n", toString(other_pkgs[!has_other_pkg]))) } - # IINM rcmdcheck isolates its env from the calling process', besides what's passed to env= - env = c( - TEST_DATA_TABLE_WITH_OTHER_PACKAGES=as.character(run_other) - ) + Sys.setenv(TEST_DATA_TABLE_WITH_OTHER_PACKAGES=as.character(run_other)) do_vignettes = requireNamespace("litedown", quietly=TRUE) @@ -148,13 +160,13 @@ jobs: check_args = c(check_args, "--no-build-vignettes", "--ignore-vignettes") } if (requireNamespace("rcmdcheck", quietly=TRUE)) { - rcmdcheck::rcmdcheck(args = check_args, build_args = build_args, error_on = "warning", check_dir = "check", env=env) + rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check") } else { Rbin = if (.Platform$OS.type == "windows") "R.exe" else "R" system2(Rbin, c("CMD", "build", ".", build_args)) dt_tar = list.files(pattern = "^data[.]table_.*[.]tar[.]gz$") if (!length(dt_tar)) stop("Built tar.gz not found among: ", toString(list.files())) - res = system2(Rbin, c("CMD", "check", dt_tar[1L], check_args), stdout=TRUE, stderr=TRUE, env=sprintf("%s=%s", names(env), env)) + res = system2(Rbin, c("CMD", "check", dt_tar[1L], check_args), stdout=TRUE, stderr=TRUE) if (!is.null(attr(res, "status")) || anyNA(res) || any(grepl("^Status:.*(ERROR|WARNING)", res))) { writeLines(as.character(res)) stop("R CMD check failed") diff --git a/inst/tests/optimize.Rraw b/inst/tests/optimize.Rraw index 2c835c2c1..4c25baee8 100644 --- a/inst/tests/optimize.Rraw +++ b/inst/tests/optimize.Rraw @@ -192,7 +192,8 @@ dt = data.table(x = sample(letters, 300, TRUE), i2 = sample(c(-10:10, NA), 300, TRUE), d1 = as.numeric(sample(-10:10, 300, TRUE)), d2 = as.numeric(sample(c(NA, NaN, -10:10), 300, TRUE))) -if (test_bit64) { +# is.na() test for ancient {bit64} on ancient R +if (test_bit64 && is.na(integer64()[1L])) { dt[, `:=`(d3 = as.integer64(sample(-10:10, 300, TRUE)))] dt[, `:=`(d4 = as.integer64(sample(c(-10:10,NA), 300, TRUE)))] } diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index 9ae3ffe38..7f45bd86e 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -1,9 +1,11 @@ -pkgs = c("DBI", "RSQLite", "bit64", "ggplot2", "caret", "dplyr", "gdata", "hexbin", "knitr", "nanotime", "nlme", "parallel", "plyr", "R.utils", "sf", "vctrs", "zoo", "xts", "yaml") +pkgs = c("DBI", "RSQLite", "bit64", "ggplot2", "caret", "dplyr", "gdata", "hexbin", "knitr", "nanotime", "nlme", "parallel", "plyr", "R.oo", "R.utils", "sf", "vctrs", "zoo", "xts", "yaml") # First expression of this file must be as above: .gitlab-ci.yml uses parse(,n=1L) to read one expression from this file and installs pkgs. # So that these dependencies of other.Rraw are maintained in a single place. # TODO(R>=3.6.0): use attach.required=FALSE to let us keep pkgs= in alphabetical order (https://stat.ethz.ch/pipermail/r-devel/2026-July/084630.html) # TEST_DATA_TABLE_WITH_OTHER_PACKAGES is off by default so this other.Rraw doesn't run on CRAN. It is run by GLCI, locally in dev, and by # users running test.data.table("other.Rraw"). +# TODO(HenrikBengtsson/R.oo#31): I think we can remove 'R.oo' once it can install in certain locales; +# for now, we have to include it in 'pkgs' to ensure tests don't try to proceed when 'R.oo' is found missing. # Optional Suggest-ed package tests moved from tests.Rraw to here in #5516. Retaining their comments: # "xts", # we have xts methods in R/xts.R @@ -100,7 +102,9 @@ if (loaded[["dplyr"]]) { DT = data.table(A=c("b","c","a"), B=10:12) setindex(DT, A) DT2 = dplyr::arrange(DT, A) - test(2.2, DT2[A=="c"], data.table(A="c", B=11L)) + # TODO(R>=3.6.0): Old versions of dplyr might coerce to tbl or data.frame; try removing this + if (is.data.table(DT2)) + test(2.2, DT2[A=="c"], data.table(A="c", B=11L)) } if (FALSE) { # loaded[["reshape"]] @@ -201,7 +205,9 @@ if (loaded[["knitr"]]) { tmp = tempfile() on.exit({unlink(tmp); options(old)}) invisible(knit(testDir("knitr.Rmd"), tmp, quiet=TRUE)) - test(11.2, tools::Rdiff(tmp, testDir("knitr.md.save")), 0L) + # TODO(R>=3.6.0): Try removing this kludge + if (packageVersion("knitr") > "1.45") + test(11.2, tools::Rdiff(tmp, testDir("knitr.md.save")), 0L) }) } @@ -716,13 +722,13 @@ if (loaded[["nanotime"]]) { test(27, na.omit(DT), DT[c(1,3)]) # rbind with vectors with class attributes #5309 - x = data.table(a=1L, b=as.nanotime(0)) + x = data.table(a=1L, b=nanotime(0)) y = data.table(a=2L, b=NA) - test(27.01, rbind(x,y), data.table(a = c(1L, 2L), b=as.nanotime(c(0, NA)))) - test(27.02, rbind(y,x), data.table(a = c(2L, 1L), b=as.nanotime(c(NA, 0)))) + test(27.01, rbind(x,y), data.table(a = c(1L, 2L), b=nanotime(c(0, NA)))) + test(27.02, rbind(y,x), data.table(a = c(2L, 1L), b=nanotime(c(NA, 0)))) y[, b := NULL] - test(27.03, rbind(x,y, fill = TRUE), data.table(a = c(1L, 2L), b=as.nanotime(c(0, NA)))) - test(27.04, rbind(y,x, fill = TRUE), data.table(a = c(2L, 1L), b=as.nanotime(c(NA, 0)))) + test(27.03, rbind(x,y, fill = TRUE), data.table(a = c(1L, 2L), b=nanotime(c(0, NA)))) + test(27.04, rbind(y,x, fill = TRUE), data.table(a = c(2L, 1L), b=nanotime(c(NA, 0)))) # Was 1.91-1.94 in nafill.Rraw, #6139 l = list(a=nanotime(c(1:2,NA,4:5)), b=nanotime(c(NA,2L,NA,4L,NA))) @@ -782,7 +788,7 @@ if (loaded[["dplyr"]]) { if (loaded[["nanotime"]]) { # respect dec=',' for nanotime, related to #6446, corresponding to tests 2281.* - test(31, fwrite(data.table(as.nanotime(.POSIXct(0))), dec=',', sep=';'), output="1970-01-01T00:00:00,000000000Z") + test(31, fwrite(data.table(nanotime(.POSIXct(0))), dec=',', sep=';'), output="1970-01-01T00:00:00,000000000Z") } # tables() with large environment #6607 diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 5a3824b8a..04ebb8d18 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -135,9 +135,11 @@ sugg = c( "R.utils" # many fread test input files are compressed to save space; fundamental to test environment ) for (s in sugg) { - assign(paste0("test_",s), loaded<-suppressWarnings(suppressMessages( - library(s, character.only=TRUE, logical.return=TRUE, quietly=TRUE, warn.conflicts=FALSE, pos="package:base") # attach at the end for #5101 - ))) + assign(paste0("test_",s), loaded <- !inherits(what="error", suppressWarnings(suppressMessages( + # tryCatch() here, not library(logical.return=), because of https://github.com/HenrikBengtsson/R.oo/issues/31; + # library(logical.return=) throws an error when R.utils doesn't find R.oo, not logical FALSE. + tryCatch(library(s, character.only=TRUE, quietly=TRUE, warn.conflicts=FALSE, pos="package:base"), error=identity) # attach at the end for #5101 + )))) if (!loaded) cat("\n**** Suggested package",s,"is not installed or has dependencies missing. Tests using it will be skipped.\n\n") } @@ -625,15 +627,12 @@ test(166, suppressWarnings(split(DT,DT$grp)[[2]]), DT[grp==2]) # 167 tested graphics::plot, moved to other.Rraw 28 to save ram, #5517 # IDateTime conversion methods that ggplot2 uses (it calls as.data.frame method) -# Since %b is e.g. "nov." in LC_TIME=fr_FR.UTF-8 locale, we need to -# have the target/y value in these tests depend on the locale as well, #3450. -NOV = format(strptime("2000-11-01", "%Y-%m-%d"), "%b") -x = c("09:29:16","10:42:40","23:47:12","01:06:01","11:35:34","11:51:09") -datetimes = paste0("2011 ", NOV, c(18,18,18,19,19,19), " ", x) -DT = IDateTime(strptime(datetimes,"%Y %b%d %H:%M:%S")) -test(168.1, DT[,as.data.frame(itime)], data.frame(V1=as.ITime(x))) -test(168.2, as.character(DT[,as.POSIXct(itime,tz="UTC")]), paste(Sys.Date(), x)) -test(168.3, as.character(DT[,as.POSIXct(idate,tz="UTC")]), c("2011-11-18","2011-11-18","2011-11-18","2011-11-19","2011-11-19","2011-11-19")) +dates = paste0("2011-11-", rep(18:19, each=3L)) +times = c("09:29:16", "10:42:40", "23:47:12", "01:06:01", "11:35:34", "11:51:09") +DT = IDateTime(as.POSIXlt(paste(dates, times))) +test(168.1, DT[, as.data.frame(itime)], data.frame(V1=as.ITime(times))) +test(168.2, as.character(DT[, as.POSIXct(itime, tz="UTC")]), paste(Sys.Date(), times)) +test(168.3, as.character(DT[, as.POSIXct(idate, tz="UTC")]), dates) # test of . in formula, using inheritance DT = data.table(y=1:100,x=101:200,y=201:300,grp=1:5) @@ -20767,8 +20766,10 @@ DT[1, V1 := factor("a", levels = c("a", samelevel))] test(2311.3, nlevels(DT$V1), 2L) # used to be 3 # avoid translateChar*() in OpenMP threads, #6883 -DF = list(rep(iconv("\uf8", from = "UTF-8", to = "latin1"), 2e6)) -test(2312, fwrite(DF, nullfile(), encoding = "UTF-8", nThread = 2L), NULL) +DF = list(rep(iconv("\uf8", from="UTF-8", to="latin1"), 2e6)) +# TODO(R>=3.6.0): nullfile() added to base +if (!exists("nullfile")) nullfile <- function() if (.Platform$OS.type == "windows") "nul:" else "/dev/null" +test(2312, fwrite(DF, nullfile(), encoding="UTF-8", nThread=2L), check_value=FALSE) # avoid memcpy of 0-length inputs test(2313,