# ------------------------------------------------------------------------------ # map() furrr_test_that("future_map() matches map() for simple cases", { expect_identical( future_map(1:3, ~.x), map(1:3, ~.x) ) }) furrr_test_that("names of `.x` are retained", { x <- c(a = 1, b = 2) expect_named(future_map(x, ~1), c("a", "b")) }) furrr_test_that("named empty input makes named empty output", { x <- set_names(list(), character()) expect_named(future_map(x, ~.x), character()) }) # ------------------------------------------------------------------------------ # atomic variants furrr_test_that("future_map_dbl() works", { x <- c(1, 2, 3) expect_identical( future_map_dbl(x, ~.x), map_dbl(x, ~.x) ) }) furrr_test_that("future_map_int() works", { x <- c(1L, 2L, 3L) expect_identical( future_map_int(x, ~.x), map_int(x, ~.x) ) }) furrr_test_that("future_map_lgl() works", { x <- c(TRUE, FALSE, TRUE) expect_identical( future_map_lgl(x, ~.x), map_lgl(x, ~.x) ) }) furrr_test_that("future_map_chr() works", { x <- c("a", "b", "c") expect_identical( future_map_chr(x, ~.x), map_chr(x, ~.x) ) }) furrr_test_that("future_map_vec() works", { x <- as.Date(c("2020-01-01", "2020-01-02", "2020-01-03")) expect_identical( future_map_vec(x, ~.x), map_vec(x, ~.x) ) expect_identical( future_map_vec(x, ~1, .ptype = integer()), map_vec(x, ~1, .ptype = integer()) ) expect_identical( future_map_vec(integer(), identity), map_vec(integer(), identity) ) expect_identical( future_map_vec(set_names(integer(), character()), identity), map_vec(set_names(integer(), character()), identity) ) # Vector error expect_snapshot(error = TRUE, { future_map_vec(1:2, ~NULL) }) # Size error expect_snapshot(error = TRUE, { future_map_vec(1:2, ~ 1:2) }) # Type error expect_snapshot(error = TRUE, { future_map_vec(1:2, ~ if (.x == 1L) 1 else "x") }) }) furrr_test_that("names of `.x` are retained", { x <- c(a = 1, b = 2) expect_named(future_map_dbl(x, ~1), c("a", "b")) x <- c(a = as.Date("2020-01-01"), b = as.Date("2020-01-02")) expect_named(future_map_vec(x, ~1), c("a", "b")) }) # ------------------------------------------------------------------------------ # data frame variants furrr_test_that("future_map_dfr() works", { x <- c("a", "b", "c") expect_identical( future_map_dfr(x, ~ data.frame(x = .x)), map_dfr(x, ~ data.frame(x = .x)) ) }) furrr_test_that("future_map_dfc() works", { x <- c("a", "b", "c") expect_identical( future_map_dfc(x, ~ as.data.frame(set_names(list(1), .x))), map_dfc(x, ~ as.data.frame(set_names(list(1), .x))) ) }) # ------------------------------------------------------------------------------ # size furrr_test_that("future_map() works with size zero input", { expect_identical(future_map(list(), identity), list()) }) furrr_test_that("atomic variants work with size zero input", { expect_identical(future_map_chr(list(), identity), character()) expect_identical(future_map_dbl(list(), identity), double()) expect_identical(future_map_int(list(), identity), integer()) expect_identical(future_map_lgl(list(), identity), logical()) }) furrr_test_that("generic variant works with size zero input", { expect_identical( future_map_vec(list(), identity), NULL ) expect_identical( future_map_vec(list(), identity, .ptype = integer()), integer() ) }) # ------------------------------------------------------------------------------ # at / if variants furrr_test_that("future_map_at() works", { x <- list("a", "b", "c") expect_identical( future_map_at(x, 2, ~3), map_at(x, 2, ~3) ) }) furrr_test_that("names of `.x` are retained", { x <- list(a = "a", b = "b", c = "c") expect_named(future_map_at(x, 2, ~3), c("a", "b", "c")) }) furrr_test_that("future_map_if() works", { x <- list("a", "b", "c") expect_identical( future_map_if(x, ~ .x %in% c("a", "c"), ~3), map_if(x, ~ .x %in% c("a", "c"), ~3) ) }) furrr_test_that("names of `.x` are retained", { x <- list(a = "a", b = "b", c = "c") expect_named(future_map_if(x, ~ .x %in% c("a", "c"), ~3), c("a", "b", "c")) }) furrr_test_that("`.else` can be used", { x <- list("a", "b", "c") expect_identical( future_map_if(x, ~ .x %in% c("a", "c"), ~3, .else = ~ -1), map_if(x, ~ .x %in% c("a", "c"), ~3, .else = ~ -1) ) }) # ------------------------------------------------------------------------------ # Miscellaneous furrr_test_that("Calling `~` from within `.f` works", { x <- list( list(a = 4, b = 6), list(c = 5, d = 7) ) expect_identical(future_map(x, ~ map(.x, ~.x)), x) }) furrr_test_that("Calling `~` from within `.f` inside a `mutate()` works (#7, #123)", { x <- list( list(a = 4, b = 6), list(c = 5, d = 7) ) df <- dplyr::tibble(x = x) expect_identical( dplyr::mutate(df, x = future_map(x, ~ map(.x, ~.x))), df ) }) furrr_test_that("globals in `.x` are found (#16)", { fn <- function(x) sum(x, na.rm = TRUE) x <- list(c(1, 2, NA), c(2, 3, 4)) fns1 <- map(x, ~ purrr::partial(fn, x = .x)) fns2 <- map(x, ~ function() fn(.x)) expect_identical(future_map_dbl(fns1, ~ .x()), c(3, 9)) expect_identical(future_map_dbl(fns2, ~ .x()), c(3, 9)) }) test_that("globals in `.x` are only exported to workers that use them", { plan(multisession, workers = 2) on.exit(plan(sequential), add = TRUE) # Use `local()` to ensure that the wrapper functions and the anonymous # functions created with `~` don't pick up extra globals my_wrapper1 <- local({ my_mean1 <- function(x) mean(x, na.rm = TRUE) function(x) { my_mean1(x) exists("my_mean1") } }) my_wrapper2 <- local({ my_mean2 <- function(x) mean(x, na.rm = FALSE) function(x) { my_mean2(x) exists("my_mean1") } }) x <- list(my_wrapper1, my_wrapper2) expect_identical( future_map_lgl(.x = x, .f = ~ .x(c(1, NA))), c(TRUE, FALSE) ) }) furrr_test_that("base package functions can be exported to workers (HenrikBengtsson/future#401)", { expect_identical(future_map(1:2, identity), list(1L, 2L)) }) furrr_test_that("`.f` globals are only looked up in the function env of `.f` (#153)", { fn <- function(x) { y } fn2 <- local({ y <- -1 function(x) { y } }) wrapper <- function(f) { y <- 1 future_map(1:2, f) } # TODO: Reenable this test after future issue is fixed # https://github.com/futureverse/future/issues/820 # https://github.com/futureverse/furrr/issues/307 # expect_error(wrapper(fn), "'y' not found") expect_identical(wrapper(fn2), list(-1, -1)) }) furrr_test_that("`...` globals/packages are found", { # We set the function environments to the global environment to ensure # that they aren't set to something else while `test()` is running fn <- function(x, fn_arg) { fn_arg() } environment(fn) <- .GlobalEnv fn_arg_env <- new_environment(list(x = 1), parent = .GlobalEnv) # This function is passed through `...` fn_arg <- function() { x } environment(fn_arg) <- fn_arg_env expect_identical( future_map(1:2, fn, fn_arg = fn_arg), list(1, 1) ) }) furrr_test_that("errors don't report purrr's indices (#250)", { fail_on_five <- function(x) { if (x == 5) { stop("Failure!") } 1L } x <- 1:20 expect_snapshot(error = TRUE, { future_map(x, fail_on_five) }) })