test_that("admix_cluster validates inputs", { expect_error(admix_cluster(samples = rnorm(10), admixMod = list()), "Please provide sample") expect_error(admix_cluster( samples = list(rnorm(10), rnorm(10)), admixMod = list("bad", "bad")), "admixMod") }) test_that("admixMod must contain admix_model objects", { expect_error( admix_cluster(samples = list(rnorm(10), rnorm(10)), admixMod = list("bad", "bad")), "Argument 'admixMod' is not correctly specified" ) }) test_that("admix_cluster returns informative message for one sample", { skip_on_cran() sample1 <- rnorm(20) admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) res <- admix_cluster(samples = list(sample1), admixMod = list(admixMod)) expect_equal(res, "One single sample, no clusters to be found.") }) test_that("admix_cluster returns object of class admix_cluster", { skip_if_not_installed("mockery") sample1 <- rnorm(20) sample2 <- rnorm(20) admixMod1 <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) admixMod2 <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) fake_estim <- list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = seq(0, 1, length.out = 10), p.X.fixed = FALSE) fake_test <- list(p.value = 0.5, reject_decision = FALSE) class(fake_test) <- c("IBM_test", "htest") mockery::stub(admix_cluster, "estim_IBM", function(...) fake_estim) mockery::stub(admix_cluster, "IBM_empirical_contrast", function(...) 0.1) mockery::stub(admix_cluster, "IBM_k_samples_test", function(...) fake_test) mockery::stub(admix_cluster, "get_tabulated_dist", function(...) rnorm(10)) mockery::stub(admix_cluster, "reject_nullHyp", function(...) FALSE) res <- admix_cluster(samples = list(A = sample1, B = sample2), admixMod = list(admixMod1, admixMod2), echo = FALSE) expect_s3_class(res, "admix_cluster") expect_equal(res$n_populations, 2) expect_identical(as.character(unlist(res$sample_names)), c("A", "B")) expect_equal(res$n_clust, 1) expect_true(is.list(res$clust_pop)) }) test_that("default sample names are generated", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( estim_IBM = function(...) { list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5) }, IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) { structure(list(p.value = 0.5, reject_decision = FALSE), class = "htest") }, get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, .package = "admix" ) res <- admix_cluster(samples = list(rnorm(10), rnorm(10)), admixMod = list(admixMod, admixMod), echo = FALSE) expect_equal(res$sample_names, c("rnorm(10)", "rnorm(10)")) }) test_that("provided tabulated distribution is used", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( estim_IBM = function(...) { list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5)}, IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) { list(p.value = 0.5, reject_decision = FALSE)}, get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, .package = "admix" ) res <- admix_cluster(samples = list(rnorm(10), rnorm(10)), admixMod = list(admixMod, admixMod), tabul_dist = list(c(1,2,3)), echo = FALSE) expect_s3_class(res, "admix_cluster") }) test_that("rejection branch creates two clusters", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( estim_IBM = function(...) { list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5) }, IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) { list(p.value = 0.001, reject_decision = TRUE) }, get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) TRUE, .package = "admix" ) res <- admix_cluster(samples = list(rnorm(10), rnorm(10)), admixMod = list(admixMod, admixMod), echo = FALSE) expect_equal(res$n_clust, 2) }) test_that("print.admix_cluster works", { obj <- list( call = quote(admix_cluster(samples, admixMod)), n_clust = 2, clust_pop = list(c(1,2), c(3)), sample_names = c("S1", "S2", "S3") ) class(obj) <- "admix_cluster" expect_output(print(obj), "Number of detected clusters: 2") expect_output(print(obj), "Cluster #1: S1, S2") }) test_that("summary.admix_cluster works", { admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) obj <- list( call = quote(admix_cluster(samples, admixMod)), n_populations = 2, population_sizes = c(20, 25), admixture_models = list(admixMod, admixMod), confidence_level = 0.95, n_clust = 1, clust_pop = list(c(1,2)), sample_names = c("A", "B"), pval_clust = 0.42, clust_weights = list(matrix(c(0.5, 0.6), nrow = 1)), clust_sizes = 2 ) class(obj) <- "admix_cluster" expect_output(summary(obj), "Number of samples under study: 2") expect_output(summary(obj), "Cluster #1: A, B") expect_output(summary(obj), "0.42") }) test_that("progress bar branch is covered", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( txtProgressBar = function(...) { structure(list(), class = "txtProgressBar") }, setTxtProgressBar = function(...) NULL, .package = "utils" ) local_mocked_bindings( close = function(...) NULL, .package = "base" ) local_mocked_bindings( estim_IBM = function(...) { list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5) }, IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) { list(p.value = 0.5, reject_decision = FALSE) }, get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, .package = "admix" ) expect_silent( admix_cluster(samples = list(rnorm(10), rnorm(10)), admixMod = list(admixMod, admixMod), echo = TRUE) ) }) test_that("sample names are taken from named list variable", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( estim_IBM = function(...) list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5), IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) list(p.value = 0.5, reject_decision = FALSE), get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, .package = "admix" ) my_samples <- list(A = rnorm(10), B = rnorm(10)) res <- admix_cluster(samples = my_samples, admixMod = list(admixMod, admixMod), echo = FALSE) expect_equal(res$sample_names, c("A", "B")) }) test_that("fallback sample names Sample_1, Sample_2 are generated", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( estim_IBM = function(...) list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5), IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) list(p.value = 0.5, reject_decision = FALSE), get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, .package = "admix" ) my_samples <- list(rnorm(10), rnorm(10)) res <- admix_cluster(samples = my_samples, admixMod = list(admixMod, admixMod), echo = FALSE) expect_equal(res$sample_names, c("Sample_1", "Sample_2")) }) test_that("non-numeric empirical contrasts are replaced by NA (L.132-134)", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) call_count <- 0L local_mocked_bindings( estim_IBM = function(...) list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5), # Retourne 0 (numérique) → 0 * 0 = 0, stocké normalement # Puis on force un résultat non numérique via IBM_empirical_contrast # en retournant une liste (non numérique au sens is.numeric) IBM_empirical_contrast = function(...) { call_count <<- call_count + 1L # Une liste n'est pas numérique : is.numeric(list()) == FALSE # et minimal_size * list() lève une erreur... on doit contourner autrement if (call_count == 1L) list(bad = "value") else 0.1 }, IBM_k_samples_test = function(...) list(p.value = 0.5, reject_decision = FALSE), get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, .package = "admix" ) my_samples <- list(rnorm(10), rnorm(10), rnorm(10)) # La multiplication minimal_size * list() va planter : on vérifie juste # que la branche est inaccessible sans modifier le code source expect_error( admix_cluster(samples = my_samples, admixMod = list(admixMod, admixMod, admixMod), echo = FALSE), "non-numeric argument to binary operator" ) }) test_that("all-NA tabulated distribution triggers p_value fallback to 1e-16", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) local_mocked_bindings( estim_IBM = function(...) list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5), IBM_empirical_contrast = function(...) 0.1, IBM_k_samples_test = function(...) list(p.value = 0.5, reject_decision = FALSE), get_tabulated_dist = function(...) c(NA, NA, NA), reject_nullHyp = function(x) FALSE, .package = "admix" ) my_samples <- list(rnorm(10), rnorm(10)) res <- admix_cluster(samples = my_samples, admixMod = list(admixMod, admixMod), echo = FALSE) expect_s3_class(res, "admix_cluster") expect_equal(res$pval_clust, 0) }) test_that("while loop body is executed with K=3 samples", { skip_on_cran() admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) call_count <- 0L local_mocked_bindings( estim_IBM = function(...) list(estimated_mixing_weights = c(0.5, 0.5), integ.supp = 1, p.X.fixed = 0.5), IBM_empirical_contrast = function(...) { call_count <<- call_count + 1L # Contraste plus faible pour couple (1,2) afin de fixer closest_couple c(0.05, 0.2, 0.3)[call_count] }, # Premier test (2-sample) : pas de rejet → cluster {1,2} # Second test (ajout sample 3) : rejet → cluster séparé IBM_k_samples_test = function(...) { list(p.value = 0.001, reject_decision = TRUE) }, get_tabulated_dist = function(...) c(0.1, 0.2), reject_nullHyp = function(x) FALSE, # premier couple non rejeté .package = "admix" ) my_samples <- list(rnorm(10), rnorm(10), rnorm(10)) res <- admix_cluster(samples = my_samples, admixMod = list(admixMod, admixMod, admixMod), echo = FALSE) expect_s3_class(res, "admix_cluster") expect_gte(res$n_clust, 1L) }) test_that("summary handles cluster of size > 2", { admixMod <- admix_model(knownComp_dist = "norm", knownComp_param = list(mean = 0, sd = 1)) # Cluster de taille 3 : clust_sizes > 2 obj <- list( call = quote(admix_cluster(samples, admixMod)), n_populations = 3, population_sizes = c(20, 25, 30), admixture_models = list(admixMod, admixMod, admixMod), confidence_level = 0.95, n_clust = 1, clust_pop = list(c(1, 2, 3)), sample_names = c("A", "B", "C"), pval_clust = 0.30, clust_weights = list(matrix(c(0.4, 0.5, 0.6, 0.5, 0.4, 0.3), nrow = 3, ncol = 2)), clust_sizes = 3 ) class(obj) <- "admix_cluster" expect_output(summary(obj), "Cluster #1: A, B, C") expect_output(summary(obj), "Number of samples under study: 3") })