Nothing
test_that("smap functions preserve names in output", {
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
names(structures) <- c("A", "B", "C")
# smap_int should preserve names
result <- smap_int(structures, igraph::vcount)
expect_equal(names(result), c("A", "B", "C"))
# smap_chr should preserve names
result_chr <- smap_chr(structures, ~ .x$anomer)
expect_equal(names(result_chr), c("A", "B", "C"))
# smap should preserve names in list
result_list <- smap(structures, ~ igraph::vcount(.x))
expect_equal(names(result_list), c("A", "B", "C"))
})
test_that("smap functions work with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test smap_int with regular function
result <- smap_int(structures, igraph::vcount)
expect_equal(length(result), 3)
expect_type(result, "integer")
# Test smap_chr with regular function
result_chr <- smap_chr(structures, function(g) g$anomer)
expect_equal(length(result_chr), 3)
expect_type(result_chr, "character")
# Test smap_lgl with regular function
result_lgl <- smap_lgl(structures, function(g) igraph::vcount(g) > 5)
expect_equal(length(result_lgl), 3)
expect_type(result_lgl, "logical")
})
test_that("smap functions work with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test smap_int with purrr lambda
result_lambda <- smap_int(structures, ~ igraph::vcount(.x))
result_regular <- smap_int(structures, igraph::vcount)
expect_equal(result_lambda, result_regular)
# Test smap_chr with purrr lambda
result_chr_lambda <- smap_chr(structures, ~ .x$anomer)
result_chr_regular <- smap_chr(structures, function(g) g$anomer)
expect_equal(result_chr_lambda, result_chr_regular)
# Test smap_lgl with purrr lambda
result_lgl_lambda <- smap_lgl(structures, ~ igraph::vcount(.x) > 5)
result_lgl_regular <- smap_lgl(structures, function(g) igraph::vcount(g) > 5)
expect_equal(result_lgl_lambda, result_lgl_regular)
})
test_that("smap_unique works with purrr-style lambda functions", {
# Create test structures with duplicates
core1 <- o_glycan_core_1()
structures <- c(core1, core1, core1)
# Test with regular function
result_regular <- smap_unique(structures, igraph::vcount)
expect_equal(length(result_regular), 1) # Only one unique structure
# Test with purrr lambda
result_lambda <- smap_unique(structures, ~ igraph::vcount(.x))
expect_equal(result_lambda, result_regular)
})
test_that("smap_structure works with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
structures <- c(core1, core1)
# Function that adds vertex names if not present
add_names_regular <- function(g) {
if (!("name" %in% igraph::vertex_attr_names(g))) {
igraph::set_vertex_attr(
g,
"name",
value = paste0("v", seq_len(igraph::vcount(g)))
)
} else {
g
}
}
# Test with regular function
result_regular <- smap_structure(structures, add_names_regular)
# Test with purrr lambda
result_lambda <- smap_structure(
structures,
~ {
if (!("name" %in% igraph::vertex_attr_names(.x))) {
igraph::set_vertex_attr(
.x,
"name",
value = paste0("v", seq_len(igraph::vcount(.x)))
)
} else {
.x
}
}
)
# Both results should be equivalent
expect_s3_class(result_lambda, "glyrepr_structure")
expect_equal(length(result_lambda), length(result_regular))
})
test_that("get_anomer function works correctly", {
# Test the specific case from the user's example
x <- n_glycan_core()
result <- get_anomer(x)
expect_type(result, "character")
expect_equal(length(result), 1)
expect_equal(result, "b1")
# Test that it's equivalent to purrr lambda style
result_lambda <- smap_chr(x, ~ .x$anomer)
expect_equal(result, result_lambda)
})
test_that("ssome works with regular functions", {
# Create test structures
core1 <- o_glycan_core_1() # smaller structure
core2 <- n_glycan_core() # larger structure
structures <- c(core1, core2, core1)
# Test if some structures have more than 5 vertices
result <- ssome(structures, function(g) igraph::vcount(g) > 5)
expect_type(result, "logical")
expect_equal(length(result), 1)
expect_true(is.logical(result))
# Test if some structures have more than 20 vertices (should be FALSE)
result_false <- ssome(structures, function(g) igraph::vcount(g) > 20)
expect_false(result_false)
# Test if some structures have at least 1 vertex (should be TRUE)
result_true <- ssome(structures, function(g) igraph::vcount(g) >= 1)
expect_true(result_true)
})
test_that("ssome works with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test with purrr lambda
result_lambda <- ssome(structures, ~ igraph::vcount(.x) > 5)
result_regular <- ssome(structures, function(g) igraph::vcount(g) > 5)
expect_equal(result_lambda, result_regular)
# Test with another lambda
result_lambda2 <- ssome(structures, ~ igraph::vcount(.x) >= 1)
expect_true(result_lambda2)
})
test_that("severy works with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test if all structures have at least 1 vertex (should be TRUE)
result_true <- severy(structures, function(g) igraph::vcount(g) >= 1)
expect_true(result_true)
# Test if all structures have more than 10 vertices (should be FALSE)
result_false <- severy(structures, function(g) igraph::vcount(g) > 10)
expect_false(result_false)
# Test if all structures have at least 3 vertices
result <- severy(structures, function(g) igraph::vcount(g) >= 3)
expect_type(result, "logical")
expect_equal(length(result), 1)
})
test_that("severy works with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test with purrr lambda
result_lambda <- severy(structures, ~ igraph::vcount(.x) >= 1)
result_regular <- severy(structures, function(g) igraph::vcount(g) >= 1)
expect_equal(result_lambda, result_regular)
# Test with another lambda
result_lambda2 <- severy(structures, ~ igraph::vcount(.x) >= 3)
expect_type(result_lambda2, "logical")
})
test_that("snone works with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test if no structures have more than 50 vertices (should be TRUE)
result_true <- snone(structures, function(g) igraph::vcount(g) > 50)
expect_true(result_true)
# Test if no structures have at least 1 vertex (should be FALSE)
result_false <- snone(structures, function(g) igraph::vcount(g) >= 1)
expect_false(result_false)
# Test return type
result <- snone(structures, function(g) igraph::vcount(g) > 20)
expect_type(result, "logical")
expect_equal(length(result), 1)
})
test_that("snone works with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test with purrr lambda
result_lambda <- snone(structures, ~ igraph::vcount(.x) > 50)
result_regular <- snone(structures, function(g) igraph::vcount(g) > 50)
expect_equal(result_lambda, result_regular)
# Test with another lambda
result_lambda2 <- snone(structures, ~ igraph::vcount(.x) >= 1)
expect_false(result_lambda2)
})
test_that("structure predicate functions work with duplicate structures efficiently", {
# Create structures with many duplicates to test efficiency
core1 <- o_glycan_core_1()
structures <- c(core1, core1, core1, core1, core1) # same structure 5 times
# These should only evaluate the predicate once for the unique structure
result_some <- ssome(structures, function(g) igraph::vcount(g) > 3)
result_every <- severy(structures, function(g) igraph::vcount(g) > 3)
result_none <- snone(structures, function(g) igraph::vcount(g) > 50)
expect_type(result_some, "logical")
expect_type(result_every, "logical")
expect_type(result_none, "logical")
expect_equal(length(result_some), 1)
expect_equal(length(result_every), 1)
expect_equal(length(result_none), 1)
})
test_that("structure predicate functions handle edge cases", {
# Test with single structure
single <- o_glycan_core_1()
expect_type(ssome(single, ~ igraph::vcount(.x) > 0), "logical")
expect_type(severy(single, ~ igraph::vcount(.x) > 0), "logical")
expect_type(snone(single, ~ igraph::vcount(.x) > 50), "logical")
})
# Tests for smap2 functions -----------------------------------------
test_that("smap2 functions work with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
weights <- c(1.0, 2.0, 1.5)
# Test smap2_dbl with regular function
result <- smap2_dbl(structures, weights, function(g, w) igraph::vcount(g) * w)
expect_equal(length(result), 3)
expect_type(result, "double")
# Test smap2_int with regular function
n_vertices <- c(1, 2, 1)
result_int <- smap2_int(structures, n_vertices, function(g, n) {
igraph::vcount(g) + n
})
expect_equal(length(result_int), 3)
expect_type(result_int, "integer")
# Test smap2_lgl with regular function
thresholds <- c(5, 6, 5)
result_lgl <- smap2_lgl(structures, thresholds, function(g, t) {
igraph::vcount(g) > t
})
expect_equal(length(result_lgl), 3)
expect_type(result_lgl, "logical")
})
test_that("smap2 functions work with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
weights <- c(1.0, 2.0, 1.5)
# Test smap2_dbl with purrr lambda
result_lambda <- smap2_dbl(structures, weights, ~ igraph::vcount(.x) * .y)
result_regular <- smap2_dbl(structures, weights, function(g, w) {
igraph::vcount(g) * w
})
expect_equal(result_lambda, result_regular)
# Test smap2_lgl with purrr lambda
thresholds <- c(5, 6, 5)
result_lgl_lambda <- smap2_lgl(
structures,
thresholds,
~ igraph::vcount(.x) > .y
)
result_lgl_regular <- smap2_lgl(structures, thresholds, function(g, t) {
igraph::vcount(g) > t
})
expect_equal(result_lgl_lambda, result_lgl_regular)
})
test_that("smap2 functions work with recycling", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test with single weight (should be recycled)
single_weight <- 2.5
result <- smap2_dbl(structures, single_weight, ~ igraph::vcount(.x) * .y)
expect_equal(length(result), 3)
expect_type(result, "double")
# All results should use the same weight
expected <- smap_dbl(structures, ~ igraph::vcount(.x) * 2.5)
expect_equal(result, expected)
})
test_that("smap2_structure works with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2) # different structures
# Function that adds a graph attribute (doesn't change structure topology)
add_attribute <- function(g, attr_val) {
igraph::set_graph_attr(g, "test_attr", attr_val)
}
attr_values <- c("value1", "value2")
result <- smap2_structure(structures, attr_values, add_attribute)
expect_s3_class(result, "glyrepr_structure")
expect_equal(length(result), 2)
# Check that the attributes were added correctly
result_graphs <- get_structure_graphs(result)
expect_equal(igraph::graph_attr(result_graphs[[1]], "test_attr"), "value1")
expect_equal(igraph::graph_attr(result_graphs[[2]], "test_attr"), "value2")
})
test_that("smap2_structure works with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2) # different structures
# Test with purrr lambda that adds vertex attribute based on second argument
labels <- c("label1", "label2")
result <- smap2_structure(
structures,
labels,
~ {
igraph::set_graph_attr(.x, "custom_label", .y)
}
)
expect_s3_class(result, "glyrepr_structure")
expect_equal(length(result), 2)
# Check that the custom attributes were added
result_graphs <- get_structure_graphs(result)
expect_equal(igraph::graph_attr(result_graphs[[1]], "custom_label"), "label1")
expect_equal(igraph::graph_attr(result_graphs[[2]], "custom_label"), "label2")
})
test_that("smap2 functions handle duplicate structures efficiently", {
# Create structures with duplicates to test efficiency
core1 <- o_glycan_core_1()
structures <- c(core1, core1, core1) # same structure 3 times
weights <- c(1.0, 2.0, 1.0) # first and third are same
# This should only compute twice: once for (core1, 1.0) and once for (core1, 2.0)
result <- smap2_dbl(structures, weights, function(g, w) igraph::vcount(g) * w)
expect_equal(length(result), 3)
expect_type(result, "double")
# First and third results should be equal since they have same structure and weight
expect_equal(result[1], result[3])
# Second result should be different
expect_true(result[2] != result[1])
})
test_that("smap2 functions validate inputs", {
core1 <- o_glycan_core_1()
structures <- core1
# Test that first argument must be glycan_structure
expect_error(smap2_dbl(c(1, 2, 3), c(1, 2, 3), ~ .x * .y), "glycan_structure")
expect_error(
smap2_structure("not_a_structure", c(1), ~.x),
"glycan_structure"
)
# Test that smap2_structure validates return type
expect_error(
smap2_structure(structures, 1, ~"not_an_igraph"),
"igraph object"
)
})
test_that("smap2 functions handle edge cases", {
# Test with single structure
single <- o_glycan_core_1()
result <- smap2_dbl(single, 3.0, ~ igraph::vcount(.x) * .y)
expect_equal(length(result), 1)
expect_type(result, "double")
# Test with empty structures
empty <- glycan_structure()
empty_result <- smap2_dbl(empty, numeric(0), ~ igraph::vcount(.x) * .y)
expect_equal(length(empty_result), 0)
expect_type(empty_result, "double")
})
test_that("smap2 basic functionality works", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
values <- c("a", "b", "c")
# Test smap2 (returns list)
result <- smap2(structures, values, function(g, v) {
list(vcount = igraph::vcount(g), value = v)
})
expect_type(result, "list")
expect_equal(length(result), 3)
expect_equal(result[[1]]$value, "a")
expect_equal(result[[2]]$value, "b")
expect_equal(result[[3]]$value, "c")
})
test_that("smap2_chr works correctly", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
prefixes <- c("prefix1_", "prefix2_", "prefix3_")
# Test smap2_chr
result <- smap2_chr(structures, prefixes, function(g, p) {
paste0(p, igraph::vcount(g))
})
expect_type(result, "character")
expect_equal(length(result), 3)
expect_true(all(grepl("^prefix[123]_\\d+$", result)))
})
# Tests for spmap functions -----------------------------------------
test_that("spmap functions work with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
weights <- c(1.0, 2.0)
factors <- c(2, 3)
# Test spmap_dbl with regular function
result <- spmap_dbl(list(structures, weights, factors), function(g, w, f) {
igraph::vcount(g) * w * f
})
expect_equal(length(result), 2)
expect_type(result, "double")
# Test spmap_int with regular function
add_values <- c(1, 2)
result_int <- spmap_int(list(structures, add_values), function(g, a) {
igraph::vcount(g) + a
})
expect_equal(length(result_int), 2)
expect_type(result_int, "integer")
# Test spmap_lgl with regular function
thresholds <- c(5, 6)
result_lgl <- spmap_lgl(list(structures, thresholds), function(g, t) {
igraph::vcount(g) > t
})
expect_equal(length(result_lgl), 2)
expect_type(result_lgl, "logical")
})
test_that("spmap functions work with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
weights <- c(1.0, 2.0)
factors <- c(2, 3)
# Test spmap_dbl with purrr lambda
result_lambda <- spmap_dbl(
list(structures, weights, factors),
~ igraph::vcount(..1) * ..2 * ..3
)
result_regular <- spmap_dbl(
list(structures, weights, factors),
function(g, w, f) igraph::vcount(g) * w * f
)
expect_equal(result_lambda, result_regular)
# Test spmap_chr with purrr lambda
prefixes <- c("pre1_", "pre2_")
result_chr_lambda <- spmap_chr(
list(structures, prefixes),
~ paste0(..2, igraph::vcount(..1))
)
expect_equal(length(result_chr_lambda), 2)
expect_type(result_chr_lambda, "character")
})
test_that("spmap functions work with recycling", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test with single weight (should be recycled)
single_weight <- 2.0
single_factor <- 3
result <- spmap_dbl(
list(structures, single_weight, single_factor),
~ igraph::vcount(..1) * ..2 * ..3
)
expect_equal(length(result), 3)
expect_type(result, "double")
# All results should use the same weight and factor
expected <- smap_dbl(structures, ~ igraph::vcount(.x) * 2.0 * 3)
expect_equal(result, expected)
})
test_that("spmap_structure works with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
# Function that adds graph attribute based on multiple arguments
add_attributes <- function(g, label, value) {
g <- igraph::set_graph_attr(g, "custom_label", label)
g <- igraph::set_graph_attr(g, "custom_value", value)
g
}
labels <- c("label1", "label2")
values <- c(10, 20)
result <- spmap_structure(list(structures, labels, values), add_attributes)
expect_s3_class(result, "glyrepr_structure")
expect_equal(length(result), 2)
# Check that attributes were added
graphs <- attr(result, "graphs")
first_structure <- graphs[[vctrs::vec_data(result)[1]]]
expect_equal(igraph::graph_attr(first_structure, "custom_label"), "label1")
expect_equal(igraph::graph_attr(first_structure, "custom_value"), 10)
})
test_that("spmap functions handle duplicate structures efficiently", {
# Create structures with duplicates to test efficiency
core1 <- o_glycan_core_1()
structures <- c(core1, core1, core1)
weights <- c(1.0, 2.0, 1.0)
factors <- c(2, 3, 2)
# This should only compute twice: once for (core1, 1.0, 2) and once for (core1, 2.0, 3)
result <- spmap_dbl(list(structures, weights, factors), function(g, w, f) {
igraph::vcount(g) * w * f
})
expect_equal(length(result), 3)
expect_type(result, "double")
# First and third should be equal (same combination)
expect_equal(result[1], result[3])
expect_false(result[1] == result[2]) # Different combination
})
test_that("spmap functions validate inputs", {
core1 <- o_glycan_core_1()
structures <- core1
# Test that .l must be a list
expect_error(spmap_dbl(structures, ~ igraph::vcount(.x)), "non-empty list")
expect_error(spmap_dbl(list(), ~ igraph::vcount(.x)), "non-empty list")
# Test that first element must be glycan_structure
expect_error(
spmap_dbl(list(c(1, 2, 3), c(1, 2, 3)), ~ .x * .y),
"glycan_structure"
)
expect_error(
spmap_structure(list("not_a_structure"), ~.x),
"glycan_structure"
)
# Test that spmap_structure validates return type
expect_error(
spmap_structure(list(structures, 1), ~"not_an_igraph"),
"igraph object"
)
})
test_that("spmap functions handle edge cases", {
# Test with single structure
single <- o_glycan_core_1()
result <- spmap_dbl(list(single, 3.0, 2), ~ igraph::vcount(..1) * ..2 * ..3)
expect_equal(length(result), 1)
expect_type(result, "double")
# Test with empty structures
empty <- glycan_structure()
empty_result <- spmap_dbl(
list(empty, numeric(0), numeric(0)),
~ igraph::vcount(..1) * ..2 * ..3
)
expect_equal(length(empty_result), 0)
expect_type(empty_result, "double")
})
test_that("spmap basic functionality works", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
values1 <- c("a", "b")
values2 <- c(1, 2)
# Test spmap (returns list)
result <- spmap(list(structures, values1, values2), function(g, v1, v2) {
list(vcount = igraph::vcount(g), value1 = v1, value2 = v2)
})
expect_type(result, "list")
expect_equal(length(result), 2)
expect_equal(result[[1]]$value1, "a")
expect_equal(result[[1]]$value2, 1)
expect_equal(result[[2]]$value1, "b")
expect_equal(result[[2]]$value2, 2)
})
# Tests for simap functions -----------------------------------------
test_that("simap functions work with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test simap_chr with regular function (using index)
result <- simap_chr(structures, function(g, i) {
paste0("Structure_", i, "_vcount_", igraph::vcount(g))
})
expect_equal(length(result), 3)
expect_type(result, "character")
expect_true(grepl("Structure_1_", result[1]))
expect_true(grepl("Structure_2_", result[2]))
expect_true(grepl("Structure_3_", result[3]))
# Test simap_int with regular function (using index)
result_int <- simap_int(structures, function(g, i) igraph::vcount(g) + i)
expect_equal(length(result_int), 3)
expect_type(result_int, "integer")
# Test simap_lgl with regular function (using index)
result_lgl <- simap_lgl(structures, function(g, i) i > 1)
expect_equal(length(result_lgl), 3)
expect_type(result_lgl, "logical")
expect_false(result_lgl[1]) # index 1
expect_true(result_lgl[2]) # index 2
expect_true(result_lgl[3]) # index 3
})
test_that("simap functions work with purrr-style lambda functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
# Test simap_chr with purrr lambda
result_lambda <- simap_chr(
structures,
~ paste0("Pos", .y, "_vertices", igraph::vcount(.x))
)
result_regular <- simap_chr(structures, function(g, i) {
paste0("Pos", i, "_vertices", igraph::vcount(g))
})
expect_equal(result_lambda, result_regular)
# Test simap_dbl with purrr lambda
result_dbl <- simap_dbl(structures, ~ igraph::vcount(.x) * .y)
expect_equal(length(result_dbl), 3)
expect_type(result_dbl, "double")
})
test_that("simap_structure works with regular functions", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
# Function that adds index/name as graph attribute
add_index_attr <- function(g, idx) {
igraph::set_graph_attr(g, "position", idx)
}
result <- simap_structure(structures, add_index_attr)
expect_s3_class(result, "glyrepr_structure")
expect_equal(length(result), 2)
# Check that attributes were added
graphs <- attr(result, "graphs")
first_structure <- graphs[[vctrs::vec_data(result)[1]]]
expect_equal(igraph::graph_attr(first_structure, "position"), 1)
})
test_that("simap functions handle duplicate structures efficiently", {
# Create structures with duplicates to test efficiency
core1 <- o_glycan_core_1()
structures <- c(core1, core1, core1)
# This should compute three times since indices are different: (core1, 1), (core1, 2), (core1, 3)
result <- simap_chr(structures, function(g, i) {
paste0("Structure_", i, "_vcount_", igraph::vcount(g))
})
expect_equal(length(result), 3)
expect_type(result, "character")
# All should be different because indices are different
expect_false(result[1] == result[2])
expect_false(result[1] == result[3])
expect_false(result[2] == result[3])
# Test that each result contains the expected structure and index information
expect_true(grepl("Structure_1_", result[1]))
expect_true(grepl("Structure_2_", result[2]))
expect_true(grepl("Structure_3_", result[3]))
})
test_that("simap functions validate inputs", {
core1 <- o_glycan_core_1()
structures <- core1
# Test that first argument must be glycan_structure
expect_error(simap_chr(c(1, 2, 3), ~ paste(.x, .y)), "glycan_structure")
expect_error(simap_structure("not_a_structure", ~.x), "glycan_structure")
# Test that simap_structure validates return type
expect_error(
simap_structure(structures, ~"not_an_igraph"),
"igraph object"
)
})
test_that("simap functions handle edge cases", {
# Test with single structure
single <- o_glycan_core_1()
result <- simap_chr(
single,
~ paste0("Index", .y, "_vertices", igraph::vcount(.x))
)
expect_equal(length(result), 1)
expect_type(result, "character")
expect_true(grepl("Index1_", result[1]))
# Test with empty structures
empty <- glycan_structure()
empty_result <- simap_chr(empty, ~ paste0(.y, "_", igraph::vcount(.x)))
expect_equal(length(empty_result), 0)
expect_type(empty_result, "character")
})
test_that("simap basic functionality works", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
# Test simap (returns list)
result <- simap(structures, function(g, i) {
list(vcount = igraph::vcount(g), index = i)
})
expect_type(result, "list")
expect_equal(length(result), 2)
expect_equal(result[[1]]$index, 1)
expect_equal(result[[2]]$index, 2)
expect_true(is.numeric(result[[1]]$vcount))
expect_true(is.numeric(result[[2]]$vcount))
})
# Tests for map interface cleanliness --------------------------------------
test_that("smap interfaces do not expose parallel arguments", {
map_functions <- list(
smap,
smap_vec,
smap_lgl,
smap_int,
smap_dbl,
smap_chr,
smap_structure,
smap_unique,
smap2,
smap2_vec,
smap2_lgl,
smap2_int,
smap2_dbl,
smap2_chr,
smap2_structure,
spmap,
spmap_vec,
spmap_lgl,
spmap_int,
spmap_dbl,
spmap_chr,
spmap_structure
)
purrr::walk(map_functions, function(map_function) {
expect_false(".parallel" %in% names(formals(map_function)))
})
})
test_that("smap handles additional arguments correctly", {
# Create test structures
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
# Function that takes additional arguments
func_with_args <- function(g, multiplier = 1, offset = 0) {
igraph::vcount(g) * multiplier + offset
}
# Test with additional arguments
result1 <- smap_int(
structures,
func_with_args,
multiplier = 2,
offset = 1
)
expect_equal(length(result1), 2)
expect_type(result1, "integer")
# Verify the calculation is correct by computing expected values
# Get the actual structures from the glycan_structure object
graphs <- attr(structures, "graphs")
codes <- vctrs::vec_data(structures)
expected1 <- igraph::vcount(graphs[[codes[1]]]) * 2 + 1
expected2 <- igraph::vcount(graphs[[codes[2]]]) * 2 + 1
expect_equal(result1[1], expected1)
expect_equal(result1[2], expected2)
})
test_that("smap_structure correctly updates unique structures count when modifications create duplicates", {
# Create structures that will become identical after modification
glycans <- c("Gal(a1-3)GalNAc(a1-", "Gal(a1-4)GalNAc(a1-")
structures <- as_glycan_structure(glycans)
# Before modification: should have 2 unique structures
expect_equal(length(attr(structures, "graphs")), 2)
# Remove linkages - both structures should become identical
result <- remove_linkages(structures)
# After modification: should have only 1 unique structure
expect_equal(length(attr(result, "graphs")), 1)
# Both elements should have the same IUPAC code
expect_equal(as.character(result)[1], as.character(result)[2])
expect_equal(as.character(result)[1], "Gal(??-?)GalNAc(??-")
})
test_that("smap2_structure correctly updates unique structures count when modifications create duplicates", {
# Create structures that will become identical after modification
glycans <- c("Gal(a1-3)GalNAc(a1-", "Gal(a1-4)GalNAc(a1-")
structures <- as_glycan_structure(glycans)
values <- c("test1", "test2")
# Before modification: should have 2 unique structures
expect_equal(length(attr(structures, "graphs")), 2)
# Function that removes linkages regardless of second argument
remove_linkages_func <- function(g, val) {
igraph::set_edge_attr(g, "linkage", value = "??-?") |>
igraph::set_graph_attr("anomer", value = "??")
}
result <- smap2_structure(structures, values, remove_linkages_func)
# After modification: should have only 1 unique structure
expect_equal(length(attr(result, "graphs")), 1)
# Both elements should have the same IUPAC code
expect_equal(as.character(result)[1], as.character(result)[2])
expect_equal(as.character(result)[1], "Gal(??-?)GalNAc(??-")
})
test_that("spmap_structure correctly updates unique structures count when modifications create duplicates", {
# Create structures that will become identical after modification
glycans <- c("Gal(a1-3)GalNAc(a1-", "Gal(a1-4)GalNAc(a1-")
structures <- as_glycan_structure(glycans)
values1 <- c("test1", "test2")
values2 <- c(1, 2)
# Before modification: should have 2 unique structures
expect_equal(length(attr(structures, "graphs")), 2)
# Function that removes linkages regardless of other arguments
remove_linkages_func <- function(g, val1, val2) {
igraph::set_edge_attr(g, "linkage", value = "??-?") |>
igraph::set_graph_attr("anomer", value = "??")
}
result <- spmap_structure(
list(structures, values1, values2),
remove_linkages_func
)
# After modification: should have only 1 unique structure
expect_equal(length(attr(result, "graphs")), 1)
# Both elements should have the same IUPAC code
expect_equal(as.character(result)[1], as.character(result)[2])
expect_equal(as.character(result)[1], "Gal(??-?)GalNAc(??-")
})
test_that("structure mappers recanonicalize floating candidate indices", {
glycan <- as_glycan_structure(
"{Neu5Ac(a2-4)|3,4}Fuc(a1-2)[Gal(a1-3)]Man(a1-"
)
strip_tree_linkages <- function(graph, ...) {
graph <- igraph::set_edge_attr(graph, "linkage", value = "??-?")
igraph::set_graph_attr(graph, "anomer", value = "??")
}
results <- list(
smap = smap_structure(glycan, strip_tree_linkages),
smap2 = smap2_structure(glycan, 1, strip_tree_linkages),
spmap = spmap_structure(list(glycan, 1), strip_tree_linkages),
simap = simap_structure(glycan, strip_tree_linkages)
)
purrr::walk(results, function(result) {
expect_identical(
as.character(result),
"{Neu5Ac(a2-4)|2,4}Gal(??-?)[Fuc(??-?)]Man(??-"
)
expect_identical(
structure_floating_parts(result)$parents[[1]],
c(2L, 4L)
)
})
})
test_that("structure mappers preserve cross-component parent relations", {
glycan <- as_glycan_structure(
paste0(
"{?S|1,3}",
"{Fuc(a1-2)|2,3}",
"{Man(a1-3)|1,3}",
"Glc(a1-"
)
)
permute_forest <- function(graph, ...) {
igraph::V(graph)$source_id <- seq_len(igraph::vcount(graph))
graph <- igraph::permute(graph, rev(seq_len(igraph::vcount(graph))))
old_to_new <- match(
seq_len(igraph::vcount(graph)),
igraph::V(graph)$source_id
)
parts <- purrr::map(graph$floating_parts, function(part) {
part$root <- as.integer(old_to_new[part$root])
part$nodes <- sort(as.integer(old_to_new[part$nodes]))
part$parents <- sort(as.integer(old_to_new[part$parents]))
part
})
substituents <- purrr::map(
graph$floating_substituents,
function(substituent) {
substituent$parents <- sort(as.integer(
old_to_new[substituent$parents]
))
substituent
}
)
graph <- set_floating_parts_attr(graph, parts)
graph <- set_floating_substituents_attr(graph, substituents)
igraph::delete_vertex_attr(graph, "source_id")
}
transformed <- smap_structure(glycan, permute_forest)
expect_identical(as.character(transformed), as.character(glycan))
expect_true(unname(transformed == glycan))
expect_identical(
structure_floating_parts(transformed)$parents,
list(c(2L, 3L), c(1L, 3L))
)
expect_identical(
structure_floating_substituents(transformed)$parents,
list(c(1L, 3L))
)
})
test_that("structure mappers validate floating metadata returned by callbacks", {
glycan <- as_glycan_structure(
"{Neu5Ac(a2-6)|2,3}Gal(b1-3)GalNAc(a1-"
)
expect_snapshot(
smap_structure(glycan, delete_floating_parts_attr),
error = TRUE
)
})
test_that("structure mappers reuse unchanged validated graphs", {
glycan <- c(
first = o_glycan_core_1(),
duplicate = o_glycan_core_1(),
missing = glycan_structure(NA)
)
original_validator <- validate_glycan_graph
validation_count <- 0
testthat::local_mocked_bindings(
validate_glycan_graph = function(graph) {
validation_count <<- validation_count + 1
original_validator(graph)
}
)
unchanged <- list(
smap = smap_structure(glycan, identity),
smap2 = smap2_structure(glycan, 1, function(graph, ...) graph),
spmap = spmap_structure(
list(glycan, 1),
function(graph, ...) graph
),
simap = simap_structure(glycan, function(graph, ...) graph)
)
purrr::walk(unchanged, function(result) {
expect_identical(as.character(result), as.character(glycan))
expect_identical(names(result), names(glycan))
expect_identical(is.na(result), is.na(glycan))
expect_length(attr(result, "graphs"), 1)
})
expect_equal(validation_count, 0)
smap_structure(
glycan[1],
function(graph) {
igraph::set_graph_attr(graph, "mapped", value = TRUE)
}
)
expect_equal(validation_count, 1)
})
# Additional regression tests for the smap2 nested list fix
test_that("smap2 handles real glycan structures with nested match results correctly", {
# Create a realistic glycan structure (simulating glyenzy use case)
glycan_code <- "GlcNAc(b1-2)Man(a1-3)[Man(a1-6)]Man(b1-4)GlcNAc(b1-4)GlcNAc(b1-"
structures <- as_glycan_structure(glycan_code)
# Create nested list simulating enzyme rule match results
# This is the exact structure that was causing the original bug
rule_matches <- list(list(c(6, 5, 4, 3, 2, 1)))
# Test that smap2 processes this correctly
call_count <- 0
result <- smap2(structures, rule_matches, function(graph, match_data) {
call_count <<- call_count + 1
# Verify the graph is correct
expect_true(igraph::is_igraph(graph))
expect_equal(igraph::vcount(graph), 6)
# Verify the match data structure is preserved
expect_true(is.list(match_data))
expect_length(match_data, 1)
expect_equal(match_data[[1]], c(6, 5, 4, 3, 2, 1))
return("processed")
})
# Should be called exactly once (not 6 times due to expansion bug)
expect_equal(call_count, 1)
expect_length(result, 1)
expect_equal(result[[1]], "processed")
})
test_that("smap2 tibble fix handles multiple glycans with different nested structures", {
# Create multiple structures
glycan_codes <- c(
"GlcNAc(b1-2)Man(a1-3)[Man(a1-6)]Man(b1-4)GlcNAc(b1-4)GlcNAc(b1-",
"Gal(a1-3)GalNAc(a1-"
)
structures <- as_glycan_structure(glycan_codes)
# Create different nested structures for each glycan
nested_data <- list(
list(c(6, 5, 4, 3, 2, 1)), # First glycan: complex match
list(c(2, 1)) # Second glycan: simple match
)
results <- smap2(structures, nested_data, function(graph, match_data) {
return(list(
vertex_count = igraph::vcount(graph),
match_length = length(match_data[[1]])
))
})
# Verify results correspond correctly to inputs
expect_length(results, 2)
expect_equal(results[[1]]$vertex_count, 6)
expect_equal(results[[1]]$match_length, 6)
expect_equal(results[[2]]$vertex_count, 2)
expect_equal(results[[2]]$match_length, 2)
})
test_that("smap2 hash generation works correctly for different list structures", {
# Test the hash-based key generation with various list structures
structures <- as_glycan_structure("Gal(a1-3)GalNAc(a1-")[1]
# Different nested list structures that should produce different keys
list_variants <- list(
list(c(1, 2, 3)),
list(c(3, 2, 1)), # Same elements, different order
list(c(1, 2, 3, 4)), # Different length
list(list(a = 1, b = 2)) # Named list
)
# Each should be handled correctly without expansion
for (i in seq_along(list_variants)) {
result <- smap2(structures, list_variants[i], function(graph, data) {
expect_true(is.list(data))
return(paste0("variant_", i))
})
expect_length(result, 1)
expect_equal(result[[1]], paste0("variant_", i))
}
})
test_that("smap2 refactored code maintains performance with complex inputs", {
# Performance regression test for the refactored hash generation
glycan_codes <- c(
"Gal(a1-3)GalNAc(a1-",
"GlcNAc(b1-2)Man(a1-3)[Man(a1-6)]Man(b1-4)GlcNAc(b1-4)GlcNAc(b1-",
"Man(a1-2)Man(a1-3)[Man(a1-6)]Man(b1-4)GlcNAc(b1-4)GlcNAc(b1-"
)
structures <- as_glycan_structure(glycan_codes)
# Create moderately complex nested structures
complex_nested <- list(
list(c(1:10)),
list(list(x = 1:5, y = letters[1:5])),
list(matrix(1:6, nrow = 2))
)
# Should complete without errors and reasonable time
start_time <- Sys.time()
result <- smap2(structures, complex_nested, function(graph, data) {
return("completed")
})
end_time <- Sys.time()
# Basic correctness checks
expect_length(result, 3)
expect_true(all(unlist(result) == "completed"))
# Performance should be reasonable (less than 1 second for this simple case)
expect_true(as.numeric(end_time - start_time) < 1)
})
test_that("smap2 edge case: empty lists and mixed types", {
glycan_codes <- c(
"Gal(a1-3)GalNAc(a1-",
"GlcNAc(b1-2)Man(a1-3)[Man(a1-6)]Man(b1-4)GlcNAc(b1-4)GlcNAc(b1-"
)
structures <- as_glycan_structure(glycan_codes)
# Test with empty lists and mixed simple/complex types
mixed_data <- list(
list(), # Empty list
"simple_string" # Non-list data
)
result <- smap2(structures, mixed_data, function(graph, data) {
if (is.list(data)) {
return(paste0("list_", length(data)))
} else {
return(paste0("non_list_", data))
}
})
expect_length(result, 2)
expect_equal(result[[1]], "list_0")
expect_equal(result[[2]], "non_list_simple_string")
})
# Tests for names preservation -----------------------------------------
test_that("smap_structure preserves names", {
core1 <- o_glycan_core_1()
structures <- c(core1, core1)
names(structures) <- c("X", "Y")
add_attr <- function(g) {
igraph::set_graph_attr(g, "test", "value")
}
result <- smap_structure(structures, add_attr)
expect_equal(names(result), c("X", "Y"))
})
test_that("smap2 functions preserve names", {
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
names(structures) <- c("A", "B", "C")
weights <- c(1.0, 2.0, 1.0)
# smap2_dbl should preserve names
result <- smap2_dbl(structures, weights, function(g, w) igraph::vcount(g) * w)
expect_equal(names(result), c("A", "B", "C"))
# smap2 should preserve names in list
result_list <- smap2(structures, weights, function(g, w) {
list(count = igraph::vcount(g), weight = w)
})
expect_equal(names(result_list), c("A", "B", "C"))
})
test_that("smap2_structure preserves names", {
core1 <- o_glycan_core_1()
structures <- c(core1, core1)
names(structures) <- c("X", "Y")
values <- c(1, 2)
add_attr <- function(g, v) {
igraph::set_graph_attr(g, "value", v)
}
result <- smap2_structure(structures, values, add_attr)
expect_equal(names(result), c("X", "Y"))
})
# Tests for spmap names preservation -----------------------------------------
test_that("spmap functions preserve names", {
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2)
names(structures) <- c("A", "B")
weights <- c(1.0, 2.0)
factors <- c(2, 3)
# spmap_dbl should preserve names
result <- spmap_dbl(list(structures, weights, factors), function(g, w, f) {
igraph::vcount(g) * w * f
})
expect_equal(names(result), c("A", "B"))
# spmap should preserve names in list
result_list <- spmap(list(structures, weights, factors), function(g, w, f) {
list(count = igraph::vcount(g), weight = w)
})
expect_equal(names(result_list), c("A", "B"))
})
test_that("spmap_structure preserves names", {
core1 <- o_glycan_core_1()
structures <- c(core1, core1)
names(structures) <- c("X", "Y")
values1 <- c("a", "b")
values2 <- c(1, 2)
add_attrs <- function(g, v1, v2) {
g <- igraph::set_graph_attr(g, "label", v1)
igraph::set_graph_attr(g, "num", v2)
}
result <- spmap_structure(list(structures, values1, values2), add_attrs)
expect_equal(names(result), c("X", "Y"))
})
# Tests for simap names preservation -----------------------------------------
test_that("simap functions preserve names", {
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
names(structures) <- c("A", "B", "C")
# simap_chr should preserve names
result <- simap_chr(structures, function(g, i) paste0("Structure_", i))
expect_equal(names(result), c("A", "B", "C"))
# simap should preserve names in list
result_list <- simap(structures, function(g, i) list(index = i))
expect_equal(names(result_list), c("A", "B", "C"))
})
test_that("simap_structure preserves names", {
core1 <- o_glycan_core_1()
structures <- c(core1, core1)
names(structures) <- c("X", "Y")
add_index_attr <- function(g, idx) {
igraph::set_graph_attr(g, "index", idx)
}
result <- simap_structure(structures, add_index_attr)
expect_equal(names(result), c("X", "Y"))
})
test_that("smap_unique documents behavior with named input", {
core1 <- o_glycan_core_1()
structures <- c(core1, core1, core1)
names(structures) <- c("A", "B", "C") # All same structure, different names
# smap_unique operates on unique structures only
result <- smap_unique(structures, igraph::vcount)
# Result is named by structure hash (IUPAC), not input names
expect_true(is.null(names(result)) || startsWith(names(result), "Gal"))
})
test_that("get_structure_level preserves names", {
core1 <- o_glycan_core_1()
core2 <- n_glycan_core()
structures <- c(core1, core2, core1)
names(structures) <- c("A", "B", "C")
result <- get_structure_level(structures)
expect_identical(result, c(A = "intact", B = "intact", C = "intact"))
})
test_that("smap_structure can create mixed residue types", {
structures <- c(
o_glycan_core_1(),
n_glycan_core(mono_type = "generic")
)
result <- smap_structure(structures, function(graph) {
replacement <- if (get_mono_type(graph) == "concrete") "Hex" else "Gal"
igraph::set_vertex_attr(graph, "mono", index = 1, value = replacement)
})
expect_identical(get_mono_type(result), c("mixed", "mixed"))
})
# Tests for NA handling in smap functions -----------------------------------
test_that("smap skips NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
counts <- smap_int(structs, igraph::vcount)
expect_equal(length(counts), 3)
expect_false(is.na(counts[1]))
expect_true(is.na(counts[2]))
expect_false(is.na(counts[3]))
})
test_that("smap_structure skips NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
result <- smap_structure(structs, identity)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
})
test_that("ssome skips NA elements", {
structs <- c(glycan_structure(NA), o_glycan_core_1())
expect_true(ssome(structs, function(g) igraph::vcount(g) > 1))
})
test_that("severy skips NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA))
expect_true(severy(structs, function(g) igraph::vcount(g) > 1))
})
test_that("snone skips NA elements", {
structs <- glycan_structure(NA, NA)
expect_true(snone(structs, function(g) igraph::vcount(g) > 100))
})
test_that(".smap_base handles NA elements correctly", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
# smap_int should return NA for position 2
result <- smap_int(structs, igraph::vcount)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
# smap_chr should return NA for position 2
result_chr <- smap_chr(structs, ~ .x$anomer)
expect_equal(length(result_chr), 3)
expect_false(is.na(result_chr[1]))
expect_true(is.na(result_chr[2]))
expect_false(is.na(result_chr[3]))
# smap should return NULL for position 2 (for composition compatibility)
result_list <- smap(structs, igraph::vcount)
expect_equal(length(result_list), 3)
expect_false(is.na(result_list[[1]]))
expect_true(is.null(result_list[[2]]))
expect_false(is.na(result_list[[3]]))
})
test_that(".smap_base handles all-NA vector with correct NA types", {
# All-NA vector
all_na_structs <- glycan_structure(NA, NA, NA)
# smap_chr should return NA_character_, not "NA" string
result_chr <- smap_chr(all_na_structs, ~ .x$anomer)
expect_equal(length(result_chr), 3)
expect_type(result_chr, "character")
expect_true(all(is.na(result_chr)))
# Verify it's true NA_character_, not the string "NA"
expect_identical(result_chr[1], NA_character_)
# smap_int should return NA_integer_
result_int <- smap_int(all_na_structs, igraph::vcount)
expect_equal(length(result_int), 3)
expect_type(result_int, "integer")
expect_true(all(is.na(result_int)))
# smap_dbl should return NA_real_
result_dbl <- smap_dbl(all_na_structs, igraph::vcount)
expect_equal(length(result_dbl), 3)
expect_type(result_dbl, "double")
expect_true(all(is.na(result_dbl)))
# smap_lgl should return NA (logical)
result_lgl <- smap_lgl(all_na_structs, ~ igraph::vcount(.x) > 0)
expect_equal(length(result_lgl), 3)
expect_type(result_lgl, "logical")
expect_true(all(is.na(result_lgl)))
# smap returns list with NULL for NA elements
result_list <- smap(all_na_structs, igraph::vcount)
expect_equal(length(result_list), 3)
expect_true(all(purrr::map_lgl(result_list, is.null)))
})
# Tests for NA handling in smap2 functions -----------------------------------
test_that("smap2 handles NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
# smap2_dbl should return NA for position 2
result <- smap2_dbl(structs, c(1, 2, 3), function(g, n) igraph::vcount(g) + n)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
# smap2 with lambda should work
result_lambda <- smap2_dbl(structs, c(1, 2, 3), ~ igraph::vcount(.x) + .y)
expect_equal(result, result_lambda)
})
test_that("smap2 handles NA at different positions", {
# NA at beginning
structs1 <- c(glycan_structure(NA), o_glycan_core_1(), n_glycan_core())
result1 <- smap2_dbl(structs1, c(1, 2, 3), ~ igraph::vcount(.x) + .y)
expect_true(is.na(result1[1]))
expect_false(is.na(result1[2]))
expect_false(is.na(result1[3]))
# NA at end
structs3 <- c(o_glycan_core_1(), n_glycan_core(), glycan_structure(NA))
result3 <- smap2_dbl(structs3, c(1, 2, 3), ~ igraph::vcount(.x) + .y)
expect_false(is.na(result3[1]))
expect_false(is.na(result3[2]))
expect_true(is.na(result3[3]))
})
test_that("smap2_structure handles NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
names(structs) <- c("A", "B", "C")
values <- c(1, 2, 3)
add_attr <- function(g, v) {
igraph::set_graph_attr(g, "value", v)
}
result <- smap2_structure(structs, values, add_attr)
expect_equal(length(result), 3)
expect_equal(names(result), c("A", "B", "C"))
# Check the graphs directly - there should be 2 unique graphs
result_graphs <- attr(result, "graphs")
expect_equal(length(result_graphs), 2)
# Check that attributes were set correctly on the graphs
expect_equal(igraph::graph_attr(result_graphs[[1]], "value"), 1)
expect_equal(igraph::graph_attr(result_graphs[[2]], "value"), 3)
# Verify result has correct codes (2 actual codes + 1 NA)
result_codes <- vctrs::vec_data(result)
expect_equal(sum(is.na(result_codes)), 1)
expect_equal(sum(!is.na(result_codes)), 2)
})
# Tests for NA handling in spmap functions -----------------------------------
test_that("spmap handles NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
# spmap_dbl should return NA for position 2
result <- spmap_dbl(list(structs, c(1, 2, 3)), ~ igraph::vcount(..1) + ..2)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
# spmap with lambda should work
result_lambda <- spmap_dbl(list(structs, c(1, 2, 3)), function(g, n) {
igraph::vcount(g) + n
})
expect_equal(result, result_lambda)
})
test_that("spmap_structure handles NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
result <- spmap_structure(list(structs, c(1, 2, 3)), function(g, n) g)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
})
# Tests for NA handling in simap functions -----------------------------------
test_that("simap handles NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
result <- simap_int(structs, function(g, i) igraph::vcount(g) + i)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
})
test_that("simap_structure handles NA elements", {
structs <- c(o_glycan_core_1(), glycan_structure(NA), n_glycan_core())
result <- simap_structure(structs, function(g, i) g)
expect_equal(length(result), 3)
expect_false(is.na(result[1]))
expect_true(is.na(result[2]))
expect_false(is.na(result[3]))
})
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.