diff --git a/tests/test-arch-system-file.R b/tests/test-arch-system-file.R new file mode 100644 index 00000000..915f8109 --- /dev/null +++ b/tests/test-arch-system-file.R @@ -0,0 +1,49 @@ +# Unit tests for archSystemFile(), the arch-aware wrapper around system.file() +# introduced when systemFile() was renamed (see #251, #252). When R is built +# multi-arch -- typically Windows, but also possible on Linux and macOS -- it +# installs compiled libraries under an architecture-specific subdirectory named +# by .Platform$r_arch, e.g. 'libs/x64'. archSystemFile() injects that subdir, +# and behaves like system.file() when r_arch is unset. Note the subdir only +# ever holds compiled libraries ('lib', 'libs'); headers and other resources +# are never installed under it. + +RcppParallel:::test_init() + +arch <- .Platform$r_arch + +# compare two file paths for equality. system.file() returns "" when a path is +# not found, so preserve that sentinel; otherwise normalize both sides, since +# strings that differ only in separators, case, or symlinks can still denote +# the same file (and normalizePath("") would resolve to the working directory). +samePath <- function(a, b) { + norm <- function(p) { + if (nzchar(p)) normalizePath(p, winslash = "/", mustWork = FALSE) else p + } + identical(norm(a), norm(b)) +} + +# with no arch subdirectory (the usual case off Windows), archSystemFile() +# should be equivalent to a plain system.file() call +if (!nzchar(arch)) { + assert(samePath( + archSystemFile("libs"), + system.file("libs", package = "RcppParallel") + )) +} + +# the composed relative path must match what system.file() is handed: dir, +# then the arch subdir when set, then the optional name -- joined with '/' +expected <- function(dir, name = NULL) { + parts <- c(dir, if (nzchar(arch)) arch, name) + system.file(paste(parts, collapse = "/"), package = "RcppParallel") +} + +assert(samePath(archSystemFile("lib"), expected("lib"))) +assert(samePath(archSystemFile("lib", "libtbb.so"), expected("lib", "libtbb.so"))) + +# the package's own compiled code is installed under 'libs' (or 'libs/' +# under a multi-arch R) -- exactly the arch-aware lookup archSystemFile() +# exists for -- so it must resolve to an existing directory on every platform +libs <- archSystemFile("libs") +assert(nzchar(libs)) +assert(dir.exists(libs)) diff --git a/tests/test-fork.R b/tests/test-fork.R new file mode 100644 index 00000000..08186544 --- /dev/null +++ b/tests/test-fork.R @@ -0,0 +1,26 @@ +# Unit tests for isProcessForkedChild(). +# +# The contract: it returns FALSE in the process where RcppParallel was loaded, +# and TRUE in a fork() of that process (e.g. a parallel::mclapply worker). On +# Windows there is no fork(), so it always returns FALSE. + +RcppParallel:::test_init() + +# in the parent process, we are never a forked child +assert(isProcessForkedChild() == FALSE) + +# parallel::mclapply uses fork() on unix, so its workers must report TRUE. +# on Windows there is no fork() (mclapply falls back to serial), so skip: the +# workers there run in the parent process and would correctly report FALSE. +if (!is_windows()) { + + results <- parallel::mclapply(1:2, function(i) { + RcppParallel::isProcessForkedChild() + }, mc.cores = 2L) + + assert(all(vapply(results, isTRUE, logical(1L)))) + +} + +# forking must not disturb the parent's own view of itself +assert(isProcessForkedChild() == FALSE)