# constructor and accessors -----------------------------------------------
test_that("can construct and access components", {
r <- new_rcrd(list(x = 1, y = 2))
expect_equal(length(r), 1)
expect_equal(n_fields(r), 2)
expect_equal(names(r), NULL)
expect_equal(fields(r), c("x", "y"))
expect_error(r$x, class = "vctrs_error_unsupported")
expect_equal(field(r, "x"), 1)
})
test_that("requires format method", {
x <- new_rcrd(list(x = 1))
expect_error(format(x), class = "vctrs_error_unimplemented")
})
test_that("vec_proxy() transforms records to data frames", {
expect_identical(
vec_proxy(new_rcrd(list(a = "1"))),
new_data_frame(list(a = "1"))
)
})
test_that("equality, comparison, and order proxies are recursive and fall through (#1503, #1664)", {
base <- new_rcrd(list(a = 1), class = "custom")
x <- new_rcrd(list(x = base))
expect_identical(vec_proxy_equal(x), 1)
expect_identical(vec_proxy_compare(x), 1)
expect_identical(vec_proxy_order(x), 1)
local_methods(vec_proxy_equal.custom = function(x, ...) rep("equal", length(x)))
expect_identical(vec_proxy_equal(x), "equal")
expect_identical(vec_proxy_compare(x), "equal")
expect_identical(vec_proxy_order(x), "equal")
local_methods(vec_proxy_compare.custom = function(x, ...) rep("compare", length(x)))
expect_identical(vec_proxy_equal(x), "equal")
expect_identical(vec_proxy_compare(x), "compare")
expect_identical(vec_proxy_order(x), "compare")
local_methods(vec_proxy_order.custom = function(x, ...) rep("order", length(x)))
expect_identical(vec_proxy_equal(x), "equal")
expect_identical(vec_proxy_compare(x), "compare")
expect_identical(vec_proxy_order(x), "order")
y <- new_rcrd(list(a = 1), class = "custom2")
local_methods(vec_proxy_compare.custom2 = function(x, ...) rep("compare2", length(x)))
z <- data_frame(x = x, y = y)
# Each column falls back independently
expect_identical(vec_proxy_equal(z), data_frame(x = "equal", y = 1))
expect_identical(vec_proxy_compare(z), data_frame(x = "compare", y = "compare2"))
expect_identical(vec_proxy_order(z), data_frame(x = "order", y = "compare2"))
})
# base methods ------------------------------------------------------------
test_that("has no names", {
x <- new_rcrd(list(a = 1, b = 2L))
expect_null(names(x))
expect_null(vec_names(x))
})
test_that("removing names with `NULL` is a no-op (#1419)", {
x <- new_rcrd(list(a = 1, b = 2L))
expect_identical(`names<-`(x, NULL), x)
expect_identical(vec_set_names(x, NULL), x)
})
test_that("setting character names is an error (#1419)", {
x <- new_rcrd(list(a = 1, b = 2L))
expect_error(`names<-`(x, "x"), "Can't assign names")
expect_error(vec_set_names(x, "x"), "Can't assign names")
})
test_that("na.omit() works and retains metadata (#1413)", {
x <- new_rcrd(list(a = c(1, 1, NA, NA), b = c(1, NA, 1, NA)))
result <- na.omit(x)
expect <- vec_slice(x, 1:3)
attr(expect, "na.action") <- structure(4L, class = "omit")
expect_identical(result, expect)
})
test_that("na.fail() works", {
# Only considered missing if all fields are missing
x <- new_rcrd(list(a = c(1, 1, NA), b = c(1, NA, 1)))
expect_identical(na.fail(x), x)
x <- new_rcrd(list(a = c(1, 1, NA, NA), b = c(1, NA, 1, NA)))
expect_snapshot(error = TRUE, na.fail(x))
})
# coercion ----------------------------------------------------------------
test_that("can't cast list to rcrd", {
l <- list(
new_rcrd(list(a = "1", b = 3L)),
new_rcrd(list(b = "4", a = 2))
)
expect_error(
vec_cast(l, new_rcrd(list(a = 1L, b = 2L))),
class = "vctrs_error_incompatible_type"
)
})
test_that("can recast rcrd from list", {
r <- new_rcrd(list(x = integer(), y = numeric()))
expect_equal(
vec_restore(list(x = 1L, y = 1), r),
new_rcrd(list(x = 1L, y = 1))
)
})
test_that("can't cast rcrd to list", {
r <- new_rcrd(list(x = 1:2, y = 2:3))
expect_error(vec_cast(r, list()), class = "vctrs_error_incompatible_type")
expect_error(vec_cast(r, list()), class = "vctrs_error_incompatible_type")
})
test_that("default casts are implemented correctly", {
r <- new_rcrd(list(x = 1, y = 1))
expect_error(vec_cast(1, r), class = "vctrs_error_incompatible_type")
expect_equal(vec_cast(NULL, r), NULL)
})
test_that("can't cast incompatible rcrd", {
expect_error(
vec_cast(
new_rcrd(list(a = "1", b = 3L)),
new_rcrd(list(a = "1"))
),
class = "vctrs_error_cast_lossy"
)
expect_error(
vec_cast(
new_rcrd(list(a = "1", b = 3L)),
new_rcrd(list(a = "1", c = 3L))
),
class = "vctrs_error_cast_lossy"
)
expect_error(
vec_cast(
new_rcrd(list(a = "a", b = 3L)),
new_rcrd(list(a = 1, b = 3L))
),
class = "vctrs_error_incompatible_type"
)
})
# input validation --------------------------------------------------------
test_that("must be list of equal length vectors", {
expect_error(new_rcrd(list()), "list of length 1")
expect_error(new_rcrd(list(x = environment())), class = "vctrs_error_scalar_type")
expect_error(new_rcrd(list(x = 1:2, y = 1:3)), "same size")
})
test_that("names must be unique", {
expect_error(new_rcrd(list(1, 2)), class = "vctrs_error_names_cannot_be_empty")
expect_error(new_rcrd(list(x = 1, 2)), class = "vctrs_error_names_cannot_be_empty")
expect_error(new_rcrd(list(x = 1, x = 2)), class = "vctrs_error_names_must_be_unique")
expect_error(new_rcrd(setNames(list(1, 2), "x")), "can't return `NA`")
})
test_that("subset assignment throws error", {
x <- new_rcrd(list(x = 1))
expect_error(
x$y <- 2,
class = "vctrs_error_unsupported"
)
})
test_that("can supply data frame as fields", {
expect_identical(
new_rcrd(list(x = 1)),
new_rcrd(tibble(x = 1))
)
})
test_that("fields are not recycled", {
expect_error(
new_rcrd(list(x = 1, y = 1:2)),
"must be the same size"
)
})
# tuple class ----------------------------------------------------------
# use simple class to test essential features of rcrds
test_that("print and str use format", {
local_tuple_methods()
r <- tuple(1, 1:100)
expect_snapshot(r)
expect_snapshot(str(r[1:10]))
expect_snapshot(str(list(list(list(r, 1:100)))))
})
test_that("subsetting methods applied to each field", {
local_tuple_methods()
x <- tuple(1:2, 1)
expect_equal(x[1], tuple(1, 1))
expect_equal(x[[1]], tuple(1, 1))
expect_equal(rep(tuple(1, 1), 2), tuple(c(1, 1), 1))
length(x) <- 1
expect_equal(x, tuple(1, 1))
})
test_that("subset assignment modifies each field", {
local_tuple_methods()
x <- tuple(c(1, 1), c(2, 2))
expect_error(x[[]] <- tuple(), "missing")
x[[1]] <- tuple(3, 3)
expect_equal(x, tuple(c(3, 1), c(3, 2)))
x[1] <- tuple(4, 4)
expect_equal(x, tuple(c(4, 1), c(4, 2)))
})
test_that("subset assignment recycles", {
local_tuple_methods()
x <- tuple(c(1, 1), c(2, 2))
x[1:2] <- tuple(1, 1)
expect_equal(x, tuple(c(1, 1), c(1, 1)))
x[] <- tuple(2, 2)
expect_equal(x, tuple(c(2, 2), c(2, 2)))
})
test_that("can sort rcrd", {
local_tuple_methods()
x <- tuple(c(1, 2, 1), c(3, 1, 2))
expect_equal(xtfrm(x), c(2, 3, 1))
expect_equal(order(x), c(3, 1, 2))
expect_equal(sort(x), tuple(c(1, 1, 2), c(2, 3, 1)))
})
test_that("can use dictionary methods on a rcrd", {
local_tuple_methods()
x <- tuple(c(1, 2, 1), c(3, 1, 3))
expect_equal(unique(x), x[1:2])
expect_equal(duplicated(x), c(FALSE, FALSE, TRUE))
expect_equal(anyDuplicated(x), TRUE)
})
test_that("cannot round trip through list", {
local_tuple_methods()
t <- tuple(1:2, 3:4)
# Used to be allowed
expect_error(vec_cast(t, list()), class = "vctrs_error_incompatible_type")
})
test_that("can convert to list using as.list() or vec_chop() (#1113)", {
local_tuple_methods()
t <- tuple(1:2, 3:4)
expect <- list(tuple(1L, 3L), tuple(2L, 4L))
expect_identical(as.list(t), expect)
expect_identical(vec_chop(t), expect)
})
test_that("dangerous methods marked as unimplemented", {
local_tuple_methods()
t <- tuple()
expect_error(mean(t), class = "vctrs_error_unsupported")
expect_error(abs(t), class = "vctrs_error_unsupported")
expect_error(is.finite(t), class = "vctrs_error_unsupported")
expect_error(is.nan(t), class = "vctrs_error_unsupported")
})
# slicing -----------------------------------------------------------------
test_that("dots are an error (#1295)", {
foo <- new_rcrd(list(foo = "foo"))
expect_snapshot(error = TRUE, foo[1, 2])
})
test_that("records are restored after slicing the proxy", {
expect_identical(new_rcrd(list(x = 1:2))[1], new_rcrd(list(x = 1L)))
})
test_that("can slice with df-cols fields", {
x <- new_rcrd(data_frame(x = data_frame(y = 1:2)))
out <- vec_slice(x, 2)
expect_identical(
out,
new_rcrd(data_frame(x = data_frame(y = 2L)))
)
expect_identical(
x[2],
out
)
expect_identical(
x[[2]],
out
)
})
test_that("can rep with df-cols fields", {
x <- new_rcrd(data_frame(x = data_frame(y = 1:2)))
expect_identical(
rep(x, length.out = 4),
vec_slice(x, c(1:2, 1:2))
)
})
test_that("can assign with df-cols fields", {
x <- new_rcrd(data_frame(x = data_frame(y = 1:3)))
y <- new_rcrd(data_frame(x = data_frame(y = FALSE)))
exp <- new_rcrd(data_frame(x = data_frame(y = c(1L, 2L, 0L))))
expect_identical(vec_assign(x, 3, y), exp)
out <- x
out[[3]] <- y
expect_identical(out, exp)
})
test_that("can resize with df-cols fields", {
x <- new_rcrd(data_frame(x = data_frame(y = 1:3)))
length(x) <- 2
expect_identical(x, new_rcrd(data_frame(x = data_frame(y = 1:2))))
length(x) <- 4
expect_identical(x, new_rcrd(data_frame(x = data_frame(y = c(1:2, NA, NA)))))
})
test_that("`[[` preserves type of record fields (#1205)", {
x <- new_rcrd(list(x = 1:3, a = list(1, 2:3, 4:6)))
expect_identical(field(x[3], "a"), list(4:6))
expect_identical(field(x[[3]], "a"), list(4:6))
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.