test_that("ptype2 base methods are not inherited", {
ptypes <- vec_remove(base_empty_types, c("null", "dataframe"))
for (ptype in ptypes) {
x <- new_vctr(ptype, class = "foobar", inherit_base_type = TRUE)
expect_s3_class(vec_ptype2(x, x), "foobar")
expect_error(vec_ptype2(x, ptype), class = "vctrs_error_incompatible_type")
expect_error(vec_ptype2(ptype, x), class = "vctrs_error_incompatible_type")
}
})
test_that("cast base methods are not inherited", {
ptypes <- vec_remove(base_empty_types, c("null", "dataframe"))
for (ptype in ptypes) {
x <- new_vctr(ptype, class = "foobar", inherit_base_type = TRUE)
expect_s3_class(vec_cast(ptype, x), "foobar")
expect_error(vec_cast(x, ptype), class = "vctrs_error_incompatible_type")
}
})
test_that("default cast allows objects with the same type", {
x <- structure(1, class = c("foo", "double"))
expect_equal(vec_cast(x, x), x)
})
# vec_shaped_ptype -------------------------------------------------------
test_that("array dimensions are preserved", {
mat1 <- matrix(lgl(), nrow = 1, ncol = 1)
mat2 <- matrix(lgl(), nrow = 2, ncol = 2)
mat3 <- matrix(lgl(), nrow = 2, ncol = 3)
expect_equal(vec_ptype2(mat1, mat1), matrix(lgl(), nrow = 0, ncol = 1))
expect_equal(vec_ptype2(mat1, mat2), matrix(lgl(), nrow = 0, ncol = 2))
expect_error(vec_ptype2(mat2, mat3), class = "vctrs_error_incompatible_type")
})
test_that("vec_shaped_ptype()", {
int <- function(...) array(NA_integer_, c(...))
expect_identical(vec_shaped_ptype(integer(), int(5), int(10)), new_shape(integer()))
expect_identical(vec_shaped_ptype(integer(), int(5, 1), int(10, 1)), new_shape(integer(), 1))
expect_identical(vec_shaped_ptype(integer(), int(5, 1, 2), int(10, 1, 2)), new_shape(integer(), 1:2))
})
test_that("vec_shaped_ptype() evaluates arg lazily", {
expect_silent(vec_shaped_ptype(integer(), int(5), int(10), x_arg = print("oof")))
expect_silent(vec_shaped_ptype(integer(), int(5), int(10), y_arg = print("oof")))
})
# vec_cast() --------------------------------------------------------------
# NULL
test_that("NULL is idempotent", {
expect_equal(vec_cast(NULL, NULL), NULL)
expect_equal(vec_cast(list(1:3), NULL), list(1:3))
})
# Logical
test_that("safe casts work as expected", {
exp <- lgl(TRUE, FALSE)
expect_equal(vec_cast(NULL, logical()), NULL)
expect_equal(vec_cast(lgl(TRUE, FALSE), logical()), exp)
expect_equal(vec_cast(int(1L, 0L), logical()), exp)
expect_equal(vec_cast(dbl(1, 0), logical()), exp)
# These used to be allowed
expect_error(vec_cast(chr("T", "F"), logical()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(chr("TRUE", "FALSE"), logical()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(chr("true", "false"), logical()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(1, 0), logical()), class = "vctrs_error_incompatible_type")
})
test_that("NA casts work as expected", {
exp <- lgl(NA)
to <- lgl()
expect_equal(vec_cast(lgl(NA), to), exp)
expect_equal(vec_cast(int(NA), to), exp)
expect_equal(vec_cast(dbl(NA), to), exp)
# These used to be allowed
expect_error(vec_cast(chr(NA), to), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(NA), to), class = "vctrs_error_incompatible_type")
})
test_that("Shaped NA casts work as expected", {
mat <- matrix
exp_mat <- mat(lgl(NA))
to_mat <- matrix(lgl())
expect_equal(vec_cast(mat(lgl(NA)), to_mat), exp_mat)
expect_equal(vec_cast(mat(int(NA)), to_mat), exp_mat)
expect_equal(vec_cast(mat(dbl(NA)), to_mat), exp_mat)
# These used to be allowed
expect_error(vec_cast(mat(chr(NA)), to_mat), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(mat(list(NA)), to_mat), class = "vctrs_error_incompatible_type")
})
test_that("lossy casts generate warning", {
expect_lossy(vec_cast(int(2L, 1L), lgl()), lgl(TRUE, TRUE), x = int(), to = lgl())
expect_lossy(vec_cast(dbl(2, 1), lgl()), lgl(TRUE, TRUE), x = dbl(), to = lgl())
# These used to be allowed
expect_error(vec_cast(chr("x", "TRUE"), lgl()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(chr("t", "T"), lgl()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(chr("f", "F"), lgl()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(c(TRUE, FALSE), TRUE), lgl()), class = "vctrs_error_incompatible_type")
})
test_that("invalid casts generate error", {
expect_error(vec_cast(factor("a"), logical()), class = "vctrs_error_incompatible_type")
})
test_that("dimensionality matches output" ,{
x1 <- matrix(TRUE, nrow = 1, ncol = 1)
x2 <- matrix(1, nrow = 0, ncol = 2)
expect_dim(vec_cast(x1, x2), c(1, 2))
expect_dim(vec_cast(TRUE, x2), c(1, 2))
x <- matrix(1, nrow = 2, ncol = 2)
expect_error(vec_cast(x, logical()), class = "vctrs_error_incompatible_type")
})
test_that("the common type of two `NA` vectors is unspecified", {
expect_equal(vec_ptype2(NA, NA), unspecified())
})
# Integer
test_that("safe casts work as expected", {
expect_equal(vec_cast(NULL, integer()), NULL)
expect_equal(vec_cast(lgl(TRUE, FALSE), integer()), int(1L, 0L))
expect_equal(vec_cast(int(1L, 2L), integer()), int(1L, 2L))
expect_equal(vec_cast(dbl(1, 2), integer()), int(1L, 2L))
# These used to be allowed
expect_error(vec_cast(chr("1", "2"), integer()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(1L, 2L), integer()), class = "vctrs_error_incompatible_type")
})
test_that("NA casts work as expected", {
exp <- int(NA)
to <- int()
expect_equal(vec_cast(lgl(NA), to), exp)
expect_equal(vec_cast(int(NA), to), exp)
expect_equal(vec_cast(dbl(NA), to), exp)
# These used to be allowed
expect_error(vec_cast(chr(NA), to), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(NA), to), class = "vctrs_error_incompatible_type")
})
test_that("Shaped NA casts work as expected", {
mat <- matrix
exp_mat <- mat(int(NA))
to_mat <- matrix(int())
expect_equal(vec_cast(mat(lgl(NA)), to_mat), exp_mat)
expect_equal(vec_cast(mat(int(NA)), to_mat), exp_mat)
expect_equal(vec_cast(mat(dbl(NA)), to_mat), exp_mat)
# These used to be allowed
expect_error(vec_cast(mat(chr(NA)), to_mat), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(mat(list(NA)), to_mat), class = "vctrs_error_incompatible_type")
})
test_that("lossy casts generate error", {
expect_lossy(vec_cast(c(2.5, 2), int()), int(2, 2), x = dbl(), to = int())
expect_lossy(vec_cast(c(.Machine$integer.max + 1, 1), int()), int(NA, 1L), x = dbl(), to = int())
expect_lossy(vec_cast(c(-.Machine$integer.max - 1, 1), int()), int(NA, 1L), x = dbl(), to = int())
# These used to be allowed
expect_error(vec_cast(c("2.5", "2"), int()), class = "vctrs_error_incompatible_type")
})
test_that("invalid casts generate error", {
expect_error(vec_cast(factor("a"), integer()), class = "vctrs_error_incompatible_type")
})
# Double
test_that("safe casts work as expected", {
expect_equal(vec_cast(NULL, double()), NULL)
expect_equal(vec_cast(lgl(TRUE, FALSE), double()), dbl(1, 0))
expect_equal(vec_cast(int(1, 0), double()), dbl(1, 0))
expect_equal(vec_cast(dbl(1, 1.5), double()), dbl(1, 1.5))
# These used to be allowed
expect_error(vec_cast(chr("1", "1.5"), double()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(1, 1.5), double()), class = "vctrs_error_incompatible_type")
})
test_that("NA casts work as expected", {
exp <- dbl(NA)
to <- dbl()
expect_equal(vec_cast(lgl(NA), to), exp)
expect_equal(vec_cast(int(NA), to), exp)
expect_equal(vec_cast(dbl(NA), to), exp)
# These used to be allowed
expect_error(vec_cast(chr(NA), to), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(NA), to), class = "vctrs_error_incompatible_type")
})
test_that("Shaped NA casts work as expected", {
mat <- matrix
exp_mat <- mat(dbl(NA))
to_mat <- matrix(dbl())
expect_equal(vec_cast(mat(lgl(NA)), to_mat), exp_mat)
expect_equal(vec_cast(mat(int(NA)), to_mat), exp_mat)
expect_equal(vec_cast(mat(dbl(NA)), to_mat), exp_mat)
# These used to be allowed
expect_error(vec_cast(mat(chr(NA)), to_mat), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(mat(list(NA)), to_mat), class = "vctrs_error_incompatible_type")
})
test_that("invalid casts generate error", {
expect_error(vec_cast(factor("a"), double()), class = "vctrs_error_incompatible_type")
})
# Complex
test_that("safe casts to complex works", {
expect_identical(vec_cast(NULL, cpl()), NULL)
expect_identical(vec_cast(lgl(TRUE, FALSE), cpl()), cpl(1, 0))
expect_identical(vec_cast(int(1, 0), cpl()), cpl(1, 0))
expect_identical(vec_cast(dbl(1, 1.5), cpl()), cpl(1, 1.5))
# This used to be allowed
expect_error(vec_cast(list(1, 1.5), cpl()), class = "vctrs_error_incompatible_type")
})
test_that("NA casts work as expected", {
# This goes through a special path for <unspecified>
expect_equal(vec_cast(lgl(NA), cpl()), NA_complex_)
# TODO: Use our own cast routines here?
# It isn't great that this logical `NA` cast returns a different `NA`
# than the one above with just `lgl(NA)` (which is seen as unspecified). i.e.
# check the `Im()` slot between the two in R >=4.4.0. We can fix this with our
# own cast routines rather than using `vec_coerce_bare()`.
expect_type(vec_cast(lgl(NA, TRUE), cpl()), "complex")
expect_identical(is.na(vec_cast(lgl(NA, TRUE), cpl())), c(TRUE, FALSE))
# TODO: Use our own cast routines here?
# `as.complex(NA/NA_real_/NA_integer_)` and `Rf_CoerceVector(NA/NA_real_/NA_integer_)`
# have gone back and forth about what they return in the `Im()` slot. In some
# R versions they return `0` and in others they return `NA_real_`.
# https://stat.ethz.ch/pipermail/r-devel/2023-April/082545.html
# https://stat.ethz.ch/pipermail/r-devel/2023-September/082864.html
# expect_equal(vec_cast(int(NA), cpl()), NA_complex_)
expect_type(vec_cast(int(NA), cpl()), "complex")
expect_identical(is.na(vec_cast(int(NA), cpl())), TRUE)
# expect_equal(vec_cast(dbl(NA), cpl()), NA_complex_)
expect_type(vec_cast(dbl(NA), cpl()), "complex")
expect_identical(is.na(vec_cast(dbl(NA), cpl())), TRUE)
# This used to be allowed
expect_error(vec_cast(list(NA), cpl()), class = "vctrs_error_incompatible_type")
})
test_that("Shaped NA casts work as expected", {
mat <- matrix
exp_mat <- mat(NA_complex_)
to_mat <- matrix(cpl())
# TODO: Use our own cast routines here?
# `as.complex(NA/NA_real_/NA_integer_)` and `Rf_CoerceVector(NA/NA_real_/NA_integer_)`
# have gone back and forth about what they return in the `Im()` slot. In some
# R versions they return `0` and in others they return `NA_real_`.
# https://stat.ethz.ch/pipermail/r-devel/2023-April/082545.html
# https://stat.ethz.ch/pipermail/r-devel/2023-September/082864.html
# expect_equal(vec_cast(mat(lgl(NA)), to_mat), exp_mat)
expect_type(vec_cast(mat(lgl(NA)), to_mat), "complex")
expect_identical(is.na(vec_cast(mat(lgl(NA)), to_mat)), matrix(TRUE))
# expect_equal(vec_cast(mat(int(NA)), to_mat), exp_mat)
expect_type(vec_cast(mat(int(NA)), to_mat), "complex")
expect_identical(is.na(vec_cast(mat(int(NA)), to_mat)), matrix(TRUE))
# expect_equal(vec_cast(mat(dbl(NA)), to_mat), exp_mat)
expect_type(vec_cast(mat(dbl(NA)), to_mat), "complex")
expect_identical(is.na(vec_cast(mat(dbl(NA)), to_mat)), matrix(TRUE))
# This used to be allowed
expect_error(vec_cast(mat(list(NA)), to_mat), class = "vctrs_error_incompatible_type")
})
test_that("complex is coercible to numeric types", {
expect_identical(vec_ptype2(cpl(), NULL), cpl())
expect_identical(vec_ptype2(NULL, cpl()), cpl())
expect_identical(vec_ptype2(cpl(), int()), cpl())
expect_identical(vec_ptype2(int(), cpl()), cpl())
expect_identical(vec_ptype2(cpl(), dbl()), cpl())
expect_identical(vec_ptype2(dbl(), cpl()), cpl())
expect_identical(vec_ptype2(cpl(), cpl()), cpl())
expect_identical(vec_c(0, 1i), cpl(0i, 1i))
})
test_that("complex is not coercible to logical", {
expect_error(vec_ptype2(cpl(), lgl()), class = "vctrs_error_incompatible_type")
expect_error(vec_ptype2(lgl(), cpl()), class = "vctrs_error_incompatible_type")
})
# Character
test_that("safe casts work as expected", {
expect_equal(vec_cast(NULL, character()), NULL)
expect_equal(vec_cast(NA, character()), NA_character_)
# These used to be allowed
expect_error(vec_cast(lgl(TRUE, FALSE), character()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list("x", "y"), character()), class = "vctrs_error_incompatible_type")
})
test_that("NA casts work as expected", {
exp <- chr(NA)
to <- chr()
expect_equal(vec_cast(lgl(NA), to), exp)
expect_equal(vec_cast(chr(NA), to), exp)
# These used to be allowed
expect_error(vec_cast(int(NA), to), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(dbl(NA), to), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(list(NA), to), class = "vctrs_error_incompatible_type")
})
test_that("Shaped NA casts work as expected", {
mat <- matrix
exp_mat <- mat(chr(NA))
to_mat <- matrix(chr())
expect_equal(vec_cast(mat(chr(NA)), to_mat), exp_mat)
# These used to be allowed
expect_error(vec_cast(mat(lgl(NA)), to_mat), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(mat(int(NA)), to_mat), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(mat(dbl(NA)), to_mat), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(mat(list(NA)), to_mat), class = "vctrs_error_incompatible_type")
})
test_that("difftime does not get special treatment", {
dt1 <- as.difftime(600, units = "secs")
# This used to be allowed
expect_error(vec_cast(dt1, character()), class = "vctrs_error_incompatible_type")
})
# Raw
test_that("safe casts work as expected", {
expect_equal(vec_cast(NULL, raw()), NULL)
# This used to be allowed
expect_error(vec_cast(list(raw(1)), raw()), class = "vctrs_error_incompatible_type")
})
test_that("invalid casts generate error", {
expect_error(vec_cast(raw(1), double()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(double(1), raw()), class = "vctrs_error_incompatible_type")
})
test_that("can sort raw", {
x <- as.raw(c(3, 1, 2, 4))
expect_identical(vec_order(x), int(2, 3, 1, 4))
expect_identical(x[vec_order(x)], as.raw(1:4))
})
test_that("raw has informative type summaries", {
expect_equal(vec_ptype_abbr(raw()), "raw")
expect_equal(vec_ptype_full(raw()), "raw")
})
test_that("can provide common type with raw", {
local_methods(
vec_ptype2.raw.vctrs_foobar = function(...) "dispatched-left",
vec_ptype2.vctrs_foobar = function(...) NULL,
vec_ptype2.vctrs_foobar.raw = function(...) "dispatched-right"
)
expect_identical(vec_ptype2(raw(), foobar("")), "dispatched-left")
expect_identical(vec_ptype2(foobar(""), raw()), "dispatched-right")
})
# Lists
test_that("safe casts work as expected", {
expect_equal(vec_cast(NULL, list()), NULL)
expect_equal(vec_cast(NA, list()), list(NULL))
expect_equal(vec_cast(list(1L, 2L), list()), list(1L, 2L))
# This used to be allowed
expect_error(vec_cast(1:2, list()), class = "vctrs_error_incompatible_type")
})
test_that("dimensionality matches to" ,{
x1 <- matrix(TRUE, nrow = 1, ncol = 1)
x2 <- matrix(1L, nrow = 0, ncol = 2)
expect_dim(vec_cast(x1, x2), c(1, 2))
expect_dim(vec_cast(TRUE, x2), c(1, 2))
})
test_that("data frames are cast to list row wise (#639)", {
x <- data.frame(x = 1:2, row.names = c("a", "b"))
expect <- list(data.frame(x = 1L), data.frame(x = 2L))
# This used to be allowed
expect_error(vec_cast(x, list()), class = "vctrs_error_incompatible_type")
})
test_that("data frames can be cast to shaped lists", {
to <- array(list(), dim = c(0, 2, 1))
x <- data.frame(x = 1:2, y = 3:4)
expect <- list(vec_slice(x, 1), vec_slice(x, 2))
expect <- array(expect, dim = c(2, 2, 1))
# This used to be allowed
expect_error(vec_cast(x, to), class = "vctrs_error_incompatible_type")
})
test_that("Casting atomic `NA` values to list results in a `NULL`", {
x <- c(NA, 1)
expect <- list(NULL, 1)
# This used to be allowed
expect_error(vec_cast(x, list()), class = "vctrs_error_incompatible_type")
})
test_that("Casting data frame `NA` rows to list results in a `NULL`", {
x <- data.frame(x = c(NA, NA, 1), y = c(NA, 1, 2))
expect <- list(NULL, vec_slice(x, 2), vec_slice(x, 3))
# This used to be allowed
expect_error(vec_cast(x, list()), class = "vctrs_error_incompatible_type")
})
# Unspecified
test_that("unspecified can be cast to bare methods", {
for (x in vectors[-4]) {
expect_identical(vec_cast(unspecified(3), x), vec_init(x, 3))
}
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.