test_that("Errors are handled", { skip_if(Sys.getenv("USING_ASAN") != "") expect_error(RootedTreeWithShape(as.integer64(-1)), "Shape may not be negative") expect_error(RootedTreeWithShape(as.integer64(0), -1), "Tree must have at least zero leaves") expect_error(RootedTreeWithShape(as.integer64(2)^31), "Shapes this large are not.* implemented") expect_error(UnrootedTreeWithShape(31, 31), " < 31 leaves") expect_error(.UnrootedKeys(29L), " 29 leaves") expect_error(NRootedShapes(56L), "Too many shapes ") expect_error(NUnrootedShapes(61L), "Too many shapes ") }) test_that("Tree shapes counted", { expect_equal(as.integer64(c(1, 1, 1, 2, 3, 6, 11, 23)), structure(vapply(1:8, NRootedShapes, bit64::integer64(1L)), class = "integer64")) expect_equal(as.integer64(lengths(unrootedKeys)), structure(vapply(seq_along(unrootedKeys), NUnrootedShapes, integer64(1)), class = "integer64")) }) test_that("Nasty node order not fatal", { nastyBinary <- structure(list(edge = structure( c(9, 12, 10, 13, 11, 10, 11, 14, 15, 13, 12, 9, 14, 15, 5, 10, 15, 14, 3, 13, 9, 4, 11, 7, 8, 6, 2, 1), .Dim = c(14, 2)), Nnode = 7L, tip.label = letters[1:8]), class = "phylo") # Danger: Do not plot! expect_equal(RootedTreeShape(Preorder(nastyBinary)), RootedTreeShape(nastyBinary)) skip_if(Sys.getenv("USING_ASAN") != "") expect_error(edge_to_rooted_shape(1:10, 1:11, 6), "must be the same length") expect_error(edge_to_rooted_shape(1:10, 1:10, 5), "is tree binary\\?") }) test_that("Rooted tree shapes counted", { # https://oeis.org/A001190 expect_equal(as.integer64(c(1, 1, 1, 2, 3, 6, 11, 23, 46, 98, 207, 451, 983, 2179, 4850, 10905, 24631, 56011, 127912, 293547, 676157, 1563372, 3626149, 8436379, 19680277, 46026618, 107890609, 253450711, 596572387, 1406818759, "3323236238", "7862958391", "18632325319", "44214569100")), structure(vapply(1:34, NRootedShapes, integer64(1)), class = "integer64")) }) test_that("Rooted tree shapes fail gracefully", { skip_if(Sys.getenv("USING_ASAN") != "") expect_error(RootedTreeShape(BalancedTree(56)), "> 55 leaves") }) test_that("Rooted tree shapes calculated", { expect_equal(NRootedShapes(8) - 1L, RootedTreeShape(BalancedTree(0:7))) expect_equal(NRootedShapes(54) - 1L, RootedTreeShape(BalancedTree(54))) expect_equal(NRootedShapes(55), RootedTreeShape(BalancedTree(55))) expect_equal(as.integer64(0L), RootedTreeShape(PectinateTree(0:3))) expect_equal(as.integer64(0L), RootedTreeShape(SortTree(PectinateTree(0:3)))) expect_equal(0L, UnrootedTreeShape(PectinateTree(0:3))) expect_equal(as.integer64(1L), RootedTreeShape(BalancedTree(0:3))) expect_equal(as.integer64(0L), RootedTreeShape(PectinateTree(0:4))) expect_equal(0L, UnrootedTreeShape(PectinateTree(0:4))) expect_equal(as.integer64(1L), RootedTreeShape(as.phylo(1, 5))) expect_equal(as.integer64(2L), RootedTreeShape(BalancedTree(0:4))) expect_equal(as.integer64(0L), RootedTreeShape(PectinateTree(0:5))) expect_equal(0L, UnrootedTreeShape(PectinateTree(0:5))) expect_equal(as.integer64(1L), RootedTreeShape(as.phylo(58, 6))) expect_equal(as.integer64(2L), RootedTreeShape(as.phylo(1, 6))) expect_equal(as.integer64(3L), RootedTreeShape( ape::read.tree(text = "((a, b), (c, (d, (e, f))));"))) expect_equal(as.integer64(4L), RootedTreeShape( ape::read.tree(text = "((a, b), ((c, d), (e, f)));"))) expect_equal(as.integer64(5L), RootedTreeShape(BalancedTree(0:5))) PectinateTest <- function(i) { expect_equal(as.integer64(0L), RootedTreeShape(PectinateTree(i))) } lapply(4:16, PectinateTest) BalancedTest <- function(i) { expect_equal(NRootedShapes(i) - 1L, RootedTreeShape(BalancedTree(i))) } lapply(c(2 ^ (1:4), 10), BalancedTest) expect_equal(0L, .UnrootedKeys(4)) expect_equal(0L, .UnrootedKeys(5)) expect_equal(0:1, .UnrootedKeys(6)) expect_equal(0:1, .UnrootedKeys(7)) expect_equal(c(0:2, 4), .UnrootedKeys(8)) expect_equal(c(0:2, 4:5, 7), .UnrootedKeys(9)) }) expect_treequal <- function(...) expect_true(all.equal(...)) test_that("Rooted tree shapes built", { expect_error(RootedTreeWithShape(-1, 5)) expect_treequal(RootedTreeWithShape(0, 4), PectinateTree(rep("", 4))) expect_treequal(RootedTreeWithShape(1, 4), BalancedTree(rep("", 4))) expect_treequal(RootedTreeWithShape(0L, 5L), PectinateTree(rep("", 5))) expect_treequal(RootedTreeWithShape(1L, 5L), as.phylo(1, 5, rep("", 5))) expect_treequal(RootedTreeWithShape(2L, 5L), BalancedTree(rep("", 5))) blank6 <- rep("", 6L) expect_treequal(RootedTreeWithShape(0L, 6L), PectinateTree(blank6)) expect_treequal(RootedTreeWithShape(1L, 6L), as.phylo(58, 6, blank6)) expect_treequal(RootedTreeWithShape(2L, 6L), as.phylo(1, 6, blank6)) expect_treequal(RootedTreeWithShape(3L, 6L), ape::read.tree(text = "((,),(,(,(,))));")) expect_treequal(RootedTreeWithShape(4L, 6L), ape::read.tree(text = "((,),((,),(,)));")) expect_treequal(RootedTreeWithShape(5L, 6L), BalancedTree(blank6)) expect_treequal(RootedTreeWithShape(0, 8), PectinateTree(rep("", 8))) expect_treequal(RootedTreeWithShape(NRootedShapes(8), 8), BalancedTree(rep("", 8))) BalancedTest <- function(i) { expect_treequal(BalancedTree(rep("", i)), RootedTreeWithShape(NRootedShapes(i) - 1L, i)) } lapply(2 ^ (1:4), BalancedTest) }) test_that("Unrooted tree shapes fail gracefully", { skip_if(Sys.getenv("USING_ASAN") != "") expect_error(UnrootedTreeWithShape(4, 8), "must be between 0 and 3") }) test_that("Unrooted tree shapes built", { expect_treequal(UnrootedTreeWithShape(0, 9), UnrootTree(PectinateTree(rep("", 9)))) TestSym <- function(tree, shape) { expect_equal(shape, UnrootedTreeShape(tree)) expect_equal(UnrootedTreeKey(tree), UnrootedTreeKey(UnrootedTreeWithShape(shape, NTip(tree)))) } blank9 <- rep("", 9) TestSym(PectinateTree(blank9), 0) TestSym(as.phylo(72292, nTip = 9, blank9), 1) TestSym(as.phylo(67987, nTip = 9, blank9), 2) TestSym(BalancedTree(blank9), 3) TestSym(as.phylo(72237, nTip = 9, blank9), 3) TestSym(as.phylo(67882, nTip = 9, blank9), 4) TestSym(as.phylo(72298, nTip = 9, blank9), 5) })