The first trial-build gate run correctly went red: the 10 auto-proposed
tbb-stddef packages (BFpack, BayesERtools, GMLTM, ...) all fail while building
their shared `rstan` dependency, not in their own code -- the `tbb/tbb_stddef.h`
error is in rstan's Module.cpp. So a per-package makevars entry is useless for
them; they are blocked on rstan (which already has an entry). This is the same
cascade the RcppParallel `applies_to` guard catches, but the tbb-stddef
signature is generic and had no such pin.
Add `failing_dependency(error_text, package)`: when the log shows a DIFFERENT
package failed to compile ("Failed to build source package X", "compilation
failed for package 'X'", ...), that package is the real cause. build_triage_report
now blocks any package whose every failing build is such a cascade -- reported
as blocked_on the dependency, never proposed a bogus entry. A package that fails
in its OWN compilation is still proposed. This unifies the applies_to and
data-driven cases into one `blocked_packages` / `blocked_on` model.
- report/proposer/blocked_summary now count the actually-blocked packages
- blocked note shows even when a group also has genuine proposals
- tests cover the rstan-cascade vs own-compile split (with the real log strings)
165 lines
6.3 KiB
R
165 lines
6.3 KiB
R
source(file.path("..", "failing-builds-classify.R"))
|
||
|
||
test_that("normalise_error collapses temp paths, versions, and package tokens", {
|
||
a <- normalise_error(
|
||
"In file /tmp/RtmpAb12/foo.c: RcppParallel 5.1.9 failed at 0xdeadbeef",
|
||
package = "RcppParallel"
|
||
)
|
||
expect_false(grepl("RtmpAb12", a))
|
||
expect_false(grepl("5\\.1\\.9", a))
|
||
expect_false(grepl("0xdeadbeef", a))
|
||
expect_true(grepl("<pkg>", a))
|
||
expect_true(grepl("<tmp>", a))
|
||
|
||
# Same root error across two versions collapses to one fingerprint.
|
||
e1 <- "StanHeaders 2.32.1: tbb/tbb_stddef.h: No such file or directory"
|
||
e2 <- "StanHeaders 2.33.0: tbb/tbb_stddef.h: No such file or directory"
|
||
expect_identical(
|
||
fingerprint_error(e1, "StanHeaders"),
|
||
fingerprint_error(e2, "StanHeaders")
|
||
)
|
||
})
|
||
|
||
test_that("normalise_error is safe on NA/empty input", {
|
||
expect_identical(normalise_error(NA_character_), "")
|
||
expect_identical(normalise_error(""), "")
|
||
expect_identical(fingerprint_error(NA_character_), "<empty>")
|
||
})
|
||
|
||
test_that("fingerprint_error picks the salient error line, not the last line", {
|
||
txt <- paste(
|
||
"* installing *source* package 'foo' ...",
|
||
"error: bar.h: No such file or directory",
|
||
"* removing '/tmp/lib/foo'",
|
||
sep = "\n"
|
||
)
|
||
fp <- fingerprint_error(txt, "foo")
|
||
expect_true(grepl("no such file", fp))
|
||
expect_false(grepl("removing", fp))
|
||
})
|
||
|
||
test_that("classify_error matches the removed TBB header signature (makevars, auto)", {
|
||
sig <- classify_error(
|
||
"fatal error: tbb/tbb_stddef.h: No such file or directory"
|
||
)
|
||
expect_identical(sig$id, "tbb-stddef-removed")
|
||
expect_identical(sig$tier, "makevars")
|
||
expect_true(sig$auto)
|
||
expect_true(sig$matched)
|
||
})
|
||
|
||
test_that("classify_error matches RcppParallel bundled-TBB failures", {
|
||
sig <- classify_error(
|
||
"Error: USE_TBB=Linux is not supported on this toolchain"
|
||
)
|
||
expect_identical(sig$id, "rcppparallel-bundled-tbb")
|
||
expect_identical(sig$tier, "patch")
|
||
expect_true(sig$auto)
|
||
})
|
||
|
||
test_that("system libuv link leak is classified but stays human-only (novel diff)", {
|
||
sig <- classify_error("cannot open shared object file: libuv.so.1")
|
||
expect_identical(sig$id, "system-libuv-link-leak")
|
||
expect_true(sig$matched)
|
||
expect_false(sig$auto)
|
||
})
|
||
|
||
test_that("unknown signatures are never guessed at", {
|
||
sig <- classify_error("segfault: memory not mapped at address")
|
||
expect_identical(sig$id, "unclassified")
|
||
expect_false(sig$matched)
|
||
expect_false(sig$auto)
|
||
expect_true(is.na(sig$tier))
|
||
})
|
||
|
||
test_that("propose_registry_entry fills a schema-valid entry for a known lever", {
|
||
sig <- classify_error("tbb/tbb_stddef.h: No such file")
|
||
json <- propose_registry_entry(sig, "StanHeaders", c("alpine", "ubuntu-2604"))
|
||
entry <- jsonlite::fromJSON(json, simplifyVector = FALSE)
|
||
expect_identical(entry$package, "StanHeaders")
|
||
expect_identical(entry$versions, "*")
|
||
expect_identical(entry$platforms, list("alpine", "ubuntu-2604"))
|
||
expect_identical(entry$makevars$CPPFLAGS, "-DTBB_INTERFACE_NEW")
|
||
expect_true(nzchar(entry$reason))
|
||
|
||
# No template -> no proposal (unclassified path).
|
||
expect_null(propose_registry_entry(classify_error("weird"), "x", "alpine"))
|
||
})
|
||
|
||
test_that("RcppParallel dependents are blocked, not proposed a per-package patch", {
|
||
# Hundreds of packages fail on ubuntu-2604 only because their RcppParallel
|
||
# dependency fails to build, so they carry RcppParallel's TBB error text.
|
||
failures <- data.frame(
|
||
name = c("ACEsimFit", "AovBay", "AdaptGauss"),
|
||
platform = "ubuntu-2604",
|
||
arch = "amd64",
|
||
error_text = "Error: USE_TBB=Linux is not supported on this toolchain",
|
||
stringsAsFactors = FALSE
|
||
)
|
||
report <- build_triage_report(failures, registered_pkgs = character(0L))
|
||
grp <- Filter(function(g) g$signature == "rcppparallel-bundled-tbb", report)[[
|
||
1L
|
||
]]
|
||
# No bogus per-dependent entries (the patch targets RcppParallel's source).
|
||
expect_null(grp$proposed_entries)
|
||
expect_identical(grp$blocked_on, "RcppParallel")
|
||
})
|
||
|
||
test_that("failing_dependency names the dependency that actually failed", {
|
||
# A leaf package (BFpack) that fails building its rstan dependency.
|
||
txt <- paste(
|
||
"Error in installing dependencies for package BFpack with tag 1.6.1",
|
||
"Failed to build source package rstan.",
|
||
"ERROR: compilation failed for package ‘rstan’",
|
||
sep = "\n"
|
||
)
|
||
expect_identical(failing_dependency(txt, "BFpack"), "rstan")
|
||
# A package failing in its OWN compilation is not a cascade.
|
||
own <- "ERROR: compilation failed for package ‘BFpack’"
|
||
expect_true(is.na(failing_dependency(own, "BFpack")))
|
||
expect_true(is.na(failing_dependency(NA_character_, "x")))
|
||
expect_true(is.na(failing_dependency("some unrelated error", "x")))
|
||
})
|
||
|
||
test_that("Stan packages blocked on rstan are not proposed a per-package entry", {
|
||
# BFpack/GMLTM fail building rstan; the tbb error is in rstan's compile.
|
||
cascade <- paste(
|
||
"Failed to build source package rstan.",
|
||
"fatal error: tbb/tbb_stddef.h: No such file or directory",
|
||
sep = "\n"
|
||
)
|
||
failures <- data.frame(
|
||
name = c("BFpack", "GMLTM", "someOwnPkg"),
|
||
platform = "ubuntu-2604",
|
||
arch = "amd64",
|
||
error_text = c(
|
||
cascade,
|
||
cascade,
|
||
# someOwnPkg fails in its OWN compile on the same header -> fixable.
|
||
"someOwnPkg.cpp: fatal error: tbb/tbb_stddef.h: No such file or directory"
|
||
),
|
||
stringsAsFactors = FALSE
|
||
)
|
||
report <- build_triage_report(failures, registered_pkgs = character(0L))
|
||
grp <- Filter(function(g) g$signature == "tbb-stddef-removed", report)[[1L]]
|
||
# Only the own-compile package is proposed; the rstan cascades are blocked.
|
||
expect_identical(names(grp$proposed_entries), "someOwnPkg")
|
||
expect_setequal(grp$blocked_packages, c("BFpack", "GMLTM"))
|
||
expect_identical(grp$blocked_on, "rstan")
|
||
})
|
||
|
||
test_that("RcppParallel itself is still proposed when it is the failing package", {
|
||
failures <- data.frame(
|
||
name = "RcppParallel",
|
||
platform = "ubuntu-2604",
|
||
arch = "amd64",
|
||
error_text = "Error: USE_TBB=Linux is not supported on this toolchain",
|
||
stringsAsFactors = FALSE
|
||
)
|
||
report <- build_triage_report(failures, registered_pkgs = character(0L))
|
||
grp <- report[[1L]]
|
||
expect_identical(grp$signature, "rcppparallel-bundled-tbb")
|
||
expect_false(is.null(grp$proposed_entries))
|
||
expect_true("RcppParallel" %in% names(grp$proposed_entries))
|
||
expect_null(grp$blocked_on) # RcppParallel is the target, not a dependent
|
||
})
|