/* Oracle test for the util.inspect runtime engine (scr_inspect.c). * Reads case lines ("\t\t\n" — see * gen-inspect-cases.mjs) from argv[1] and asserts byte equality against * what Node's util.inspect produced: numbers, the string quoting ladder, * the layout engine (driven through scr_insp_dyn over parsed JSON — * frames, break length, grid grouping, depth placeholders), and Buffer's * hex form. Exit 0 = all pass; prints each mismatch (capped) otherwise. */ #include "../src/scr_runtime.h" #include #include #include #define MAX_FIELD (1 << 16) static int hex_val(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static size_t hex_decode(const char *hex, char *out) { if (strcmp(hex, "-") == 0) return 0; size_t n = strlen(hex); if (n % 2 != 0 || n / 2 > MAX_FIELD) return (size_t)-1; for (size_t i = 0; i < n; i += 2) { int hi = hex_val(hex[i]), lo = hex_val(hex[i + 1]); if (hi < 0 || lo < 0) return (size_t)-1; out[i / 2] = (char)((hi << 4) | lo); } return n / 2; } static long total = 0, failed = 0; static void check(const char *op, const char *arg, size_t arg_len, ScrStr *got, const char *expected, size_t expected_len) { total++; if (got->len == expected_len && memcmp(got->data, expected, expected_len) == 0) return; failed++; if (failed <= 25) { fprintf(stderr, "MISMATCH %s(%.*s)\n expected=%.*s\n got=%.*s\n", op, (int)(arg_len > 200 ? 200 : arg_len), arg, (int)expected_len, expected, (int)got->len, got->data); } } int main(int argc, char **argv) { if (argc < 2) { fputs("usage: test_inspect \n", stderr); return 2; } FILE *f = fopen(argv[1], "r"); if (!f) { perror("fopen"); return 2; } static char line[MAX_FIELD * 4 + 64]; static char argbuf[MAX_FIELD]; static char expbuf[MAX_FIELD]; while (fgets(line, sizeof line, f)) { size_t linelen = strlen(line); while (linelen > 0 && (line[linelen - 1] == '\n' || line[linelen - 1] == '\r')) { line[--linelen] = 0; } if (linelen == 0) continue; char *fields[3]; int nfields = 0; char *cursor = line; while (nfields < 3) { fields[nfields++] = cursor; char *tab = strchr(cursor, '\t'); if (!tab) break; *tab = 0; cursor = tab + 1; } if (nfields != 3) { fprintf(stderr, "bad line: %s\n", line); return 2; } const char *op = fields[0]; size_t arg_len = hex_decode(fields[1], argbuf); size_t exp_len = hex_decode(fields[2], expbuf); if (arg_len == (size_t)-1 || exp_len == (size_t)-1) { fprintf(stderr, "bad hex: %s\n", line); return 2; } ScrStr *result = NULL; if (strcmp(op, "f64") == 0) { argbuf[arg_len] = 0; result = scr_insp_f64(strtod(argbuf, NULL)); } else if (strcmp(op, "str") == 0) { ScrStr *s = scr_str_new(argbuf, arg_len); result = scr_insp_str(s); scr_str_release(s); } else if (strcmp(op, "json") == 0) { ScrStr *text = scr_str_new(argbuf, arg_len); ScrDyn *d = scr_json_parse(text); scr_str_release(text); if (!d) { fprintf(stderr, "json parse failed: %.*s\n", (int)arg_len, argbuf); return 2; } result = scr_insp_dyn(d, 0, 2); scr_dyn_release(d); } else if (strcmp(op, "buffer") == 0) { ScrBytes *b = scr_bytes_new(SCR_BYTES_U8, (double)arg_len); memcpy(b->data, argbuf, arg_len); result = scr_insp_buffer(b); scr_bytes_release(b); } else { fprintf(stderr, "unknown op: %s\n", op); return 2; } check(op, argbuf, arg_len, result, expbuf, exp_len); scr_str_release(result); } fclose(f); fprintf(stderr, "%ld/%ld cases passed\n", total - failed, total); return failed ? 1 : 0; }