From 913ea749a12db2d1d26ebaa871902986c21dbae6 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Sun, 19 Jul 2026 07:40:37 +1000 Subject: [PATCH] tests: decode console utf-16le stderr in capture_stderr helpers dynamic_bad_tag_warns_once failed (count 0) ONLY in console-attached singleproc runs (user report; reproduced deterministically with stderr on a real console and stdout redirected): when stderr is backed by a windows console channel, a pushed chan transform receives the console driver's utf-16le wide-char byte stream - every ascii char arrives NUL-interleaved, so content regexps never match. The punk::args warning itself emits correctly, exactly once, inside the capture window (proven with marker writes: markers and warning all captured, all wide). Piped/file stderr and -jobs child processes deliver plain bytes, which is why every piped run passed. Fix in all three capture_stderr helpers (punk/args dynamic.test, punk/ansi grepstr.test, punk/ns corp.test - identical latent defect): if the captured data is NUL-interleaved, decode it as utf-16le (fallback 'unicode' for tcl 8.6) before returning. Verified: the console-attached args subtree run is green (246/243/3/0); piped runs unchanged. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- src/tests/modules/punk/ansi/testsuites/ansi/grepstr.test | 9 +++++++++ src/tests/modules/punk/args/testsuites/args/dynamic.test | 9 +++++++++ src/tests/modules/punk/ns/testsuites/ns/corp.test | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/src/tests/modules/punk/ansi/testsuites/ansi/grepstr.test b/src/tests/modules/punk/ansi/testsuites/ansi/grepstr.test index d2593606..d09e3d75 100644 --- a/src/tests/modules/punk/ansi/testsuites/ansi/grepstr.test +++ b/src/tests/modules/punk/ansi/testsuites/ansi/grepstr.test @@ -70,6 +70,15 @@ namespace eval ::testspace { if {$code} { return -options $ropts $r } + if {[string first \x00 $caught] >= 0} { + #stderr backed by a windows console: the pushed transform receives the console + #driver's utf-16le wide-char byte stream rather than encoded bytes (each ascii + #char arrives NUL-interleaved), so content assertions never match - decode. + #(found 2026-07-19 via the sibling helper in punk/args dynamic.test failing in + #console-attached singleproc runs; piped stderr and -jobs children are unaffected) + set enc [expr {"utf-16le" in [encoding names] ? "utf-16le" : "unicode"}] + set caught [encoding convertfrom $enc $caught] + } return $caught } diff --git a/src/tests/modules/punk/args/testsuites/args/dynamic.test b/src/tests/modules/punk/args/testsuites/args/dynamic.test index db073022..940aaa29 100644 --- a/src/tests/modules/punk/args/testsuites/args/dynamic.test +++ b/src/tests/modules/punk/args/testsuites/args/dynamic.test @@ -34,6 +34,15 @@ namespace eval ::testspace { if {$code} { return -options $ropts $r } + if {[string first \x00 $caught] >= 0} { + #stderr backed by a windows console: the pushed transform receives the console + #driver's utf-16le wide-char byte stream rather than encoded bytes (each ascii + #char arrives NUL-interleaved), so content assertions never match - decode. + #(found 2026-07-19: dynamic_bad_tag_warns_once failed ONLY in console-attached + #singleproc runs; piped/file stderr and -jobs child processes deliver plain bytes) + set enc [expr {"utf-16le" in [encoding names] ? "utf-16le" : "unicode"}] + set caught [encoding convertfrom $enc $caught] + } return $caught } diff --git a/src/tests/modules/punk/ns/testsuites/ns/corp.test b/src/tests/modules/punk/ns/testsuites/ns/corp.test index 74681831..4bdd024e 100644 --- a/src/tests/modules/punk/ns/testsuites/ns/corp.test +++ b/src/tests/modules/punk/ns/testsuites/ns/corp.test @@ -198,6 +198,15 @@ namespace eval ::testspace { if {$code} { return -options $ropts $r } + if {[string first \x00 $caught] >= 0} { + #stderr backed by a windows console: the pushed transform receives the console + #driver's utf-16le wide-char byte stream rather than encoded bytes (each ascii + #char arrives NUL-interleaved), so content assertions never match - decode. + #(found 2026-07-19 via the sibling helper in punk/args dynamic.test failing in + #console-attached singleproc runs; piped stderr and -jobs children are unaffected) + set enc [expr {"utf-16le" in [encoding names] ? "utf-16le" : "unicode"}] + set caught [encoding convertfrom $enc $caught] + } return $caught } #sp n - n plain spaces (keeps expected values reviewable)