mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:07:03 +01:00
Split the last two over-cap shell test suites
test_pacman_wrapper_security.sh (287) and test_i3blocks_efficiency.sh (345). Both keep their filenames -- shell-tests.yml runs them by name -- and both were verified by diffing a full run against the pre-split code: byte-identical output, exit 0 either side. The i3blocks setup half stays in the entry on purpose. Its five fake $BIN_DIR binaries are written with heredocs, and a seam inside a heredoc yields a lib that will not parse -- the worst failure this effort has produced so far. Only the two heredoc-free regions moved. Both i3blocks lib functions end in an explicit `return 0`. Their last statement is a `|| fail ...`, which as a function tail under set -e becomes the return value and would abort a run in which every check passed. `fail` exits on its own, so reaching the end means success. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
656375275b
commit
c4bdaad038
@ -0,0 +1,21 @@
|
||||
{
|
||||
"title": "Split the two remaining over-cap shell test suites in linux_configuration/tests",
|
||||
"objective": "Bring test_pacman_wrapper_security.sh (287) and test_i3blocks_efficiency.sh (345) under the repo-wide 250-line cap by moving blocks of checks into sourced libs, with both suites producing byte-identical output to their pre-split runs.",
|
||||
"acceptance_criteria": [
|
||||
"Both entry scripts and all four new libs are at most 250 lines.",
|
||||
"Each entry keeps its filename, because .github/workflows/shell-tests.yml runs both suites by filename.",
|
||||
"test_pacman_wrapper_security.sh output is byte-identical to a run from a detached worktree at HEAD, exiting 0.",
|
||||
"test_i3blocks_efficiency.sh output is byte-identical to the pre-split run, exiting 0.",
|
||||
"Every new lib passes shellcheck ALONE, without -x, which is the check that decides whether the seam is real.",
|
||||
"No check is changed, deleted, skipped or weakened, and no suppression is added.",
|
||||
"No seam falls inside a heredoc: the i3blocks fake-binary setup stays in the entry script for exactly this reason.",
|
||||
"Each i3blocks lib function ends in an explicit return 0, so a trailing `|| fail` conditional cannot become the function's return value under set -e."
|
||||
],
|
||||
"out_of_scope": [
|
||||
"Changing what any check asserts.",
|
||||
"Reformatting test_i3blocks_efficiency.sh to satisfy shfmt. It uses 2-space indent and was already shfmt-dirty before this change; the new libs match the style of the code they hold.",
|
||||
"Splitting block_compulsive_opening.sh, whose installer copies the running script to /usr/local/bin and would leave an entry script unable to find its libs.",
|
||||
"Wiring the file-length pre-commit gate, which must land only once --all already exits 0."
|
||||
],
|
||||
"verifier": "bash linux_configuration/tests/test_pacman_wrapper_security.sh diffed against the same suite from a detached worktree at HEAD, and bash linux_configuration/tests/test_i3blocks_efficiency.sh diffed against its pre-split run (both expect identical output and exit 0), plus shellcheck on each new lib alone, shellcheck -x on both entries, and pre-commit run --files over every touched file."
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
{
|
||||
"intent": "Bring the two remaining over-cap shell test suites in linux_configuration/tests under the 250-line cap without changing a single assertion or its result.",
|
||||
"scope": [
|
||||
"linux_configuration/tests/test_pacman_wrapper_security.sh (287 -> 128 lines)",
|
||||
"linux_configuration/tests/lib/pacman_wrapper_syntax.sh (new)",
|
||||
"linux_configuration/tests/lib/pacman_wrapper_makepkg.sh (new)",
|
||||
"linux_configuration/tests/test_i3blocks_efficiency.sh (345 -> 214 lines)",
|
||||
"linux_configuration/tests/lib/i3blocks_config_checks.sh (new)",
|
||||
"linux_configuration/tests/lib/i3blocks_claude_usage.sh (new)",
|
||||
"Non-goal: changing, weakening, skipping or deleting any check",
|
||||
"Non-goal: reformatting test_i3blocks_efficiency.sh, which was already shfmt-dirty (2-space indent) before this change"
|
||||
],
|
||||
"changes": [
|
||||
"test_pacman_wrapper_security.sh: tests 1-12 and 13-19 moved into two sourced libs, each wrapped in a function and called in the original order. The trailing checks keep their heredocs and their trap ... EXIT in the entry script, so trap scope is unchanged.",
|
||||
"test_i3blocks_efficiency.sh: the config/guard checks and the claude_usage checks moved into two sourced libs. The setup half stays in the entry deliberately: the five fake $BIN_DIR binaries are written with heredocs, and a seam inside a heredoc yields a lib that will not parse.",
|
||||
"Both i3blocks lib functions end in an explicit `return 0`. Their last statement is a `|| fail ...` conditional, which as a function tail under `set -e` would become the return value and abort a fully passing run; `fail` itself exits, so reaching the end means every check passed.",
|
||||
"Both entry scripts keep their filenames, because .github/workflows/shell-tests.yml runs these suites by filename."
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "bash -n on both entries and all four new libs",
|
||||
"result": "pass",
|
||||
"evidence": "OK for all six files."
|
||||
},
|
||||
{
|
||||
"command": "shellcheck on each new lib ALONE (no -x), plus shellcheck -x on both entries",
|
||||
"result": "pass",
|
||||
"evidence": "LIBS CLEAN and ENTRY CLEAN for both suites. No suppression added."
|
||||
},
|
||||
{
|
||||
"command": "bash test_pacman_wrapper_security.sh, diffed against the same suite run from a detached worktree at HEAD",
|
||||
"result": "pass",
|
||||
"evidence": "OUTPUT BYTE-IDENTICAL PRE/POST SPLIT; both runs exit 0."
|
||||
},
|
||||
{
|
||||
"command": "bash test_i3blocks_efficiency.sh, diffed against the pre-split run captured before editing",
|
||||
"result": "pass",
|
||||
"evidence": "OUTPUT BYTE-IDENTICAL PRE/POST SPLIT; both runs exit 0, ending in 'All i3blocks efficiency regression tests passed.'"
|
||||
},
|
||||
{
|
||||
"command": "shfmt -d on the pacman entry and its two libs",
|
||||
"result": "pass",
|
||||
"evidence": "SHFMT CLEAN. The i3blocks files are shfmt-dirty both before and after: the original uses 2-space indent, and the new libs inherit the style of the code they hold rather than being reformatted."
|
||||
},
|
||||
{
|
||||
"command": "bash ~/utils/scripts/check_file_length.sh --all | grep -c 'over by'",
|
||||
"result": "pass",
|
||||
"evidence": "63 -> 61 violations; neither suite appears any more."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"The libs are only valid when sourced from their entry script, which owns the helpers, paths and fake $BIN_DIR binaries. Running one directly is not supported and never was a use case.",
|
||||
"A future check appended to an i3blocks lib must keep the `return 0` last, or a passing run can abort on the set -e function-tail trap."
|
||||
],
|
||||
"rollback": [
|
||||
"git revert the commit; both entry scripts return to single files and the four libs disappear.",
|
||||
"After rollback, run both suites and confirm test_pacman_wrapper_security.sh ends in 'All Tests Passed!' and test_i3blocks_efficiency.sh in 'All i3blocks efficiency regression tests passed.', each exiting 0."
|
||||
]
|
||||
}
|
||||
89
linux_configuration/tests/lib/i3blocks_claude_usage.sh
Executable file
89
linux_configuration/tests/lib/i3blocks_claude_usage.sh
Executable file
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
# i3blocks efficiency: the claude_usage block's output and fork count.
|
||||
# Sourced by test_i3blocks_efficiency.sh; inherits its strict mode and its
|
||||
# helpers (fail, assert_equals, assert_le, epoch_utc, count_execs) plus the
|
||||
# BIN_DIR / TMP_DIR / CONFIG_FILE / I3BLOCKS_DIR paths it sets up.
|
||||
|
||||
i3_tests_claude_usage() {
|
||||
printf 'Checking Claude usage block behavior and fork count...\n'
|
||||
# claude_usage.sh parses its cache with jq and degrades to "no data" when jq is
|
||||
# missing. That is the right runtime behaviour, but it would make every
|
||||
# assertion below fail with a misleading message about percentages, so name the
|
||||
# real cause instead of letting a missing tool look like a logic bug.
|
||||
# Probe by running jq, not with `command -v`: a jq that exists but cannot
|
||||
# execute produces exactly the same "no data" output as one that is absent.
|
||||
printf '{}' | jq -e . >/dev/null 2>&1 \
|
||||
|| fail 'a working jq is required for the claude_usage tests (pacman -S jq)'
|
||||
CLAUDE_STATE_DIR="$TMP_DIR/limit-state"
|
||||
mkdir -p "$CLAUDE_STATE_DIR"
|
||||
claude_now=1786366861
|
||||
|
||||
write_claude_state() {
|
||||
printf '{"five_hour_pct":%s,"five_hour_resets_at":%s,"seven_day_pct":%s,"seven_day_resets_at":%s,"updated_at":%s}\n' \
|
||||
"$1" "$2" "$3" "$4" "$5" >"$CLAUDE_STATE_DIR/state.json"
|
||||
}
|
||||
|
||||
run_claude_usage() {
|
||||
LIMIT_STATE_DIR="$CLAUDE_STATE_DIR" NOW_EPOCH="$claude_now" \
|
||||
bash "$I3BLOCKS_DIR/claude_usage.sh"
|
||||
}
|
||||
|
||||
# Percentages arrive as floats (e.g. 55.00000000000001) and must be truncated.
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55.00000000000001 "$((claude_now + 99999))" "$claude_now"
|
||||
claude_output=$(run_claude_usage)
|
||||
assert_equals '🤖 5h 34% · 7d 55%' "$(printf '%s\n' "$claude_output" | sed -n '1p')" \
|
||||
'claude usage should show both windows as whole percentages'
|
||||
assert_equals '#50FA7B' "$(printf '%s\n' "$claude_output" | sed -n '3p')" \
|
||||
'claude usage should be green well below the limit'
|
||||
|
||||
write_claude_state 70 "$((claude_now + 3600))" 12 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_equals '#F1FA8C' "$(run_claude_usage | sed -n '3p')" \
|
||||
'claude usage should warn when a window passes 60%'
|
||||
|
||||
write_claude_state 91 "$((claude_now + 3600))" 12 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_equals '#FF5555' "$(run_claude_usage | sed -n '3p')" \
|
||||
'claude usage should go critical when a window passes 85%'
|
||||
|
||||
# The writer only runs while a Claude session is open, so old data must be
|
||||
# labelled rather than presented as the current figure.
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55 "$((claude_now + 99999))" "$((claude_now - 5000))"
|
||||
assert_equals '🤖 5h 34% · 7d 55% (stale)' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should mark stale cache data'
|
||||
|
||||
# A window whose reset time has passed has rolled over: its cached percentage is
|
||||
# meaningless, so it must read as unknown rather than a misleading value.
|
||||
write_claude_state 99 "$((claude_now - 10))" 55 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_equals '🤖 5h ?% · 7d 55%' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should not report a rolled-over window as current'
|
||||
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55 null "$claude_now"
|
||||
assert_equals '🤖 5h 34% · 7d 55%' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should tolerate a null seven_day reset time'
|
||||
|
||||
printf 'not json\n' >"$CLAUDE_STATE_DIR/state.json"
|
||||
assert_equals '🤖 no data' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should degrade gracefully on unparsable cache data'
|
||||
|
||||
claude_missing_output=$(LIMIT_STATE_DIR="$TMP_DIR/no-such-dir" NOW_EPOCH="$claude_now" \
|
||||
bash "$I3BLOCKS_DIR/claude_usage.sh")
|
||||
assert_equals '🤖 no data' "$(printf '%s\n' "$claude_missing_output" | sed -n '1p')" \
|
||||
'claude usage should degrade gracefully when the cache directory is absent'
|
||||
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_le "$(LIMIT_STATE_DIR="$CLAUDE_STATE_DIR" NOW_EPOCH="$claude_now" \
|
||||
count_execs "$I3BLOCKS_DIR/claude_usage.sh")" 3 \
|
||||
'claude usage should stay within bash plus jq'
|
||||
|
||||
# The real cache holds one file per project (~170 on this machine), so the
|
||||
# fork budget has to be measured against a populated directory. Measuring it
|
||||
# against a single-file dir hid a `stat` call sitting inside the scan loop.
|
||||
for filler in $(seq 1 200); do
|
||||
cp "$CLAUDE_STATE_DIR/state.json" "$CLAUDE_STATE_DIR/filler-$filler.json"
|
||||
done
|
||||
assert_le "$(LIMIT_STATE_DIR="$CLAUDE_STATE_DIR" NOW_EPOCH="$claude_now" \
|
||||
count_execs "$I3BLOCKS_DIR/claude_usage.sh")" 3 \
|
||||
'claude usage fork count must not scale with the number of cached projects'
|
||||
rm -f "$CLAUDE_STATE_DIR"/filler-*.json
|
||||
|
||||
return 0
|
||||
}
|
||||
73
linux_configuration/tests/lib/i3blocks_config_checks.sh
Executable file
73
linux_configuration/tests/lib/i3blocks_config_checks.sh
Executable file
@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# i3blocks efficiency: config wiring, status icons, focus/GPU/ethernet guards.
|
||||
# Sourced by test_i3blocks_efficiency.sh; inherits its strict mode and its
|
||||
# helpers (fail, assert_equals, assert_le, epoch_utc, count_execs) plus the
|
||||
# BIN_DIR / TMP_DIR / CONFIG_FILE / I3BLOCKS_DIR paths it sets up.
|
||||
|
||||
i3_tests_config_and_guards() {
|
||||
printf 'Checking config uses dedicated low-fork scripts...\n'
|
||||
grep -q '^command=~/.config/i3blocks/time.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'time block should call time.sh'
|
||||
grep -q '^interval=persist$' "$CONFIG_FILE" \
|
||||
|| fail 'config should use persist interval for time block'
|
||||
grep -q '^command=~/.config/i3blocks/memory.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'memory block should call memory.sh'
|
||||
grep -q '^command=~/.config/i3blocks/ethernet.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'ethernet block should call ethernet.sh'
|
||||
grep -q '^command=~/.config/i3blocks/disk.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'disk block should call disk.sh'
|
||||
grep -q '^interval=10$' "$CONFIG_FILE" \
|
||||
|| fail 'cpu block should poll at 10s interval'
|
||||
grep -A2 '^\[motherboard_temperature\]$' "$CONFIG_FILE" | grep -q '^interval=30$' \
|
||||
|| fail 'motherboard block should poll at 30s interval'
|
||||
grep -A2 '^\[memory\]$' "$CONFIG_FILE" | grep -q '^interval=30$' \
|
||||
|| fail 'memory block should poll at 30s interval'
|
||||
grep -A2 '^\[ethernet\]$' "$CONFIG_FILE" | grep -q '^interval=persist$' \
|
||||
|| fail 'ethernet block should use persist mode'
|
||||
grep -A2 '^\[claude_usage\]$' "$CONFIG_FILE" | grep -q '^interval=60$' \
|
||||
|| fail 'claude_usage block should poll at 60s interval'
|
||||
grep -q '^command=~/.config/i3blocks/claude_usage.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'claude_usage block should call claude_usage.sh'
|
||||
|
||||
# Blocks for hardware/software absent from this machine were removed; make sure
|
||||
# they do not silently return. Each rendered permanently-dead text in the bar.
|
||||
for removed_block in bluetooth battery wifi activitywatch warp network_monitor; do
|
||||
if grep -q "^\[${removed_block}\]$" "$CONFIG_FILE"; then
|
||||
fail "removed block [${removed_block}] should not be in the config"
|
||||
fi
|
||||
done
|
||||
|
||||
printf 'Checking status icons avoid Font Awesome private-use codepoints...\n'
|
||||
# The fonts named in the i3 bar's pango string are not installed, so private-use
|
||||
# codepoints (U+E000-U+F8FF) fall through to whatever font claims them - which
|
||||
# rendered the ethernet icon as a star and the wifi icon as Cyrillic. Plain
|
||||
# Unicode/emoji resolve consistently instead.
|
||||
for icon_script in "$I3BLOCKS_DIR"/*.sh; do
|
||||
if grep -qP '[\x{E000}-\x{F8FF}]|\\u[eEfF][0-9a-fA-F]{3}' "$icon_script"; then
|
||||
fail "$(basename "$icon_script") should not use private-use-area icon codepoints"
|
||||
fi
|
||||
done
|
||||
|
||||
printf 'Checking focus detection path avoids extra xdotool lookups...\n'
|
||||
! grep -Fq "xdotool getwindowname \"\$wid\"" "$REPO_DIR/scripts/lib/common.sh" \
|
||||
|| fail 'focus detection should not call xdotool getwindowname in hot path'
|
||||
|
||||
printf 'Checking GPU dedupe guards exist...\n'
|
||||
grep -Fq 'emit_if_changed()' "$I3BLOCKS_DIR/gpu_monitor.sh" \
|
||||
|| fail 'gpu monitor should dedupe repeated identical samples'
|
||||
grep -Fq "source \"\$SCRIPT_DIR/persist_common.sh\"" "$I3BLOCKS_DIR/ethernet.sh" \
|
||||
|| fail 'ethernet script should use shared persist helper'
|
||||
grep -Fq "source \"\$SCRIPT_DIR/persist_common.sh\"" "$I3BLOCKS_DIR/gpu_monitor.sh" \
|
||||
|| fail 'gpu script should use shared persist helper'
|
||||
grep -Fq 'i3blocks_update_if_changed_key "ethernet_output"' "$I3BLOCKS_DIR/ethernet.sh" \
|
||||
|| fail 'ethernet script should dedupe unchanged output'
|
||||
|
||||
printf 'Checking ethernet picks a physical NIC over virtual bridges...\n'
|
||||
# Regression: the old loop returned the first non-loopback interface, which on a
|
||||
# machine with docker installed is a `br-*` bridge (always "down", and sorted
|
||||
# before enp*/eth*), so the bar reported "down" on a live wired connection.
|
||||
grep -Fq 'iface_path}/device' "$I3BLOCKS_DIR/ethernet.sh" \
|
||||
|| fail 'ethernet script should require a real device to skip virtual interfaces'
|
||||
|
||||
return 0
|
||||
}
|
||||
70
linux_configuration/tests/lib/pacman_wrapper_makepkg.sh
Executable file
70
linux_configuration/tests/lib/pacman_wrapper_makepkg.sh
Executable file
@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# Pacman wrapper security: makepkg capped runner, mkpkg helper and installer hardening (tests 13-19).
|
||||
# Sourced by test_pacman_wrapper_security.sh; inherits its strict mode
|
||||
# (set -e) and its SCRIPT_DIR / WRAPPER_DIR / VBOX_DIR paths.
|
||||
|
||||
pac_tests_makepkg_and_installer() {
|
||||
# Test 13: Verify makepkg capped wrapper script syntax
|
||||
echo "[TEST 13] Checking makepkg capped wrapper syntax..."
|
||||
if bash -n "$WRAPPER_DIR/makepkg_capped.sh"; then
|
||||
echo "✓ makepkg capped wrapper syntax is valid"
|
||||
else
|
||||
echo "✗ makepkg capped wrapper has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 14: Verify pacman wrapper exposes makepkg capped command
|
||||
echo "[TEST 14] Verifying pacman wrapper supports --makepkg-capped..."
|
||||
if grep -q -- "--makepkg-capped" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ pacman wrapper makepkg capped command found"
|
||||
else
|
||||
echo "✗ pacman wrapper makepkg capped command missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 15: Verify installer deploys makepkg capped wrapper
|
||||
echo "[TEST 15] Verifying installer deploys makepkg capped wrapper..."
|
||||
if grep -q "MAKEPKG_CAPPED" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer includes makepkg capped deployment"
|
||||
else
|
||||
echo "✗ Installer does not include makepkg capped deployment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 16: Verify mkpkg helper script syntax
|
||||
echo "[TEST 16] Checking mkpkg helper script syntax..."
|
||||
if bash -n "$WRAPPER_DIR/mkpkg.sh"; then
|
||||
echo "✓ mkpkg helper script syntax is valid"
|
||||
else
|
||||
echo "✗ mkpkg helper script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 17: Verify installer deploys mkpkg helper
|
||||
echo "[TEST 17] Verifying installer deploys mkpkg helper..."
|
||||
if grep -q "MKPKG" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer includes mkpkg helper deployment"
|
||||
else
|
||||
echo "✗ Installer does not include mkpkg helper deployment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 18: Verify installer runs in strict mode
|
||||
echo "[TEST 18] Verifying installer uses strict shell mode..."
|
||||
if grep -q "set -euo pipefail" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer strict mode enabled"
|
||||
else
|
||||
echo "✗ Installer strict mode not enabled"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 19: Verify installer handles immutable files during updates
|
||||
echo "[TEST 19] Verifying installer unlocks immutable files before copy/write..."
|
||||
if grep -q "unlock_immutable_file_if_needed" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer immutable-file handling found"
|
||||
else
|
||||
echo "✗ Installer immutable-file handling missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
}
|
||||
116
linux_configuration/tests/lib/pacman_wrapper_syntax.sh
Executable file
116
linux_configuration/tests/lib/pacman_wrapper_syntax.sh
Executable file
@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
# Pacman wrapper security: syntax, integrity and VirtualBox enforcement checks (tests 1-12).
|
||||
# Sourced by test_pacman_wrapper_security.sh; inherits its strict mode
|
||||
# (set -e) and its SCRIPT_DIR / WRAPPER_DIR / VBOX_DIR paths.
|
||||
|
||||
pac_tests_wrapper_and_vbox() {
|
||||
# Test 1: Check wrapper syntax
|
||||
echo "[TEST 1] Checking wrapper script syntax..."
|
||||
if bash -n "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ Wrapper script syntax is valid"
|
||||
else
|
||||
echo "✗ Wrapper script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: Check installer syntax
|
||||
echo "[TEST 2] Checking installer script syntax..."
|
||||
if bash -n "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer script syntax is valid"
|
||||
else
|
||||
echo "✗ Installer script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Check VirtualBox enforcement script syntax
|
||||
echo "[TEST 3] Checking VirtualBox enforcement script syntax..."
|
||||
if bash -n "$VBOX_DIR/enforce_vbox_hosts.sh"; then
|
||||
echo "✓ VirtualBox enforcement script syntax is valid"
|
||||
else
|
||||
echo "✗ VirtualBox enforcement script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Verify integrity check function exists
|
||||
echo "[TEST 4] Verifying integrity check function exists in wrapper..."
|
||||
if grep -q "verify_policy_integrity()" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ Integrity verification function found"
|
||||
else
|
||||
echo "✗ Integrity verification function not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 5: Verify hardcoded VirtualBox cleanup function exists
|
||||
echo "[TEST 5] Verifying hardcoded VirtualBox cleanup function exists..."
|
||||
if grep -q "auto_remove_virtualbox_vms()" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ Hardcoded VirtualBox cleanup function found"
|
||||
else
|
||||
echo "✗ Hardcoded VirtualBox cleanup function not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 6: Verify VirtualBox cleanup uses VBoxManage directly
|
||||
echo "[TEST 6] Verifying VirtualBox cleanup uses VBoxManage directly..."
|
||||
if grep -q "VBoxManage" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ VirtualBox cleanup logic found"
|
||||
else
|
||||
echo "✗ VirtualBox cleanup logic not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 7: Verify integrity check is called early in execution
|
||||
echo "[TEST 7] Verifying integrity check is called before operations..."
|
||||
if grep -B 2 -A 2 "verify_policy_integrity" "$WRAPPER_DIR/pacman_wrapper.sh" | grep -q "CRITICAL"; then
|
||||
echo "✓ Integrity check is called early in execution"
|
||||
else
|
||||
echo "✗ Integrity check not found in early execution"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 8: Verify installer creates integrity file
|
||||
echo "[TEST 8] Verifying installer creates integrity checksums..."
|
||||
if grep -q "INTEGRITY_FILE" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer references integrity file"
|
||||
else
|
||||
echo "✗ Installer does not create integrity file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 9: Verify installer uses chattr to make files immutable
|
||||
echo "[TEST 9] Verifying installer makes policy files immutable..."
|
||||
if grep -q "chattr +i" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer sets immutable attributes"
|
||||
else
|
||||
echo "✗ Installer does not set immutable attributes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 10: Verify VirtualBox cleanup enforcement is integrated
|
||||
echo "[TEST 10] Verifying VirtualBox cleanup is integrated into wrapper..."
|
||||
if grep -q "auto_remove_virtualbox_vms" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ VirtualBox cleanup integration found"
|
||||
else
|
||||
echo "✗ VirtualBox cleanup integration not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 11: Verify VirtualBox script can show help
|
||||
echo "[TEST 11] Testing VirtualBox enforcement script help..."
|
||||
# Run without invoking sudo by setting EUID check (or just check for the help text in the file)
|
||||
if grep -q "VirtualBox /etc/hosts Enforcement Tool" "$VBOX_DIR/enforce_vbox_hosts.sh"; then
|
||||
echo "✓ VirtualBox enforcement script has help text"
|
||||
else
|
||||
echo "✗ VirtualBox enforcement script help text not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 12: Verify installer installs VirtualBox enforcement script
|
||||
echo "[TEST 12] Verifying installer handles VirtualBox enforcement script..."
|
||||
if grep -q "VBOX_ENFORCE" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer includes VirtualBox enforcement script"
|
||||
else
|
||||
echo "✗ Installer does not include VirtualBox enforcement script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
}
|
||||
@ -127,149 +127,18 @@ exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/df"
|
||||
|
||||
printf 'Checking config uses dedicated low-fork scripts...\n'
|
||||
grep -q '^command=~/.config/i3blocks/time.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'time block should call time.sh'
|
||||
grep -q '^interval=persist$' "$CONFIG_FILE" \
|
||||
|| fail 'config should use persist interval for time block'
|
||||
grep -q '^command=~/.config/i3blocks/memory.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'memory block should call memory.sh'
|
||||
grep -q '^command=~/.config/i3blocks/ethernet.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'ethernet block should call ethernet.sh'
|
||||
grep -q '^command=~/.config/i3blocks/disk.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'disk block should call disk.sh'
|
||||
grep -q '^interval=10$' "$CONFIG_FILE" \
|
||||
|| fail 'cpu block should poll at 10s interval'
|
||||
grep -A2 '^\[motherboard_temperature\]$' "$CONFIG_FILE" | grep -q '^interval=30$' \
|
||||
|| fail 'motherboard block should poll at 30s interval'
|
||||
grep -A2 '^\[memory\]$' "$CONFIG_FILE" | grep -q '^interval=30$' \
|
||||
|| fail 'memory block should poll at 30s interval'
|
||||
grep -A2 '^\[ethernet\]$' "$CONFIG_FILE" | grep -q '^interval=persist$' \
|
||||
|| fail 'ethernet block should use persist mode'
|
||||
grep -A2 '^\[claude_usage\]$' "$CONFIG_FILE" | grep -q '^interval=60$' \
|
||||
|| fail 'claude_usage block should poll at 60s interval'
|
||||
grep -q '^command=~/.config/i3blocks/claude_usage.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'claude_usage block should call claude_usage.sh'
|
||||
# Two blocks of checks live in libs to keep this file under the 250-line cap.
|
||||
# They run in this shell and use the helpers and paths set up above. The fake
|
||||
# $BIN_DIR binaries and their heredocs stay here: a seam inside a heredoc
|
||||
# produces a lib that will not parse.
|
||||
LIB_DIR="$SCRIPT_DIR/lib"
|
||||
# shellcheck source=lib/i3blocks_config_checks.sh
|
||||
source "$LIB_DIR/i3blocks_config_checks.sh"
|
||||
# shellcheck source=lib/i3blocks_claude_usage.sh
|
||||
source "$LIB_DIR/i3blocks_claude_usage.sh"
|
||||
|
||||
# Blocks for hardware/software absent from this machine were removed; make sure
|
||||
# they do not silently return. Each rendered permanently-dead text in the bar.
|
||||
for removed_block in bluetooth battery wifi activitywatch warp network_monitor; do
|
||||
if grep -q "^\[${removed_block}\]$" "$CONFIG_FILE"; then
|
||||
fail "removed block [${removed_block}] should not be in the config"
|
||||
fi
|
||||
done
|
||||
|
||||
printf 'Checking status icons avoid Font Awesome private-use codepoints...\n'
|
||||
# The fonts named in the i3 bar's pango string are not installed, so private-use
|
||||
# codepoints (U+E000-U+F8FF) fall through to whatever font claims them - which
|
||||
# rendered the ethernet icon as a star and the wifi icon as Cyrillic. Plain
|
||||
# Unicode/emoji resolve consistently instead.
|
||||
for icon_script in "$I3BLOCKS_DIR"/*.sh; do
|
||||
if grep -qP '[\x{E000}-\x{F8FF}]|\\u[eEfF][0-9a-fA-F]{3}' "$icon_script"; then
|
||||
fail "$(basename "$icon_script") should not use private-use-area icon codepoints"
|
||||
fi
|
||||
done
|
||||
|
||||
printf 'Checking focus detection path avoids extra xdotool lookups...\n'
|
||||
! grep -Fq "xdotool getwindowname \"\$wid\"" "$REPO_DIR/scripts/lib/common.sh" \
|
||||
|| fail 'focus detection should not call xdotool getwindowname in hot path'
|
||||
|
||||
printf 'Checking GPU dedupe guards exist...\n'
|
||||
grep -Fq 'emit_if_changed()' "$I3BLOCKS_DIR/gpu_monitor.sh" \
|
||||
|| fail 'gpu monitor should dedupe repeated identical samples'
|
||||
grep -Fq "source \"\$SCRIPT_DIR/persist_common.sh\"" "$I3BLOCKS_DIR/ethernet.sh" \
|
||||
|| fail 'ethernet script should use shared persist helper'
|
||||
grep -Fq "source \"\$SCRIPT_DIR/persist_common.sh\"" "$I3BLOCKS_DIR/gpu_monitor.sh" \
|
||||
|| fail 'gpu script should use shared persist helper'
|
||||
grep -Fq 'i3blocks_update_if_changed_key "ethernet_output"' "$I3BLOCKS_DIR/ethernet.sh" \
|
||||
|| fail 'ethernet script should dedupe unchanged output'
|
||||
|
||||
printf 'Checking ethernet picks a physical NIC over virtual bridges...\n'
|
||||
# Regression: the old loop returned the first non-loopback interface, which on a
|
||||
# machine with docker installed is a `br-*` bridge (always "down", and sorted
|
||||
# before enp*/eth*), so the bar reported "down" on a live wired connection.
|
||||
grep -Fq 'iface_path}/device' "$I3BLOCKS_DIR/ethernet.sh" \
|
||||
|| fail 'ethernet script should require a real device to skip virtual interfaces'
|
||||
|
||||
printf 'Checking Claude usage block behavior and fork count...\n'
|
||||
# claude_usage.sh parses its cache with jq and degrades to "no data" when jq is
|
||||
# missing. That is the right runtime behaviour, but it would make every
|
||||
# assertion below fail with a misleading message about percentages, so name the
|
||||
# real cause instead of letting a missing tool look like a logic bug.
|
||||
# Probe by running jq, not with `command -v`: a jq that exists but cannot
|
||||
# execute produces exactly the same "no data" output as one that is absent.
|
||||
printf '{}' | jq -e . >/dev/null 2>&1 \
|
||||
|| fail 'a working jq is required for the claude_usage tests (pacman -S jq)'
|
||||
CLAUDE_STATE_DIR="$TMP_DIR/limit-state"
|
||||
mkdir -p "$CLAUDE_STATE_DIR"
|
||||
claude_now=1786366861
|
||||
|
||||
write_claude_state() {
|
||||
printf '{"five_hour_pct":%s,"five_hour_resets_at":%s,"seven_day_pct":%s,"seven_day_resets_at":%s,"updated_at":%s}\n' \
|
||||
"$1" "$2" "$3" "$4" "$5" >"$CLAUDE_STATE_DIR/state.json"
|
||||
}
|
||||
|
||||
run_claude_usage() {
|
||||
LIMIT_STATE_DIR="$CLAUDE_STATE_DIR" NOW_EPOCH="$claude_now" \
|
||||
bash "$I3BLOCKS_DIR/claude_usage.sh"
|
||||
}
|
||||
|
||||
# Percentages arrive as floats (e.g. 55.00000000000001) and must be truncated.
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55.00000000000001 "$((claude_now + 99999))" "$claude_now"
|
||||
claude_output=$(run_claude_usage)
|
||||
assert_equals '🤖 5h 34% · 7d 55%' "$(printf '%s\n' "$claude_output" | sed -n '1p')" \
|
||||
'claude usage should show both windows as whole percentages'
|
||||
assert_equals '#50FA7B' "$(printf '%s\n' "$claude_output" | sed -n '3p')" \
|
||||
'claude usage should be green well below the limit'
|
||||
|
||||
write_claude_state 70 "$((claude_now + 3600))" 12 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_equals '#F1FA8C' "$(run_claude_usage | sed -n '3p')" \
|
||||
'claude usage should warn when a window passes 60%'
|
||||
|
||||
write_claude_state 91 "$((claude_now + 3600))" 12 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_equals '#FF5555' "$(run_claude_usage | sed -n '3p')" \
|
||||
'claude usage should go critical when a window passes 85%'
|
||||
|
||||
# The writer only runs while a Claude session is open, so old data must be
|
||||
# labelled rather than presented as the current figure.
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55 "$((claude_now + 99999))" "$((claude_now - 5000))"
|
||||
assert_equals '🤖 5h 34% · 7d 55% (stale)' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should mark stale cache data'
|
||||
|
||||
# A window whose reset time has passed has rolled over: its cached percentage is
|
||||
# meaningless, so it must read as unknown rather than a misleading value.
|
||||
write_claude_state 99 "$((claude_now - 10))" 55 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_equals '🤖 5h ?% · 7d 55%' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should not report a rolled-over window as current'
|
||||
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55 null "$claude_now"
|
||||
assert_equals '🤖 5h 34% · 7d 55%' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should tolerate a null seven_day reset time'
|
||||
|
||||
printf 'not json\n' >"$CLAUDE_STATE_DIR/state.json"
|
||||
assert_equals '🤖 no data' "$(run_claude_usage | sed -n '1p')" \
|
||||
'claude usage should degrade gracefully on unparsable cache data'
|
||||
|
||||
claude_missing_output=$(LIMIT_STATE_DIR="$TMP_DIR/no-such-dir" NOW_EPOCH="$claude_now" \
|
||||
bash "$I3BLOCKS_DIR/claude_usage.sh")
|
||||
assert_equals '🤖 no data' "$(printf '%s\n' "$claude_missing_output" | sed -n '1p')" \
|
||||
'claude usage should degrade gracefully when the cache directory is absent'
|
||||
|
||||
write_claude_state 34 "$((claude_now + 3600))" 55 "$((claude_now + 99999))" "$claude_now"
|
||||
assert_le "$(LIMIT_STATE_DIR="$CLAUDE_STATE_DIR" NOW_EPOCH="$claude_now" \
|
||||
count_execs "$I3BLOCKS_DIR/claude_usage.sh")" 3 \
|
||||
'claude usage should stay within bash plus jq'
|
||||
|
||||
# The real cache holds one file per project (~170 on this machine), so the
|
||||
# fork budget has to be measured against a populated directory. Measuring it
|
||||
# against a single-file dir hid a `stat` call sitting inside the scan loop.
|
||||
for filler in $(seq 1 200); do
|
||||
cp "$CLAUDE_STATE_DIR/state.json" "$CLAUDE_STATE_DIR/filler-$filler.json"
|
||||
done
|
||||
assert_le "$(LIMIT_STATE_DIR="$CLAUDE_STATE_DIR" NOW_EPOCH="$claude_now" \
|
||||
count_execs "$I3BLOCKS_DIR/claude_usage.sh")" 3 \
|
||||
'claude usage fork count must not scale with the number of cached projects'
|
||||
rm -f "$CLAUDE_STATE_DIR"/filler-*.json
|
||||
i3_tests_config_and_guards
|
||||
i3_tests_claude_usage
|
||||
|
||||
printf 'Checking disk block behavior and fork count...\n'
|
||||
disk_output=$(PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/disk.sh")
|
||||
|
||||
@ -10,177 +10,18 @@ VBOX_DIR="$SCRIPT_DIR/../scripts/periodic_background/digital_wellbeing/virtualbo
|
||||
echo "=== Testing Pacman Wrapper Security Enhancements ==="
|
||||
echo ""
|
||||
|
||||
# Test 1: Check wrapper syntax
|
||||
echo "[TEST 1] Checking wrapper script syntax..."
|
||||
if bash -n "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ Wrapper script syntax is valid"
|
||||
else
|
||||
echo "✗ Wrapper script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
# The bulk of the checks live in libs to keep this file under the 250-line cap.
|
||||
# They are functions, but they run in this shell and use the paths above
|
||||
# exactly as the former top-level blocks did.
|
||||
LIB_DIR="$SCRIPT_DIR/lib"
|
||||
# shellcheck source=lib/pacman_wrapper_syntax.sh
|
||||
source "$LIB_DIR/pacman_wrapper_syntax.sh"
|
||||
# shellcheck source=lib/pacman_wrapper_makepkg.sh
|
||||
source "$LIB_DIR/pacman_wrapper_makepkg.sh"
|
||||
|
||||
# Test 2: Check installer syntax
|
||||
echo "[TEST 2] Checking installer script syntax..."
|
||||
if bash -n "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer script syntax is valid"
|
||||
else
|
||||
echo "✗ Installer script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Check VirtualBox enforcement script syntax
|
||||
echo "[TEST 3] Checking VirtualBox enforcement script syntax..."
|
||||
if bash -n "$VBOX_DIR/enforce_vbox_hosts.sh"; then
|
||||
echo "✓ VirtualBox enforcement script syntax is valid"
|
||||
else
|
||||
echo "✗ VirtualBox enforcement script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Verify integrity check function exists
|
||||
echo "[TEST 4] Verifying integrity check function exists in wrapper..."
|
||||
if grep -q "verify_policy_integrity()" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ Integrity verification function found"
|
||||
else
|
||||
echo "✗ Integrity verification function not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 5: Verify hardcoded VirtualBox cleanup function exists
|
||||
echo "[TEST 5] Verifying hardcoded VirtualBox cleanup function exists..."
|
||||
if grep -q "auto_remove_virtualbox_vms()" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ Hardcoded VirtualBox cleanup function found"
|
||||
else
|
||||
echo "✗ Hardcoded VirtualBox cleanup function not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 6: Verify VirtualBox cleanup uses VBoxManage directly
|
||||
echo "[TEST 6] Verifying VirtualBox cleanup uses VBoxManage directly..."
|
||||
if grep -q "VBoxManage" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ VirtualBox cleanup logic found"
|
||||
else
|
||||
echo "✗ VirtualBox cleanup logic not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 7: Verify integrity check is called early in execution
|
||||
echo "[TEST 7] Verifying integrity check is called before operations..."
|
||||
if grep -B 2 -A 2 "verify_policy_integrity" "$WRAPPER_DIR/pacman_wrapper.sh" | grep -q "CRITICAL"; then
|
||||
echo "✓ Integrity check is called early in execution"
|
||||
else
|
||||
echo "✗ Integrity check not found in early execution"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 8: Verify installer creates integrity file
|
||||
echo "[TEST 8] Verifying installer creates integrity checksums..."
|
||||
if grep -q "INTEGRITY_FILE" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer references integrity file"
|
||||
else
|
||||
echo "✗ Installer does not create integrity file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 9: Verify installer uses chattr to make files immutable
|
||||
echo "[TEST 9] Verifying installer makes policy files immutable..."
|
||||
if grep -q "chattr +i" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer sets immutable attributes"
|
||||
else
|
||||
echo "✗ Installer does not set immutable attributes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 10: Verify VirtualBox cleanup enforcement is integrated
|
||||
echo "[TEST 10] Verifying VirtualBox cleanup is integrated into wrapper..."
|
||||
if grep -q "auto_remove_virtualbox_vms" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ VirtualBox cleanup integration found"
|
||||
else
|
||||
echo "✗ VirtualBox cleanup integration not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 11: Verify VirtualBox script can show help
|
||||
echo "[TEST 11] Testing VirtualBox enforcement script help..."
|
||||
# Run without invoking sudo by setting EUID check (or just check for the help text in the file)
|
||||
if grep -q "VirtualBox /etc/hosts Enforcement Tool" "$VBOX_DIR/enforce_vbox_hosts.sh"; then
|
||||
echo "✓ VirtualBox enforcement script has help text"
|
||||
else
|
||||
echo "✗ VirtualBox enforcement script help text not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 12: Verify installer installs VirtualBox enforcement script
|
||||
echo "[TEST 12] Verifying installer handles VirtualBox enforcement script..."
|
||||
if grep -q "VBOX_ENFORCE" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer includes VirtualBox enforcement script"
|
||||
else
|
||||
echo "✗ Installer does not include VirtualBox enforcement script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 13: Verify makepkg capped wrapper script syntax
|
||||
echo "[TEST 13] Checking makepkg capped wrapper syntax..."
|
||||
if bash -n "$WRAPPER_DIR/makepkg_capped.sh"; then
|
||||
echo "✓ makepkg capped wrapper syntax is valid"
|
||||
else
|
||||
echo "✗ makepkg capped wrapper has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 14: Verify pacman wrapper exposes makepkg capped command
|
||||
echo "[TEST 14] Verifying pacman wrapper supports --makepkg-capped..."
|
||||
if grep -q -- "--makepkg-capped" "$WRAPPER_DIR/pacman_wrapper.sh"; then
|
||||
echo "✓ pacman wrapper makepkg capped command found"
|
||||
else
|
||||
echo "✗ pacman wrapper makepkg capped command missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 15: Verify installer deploys makepkg capped wrapper
|
||||
echo "[TEST 15] Verifying installer deploys makepkg capped wrapper..."
|
||||
if grep -q "MAKEPKG_CAPPED" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer includes makepkg capped deployment"
|
||||
else
|
||||
echo "✗ Installer does not include makepkg capped deployment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 16: Verify mkpkg helper script syntax
|
||||
echo "[TEST 16] Checking mkpkg helper script syntax..."
|
||||
if bash -n "$WRAPPER_DIR/mkpkg.sh"; then
|
||||
echo "✓ mkpkg helper script syntax is valid"
|
||||
else
|
||||
echo "✗ mkpkg helper script has syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 17: Verify installer deploys mkpkg helper
|
||||
echo "[TEST 17] Verifying installer deploys mkpkg helper..."
|
||||
if grep -q "MKPKG" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer includes mkpkg helper deployment"
|
||||
else
|
||||
echo "✗ Installer does not include mkpkg helper deployment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 18: Verify installer runs in strict mode
|
||||
echo "[TEST 18] Verifying installer uses strict shell mode..."
|
||||
if grep -q "set -euo pipefail" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer strict mode enabled"
|
||||
else
|
||||
echo "✗ Installer strict mode not enabled"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 19: Verify installer handles immutable files during updates
|
||||
echo "[TEST 19] Verifying installer unlocks immutable files before copy/write..."
|
||||
if grep -q "unlock_immutable_file_if_needed" "$WRAPPER_DIR/install_pacman_wrapper.sh"; then
|
||||
echo "✓ Installer immutable-file handling found"
|
||||
else
|
||||
echo "✗ Installer immutable-file handling missing"
|
||||
exit 1
|
||||
fi
|
||||
# Order matters: it is the order the checks ran in before the split.
|
||||
pac_tests_wrapper_and_vbox
|
||||
pac_tests_makepkg_and_installer
|
||||
|
||||
# Test: shared lock library syntax
|
||||
echo "[TEST] Checking shared lock library syntax..."
|
||||
|
||||
Loading…
Reference in New Issue
Block a user