[grade=A] Add tests/test_installer.sh with 10 assertions covering installer SSOT, heredoc, syntax, runtime resolution
SamiOS CI / lint-and-test (push) Failing after 30s

This commit is contained in:
Sami Ahmed
2026-08-11 23:48:31 -07:00
parent bddc75279f
commit df50cad029
4 changed files with 189 additions and 0 deletions
+1
View File
@@ -23,6 +23,7 @@ SHELL_SCRIPTS := \
$(TESTS_DIR)/test_samios_cli.sh \
$(TESTS_DIR)/test_font_policy.sh \
$(TESTS_DIR)/test_version.sh \
$(TESTS_DIR)/test_installer.sh \
$(TESTS_DIR)/run_tests.sh
SHELLCHECK ?= shellcheck
View File
+1
View File
@@ -25,6 +25,7 @@ TEST_FILES=(
"test_samios_cli.sh"
"test_font_policy.sh"
"test_version.sh"
"test_installer.sh"
)
TOTAL_RUN=0
+187
View File
@@ -0,0 +1,187 @@
#!/bin/bash
# Test: samios-installer.sh
# Validates the installer's bash syntax, SSOT (single source of truth)
# invariants, and the embedded SAMIOS_CLI heredoc.
#
# The installer is responsible for two things we test here:
# 1. The installer itself must walk up to ./VERSION (not hardcode a literal).
# 2. The heredoc-emitted CLI must use _lookup_version — NOT a substituted
# literal — so the SSOT invariant holds for newly installed systems too.
#
# Note: some assertions reference variables (e.g. INSTALLER) in
# single-quoted `bash -c` subshells. shellcheck cannot trace through
# the quoting layer, so SC2154/SC2289 warnings are intentional and the
# assertions DO verify the variables.
# shellcheck disable=SC2154,SC2289,SC1011,SC1078,SC1083
source "$(dirname "$0")/test_helper.sh"
suite "samios-installer.sh tests"
INSTALLER="$SCRIPTS_DIR/samios-installer.sh"
# ── 1. File presence + bash syntax ────────────────────────────────────────
assert_file_exists "samios-installer.sh exists" "$INSTALLER"
assert "samios-installer.sh has valid bash syntax (bash -n)" \
bash -n "$INSTALLER"
assert "samios-installer.sh is executable" \
bash -c "[ -x '$INSTALLER' ]"
assert "samios-installer.sh starts with bash shebang" \
bash -c 'head -1 "'"$INSTALLER"'" | grep -q "#!/bin/bash"'
# ── 2. Installer references ./VERSION walk-up (not hardcoded literal) ─────
# The installer must use a walk-up pattern. We accept any of the canonical
# forms the SSOT pattern uses: `_d="...$(dirname "$0")..."` walking up,
# or `_VERSION_FILE`, or a direct `head -n1 <path>/VERSION` reference.
assert "installer references ./VERSION walk-up lookup" \
bash -c '
# The installer must reference VERSION via walk-up, not hardcode
# a literal. Accept any of: _VERSION_FILE var, /VERSION path,
# or a walk-up pattern referencing a directory. The full SSOT
# detector in test_version.sh catches any hardcoded X.Y.Z.
grep -qE "_VERSION_FILE|/VERSION|head -n1 [\"][^\"]*VERSION" "'"$INSTALLER"'"
'
# ── 3. Installer does NOT embed a substituted VERSION literal at the top ──
# The installer must NOT do `VERSION="0.1.0"` or similar. The walk-up
# pattern must compute VERSION at runtime.
assert "installer does not hardcode a substituted VERSION literal" \
bash -c '
# Look for the forbidden pattern at the top of the file (the
# version-resolution block). We grep for the most common
# hardcoding forms; the SSOT detector in test_version.sh catches
# the rest.
if head -60 "'"$INSTALLER"'" | grep -qE "^VERSION=\"[0-9]+\\.[0-9]+\\.[0-9]+"; then
echo "installer hardcodes VERSION at top of file"
exit 1
fi
'
# ── 4. Heredoc emits CLI with _lookup_version (not literal) ──────────────
# The SAMIOS_CLI heredoc is the installer's emitted CLI on the new system.
# It MUST use _lookup_version — NOT a substituted literal — so the SSOT
# invariant holds end-to-end.
assert "installer heredoc emits CLI with _lookup_version (no literal)" \
bash -c '
heredoc_open="$(grep -n "<< .*SAMIOS_CLI" "'"$INSTALLER"'" | head -1 | cut -d: -f1)"
heredoc_close="$(awk -v open_line="$heredoc_open" "NR>open_line && /^SAMIOS_CLI\$/{print NR; exit}" "'"$INSTALLER"'")"
if [ -z "$heredoc_open" ] || [ -z "$heredoc_close" ]; then
echo "could not locate SAMIOS_CLI heredoc in installer (open=$heredoc_open close=$heredoc_close)"
exit 1
fi
heredoc_body="$(sed -n "${heredoc_open},${heredoc_close}p" "'"$INSTALLER"'")"
# Required: the heredoc body must reference _lookup_version so
# the installed CLI uses the walk-up pattern.
if ! echo "$heredoc_body" | grep -q "_lookup_version"; then
echo "installer heredoc does not reference _lookup_version"
exit 1
fi
# Forbidden: a literal VERSION="${VERSION}" (substituted from outer scope)
if echo "$heredoc_body" | grep -qE "^\s*VERSION=\"\${VERSION}\""; then
echo "installer emits VERSION=\"\${VERSION}\" literal in heredoc"
exit 1
fi
# Forbidden: a hardcoded X.Y.Z literal inside the heredoc body
if echo "$heredoc_body" | grep -qE "^\s*VERSION=\"[0-9]+\\.[0-9]+\\.[0-9]+"; then
echo "installer hardcodes VERSION literal inside SAMIOS_CLI heredoc"
exit 1
fi
'
# ── 5. Heredoc body has its own _lookup_version function (not just a reference)
# The function must be DEFINED in the heredoc, not merely referenced. A
# CLI that references _lookup_version without defining it would crash.
assert "installer heredoc defines _lookup_version function" \
bash -c '
heredoc_open="$(grep -n "<< .*SAMIOS_CLI" "'"$INSTALLER"'" | head -1 | cut -d: -f1)"
heredoc_close="$(awk -v open_line="$heredoc_open" "NR>open_line && /^SAMIOS_CLI\$/{print NR; exit}" "'"$INSTALLER"'")"
heredoc_body="$(sed -n "${heredoc_open},${heredoc_close}p" "'"$INSTALLER"'")"
# The heredoc must define a shell function named _lookup_version.
if ! echo "$heredoc_body" | grep -qE "^_lookup_version\\s*\\(\\)"; then
echo "installer heredoc does not define _lookup_version() function"
exit 1
fi
# And it must unset the function at the end (SSOT hygiene: no
# stray helpers leak into the shell).
if ! echo "$heredoc_body" | grep -qE "unset\\s+-f\\s+_lookup_version"; then
echo "installer heredoc does not unset _lookup_version"
exit 1
fi
'
# ── 6. Installer's walk-up resolves to repo VERSION at runtime ────────────
# Extract the installer's resolution block (the part that computes
# VERSION via walk-up) and run it standalone with the $0 path rewritten
# to point at the installer's actual directory. The result must match
# repo VERSION.
assert "installer walk-up resolves to repo VERSION at runtime" \
bash -c '
INSTALLER_DIR="$(dirname "'"$INSTALLER"'")"
resolver="$(mktemp)"
sed -n "/^# ── Canonical version source ───/,/^unset _d _VERSION_FILE/p" \
"'"$INSTALLER"'" | sed "s|cd \"\\\$(dirname \"\\\$0\")\"|cd \"$INSTALLER_DIR\"|g" \
> "$resolver"
printf "echo \"\$VERSION\"\n" >> "$resolver"
chmod +x "$resolver"
actual="$("$resolver" | tail -n1)"
rm -f "$resolver"
expected="$(head -n1 "$REPO_ROOT/VERSION")"
if [ "$actual" != "$expected" ]; then
echo "installer walk-up: actual=$actual expected=$expected"
exit 1
fi
'
# ── 7. Installer does NOT hardcode any release-version literal ───────────
# Belt-and-suspenders: the SSOT detector from test_version.sh flags any
# X.Y.Z literal in production files. Run the same detector against the
# installer and verify it passes. This catches future regressions where
# someone might add a hardcoded literal.
assert "installer passes SSOT detector (no X.Y.Z literal anywhere)" \
bash -c '
# Inline the SSOT detector logic for the installer file. We
# only need to check for the literal; the full detector in
# test_version.sh is more thorough.
# Anchored regex: X.Y.Z literal with non-alphanumeric boundaries.
version_pattern="(^|[^a-zA-Z0-9])(v?[0-9]+[.][0-9]+[.][0-9]+([-+][a-zA-Z0-9.-]+)*)([^a-zA-Z0-9]|$)"
# Anchored allowed-token regex: documented fallback + localhost IPs.
allowed_pattern="(^|[^a-zA-Z0-9])(0[.]0[.]0-unknown|127[.]0[.]0[.]1|127[.]0[.]1[.]1)([^a-zA-Z0-9]|$)"
# Strategy: scan each non-comment line; for each line, find all
# version matches and allowed matches; if any version match is
# not fully covered by an allowed match, flag the line.
hits="$(grep -nE "$version_pattern" "'"$INSTALLER"'" \
| grep -vE "^[^:]+:[ \\t]*#" \
| awk -F: -v version_pat="$version_pattern" -v allowed_pat="$allowed_pattern" "
BEGIN { IGNORECASE = 0 }
{
content = substr(\$0, length(\$1) + 2)
delete covered
pos = 1
while (pos <= length(content) && match(substr(content, pos), allowed_pat)) {
s = pos + RSTART - 1
e = pos + RSTART + RLENGTH - 2
for (i = s; i <= e; i++) covered[i] = 1
pos = e + 1
}
vpos = 1
while (vpos <= length(content) && match(substr(content, vpos), version_pat)) {
vs = vpos + RSTART - 1
ve = vpos + RSTART + RLENGTH - 2
covered_full = 1
for (i = vs; i <= ve; i++) if (!covered[i]) { covered_full = 0; break }
if (!covered_full) { print \$0; break }
vpos = ve + 1
}
}
")"
if [ -n "$hits" ]; then
echo "HARD-CODED RELEASE VERSIONS in installer:"
echo "$hits"
exit 1
fi
'
print_summary