fix(frank-tts): send the registration body through a file, not an argument
The deploy of the newly built engine image came back `0 voice(s) warm` with
`/app/warm-voices.sh: line 152: /usr/bin/curl: Argument list too long` above
every line, and the unit was `active` with a green `/health` beside it. The hook
built `{"name":…,"wav_b64":…}` in a shell variable and passed it as ONE curl
argument; the kernel caps a single argument at MAX_ARG_STRLEN = 131,072 bytes,
and the shipped reference clips base64 to about 1.27 MB, so curl was never
executed and the hook reported the absence as "HTTP no response".
The body now goes to a mktemp file and curl reads `@file`; the audio enters
through a redirection instead of a command substitution, so the script never
holds a 1.3 MB string at all. Every pack in the fleet is ~1 MB, i.e. ~13x the
cliff, so this was always going to happen — it took the first real packs to show
it because no fixture was ever that big.
The regression test therefore ships a 300 KB pack against the seam's REAL stub
listener with the REAL curl: it fails with the same kernel error the host did
(`Argument list too long`, then the 400-for-every-name summary), and passes once
the body is a file. Proved red before the fix, green after.
This commit is contained in:
@@ -394,6 +394,37 @@ assert {s["response_format"] for s in speech} == {"wav"}, speech
|
||||
PY
|
||||
}
|
||||
|
||||
@test "a reference clip too big for one argument still registers" {
|
||||
# The kernel caps a SINGLE command-line string at 32 pages = 131,072 bytes
|
||||
# (MAX_ARG_STRLEN), and a shipped reference clip base64's to about 1.27 MB —
|
||||
# so a warmer that hands the registration body to curl as an argument dies
|
||||
# before curl runs. That is exactly what the first real boot of 2026-10-18
|
||||
# hit with the real packs: `/usr/bin/curl: Argument list too long`, then the
|
||||
# misleading "registration failed (HTTP no response)" for all three voices.
|
||||
# The stub engine is a real listener and curl is the real binary, so this
|
||||
# test fails for the same kernel reason the host did.
|
||||
start_engine_stub
|
||||
local big="$TEST_TMP/bigvoices/bigvoice"
|
||||
mkdir -p "$big"
|
||||
head -c 300000 /dev/zero | tr '\0' 'A' > "$big/reference.wav"
|
||||
|
||||
run env ENGINE_URL="http://127.0.0.1:$STUB_PORT" VOICES_DIR="$TEST_TMP/bigvoices" \
|
||||
bash "$WARM"
|
||||
[ "$status" -eq 0 ] || { echo "$output"; false; }
|
||||
[[ "$output" == *"voice bigvoice cold="*"ms warm="*"ms"* ]] || { echo "$output"; false; }
|
||||
|
||||
# And the audio that arrived is the audio that was on disk, whole.
|
||||
python3 - "$TEST_TMP/journal.jsonl" "$big/reference.wav" <<'PY'
|
||||
import hashlib, json, sys
|
||||
entries = [json.loads(l) for l in open(sys.argv[1])]
|
||||
regs = [e for e in entries if e["path"] == "/v1/audio/voices"]
|
||||
assert len(regs) == 1, entries
|
||||
assert regs[0]["name"] == "bigvoice", regs[0]
|
||||
want = hashlib.sha256(open(sys.argv[2], "rb").read()).hexdigest()
|
||||
assert regs[0]["wav_sha256"] == want, (len(regs[0]["wav_sha256"]), want)
|
||||
PY
|
||||
}
|
||||
|
||||
@test "the warm sentence survives both readers of the env file intact" {
|
||||
# scripts/frank-tts-engine.env is read two ways and they disagree about
|
||||
# quotes. bash (`set -a; source`, what the seams and a human do) strips the
|
||||
|
||||
Reference in New Issue
Block a user