mirror of
https://github.com/xroche/httrack.git
synced 2026-07-28 19:43:02 +03:00
Under `set -e` a failing command in an EXIT trap becomes the script's exit status, so a hiccup while tearing down fixtures fails a test whose assertions all passed. That is what turned `57_local-proxy-connect.test` red on the Windows x64 leg of #765: five OK lines, no FAIL, exit 1. Every EXIT trap in the suite now runs teardown with errexit off, and the signal traps keep their own `trap` line, since sharing `set +e` with HUP/INT/QUIT/PIPE/TERM would leave errexit off for the rest of a signalled run and let a torn-down test still report success. A `|| true` on the `rm` would have been smaller, but it throws away the only diagnostic, and the evidence does not say which teardown command failed: a blocked `rm -rf` on the Windows runner exits 1 and prints "Device or resource busy", while the log shows exit 1 and nothing at all. The sharing violation in the issue is the plausible mechanism rather than a confirmed one, so whatever it really is now prints its own error. `99_teardown-status.test` pins the semantics both ways and scans the suite so a new test cannot reintroduce the shape, the leaky combined trap included. The `return 0` that three `cleanup()` bodies ended with never protected anything, since errexit fires at the failing command before it is reached. Closes #773 Signed-off-by: Xavier Roche <roche@httrack.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
127 lines
4.7 KiB
Bash
127 lines
4.7 KiB
Bash
#!/bin/bash
|
|
#
|
|
|
|
# doit.log reprise (no network). Re-running httrack in a mirror directory with
|
|
# NO url makes the engine read hts-cache/doit.log and re-insert every recorded
|
|
# argument into the command line through htscoremain.c's cmdl_ins macro (the
|
|
# x_argvblk builder). That path is distinct from the rc-file one in
|
|
# 01_engine-rcfile.test (htsalias.c) and from the url-on-command-line update in
|
|
# 02_update-cache.test, and nothing else exercises it. Two properties:
|
|
# 1. A multi-token reprise re-mirrors cleanly: every token (the url and each
|
|
# option) survives the back-to-back packing, so the no-url run reproduces
|
|
# the file set with no errors. A packing/bound bug corrupts a later token
|
|
# and surfaces as an error or a missing file.
|
|
# 2. The reprise actually re-crawls through the inserted url: changing a source
|
|
# file and re-running with no url picks up the new content.
|
|
|
|
set -euo pipefail
|
|
|
|
# Resolve httrack to an absolute path before we cd: PATH may hold a
|
|
# build-relative entry that would not resolve from the temp directory.
|
|
bin=$(command -v httrack) || {
|
|
echo "FAIL: httrack not found on PATH"
|
|
exit 1
|
|
}
|
|
case "$bin" in
|
|
/*) ;;
|
|
*) bin="$(cd "$(dirname "$bin")" && pwd)/$(basename "$bin")" ;;
|
|
esac
|
|
|
|
tmp=$(mktemp -d "${TMPDIR:-/tmp}/httrack_doitlog.XXXXXX") || exit 1
|
|
trap 'set +e; rm -rf "$tmp"' EXIT
|
|
trap 'rm -rf "$tmp"' HUP INT QUIT PIPE TERM
|
|
|
|
site="$tmp/site"
|
|
out="$tmp/out"
|
|
mkdir -p "$site/sub"
|
|
printf '<a href="a.html">a</a> <a href="sub/b.html">b</a>' >"$site/index.html"
|
|
echo 'OLDCONTENT' >"$site/a.html"
|
|
echo '<p>bbb</p>' >"$site/sub/b.html"
|
|
url="file://$site/index.html"
|
|
|
|
# count Error: lines in the log (grep -c exits 1 on zero matches: guard it)
|
|
errors() { grep -ciE '^[0-9:]*[[:space:]]Error:' "$out/hts-log.txt" || true; }
|
|
|
|
# initial mirror with the url and a handful of options, so doit.log records a
|
|
# multi-token command line for cmdl_ins to re-insert one token at a time.
|
|
rc=0
|
|
"$bin" "$url" -O "$out" --quiet -n -%v0 -r3 >/dev/null 2>&1 || rc=$?
|
|
test "$rc" -eq 0 || {
|
|
echo "FAIL: initial mirror exited $rc"
|
|
exit 1
|
|
}
|
|
test -f "$out/hts-cache/doit.log" || {
|
|
echo "FAIL: doit.log not written by the initial mirror"
|
|
exit 1
|
|
}
|
|
|
|
# --- 1. no-url reprise re-mirrors cleanly -----------------------------------
|
|
# No url on the command line, so the engine loads doit.log and re-inserts the
|
|
# recorded arguments (cmdl_ins). -O selects the mirror; argv carries no url.
|
|
rc=0
|
|
"$bin" -O "$out" --quiet >/dev/null 2>&1 || rc=$?
|
|
test "$rc" -eq 0 || {
|
|
echo "FAIL: doit.log reprise exited $rc"
|
|
exit 1
|
|
}
|
|
test "$(errors)" = 0 || {
|
|
echo "FAIL: doit.log reprise reported errors (a token may have been corrupted)"
|
|
grep -iE 'Error:' "$out/hts-log.txt" | head -3
|
|
exit 1
|
|
}
|
|
for suffix in a.html sub/b.html; do
|
|
test -n "$(find "$out" -path "*/$suffix" -print -quit)" || {
|
|
echo "FAIL: $suffix missing after the no-url reprise"
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
# --- 2. the reprise re-crawls through the inserted url -----------------------
|
|
sleep 1
|
|
echo 'NEWCONTENT' >"$site/a.html"
|
|
rc=0
|
|
"$bin" -O "$out" --quiet >/dev/null 2>&1 || rc=$?
|
|
test "$rc" -eq 0 || {
|
|
echo "FAIL: second reprise exited $rc"
|
|
exit 1
|
|
}
|
|
grep -q NEWCONTENT "$(find "$out" -path '*/a.html' -print -quit)" || {
|
|
echo "FAIL: reprise did not pick up the changed source (inserted url not re-crawled)"
|
|
exit 1
|
|
}
|
|
|
|
# --- 3. an empty quoted arg survives the doit.log round-trip (#106) ----------
|
|
# -%F "" (empty footer) records an empty "" token in doit.log; -r2 follows it so
|
|
# a "drop the empty token" bug shifts -r2 into -%F's slot (the reprise then sees
|
|
# -%F -r2 and panics "%F needs to be followed by ..."), making the bug visible
|
|
# rather than a harmless run off the end of argv.
|
|
out2="$tmp/out2"
|
|
rc=0
|
|
"$bin" "$url" -O "$out2" --quiet -n -%v0 -%F "" -r2 >/dev/null 2>&1 || rc=$?
|
|
test "$rc" -eq 0 || {
|
|
echo "FAIL: initial mirror with empty footer exited $rc"
|
|
exit 1
|
|
}
|
|
# precondition: the writer put the empty token on disk for the reader to reload.
|
|
grep -q ' -%F "" -r2' "$out2/hts-cache/doit.log" || {
|
|
echo "FAIL: empty footer not recorded as -%F \"\" -r2 in doit.log"
|
|
grep -- '-%F' "$out2/hts-cache/doit.log" || true
|
|
exit 1
|
|
}
|
|
# no-url reprise: the reader rebuilds argv from doit.log and rewrites doit.log
|
|
# from it. The empty token surviving in the regenerated file proves the reader
|
|
# kept it (a drop/swallow would panic above or rewrite -%F without the "").
|
|
rc=0
|
|
"$bin" -O "$out2" --quiet >/dev/null 2>&1 || rc=$?
|
|
test "$rc" -eq 0 || {
|
|
echo "FAIL: empty-footer reprise exited $rc (empty token dropped from doit.log?)"
|
|
exit 1
|
|
}
|
|
grep -q ' -%F "" -r2' "$out2/hts-cache/doit.log" || {
|
|
echo "FAIL: empty footer did not survive the doit.log reload round-trip"
|
|
grep -- '-%F' "$out2/hts-cache/doit.log" || true
|
|
exit 1
|
|
}
|
|
|
|
exit 0
|