@@ -226,21 +226,38 @@ fail_with_link() {
226226 FAIL=$(( FAIL + 1 ))
227227}
228228
229+ dump_debug () {
230+ local trace=" $1 "
231+ local response=" $2 "
232+ if [ -n " $trace " ] && [ -s " $trace " ]; then
233+ echo " ─── wire trace ───"
234+ sed ' s/^/ /' " $trace "
235+ fi
236+ if [ -n " $response " ]; then
237+ echo " ─── response ───"
238+ printf ' %s\n' " $response " | sed ' s/^/ /'
239+ fi
240+ [ -n " $trace " ] && rm -f " $trace "
241+ }
242+
229243check () {
230244 local label=" $1 "
231245 local expected_body=" $2 "
232246 local docs_url=" $3 "
233247 shift 3
234- local response
235- response=$( curl -s --max-time 30 -D- " $@ " || true)
248+ local response trace
249+ trace=$( mktemp)
250+ response=$( curl -s --max-time 30 -D- --trace-ascii " $trace " " $@ " || true)
236251 local body
237252 body=$( echo " $response " | tail -1)
238253
239254 if [ " $body " = " $expected_body " ]; then
240255 echo " PASS [$label ]"
241256 PASS=$(( PASS + 1 ))
257+ rm -f " $trace "
242258 else
243259 fail_with_link " [$label ]: expected body '$expected_body ', got '$body '" " $docs_url "
260+ dump_debug " $trace " " $response "
244261 fi
245262}
246263
@@ -249,14 +266,22 @@ check_status() {
249266 local expected_status=" $2 "
250267 local docs_url=" $3 "
251268 shift 3
252- local http_code
253- http_code=$( curl -s --max-time 30 -o /dev/null -w ' %{http_code}' " $@ " || true)
269+ local http_code trace body_file
270+ trace=$( mktemp)
271+ body_file=$( mktemp)
272+ http_code=$( curl -s --max-time 30 -o " $body_file " -D " $body_file .hdr" -w ' %{http_code}' --trace-ascii " $trace " " $@ " || true)
254273
255274 if [ " $http_code " = " $expected_status " ]; then
256275 echo " PASS [$label ] (HTTP $http_code )"
257276 PASS=$(( PASS + 1 ))
277+ rm -f " $trace " " $body_file " " $body_file .hdr"
258278 else
259279 fail_with_link " [$label ]: expected HTTP $expected_status , got HTTP $http_code " " $docs_url "
280+ local response=" "
281+ [ -s " $body_file .hdr" ] && response=$( cat " $body_file .hdr" )
282+ [ -s " $body_file " ] && response=" ${response} $( cat " $body_file " ) "
283+ dump_debug " $trace " " $response "
284+ rm -f " $body_file " " $body_file .hdr"
260285 fi
261286}
262287
@@ -272,15 +297,20 @@ check_fragmented() {
272297 local expected_body=" $2 "
273298 local docs_url=" $3 "
274299 shift 3
275- local body
276- body=$( PORT=" $PORT " python3 -c '
300+ local body trace
301+ trace=$( mktemp)
302+ body=$( PORT=" $PORT " TRACE=" $trace " python3 -c '
277303import os, socket, sys, time
278304port = int(os.environ["PORT"])
305+ trace_path = os.environ.get("TRACE", "")
279306frags = sys.argv[1:]
280307s = socket.create_connection(("localhost", port), timeout=5)
281308s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # no Nagle coalescing
309+ sent = b""
282310for i, f in enumerate(frags):
283- s.sendall(f.encode("latin-1"))
311+ data = f.encode("latin-1")
312+ s.sendall(data)
313+ sent += data
284314 if i < len(frags) - 1:
285315 time.sleep(0.03)
286316buf = b""
@@ -289,6 +319,13 @@ while True:
289319 if not chunk: break
290320 buf += chunk
291321s.close()
322+ if trace_path:
323+ with open(trace_path, "w") as tf:
324+ tf.write("=> Send (" + str(len(sent)) + " bytes across " + str(len(frags)) + " fragment(s))\n")
325+ tf.write(sent.decode("latin-1", errors="replace"))
326+ tf.write("\n<= Recv (" + str(len(buf)) + " bytes)\n")
327+ tf.write(buf.decode("latin-1", errors="replace"))
328+ tf.write("\n")
292329resp = buf.decode("latin-1", errors="replace")
293330try:
294331 head, raw = resp.split("\r\n\r\n", 1)
@@ -333,8 +370,10 @@ sys.stdout.write(body.strip())
333370 if [ " $body " = " $expected_body " ]; then
334371 echo " PASS [$label ]"
335372 PASS=$(( PASS + 1 ))
373+ rm -f " $trace "
336374 else
337375 fail_with_link " [$label ]: expected body '$expected_body ', got '$body '" " $docs_url "
376+ dump_debug " $trace " " "
338377 fi
339378}
340379
@@ -344,8 +383,9 @@ check_header() {
344383 local expected_value=" $3 "
345384 local docs_url=" $4 "
346385 shift 4
347- local headers
348- headers=$( curl -s --max-time 30 -D- -o /dev/null " $@ " || true)
386+ local headers trace
387+ trace=$( mktemp)
388+ headers=$( curl -s --max-time 30 -D- -o /dev/null --trace-ascii " $trace " " $@ " || true)
349389 local value
350390 value=$( echo " $headers " | grep -i " ^${header_name} :" | sed ' s/^[^:]*: *//' | tr -d ' \r' || true)
351391
@@ -356,8 +396,10 @@ check_header() {
356396 if [ " $value " = " $expected_value " ] || [[ " $value " == " $expected_value ;" * ]] || [ " $norm_value " = " $norm_expected " ] || [[ " $norm_value " == " $norm_expected ;" * ]]; then
357397 echo " PASS [$label ] ($header_name : $value )"
358398 PASS=$(( PASS + 1 ))
399+ rm -f " $trace "
359400 else
360401 fail_with_link " [$label ]: expected $header_name '$expected_value ', got '$value '" " $docs_url "
402+ dump_debug " $trace " " $headers "
361403 fi
362404}
363405
0 commit comments