commit acf989f25bf6be87ce81b0603667600523746dee
parent c04f2488cc1875033b4abeab995d2bdb10b40cc0
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 18 Jun 2026 03:00:34 -0700
test: expand build coordinator spec coverage
Diffstat:
1 file changed, 322 insertions(+), 1 deletion(-)
diff --git a/test/buildcoord/run.sh b/test/buildcoord/run.sh
@@ -22,7 +22,7 @@ kit_report_init
ws="$work/ws"
store="$work/store"
-mkdir -p "$ws/recipes" "$ws/src" "$store"
+mkdir -p "$ws/recipes" "$ws/src/globset" "$store"
cat > "$ws/BUILD.kit" <<'EOF'
kit-build 1
@@ -34,10 +34,30 @@ recipe recipes/app.sh
recipe recipes/argv.sh
[target //cfg:probe]
recipe recipes/cfg.sh
+[target //cycle:a]
+recipe recipes/cycle_a.sh
+[target //cycle:b]
+recipe recipes/cycle_b.sh
+[target //cycle:self]
+recipe recipes/cycle_self.sh
+[target //defn:probe]
+recipe recipes/defn_v1.sh
+[target //defn:unused]
+recipe recipes/defn_unused_v1.sh
+[target //env:probe]
+recipe recipes/env_probe.sh
+[target //fail:probe]
+recipe recipes/fail.sh
+[target //globset:probe]
+recipe recipes/globset.sh
[target //lib:data]
recipe recipes/lib.sh
+[target //material:probe]
+recipe recipes/material.sh
[target //needargv:probe]
recipe recipes/needargv.sh
+[target //nondet:counter]
+recipe recipes/nondet.sh
[target //recipe:stamp]
recipe recipes/recipe.sh
[target //scope:leaf]
@@ -52,6 +72,8 @@ recipe recipes/scope_plain.sh
recipe recipes/stable_dep.sh
[target //stable:parent]
recipe recipes/stable_parent.sh
+[target //submit:probe]
+recipe recipes/submit.sh
EOF
cat > "$ws/src/a.txt" <<'EOF'
@@ -63,6 +85,9 @@ EOF
cat > "$ws/src/noop.txt" <<'EOF'
first
EOF
+cat > "$ws/src/globset/one.txt" <<'EOF'
+one
+EOF
cat > "$ws/recipes/lib.sh" <<'EOF'
#!/bin/sh
@@ -111,6 +136,94 @@ mode=$("$KIT" build config-get mode || true)
printf 'mode:%s\n' "$mode" > "$KIT_BUILD_OUT/mode.txt"
EOF
+cat > "$ws/recipes/cycle_a.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+"$KIT" build need //cycle:b >/dev/null
+printf 'a\n' > "$KIT_BUILD_OUT/cycle.txt"
+EOF
+
+cat > "$ws/recipes/cycle_b.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+"$KIT" build need //cycle:a >/dev/null
+printf 'b\n' > "$KIT_BUILD_OUT/cycle.txt"
+EOF
+
+cat > "$ws/recipes/cycle_self.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+"$KIT" build need //cycle:self >/dev/null
+printf 'self\n' > "$KIT_BUILD_OUT/cycle.txt"
+EOF
+
+cat > "$ws/recipes/defn_v1.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'defn:v1\n' > "$KIT_BUILD_OUT/defn.txt"
+EOF
+
+cat > "$ws/recipes/defn_same.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'defn:v1\n' > "$KIT_BUILD_OUT/defn.txt"
+EOF
+
+cat > "$ws/recipes/defn_v2.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'defn:v2\n' > "$KIT_BUILD_OUT/defn.txt"
+EOF
+
+cat > "$ws/recipes/defn_unused_v1.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'unused:v1\n' > "$KIT_BUILD_OUT/unused.txt"
+EOF
+
+cat > "$ws/recipes/defn_unused_v2.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'unused:v2\n' > "$KIT_BUILD_OUT/unused.txt"
+EOF
+
+cat > "$ws/recipes/env_probe.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'ambient:%s\n' "${AMBIENT-unset}" > "$KIT_BUILD_OUT/env.txt"
+printf 'declared:%s\n' "${DECLARED-unset}" >> "$KIT_BUILD_OUT/env.txt"
+EOF
+
+cat > "$ws/recipes/fail.sh" <<'EOF'
+#!/bin/sh
+set -eu
+count=0
+if [ -f fail.count ]; then
+ count=$(cat fail.count)
+fi
+count=$((count + 1))
+printf '%s\n' "$count" > fail.count
+exit 1
+EOF
+
+cat > "$ws/recipes/globset.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+for p in $("$KIT" build glob 'src/globset/*.txt'); do
+ cat "$p"
+done > "$KIT_BUILD_OUT/files.txt"
+EOF
+
cat > "$ws/recipes/needargv.sh" <<'EOF'
#!/bin/sh
set -eu
@@ -126,6 +239,26 @@ mkdir -p "$KIT_BUILD_OUT"
printf 'recipe:v1\n' > "$KIT_BUILD_OUT/stamp.txt"
EOF
+cat > "$ws/recipes/material.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'material\n' > "$KIT_BUILD_OUT/material.txt"
+EOF
+
+cat > "$ws/recipes/nondet.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+count=0
+if [ -f .nondet-count ]; then
+ count=$(cat .nondet-count)
+fi
+count=$((count + 1))
+printf '%s\n' "$count" > .nondet-count
+printf 'nondet:%s\n' "$count" > "$KIT_BUILD_OUT/nondet.txt"
+EOF
+
cat > "$ws/recipes/scope_leaf.sh" <<'EOF'
#!/bin/sh
set -eu
@@ -172,6 +305,15 @@ mkdir -p "$KIT_BUILD_OUT"
dep_dir=$("$KIT" build need //stable:dep)
cat "$dep_dir/stable.txt" > "$KIT_BUILD_OUT/stable.txt"
EOF
+
+cat > "$ws/recipes/submit.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+tok=$("$KIT" build need-submit //argv:echo -- via-submit)
+dep_dir=$("$KIT" build need-await "$tok")
+cat "$dep_dir/args.txt" > "$KIT_BUILD_OUT/submit.txt"
+EOF
chmod +x "$ws"/recipes/*.sh
run_build() {
@@ -196,6 +338,22 @@ tree_path_from() {
awk 'NF >= 2 {print $2; exit}' "$1"
}
+tree_id_from() {
+ awk 'NF >= 1 {print $1; exit}' "$1"
+}
+
+cache_path_from() {
+ id=$1
+ pp=$(printf '%.2s' "$id")
+ printf '%s/build/cache/%s/%s\n' "$store" "$pp" "$id"
+}
+
+cas_tree_path_from() {
+ id=$1
+ pp=$(printf '%.2s' "$id")
+ printf '%s/cas/tree/%s/%s\n' "$store" "$pp" "$id"
+}
+
run_build cold //app:bundle
if [ $? -eq 0 ]; then
ok "buildcoord-cold-build"
@@ -438,5 +596,168 @@ argv_stat_path=$(tree_path_from "$work/buildcoord-stats-argv-change.out")
contains "buildcoord-stats-argv-change-output" "$argv_stat_path/args.txt" \
"stat-two"
+build_assert_ok buildcoord-config-unset-cold --stats //cfg:probe
+contains "buildcoord-config-unset-cold-run" \
+ "$work/buildcoord-config-unset-cold.err" "recipes_run=1"
+cfg_unset_path=$(tree_path_from "$work/buildcoord-config-unset-cold.out")
+contains "buildcoord-config-unset-cold-output" "$cfg_unset_path/mode.txt" \
+ "mode:"
+build_assert_ok buildcoord-config-set-after-unset --stats --config mode=set \
+ //cfg:probe
+contains "buildcoord-config-set-after-unset-run" \
+ "$work/buildcoord-config-set-after-unset.err" "recipes_run=1"
+cfg_set_path=$(tree_path_from "$work/buildcoord-config-set-after-unset.out")
+contains "buildcoord-config-set-after-unset-output" "$cfg_set_path/mode.txt" \
+ "mode:set"
+build_assert_ok buildcoord-config-unset-restores-trace --stats //cfg:probe
+contains "buildcoord-config-unset-restores-trace-hit" \
+ "$work/buildcoord-config-unset-restores-trace.err" "deep_hits=1"
+contains "buildcoord-config-unset-restores-trace-no-run" \
+ "$work/buildcoord-config-unset-restores-trace.err" "recipes_run=0"
+cfg_unset_again_path=$(tree_path_from \
+ "$work/buildcoord-config-unset-restores-trace.out")
+contains "buildcoord-config-unset-restores-trace-output" \
+ "$cfg_unset_again_path/mode.txt" "mode:"
+
+build_assert_ok buildcoord-defn-v1 --stats //defn:probe
+contains "buildcoord-defn-v1-run" "$work/buildcoord-defn-v1.err" \
+ "recipes_run=1"
+defn_v1_path=$(tree_path_from "$work/buildcoord-defn-v1.out")
+contains "buildcoord-defn-v1-output" "$defn_v1_path/defn.txt" "defn:v1"
+sed 's|recipe recipes/defn_v1.sh|recipe recipes/defn_same.sh|' \
+ "$ws/BUILD.kit" > "$ws/BUILD.next"
+mv "$ws/BUILD.next" "$ws/BUILD.kit"
+build_assert_ok buildcoord-defn-same-content --stats //defn:probe
+contains "buildcoord-defn-same-content-hit" \
+ "$work/buildcoord-defn-same-content.err" "deep_hits=1"
+contains "buildcoord-defn-same-content-no-run" \
+ "$work/buildcoord-defn-same-content.err" "recipes_run=0"
+sed 's|recipe recipes/defn_same.sh|recipe recipes/defn_v2.sh|' \
+ "$ws/BUILD.kit" > "$ws/BUILD.next"
+mv "$ws/BUILD.next" "$ws/BUILD.kit"
+build_assert_ok buildcoord-defn-different-content --stats //defn:probe
+contains "buildcoord-defn-different-content-run" \
+ "$work/buildcoord-defn-different-content.err" "recipes_run=1"
+defn_v2_path=$(tree_path_from "$work/buildcoord-defn-different-content.out")
+contains "buildcoord-defn-different-content-output" "$defn_v2_path/defn.txt" \
+ "defn:v2"
+sed 's|recipe recipes/defn_unused_v1.sh|recipe recipes/defn_unused_v2.sh|' \
+ "$ws/BUILD.kit" > "$ws/BUILD.next"
+mv "$ws/BUILD.next" "$ws/BUILD.kit"
+build_assert_ok buildcoord-defn-unrelated-stanza --stats //defn:probe
+contains "buildcoord-defn-unrelated-stanza-hit" \
+ "$work/buildcoord-defn-unrelated-stanza.err" "deep_hits=1"
+contains "buildcoord-defn-unrelated-stanza-no-run" \
+ "$work/buildcoord-defn-unrelated-stanza.err" "recipes_run=0"
+
+build_assert_ok buildcoord-material-cold --stats //material:probe
+contains "buildcoord-material-cold-run" "$work/buildcoord-material-cold.err" \
+ "recipes_run=1"
+material_id=$(tree_id_from "$work/buildcoord-material-cold.out")
+material_cache=$(cache_path_from "$material_id")
+rm -rf "$material_cache"
+build_assert_ok buildcoord-material-restores-from-cas --stats //material:probe
+contains "buildcoord-material-restores-from-cas-hit" \
+ "$work/buildcoord-material-restores-from-cas.err" "deep_hits=1"
+contains "buildcoord-material-restores-from-cas-no-run" \
+ "$work/buildcoord-material-restores-from-cas.err" "recipes_run=0"
+contains "buildcoord-material-restores-from-cas-no-miss" \
+ "$work/buildcoord-material-restores-from-cas.err" "materialize_misses=0"
+material_cache=$(cache_path_from "$material_id")
+material_tree=$(cas_tree_path_from "$material_id")
+rm -rf "$material_cache"
+rm -f "$material_tree"
+build_assert_ok buildcoord-material-missing-bytes-reruns --stats //material:probe
+contains "buildcoord-material-missing-bytes-reruns-run" \
+ "$work/buildcoord-material-missing-bytes-reruns.err" "recipes_run=1"
+contains "buildcoord-material-missing-bytes-reruns-miss" \
+ "$work/buildcoord-material-missing-bytes-reruns.err" "materialize_misses="
+
+build_assert_ok buildcoord-globset-cold --stats //globset:probe
+contains "buildcoord-globset-cold-run" "$work/buildcoord-globset-cold.err" \
+ "recipes_run=1"
+globset_one_path=$(tree_path_from "$work/buildcoord-globset-cold.out")
+contains "buildcoord-globset-cold-output" "$globset_one_path/files.txt" "one"
+cat > "$ws/src/globset/two.txt" <<'EOF'
+two
+EOF
+build_assert_ok buildcoord-globset-add --stats //globset:probe
+contains "buildcoord-globset-add-run" "$work/buildcoord-globset-add.err" \
+ "recipes_run=1"
+globset_two_path=$(tree_path_from "$work/buildcoord-globset-add.out")
+contains "buildcoord-globset-add-one" "$globset_two_path/files.txt" "one"
+contains "buildcoord-globset-add-two" "$globset_two_path/files.txt" "two"
+rm -f "$ws/src/globset/one.txt"
+build_assert_ok buildcoord-globset-remove --stats //globset:probe
+contains "buildcoord-globset-remove-run" "$work/buildcoord-globset-remove.err" \
+ "recipes_run=1"
+globset_remove_path=$(tree_path_from "$work/buildcoord-globset-remove.out")
+contains "buildcoord-globset-remove-output" "$globset_remove_path/files.txt" \
+ "two"
+
+run_fail "buildcoord-failure-first-fails" \
+ "$KIT" build --store "$store" --root "$ws" --def BUILD.kit \
+ --config "env.KIT=$KIT" //fail:probe
+run_fail "buildcoord-failure-second-reruns" \
+ "$KIT" build --store "$store" --root "$ws" --def BUILD.kit \
+ --config "env.KIT=$KIT" //fail:probe
+contains "buildcoord-failure-second-count" "$ws/fail.count" "2"
+cat > "$ws/recipes/fail.sh" <<'EOF'
+#!/bin/sh
+set -eu
+mkdir -p "$KIT_BUILD_OUT"
+printf 'fixed\n' > "$KIT_BUILD_OUT/fixed.txt"
+EOF
+chmod +x "$ws/recipes/fail.sh"
+build_assert_ok buildcoord-failure-fixed-runs --stats //fail:probe
+contains "buildcoord-failure-fixed-run" "$work/buildcoord-failure-fixed-runs.err" \
+ "recipes_run=1"
+fail_fixed_path=$(tree_path_from "$work/buildcoord-failure-fixed-runs.out")
+contains "buildcoord-failure-fixed-output" "$fail_fixed_path/fixed.txt" \
+ "fixed"
+
+run_fail "buildcoord-cycle-self-fails" \
+ "$KIT" build --store "$store" --root "$ws" --def BUILD.kit \
+ --config "env.KIT=$KIT" //cycle:self
+contains "buildcoord-cycle-self-diag" "$work/buildcoord-cycle-self-fails.err" \
+ "cycle"
+run_fail "buildcoord-cycle-indirect-fails" \
+ "$KIT" build --store "$store" --root "$ws" --def BUILD.kit \
+ --config "env.KIT=$KIT" //cycle:a
+contains "buildcoord-cycle-indirect-diag" \
+ "$work/buildcoord-cycle-indirect-fails.err" "cycle"
+
+export AMBIENT=leaked
+build_assert_ok buildcoord-env-cold --stats --config env.DECLARED=one \
+ //env:probe
+unset AMBIENT
+env_one_path=$(tree_path_from "$work/buildcoord-env-cold.out")
+contains "buildcoord-env-clean-ambient" "$env_one_path/env.txt" \
+ "ambient:unset"
+contains "buildcoord-env-declared-visible" "$env_one_path/env.txt" \
+ "declared:one"
+
+# Spec checks below are intentionally red until these BUILD.md promises are
+# implemented.
+build_assert_ok buildcoord-spec-env-change-invalidates --stats \
+ --config env.DECLARED=two //env:probe
+contains "buildcoord-spec-env-change-reruns" \
+ "$work/buildcoord-spec-env-change-invalidates.err" "recipes_run=1"
+env_two_path=$(tree_path_from "$work/buildcoord-spec-env-change-invalidates.out")
+contains "buildcoord-spec-env-change-output" "$env_two_path/env.txt" \
+ "declared:two"
+
+build_assert_ok buildcoord-spec-nondet-cold //nondet:counter
+run_fail "buildcoord-spec-verify-reruns-cache-hit" \
+ "$KIT" build --store "$store" --root "$ws" --def BUILD.kit \
+ --config "env.KIT=$KIT" --verify //nondet:counter
+
+build_assert_ok buildcoord-spec-need-submit-await //submit:probe
+submit_path=$(tree_path_from "$work/buildcoord-spec-need-submit-await.out")
+if [ -n "$submit_path" ] && [ -f "$submit_path/submit.txt" ]; then
+ contains "buildcoord-spec-need-submit-output" "$submit_path/submit.txt" \
+ "via-submit"
+fi
+
kit_summary "buildcoord"
kit_exit