source(file.path("_helper", "init.R"))
source(file.path("aammrtf", "ref.R")); make_ref_obj_funs("item")
options(unitizer.color = FALSE)
# These tests are intended to cover all the functions/classes/methods in:
# - item.R
# - item.sub.R
# - test_eval.R # indirectly
# - heal.R
# - unitizer.R
# Basically everything that can be tested non-interactively
# Helper funs
callDep <- function(x) paste0(deparse(x@call, width.cutoff = 500),
collapse = "")
lsObjs <- function(x) paste0(x@ls$names, x@ls$status, collapse = ", ")
lsStat <- function(x) x@ls$status
lsInv <- function(x) isTRUE(attr(x@ls, "invalid"))
# Get started
new.exps <- expression(
1 + 1,
a <- 54, # keep
b <- 38, # keep
a + b,
e <- 5 * a, # keep
a ^ 2, # Keep
f <- e * a,
matrix(rep(f, 20)) # keep
)
ref.exps <- expression(
1 + 1,
a <- 54,
b <- 38,
a + b,
e <- 5 * a,
e ^ 3
)
Sys.sleep(0.2)
my.unitizer <- new("unitizer", id = 1, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer <- my.unitizer + ref.exps)
my.unitizer2 <- new("unitizer", id = 2, zero.env = new.env())
# now convert them to reference items
coi(my.unitizer2 <- my.unitizer2 + my.unitizer@items.new)
# now test against new.exps
coi(my.unitizer2 <- my.unitizer2 + new.exps)
# - "item funs" ----------------------------------------------------------------
item <- my.unitizer@items.new[[1L]]
unitizer:::itemType(item)
try(unitizer:::itemType(item) <- "asdfasd")
unitizer:::itemType(item) <- "reference"
unitizer:::itemType(item)
try(unitizer:::itemsType(my.unitizer@items.new) <- as.character(1:1000))
try(item$booboo)
# - "unitizer creation worked as expected" -------------------------------------
validObject(my.unitizer, complete = TRUE)
all.equal(capture.output(show(my.unitizer@items.new[[1L]])), rds(100))
identical(length(my.unitizer2), length(new.exps))
identical(length(my.unitizer2@items.new), length(new.exps))
identical(length(my.unitizer2@items.ref), length(ref.exps))
all.equal(
as.expression(
lapply(unitizer:::as.list(my.unitizer2@items.new), slot, "call")
),
new.exps
)
all.equal(
as.expression(
lapply(unitizer:::as.list(my.unitizer2@items.ref), slot, "call")
),
ref.exps
)
vals <- lapply(
unitizer:::as.list(my.unitizer2@items.new), function(x) x@data@value[[1L]]
)
vals.ign <- unitizer:::ignored(my.unitizer2@items.new)
all.equal(vals[!vals.ign], lapply(new.exps, eval)[!vals.ign])
all(vapply(vals[vals.ign], is, logical(1L), "unitizerDummy"))
vals <- lapply(
unitizer:::as.list(my.unitizer2@items.ref), function(x) x@data@value[[1L]]
)
vals.ign <- unitizer:::ignored(my.unitizer2@items.ref)
all.equal(vals[!vals.ign], lapply(ref.exps, eval)[!vals.ign])
all(vapply(vals[vals.ign], is, logical(1L), "unitizerDummy"))
my.unitizer2@items.new.map
my.unitizer2@items.ref.map
my.unitizer2@tests.fail
my.unitizer2@tests.status
my.unitizer2@section.map
unitizer:::ignored(my.unitizer2@items.new)
unitizer:::ignored(my.unitizer2@items.ref)
# - "Size Measurement works" ---------------------------------------------------
# Used to produce warnings because the same base.env was used for every
# unitizer because it was created on package load as part of the S4 class
# definition instead of in "initialize", so any time we instantiated more
# than one object they all shared the same environment, causing issues with
# saveRDS
x <- unitizer:::sizeUntz(my.unitizer2)
is.matrix(x) && is.numeric(x)
colnames(x)
# - "Environment healing works" ------------------------------------------------
items.mixed <- my.unitizer2@items.new[4:5] + my.unitizer2@items.ref[[1]] +
my.unitizer2@items.new[c(2, 6, 8)]
items.sorted <- unitizer:::healEnvs(items.mixed, my.unitizer2)
env.anc <- lapply(unitizer:::as.list(items.sorted), function(x) rev(unitizer:::env_ancestry(x@env,
my.unitizer2@base.env)))
max.len <- max(vapply(env.anc, length, 1L))
env.anc.2 <- lapply(env.anc, function(x) {
length(x) <- max.len
x
})
env.anc.df <- as.data.frame(env.anc.2, stringsAsFactors = FALSE)
# Here only the first item is reference, all others
length(unique(unlist(env.anc.df[2, ])))
all(
apply(
env.anc.df[-(1:2), -1], 1,
function(x) length(unique(Filter(Negate(is.na), x)))
) == 1L
)
# First item is reference, all others are new
unitizer:::itemsType(items.sorted)
# Expected order of ids
vapply(unitizer:::as.list(items.sorted), function(x) x@id, integer(1L))
lapply(unitizer:::as.list(items.sorted), function(x) x@ls$names)
unique(unlist(lapply(unitizer:::as.list(items.sorted), function(x) x@ls$status)))
# Tests with conditions
# - "Items with conditions" ----------------------------------------------------
my_fun <- function() {
warning("hello")
25
}
ref.exps1a <- expression(stop("boom"), my_fun())
my.unitizer1a <- new("unitizer", id = 100, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer1a <- my.unitizer1a + ref.exps1a)
all.equal(capture.output(show(my.unitizer1a@items.new[[1L]])), rds(200))
all.equal(capture.output(show(my.unitizer1a@items.new[[2L]])), rds(300))
all.equal(
capture.output(show(my.unitizer1a@items.new[[1L]]@data@conditions)), rds(400)
)
# - "Environment healing works 2" ----------------------------------------------
# Stars highlight items we are selecting, but keep in mind that unitizer only
# cares about non ignored tests, and that the selection status of ignored test
# has nothing to do with what we end up with wrt to ignored tests
new.exps2 <- expression(
1 + 1, # 1 *
a <- 54, # 2
b <- runif(5), # 3
howdy <- "yowser", # 4 *
a + b, # 5 *
e <- 5 * a, # 6
a ^ 2, # 7
f <- e * a, # 8
matrix(rep(f, 20)) # 9 *
)
ref.exps2 <- expression(
1 + 1, # 1
a <- 54, # 2
b <- runif(5), # 3 *
25 + 3, # 4
q <- b ^ 2 / a, # 5 *
a + b, # 6
z <- w <- list(1, 2, 3), # 7
Reduce(`+`, z), # 8 * Doesn't exist, should connect back to `a + b`
e <- 5 * a, # 9
e ^ 3, # 10 *
e * a # 11 *
)
# Note that healEnvs modifies objects that contain environments, and as such
# you won't get the same result if you run this function twice, so don't be
# surprised if tests fail in those circumstances
my.unitizer3 <- new("unitizer", id = 1, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer3 <- my.unitizer3 + ref.exps2)
my.unitizer4 <- new("unitizer", id = 2, zero.env = new.env())
# now convert them to reference items
coi(my.unitizer4 <- my.unitizer4 + my.unitizer3@items.new)
# now test against new.exps
coi(my.unitizer4 <- my.unitizer4 + new.exps2)
coi(
items.mixed2 <- my.unitizer4@items.ref[c(8, 10, 3, 5, 11)] +
my.unitizer4@items.new[c(1, 4, 5, 9)]
)
items.sorted2 <- unitizer:::healEnvs(items.mixed2, my.unitizer4)
env.anc <- lapply(unitizer:::as.list(items.sorted2), function(x) rev(unitizer:::env_ancestry(x@env,
my.unitizer4@base.env)))
max.len <- max(vapply(env.anc, length, 1L))
env.anc.2 <- lapply(env.anc, function(x) {
length(x) <- max.len
x
})
# oldest ancestor the same
env.anc.df <- as.data.frame(env.anc.2, stringsAsFactors = FALSE)
length(unique(unname(unlist(env.anc.df[1, ])))) # 1
# "base.env should be unitizer env")
identical(
env.anc.df[1, 1], unitizer:::env_name(my.unitizer4@base.env)
)
# "all tests should also have another sub base.env")
length(unique(unlist(env.anc.df[2, ]))) == 1L
# "and it should be the items.ref here")
identical(
env.anc.df[2, 1], unitizer:::env_name(my.unitizer4@items.ref@base.env)
)
items <- items.sorted2
items.lst <- unitizer:::as.list(items)
# "new items should all have normal status",
heal.info <- cbind(
type = unitizer:::itemsType(items), ignored = unitizer:::ignored(items),
id = vapply(items.lst, slot, 1L, "id"),
call = vapply(items.lst, callDep, ""),
ls = vapply(items.lst, lsObjs, ""),
ls.invalid = vapply(items.lst, lsInv, TRUE)
)
# ""
unique(unlist(lapply(items.lst[unitizer:::itemsType(items) == "new"], lsStat)))
# "Reference tests should have no ls data",
unique(vapply(items.lst[unitizer:::ignored(items)], lsObjs, ""))
all(vapply(items.lst[unitizer:::ignored(items)], lsInv, logical(1L)))
# - "ls works" -----------------------------------------------------------------
my.unitizer5 <- new("unitizer", id = 2, zero.env = new.env())
# now add back our composite elements as references
coi(my.unitizer5 <- my.unitizer5 + items.sorted2)
# and new items
coi(my.unitizer5 <- my.unitizer5 + new.exps2)
# This is an ignored test, so there will be some problems
env.val <- new.env(parent = my.unitizer5@items.new[[3]]@env)
env.eval <- new.env(parent = env.val)
assign(".NEW", my.unitizer5@items.new[[3]], env.val)
assign(".new", my.unitizer5@items.new[[3]]@data@value[[1L]],
env.val)
assign(".REF", my.unitizer5@items.ref[[my.unitizer5@items.new.map[[3]]]],
env.val)
assign(".ref", my.unitizer5@items.ref[[my.unitizer5@items.new.map[[3]]]]@data@value[[1L]],
env.val)
ls.res <- evalq(unitizer:::unitizer_ls(), env.eval) # warn
# Reference tests won't show up since they were nuked by `healEnvs`
all.equal(ls.res, rds(500))
# These are normal tests so should work
env.val <- new.env(parent = my.unitizer5@items.new[[9]]@env)
env.eval <- new.env(parent = env.val)
assign(".NEW", my.unitizer5@items.new[[9]], env.val)
assign(".new", my.unitizer5@items.new[[9]]@data@value[[1L]],
env.val)
assign(".REF", my.unitizer5@items.ref[[my.unitizer5@items.new.map[[9]]]],
env.val)
assign(".ref", my.unitizer5@items.ref[[my.unitizer5@items.new.map[[9]]]]@data@value[[1L]],
env.val)
all.equal(evalq(unitizer:::unitizer_ls(), env.eval),
rds(600))
all.equal(capture.output(print(evalq(unitizer:::unitizer_ls(),
env.eval))), rds(700))
# - "Environment Healing Works #3" ---------------------------------------------
#
# Main difference to previous versions is that we're testing that moving the
# order of tests around between ref and new still works
#
# Test that reference tests moving around doesn't cause major issues
new.exps6 <- expression(
1 + 1, # 1 *
a <- 54, # 2
b <- runif(5), # 3
howdy <- "yowser", # 4
a + b, # 5
e <- 5 * a, # 6
a ^ 2, # 7 *
f <- 25, # 8 *
matrix(rep(f, 20)) # 9
)
ref.exps6 <- expression(
1 + 1, # 1
a <- 54, # 2
f <- 25, # 3
matrix(rep(f, 20)), # 4 *
b <- runif(5), # 5
boomboom <- "boo", # 6
a + b, # 7 *
a + b + f, # 8
e <- 5 * a, # 9
a ^ 2 # 10
)
my.unitizer10 <- new("unitizer", id = 1, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer10 <- my.unitizer10 + ref.exps6)
my.unitizer11 <- new("unitizer", id = 2, zero.env = new.env())
# now convert them to reference items
coi(my.unitizer11 <- my.unitizer11 + my.unitizer10@items.new)
# now test against new.exps
coi(my.unitizer11 <- my.unitizer11 + new.exps6)
items.mixed3 <- my.unitizer11@items.ref[c(4, 7)] +
my.unitizer11@items.new[c(1, 7, 8)]
items.sorted3 <- unitizer:::healEnvs(items.mixed3, my.unitizer11)
# Both reference tests get appended to item #1, which means among other things
# that for the second refernce test, the `a` object is absent (but `b` is
# present because it gets sucked in by virtue of being an ignored test just
# ahead of it)
items <- items.sorted3
items.lst <- unitizer:::as.list(items)
cbind(
type = unitizer:::itemsType(items), ignored = unitizer:::ignored(items),
id = vapply(items.lst, slot, 1L, "id"),
call = vapply(items.lst, callDep, ""),
ls = vapply(items.lst, lsObjs, ""),
ls.invalid = vapply(items.lst, lsInv, TRUE)
)
# - "No circular environment references" ---------------------------------------
# This is to test for issue #2, which resulted in a self referential environment
# in the stored items. The following code used to fail:
new.exps3 <- expression(1 + 1, a <- 54, b <- 5, 2 + 2, runif(1))
ref.exps3 <- expression(1 + 1, a <- 54, 2 + 2, runif(1))
my.unitizer6 <- new("unitizer", id = 1, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer6 <- my.unitizer6 + ref.exps3)
my.unitizer7 <- new("unitizer", id = 2, zero.env = new.env())
# now convert them to reference items
coi(my.unitizer7 <- my.unitizer7 + my.unitizer6@items.new)
# now test against new.exps
coi(my.unitizer7 <- my.unitizer7 + new.exps3)
# Note this doesn't test that there are no circular references, only that what
# used to fail no longer fails.
cbind(my.unitizer7@tests.new, my.unitizer7@tests.result)
# - "testFuns" -----------------------------------------------------------------
# Error objects
# these two should just work fine
is(new("testFuns", output = all.equal, value = function(x, y) TRUE), "testFuns")
is(new("testFuns"), "testFuns")
try(new("testFuns", output = all.equal, value = function(x, y, z) TRUE))
# this should work too now, since technically has two args
is(
new("testFuns", output = all.equal, value = function(x, y = 1, z = 1) TRUE),
"testFuns"
)
try(new("testFuns", cabbage = all.equal))
# - "Misc" ---------------------------------------------------------------------
new.exps4 <- expression(a <- function() b(), b <- function() TRUE, a())
my.unitizer8 <- new("unitizer", id = 3, zero.env = new.env())
new.exps5 <- expression(a <- function() b(), NULL, b <- function() TRUE, a())
my.unitizer9 <- new("unitizer", id = 4, zero.env = new.env())
coi(x <- my.unitizer9 + new.exps5)
local({
fun <- function() quote(stop("This error should not be thrown"))
is(
new(
"unitizerItem", value = fun(), call = quote(fun()),
env = sys.frame(sys.parent() + 1L)
),
"unitizerItem"
)
})
# Nested environment hand waving can break down under certain circumstances
# this first one should work because there are no tests until after all
# the pieces necessary to run `a()` are defined:
coi(res <- my.unitizer8 + new.exps4)
is(res, "unitizer")
# this should break because the NULL forces `b` to be stored in a different
# environment to `a`; note: funky error message matching because in
# at least some versions of rdevel reported fun name seems to change
# (possibly related to level 3 bytecode)
# could not find fun
x@items.new[[4]]@data@message[[1]]
# - "Comparison Function Errors" -----------------------------------------------
exps <- expression(fun <- function(x, y) warning("not gonna work"),
unitizer_sect(compare = fun, expr = {
1 + 1
}))
my.unitizer <- new("unitizer", id = 25, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer <- my.unitizer + exps)
coi(my.unitizer2 <- new("unitizer", id = 26, zero.env = new.env()) +
my.unitizer@items.new)
# warn: not gonna work
coi(my.unitizer2 <- my.unitizer2 + exps)
as.character(my.unitizer2@tests.status)
my.unitizer2@tests.errorDetails[[2]]@value@value
# - "Language Objects Tested Properly" -----------------------------------------
exps <- expression(quote(x), quote(x + y), quote(identity(x)),
expression(1 + y), quote(expression(1 + y)))
my.unitizer <- new("unitizer", id = 27, zero.env = new.env())
# add ref.exps as new items
coi(my.unitizer <- my.unitizer + exps)
coi(my.unitizer2 <- new("unitizer", id = 28, zero.env = new.env()) +
my.unitizer@items.new)
coi(my.unitizer2 <- my.unitizer2 + exps)
# This used to error b/c expressions returning unevaluated calls/symbols were
# not compared as such (they were evaluated)
as.character(my.unitizer2@tests.status)
# - "Test Fun Captured Properly" -----------------------------------------------
new("unitizerItemTestFun", fun = identical)@fun.name
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.