blob: 7e511152d9b845fa686729f1b89bcc9284269e51 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#!/usr/bin/env bats
# Tests for scripts/bootstrap-packages.sh — the headless package installer.
#
# The elisp tests cover what happens inside one Emacs. What only a shell test
# can cover is the pass loop: whether a run that reports packages still missing
# gets another pass, whether a run that converges stops early, and whether a
# broken init breaks out instead of burning every pass on the same failure.
#
# Every test drives a fake emacs whose exit statuses are scripted, so no test
# touches the network, the real elpa directory, or a real Emacs. The script
# honours $EMACS, which is the seam these hang on.
setup() {
SCRIPT="${BATS_TEST_DIRNAME}/../scripts/bootstrap-packages.sh"
BIN="${BATS_TEST_TMPDIR}/bin"
COUNTER="${BATS_TEST_TMPDIR}/attempts"
mkdir -p "$BIN"
echo 0 >"$COUNTER"
export BOOTSTRAP_PASSES=3
export BOOTSTRAP_TIMEOUT=30
# Point the script at a scratch config dir rather than the real checkout, so
# the byte-compiled-modules check reads fixture state instead of whatever
# this working tree happens to have compiled.
export BOOTSTRAP_DIR="${BATS_TEST_TMPDIR}/emacsd"
mkdir -p "$BOOTSTRAP_DIR/modules"
}
# Write a fake emacs that exits with the given statuses in order, repeating the
# last one once the list runs out. Status 1 also prints the "still missing"
# line the real cj/package-bootstrap-batch prints, so the script's grep is
# exercised rather than assumed.
fake_emacs() {
{
echo '#!/usr/bin/env bash'
echo "n=\$(cat '$COUNTER')"
echo "n=\$((n + 1))"
echo "echo \$n >'$COUNTER'"
echo "statuses=($*)"
echo 'idx=$((n - 1))'
echo 'last=$((${#statuses[@]} - 1))'
echo '[ $idx -gt $last ] && idx=$last'
echo 'status=${statuses[$idx]}'
echo '[ "$status" -eq 1 ] && echo "package-bootstrap: 2 missing: foo bar"'
echo 'exit $status'
} >"$BIN/emacs"
chmod +x "$BIN/emacs"
export EMACS="$BIN/emacs"
}
attempts() { cat "$COUNTER"; }
@test "normal: a clean first pass succeeds and stops there" {
fake_emacs 0
run bash "$SCRIPT"
[ "$status" -eq 0 ]
[ "$(attempts)" -eq 1 ]
[[ "$output" == *"every package is installed"* ]]
}
@test "normal: a pass reporting missing packages is retried until it converges" {
fake_emacs 1 0
run bash "$SCRIPT"
[ "$status" -eq 0 ]
[ "$(attempts)" -eq 2 ]
[[ "$output" == *"2 missing: foo bar"* ]]
}
@test "error: packages that never install exhaust the passes and fail" {
fake_emacs 1
run bash "$SCRIPT"
[ "$status" -eq 1 ]
[ "$(attempts)" -eq 3 ]
[[ "$output" == *"FAILED"* ]]
}
@test "error: exit 1 without a missing-packages line is not blamed on packages" {
# The fake exits 1 silently, which is any other failure, not a short install.
{
echo '#!/usr/bin/env bash'
echo "n=\$(cat '$COUNTER'); echo \$((n + 1)) >'$COUNTER'"
echo 'exit 1'
} >"$BIN/emacs"
chmod +x "$BIN/emacs"
export EMACS="$BIN/emacs"
run bash "$SCRIPT"
[ "$status" -eq 1 ]
[ "$(attempts)" -eq 1 ]
[[ "$output" == *"without reporting missing packages"* ]]
}
@test "error: a broken init breaks out instead of burning every pass" {
fake_emacs 255
run bash "$SCRIPT"
[ "$status" -eq 255 ]
[ "$(attempts)" -eq 1 ]
[[ "$output" == *"failed to load init"* ]]
}
@test "boundary: a timed-out pass is reported and still retried" {
fake_emacs 124 0
run bash "$SCRIPT"
[ "$status" -eq 0 ]
[ "$(attempts)" -eq 2 ]
[[ "$output" == *"timeout"* ]]
}
@test "boundary: the pass ceiling is honoured" {
export BOOTSTRAP_PASSES=1
fake_emacs 1
run bash "$SCRIPT"
[ "$status" -eq 1 ]
[ "$(attempts)" -eq 1 ]
}
@test "error: a byte-compiled tree is refused rather than passed vacuously" {
touch "$BOOTSTRAP_DIR/modules/foo.elc"
fake_emacs 0
run bash "$SCRIPT"
[ "$status" -eq 2 ]
[ "$(attempts)" -eq 0 ]
[[ "$output" == *"REFUSING"* ]]
[[ "$output" == *"clean-compiled"* ]]
[[ "$output" != *"every package is installed"* ]]
}
@test "boundary: a zero pass ceiling fails cleanly without a tail error" {
export BOOTSTRAP_PASSES=0
fake_emacs 0
run bash "$SCRIPT"
[ "$status" -ne 0 ]
[ "$(attempts)" -eq 0 ]
[[ "$output" != *"cannot open"* ]]
[[ "$output" == *"FAILED after 0 pass"* ]]
}
@test "boundary: recovery on the final allowed pass still succeeds" {
export BOOTSTRAP_PASSES=3
fake_emacs 1 1 0
run bash "$SCRIPT"
[ "$status" -eq 0 ]
[ "$(attempts)" -eq 3 ]
}
|