Nothing
# Tests for missing_dots() / check_missing_dots()
#
# These tests capture the expected behavior of check_missing_dots (C++
# implementation) through its R interface missing_dots().
#
# The C++ implementation was originally using Rf_findVarInFrame() to locate
# the `...` symbol in the calling environment's frame. That entry point was
# replaced with R_getVarEx() (public C API, R >= 4.5.0) to comply with CRAN
# policy on non-API entry points. The tests below were written BEFORE the
# replacement to lock down the exact behaviour, and are used to verify that
# the new implementation is identical.
test_that("missing_dots: basic usage in a function with dots", {
f <- function(...) missing_dots(environment())
# No arguments supplied → zero-length logical vector
expect_identical(f(), logical(0))
# Single non-missing argument
expect_identical(f(1), FALSE)
# Multiple non-missing arguments
expect_identical(f(1, 2, 3), c(FALSE, FALSE, FALSE))
# Single missing argument (bare comma)
expect_identical(f(,), c(TRUE, TRUE))
# Mixed: first missing, second not
expect_identical(f(, 1), c(TRUE, FALSE))
# Mixed: first not, second missing
expect_identical(f(1, ), c(FALSE, TRUE))
# Mixed interleaved
expect_identical(f(1, , 3), c(FALSE, TRUE, FALSE))
# All missing (three bare commas → four missing slots)
expect_identical(f(, , ,), c(TRUE, TRUE, TRUE, TRUE))
})
test_that("missing_dots: named arguments behave the same as positional", {
f <- function(...) missing_dots(environment())
# Named non-missing
expect_identical(f(a = 1, b = 2), c(FALSE, FALSE))
# Named with one missing
expect_identical(f(a = 1, b = , c = 3), c(FALSE, TRUE, FALSE))
# All named and missing
expect_identical(f(a = , b = ), c(TRUE, TRUE))
})
test_that("missing_dots: arguments are NOT evaluated", {
f <- function(...) missing_dots(environment())
evaluated <- FALSE
# delayedAssign creates a promise in this environment; when R wraps it as a
# dots entry for f(), the inner promise must NOT be forced by missing_dots.
delayedAssign("lazy_arg", {
evaluated <<- TRUE
99
})
result <- f(1, lazy_arg)
expect_false(evaluated,
info = "missing_dots must not force/evaluate promise arguments")
expect_identical(result, c(FALSE, FALSE))
})
test_that("missing_dots: rejects non-environment argument", {
expect_error(missing_dots(1L),
regexp = "must be an environment",
info = "passing an integer should error")
expect_error(missing_dots(NULL),
regexp = "must be an environment",
info = "passing NULL should error")
expect_error(missing_dots(list()),
regexp = "must be an environment",
info = "passing a list should error")
})
test_that("missing_dots: parent.frame() default works at one level of indirection", {
outer <- function(...) {
inner <- function() missing_dots(parent.frame())
inner()
}
expect_identical(outer(1, , 3), c(FALSE, TRUE, FALSE))
})
test_that("missing_dots: check_missing_dots C-level accepts environment only", {
# The underlying C function should reject non-environments just like the
# R wrapper does.
expect_error(check_missing_dots(42L), regexp = "environment")
expect_error(check_missing_dots("x"), regexp = "environment")
expect_error(check_missing_dots(NULL), regexp = "environment")
})
# ---------------------------------------------------------------------------
# Tests for is_namespace() / is_from_namespace()
#
# These lock down behaviour before and after replacing Rf_findVarInFrame with
# R_getVarEx in the is_namespace() C++ implementation.
# ---------------------------------------------------------------------------
test_that("is_namespace: identifies namespace environments correctly", {
# Package namespaces → TRUE
expect_true(is_namespace(getNamespace("dipsaus")))
expect_true(is_namespace(getNamespace("base")))
# Ordinary environments → FALSE
expect_false(is_namespace(globalenv()))
expect_false(is_namespace(baseenv())) # base *package* env ≠ base namespace
expect_false(is_namespace(emptyenv()))
expect_false(is_namespace(new.env()))
})
test_that("is_from_namespace: functions and environments from packages", {
# Base env itself is treated as from a package (it lives in the base namespace
# parent chain)
expect_true(is_from_namespace(baseenv()))
# A function exported from utils lives in the utils namespace
expect_true(is_from_namespace(utils::read.csv))
# NULL, plain values, empty env → FALSE
expect_false(is_from_namespace(NULL))
expect_false(is_from_namespace(emptyenv()))
# Anonymous function intended to represent a "user-space" function -> FALSE.
# We must explicitly set its enclosing env to globalenv() because when tests
# run via devtools::load_all() the test body's parent chain is rooted in the
# dipsaus namespace, making any inline `function(){}` appear to come from the
# namespace. Setting the environment to globalenv() is the context-
# independent way to represent a function that is not from any package.
anon <- function() {}
environment(anon) <- globalenv()
expect_false(is_from_namespace(anon))
# Function whose enclosing env is a plain new.env() → FALSE even recursively.
# Create f normally (so `function` is in scope), then move its enclosing env.
# Using local({}, envir = e) would fail when e's parent is emptyenv() because
# `{` and `function` cannot be found during evaluation.
e <- new.env(parent = emptyenv())
f <- function() {}
environment(f) <- e
expect_false(is_from_namespace(f, recursive = FALSE))
expect_false(is_from_namespace(f, recursive = TRUE))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.