scripts/stage-timing.test.sh
1#!/usr/bin/env bash
2# stage-timing.test.sh (Issue 10-051) -- exercises scripts/stage-timing.sh against
3# a throwaway temp file. Run: bash scripts/stage-timing.test.sh
4#
5# Pins the behaviours that matter: human-readable durations, the ring buffer
6# evicting the oldest past the cap, the mean/count, and -- the load-bearing rule
7# -- that a FAILED stage records nothing while a successful one does.
8
9set -u
10DIR_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
11export STAGE_TIMINGS_FILE="$(mktemp)"
12# shellcheck source=/dev/null
13source "${DIR_HERE}/scripts/stage-timing.sh"
14
15pass=0; fail=0
16check() { # check <label> <actual> <expected>
17 if [ "$2" = "$3" ]; then pass=$((pass+1)); echo " ok - $1"
18 else fail=$((fail+1)); echo " FAIL - $1: got [$2] want [$3]"; fi
19}
20
21# {{{ format_seconds across the unit boundaries
22check "45s" "$(stage_timing_format_seconds 45)" "45s"
23check "12m 30s" "$(stage_timing_format_seconds 750)" "12m 30s"
24check "2h 14m 0s" "$(stage_timing_format_seconds 8040)" "2h 14m 0s"
25check "1h 1m 1s (3 slots)" "$(stage_timing_format_seconds 3661)" "1h 1m 1s"
26check "1d 18h 0m" "$(stage_timing_format_seconds 151200)" "1d 18h 0m"
27check "boundary 3600 -> 1h 0m 0s" "$(stage_timing_format_seconds 3600)" "1h 0m 0s"
28# }}}
29
30# {{{ ring buffer keeps only the last RING_SIZE, oldest off the top
31rm -f "$STAGE_TIMINGS_FILE"
32for v in 100 200 300 400 500 600 700; do stage_timing_record embed "$v"; done
33check "ring count capped at 5" "$(stage_timing_count embed)" "5"
34check "mean of last 5 (300..700)" "$(stage_timing_mean embed)" "500"
35check "oldest (100,200) evicted" "$(grep -c '^100$\|^200$' "$STAGE_TIMINGS_FILE")" "0"
36# }}}
37
38# {{{ no history -> fallback label with explicit qualifier
39check "magnitude fallback label" "$(stage_timing_label ghost long)" "(long)"
40check "measured beats magnitude" "$(stage_timing_label embed long)" "(avg 8m 20s, last 5 runs)"
41check "no magnitude + no history -> empty" "$(stage_timing_label ghost '')" ""
42# }}}
43
44# {{{ record only on success (the honesty rule)
45timed_stage ok_stage true
46timed_stage fail_stage false
47check "success recorded" "$(stage_timing_count ok_stage)" "1"
48check "failure NOT recorded" "$(stage_timing_count fail_stage)" "0"
49# }}}
50
51# {{{ bad inputs are no-ops, never crash
52stage_timing_record "" 5
53stage_timing_record nostage "abc"
54check "empty stage no-op" "$(stage_timing_count '')" "0"
55check "non-integer secs no-op" "$(stage_timing_count nostage)" "0"
56# }}}
57
58rm -f "$STAGE_TIMINGS_FILE"*
59echo "---"
60if [ "$fail" -eq 0 ]; then echo "ALL ${pass} PASS"; exit 0
61else echo "${fail} FAILURE(S)"; exit 1; fi
62