Skip to content

Commit 7edf7fd

Browse files
author
Marcos Hernandez
committed
fix(engine-host): runner.c emite hex en lugar de bytes raw (cross-platform)
CI Windows fallaba en los tests de PCX decode con SHA-256 mismatch: expected 0dd56df8... received ac0e66a4... Causa: en Windows, stdout tiene LF→CRLF translation por defecto. Cuando el runner C emitía los bytes raw del buffer decodificado en stdout, cualquier byte 0x0A en el buffer se convertía a 0x0D 0x0A al salir, corrompiendo el SHA-256 del lado JS. Mac/Linux no tienen ese translation, por eso solo Windows fallaba. Fix: el runner emite el buffer como cadena hex (2 chars por byte) en lugar de bytes raw. Cero bytes 0x0A potenciales en el output. Funciona idéntico cross-platform sin necesidad de _setmode(_O_BINARY) ni similares parches específicos de Windows. Coste: ~2x bytes en stdout (cada byte = 2 chars hex). Despreciable para fixtures pequeños (32x16=512 hasta 144*16*16=36864 bytes max). Goldens NO cambian: el SHA-256 se calcula sobre los bytes decodificados (parsed del hex en el lado JS), no sobre el formato del stdout. Así que goldens/engine/pcx/*.sha256.txt siguen siendo válidos. Suite mac local: 257/257 verde. Próximo CI valida Windows.
1 parent f0b4686 commit 7edf7fd

2 files changed

Lines changed: 31 additions & 15 deletions

File tree

tests/engine_host/runner.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,16 @@ static int test_crc32_batch(void) {
4343

4444
/* Imprime el buffer decodificado en stdout en formato:
4545
* <width> <height> <num_bytes>\n
46-
* <bytes raw binario>
47-
* El test JS calcula el SHA-256 sobre los bytes raw para comparar con golden.
46+
* <hex de los N bytes>\n
47+
*
48+
* Por qué hex y no raw binarios: en Windows, stdout tiene LF→CRLF
49+
* translation por defecto, y un byte 0x0A en el buffer se convierte
50+
* a 0x0D 0x0A al salir, corrompiendo el SHA-256. El hex evita ese
51+
* issue completamente y funciona idéntico cross-platform.
52+
*
53+
* Coste: ~2x bytes en stdout (cada byte = 2 chars hex), pero los
54+
* fixtures son pequeños (32x16=512 hasta 144*16=2304 bytes), así
55+
* que es despreciable.
4856
*/
4957
static int test_pcx_decode(int argc, char** argv) {
5058
if (argc < 3) {
@@ -71,9 +79,12 @@ static int test_pcx_decode(int argc, char** argv) {
7179

7280
uint32_t bytes = (uint32_t)w * (uint32_t)h;
7381
fprintf(stdout, "%u %u %u\n", (unsigned)w, (unsigned)h, (unsigned)bytes);
74-
fflush(stdout);
75-
/* Bytes raw del buffer (longitud w*h). El test JS los lee del stdout. */
76-
fwrite(dst, 1, bytes, stdout);
82+
/* Emitir como hex (2 chars por byte). Evita LF→CRLF en Windows. */
83+
{
84+
uint32_t i;
85+
for (i = 0; i < bytes; i++) fprintf(stdout, "%02x", dst[i]);
86+
fputc('\n', stdout);
87+
}
7788
free(dst);
7889
return 0;
7990
}

tests/helpers/engine-host.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,27 @@ export function runnerCrc32Batch(inputs) {
6363

6464
/**
6565
* Ejecuta `runner pcx_decode <pcxFile>` y devuelve la imagen decodificada.
66+
*
67+
* El runner emite "W H N\n<hex de N bytes>\n". El hex es para evitar
68+
* la translation LF→CRLF de stdout en Windows que corrompía bytes 0x0A.
69+
*
6670
* @param {string} pcxFile ruta absoluta al fichero .PCX
6771
* @returns {{ width: number, height: number, pixels: Buffer }}
6872
*/
6973
export function runnerPcxDecode(pcxFile) {
70-
// El runner emite "W H N\n" + N bytes raw del buffer.
71-
const out = execFileSync(RUNNER_PATH, ['pcx_decode', pcxFile], { encoding: null })
72-
// Buscar el primer \n para separar header del payload.
73-
const nlIdx = out.indexOf(0x0A)
74-
if (nlIdx < 0) throw new Error('runner pcx_decode: stdout sin newline')
75-
const header = out.slice(0, nlIdx).toString('ascii')
76-
const [w, h, n] = header.trim().split(/\s+/).map(Number)
77-
const pixels = out.slice(nlIdx + 1, nlIdx + 1 + n)
74+
const out = execFileSync(RUNNER_PATH, ['pcx_decode', pcxFile], { encoding: 'utf8' })
75+
const lines = out.split('\n')
76+
if (lines.length < 2) throw new Error('runner pcx_decode: salida con menos de 2 líneas')
77+
const [w, h, n] = lines[0].trim().split(/\s+/).map(Number)
78+
const hex = lines[1].trim()
79+
if (hex.length !== n * 2) {
80+
throw new Error(`runner pcx_decode: hex length ${hex.length} != 2*N (${2*n})`)
81+
}
82+
const pixels = Buffer.from(hex, 'hex')
7883
if (pixels.length !== n) {
79-
throw new Error(`runner pcx_decode: payload corto (got ${pixels.length}, expected ${n})`)
84+
throw new Error(`runner pcx_decode: pixels decoded ${pixels.length} != ${n}`)
8085
}
81-
return { width: w, height: h, pixels: Buffer.from(pixels) }
86+
return { width: w, height: h, pixels }
8287
}
8388

8489
/**

0 commit comments

Comments
 (0)