test: slim uniesc carrier to .wwi roundtrip, value rows now @test-only (#4)

fold-6 carrier-split (drew's ruling): the 6 uniesc value rows (rune/string
escape decode) are already covered 1:1 by test/lang/uniesc_test.ww @test rows
-- same escape forms, same expected codepoints/bytes, same lexer escape-decode
path, and dual-stage via test-lang-byteid (frontend-swap .s byte-id proves
wwstage decode transitively, strictly more sensitive than re-running). So drop
the duplicate value rows from the C driver; 110_uniesc_run.c slims to just the
.wwi roundtrip -- a 2-package sep-build observer that can't be an in-language
@test and isn't a reject case (its eventual runww home tracked as #19). The
carrier still runs both stages for the roundtrip; no coverage lost, test count
unchanged (404).
This commit is contained in:
2026-06-24 00:39:20 +09:00
parent 11afd82e16
commit 24b7aaa33b

View File

@@ -1,20 +1,19 @@
/*
* 110_uniesc_run — \u / \U Unicode escapes, end-to-end through both
* the cstage `ww` and the wwstage `ww_ww` drivers (task #50).
* 110_uniesc_run — .wwi round-trip carrier for \u / \U Unicode escapes.
*
* Rune literals carry the raw codepoint; string literals UTF-8-encode
* it into 1-4 bytes (ref/hare/hare/lex/lex.ha:347 lex_unicode + the
* appendrune in lex_string). \x shares the same codepoint path, so a
* >0x7F \x byte now widens to its 2-byte UTF-8 form in strings. Each
* fixture returns 42 on a correct decode/encode.
* The value-row half (rune/string \u \U \x decode asserts) migrated to the
* in-language row-table test/lang/uniesc_test.ww (fold-6, task #4); this
* file retains ONLY the .wwi round-trip case, which is a two-package
* sep-build observer with no in-language @test home (it asserts the
* PRODUCER re-serializes a wide-rune `def` byte-exact, observed across a
* package boundary — not expressible as a single-compile @test).
*
* The dual-driver loop mirrors 640_int_cast_signed: the wwstage arm is
* skipped when ww_ww is absent (e.g. a cstage-only build).
*
* The final per-driver case is a .wwi round-trip: an exported wide-rune
* `def` re-serialized by the producer must re-parse byte-exact (the
* write-twin of the lexer read-fix — cmd/w6c/wwi.c wwi_rune /
* selfhost/cmd/wcc/wwi.ww wwirune emit \u/\U above 0xFF).
* An exported wide-rune `def` re-serialized by the producer must re-parse
* into the same codepoint (the write-twin of the lexer read-fix —
* cmd/w6c/wwi.c wwi_rune / selfhost/cmd/wcc/wwi.ww wwirune emit \u/\U above
* 0xFF). Runs through both the cstage `ww` and wwstage `ww_ww` drivers
* (task #50); the wwstage arm is skipped when ww_ww is absent (a
* cstage-only build), mirroring 640_int_cast_signed.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -31,109 +30,6 @@ runwait(const char *cmd)
return -1;
}
struct row { const char *label; const char *src; int want; };
static const struct row rows[] = {
/* \u (4 hex) rune → U+00E9 codepoint 233. */
{ "rune_u_2byte",
"fn main() i32 = {\n"
" let r: rune = '\\u00e9';\n"
" if ((r: u32) == 233u32) { return 42; };\n"
" return 0;\n"
"};\n",
42 },
/* \U (8 hex) rune → U+1F600 codepoint 128512 (> 0xFFFF, the case
* that forced the `0x...: rune` int-cast spelling before #50). */
{ "rune_U_emoji",
"fn main() i32 = {\n"
" let r: rune = '\\U0001F600';\n"
" if ((r: u32) == 128512u32) { return 42; };\n"
" return 0;\n"
"};\n",
42 },
/* \u é string → 2-byte UTF-8 0xC3 0xA9. */
{ "str_u_2byte",
"package main;\n"
"import strings;\n"
"fn main() i32 = {\n"
" let b: []u8 = strings.toutf8(\"\\u00e9\");\n"
" if (len(b) != 2) { return 1; };\n"
" if (b[0] != 0xc3u8) { return 2; };\n"
" if (b[1] != 0xa9u8) { return 3; };\n"
" return 42;\n"
"};\n",
42 },
/* \u € string → 3-byte UTF-8 0xE2 0x82 0xAC. */
{ "str_u_3byte",
"package main;\n"
"import strings;\n"
"fn main() i32 = {\n"
" let b: []u8 = strings.toutf8(\"\\u20ac\");\n"
" if (len(b) != 3) { return 1; };\n"
" if (b[0] != 0xe2u8) { return 2; };\n"
" if (b[1] != 0x82u8) { return 3; };\n"
" if (b[2] != 0xacu8) { return 4; };\n"
" return 42;\n"
"};\n",
42 },
/* \U 😀 string → 4-byte UTF-8 0xF0 0x9F 0x98 0x80. */
{ "str_U_4byte",
"package main;\n"
"import strings;\n"
"fn main() i32 = {\n"
" let b: []u8 = strings.toutf8(\"\\U0001F600\");\n"
" if (len(b) != 4) { return 1; };\n"
" if (b[0] != 0xf0u8) { return 2; };\n"
" if (b[1] != 0x9fu8) { return 3; };\n"
" if (b[2] != 0x98u8) { return 4; };\n"
" if (b[3] != 0x80u8) { return 5; };\n"
" return 42;\n"
"};\n",
42 },
/* \x ≥0x80 now yields a codepoint that UTF-8-encodes (\xe9 →
* U+00E9 → 0xC3 0xA9), matching Hare's shared escape path. */
{ "str_x_widens",
"package main;\n"
"import strings;\n"
"fn main() i32 = {\n"
" let b: []u8 = strings.toutf8(\"\\xe9\");\n"
" if (len(b) != 2) { return 1; };\n"
" if (b[0] != 0xc3u8) { return 2; };\n"
" if (b[1] != 0xa9u8) { return 3; };\n"
" return 42;\n"
"};\n",
42 },
};
static int
run_driver(const char *driver, const struct row *r, int i)
{
char src[128], tmpdir[64], outbin[128], rmcmd[160], cmd[1024];
snprintf(tmpdir, sizeof tmpdir, "/tmp/wwue_%d_d_%d", getpid(), i);
mkdir(tmpdir, 0755);
snprintf(src, sizeof src, "%s/wwue_%d_%d.ww", tmpdir, getpid(), i);
snprintf(outbin, sizeof outbin, "%s/wwue_%d_%d", tmpdir, getpid(), i);
snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", tmpdir);
FILE *f = fopen(src, "wb");
if (!f) { runwait(rmcmd); return -1; }
fputs(r->src, f);
fclose(f);
snprintf(cmd, sizeof cmd, "%s build -o %s %s", driver, outbin, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: build via %s failed\n",
r->label, driver);
runwait(rmcmd);
return -1;
}
int got = runwait(outbin);
runwait(rmcmd);
return got;
}
/* run_roundtrip — sep-build a two-package program where the imported
* package exports wide-rune defs; the producer must serialize them as
* \u/\U so the importer re-parses the same codepoint. Returns the built
@@ -219,7 +115,6 @@ main(void)
{ NULL, NULL, 0 },
};
int n = (int)(sizeof rows / sizeof rows[0]);
int total = 0, fail = 0;
for (int d = 0; drivers[d].name; d++) {
if (drivers[d].gated_on_existence
@@ -228,17 +123,6 @@ main(void)
drivers[d].name, drivers[d].path);
continue;
}
for (int i = 0; i < n; i++) {
int got = run_driver(drivers[d].path, &rows[i], i);
total++;
if (got != rows[i].want) {
fprintf(stderr,
"uniesc_run[%s][%s]: exit=%d want=%d\n",
drivers[d].name, rows[i].label,
got, rows[i].want);
fail++;
}
}
int rt = run_roundtrip(drivers[d].path, d);
total++;
if (rt != 42) {