Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions .trinity/seals/claw_ClawSarif.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
{
"built_by": "t27c-bootstrap@0.5.2+4ab200073",
"built_by": "t27c-bootstrap@0.5.2+9448ab4be",
"closure": [
{
"spec": "specs/claw/text.t27",
"spec_hash": "sha256:b65da69dff231c61a6d3a48558af9e17af42e1acbe3f4763348f1f0c2f118f21"
"spec_hash": "sha256:968755ec1917f766eb2cdd0ab4c0c48aef028a0e7d69e191911695e925b286ad"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:f09132016a8a74445e9e2ee835456cc5e7b99790cf78ab34c3c4ef9a4198bc3b",
"gen_hash_rust": "sha256:74aa0e64a79fa33f32fa4dec318f54a6e01cb9fe75cd096ccf2a75246f873ef0",
"gen_hash_verilog": "sha256:af953a3d72c805414462fa9fec8bb4d32da5a549263a9e45e3e6e67ff8686365",
"gen_hash_zig": "sha256:6d88653c9a12ace10d6cf9c67b6a4792244e2c4fded93c89a4d06e8cc39b67d4",
"gen_hash_c": "sha256:f3e63a8026175da4f1087b71baf47925538719544e9afaa94f66a62b3a7ba602",
"gen_hash_rust": "sha256:a56d6add49bc5caeb85b0b8423cc9e58670845923a7ae2a9a77d91915f969fb8",
"gen_hash_verilog": "sha256:9d860df423d532c5efb6af07495dd5e04151e69bcc1c885e3157968de311be58",
"gen_hash_zig": "sha256:18db9ea8b52bd2c4f5f3e880653aba6ccfdbea6639fb5f5bc1d3b9f700cd8252",
"module": "ClawSarif",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T09:41:16Z",
"sealed_at": "2026-10-18T23:37:02Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:22258cfd518c5b27ad46db8bf5c507d97e783bd79073f83ff26b20549c927db8",
"spec_hash": "sha256:f9c08d09fafe8c0e5665c3b5b803949b8c7f63432a66c3f1846f6731a15ffbdc",
"spec_path": "specs/claw/sarif.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 15,
"total": 15,
"passed": 24,
"total": 24,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
125 changes: 125 additions & 0 deletions specs/claw/sarif.t27
Original file line number Diff line number Diff line change
Expand Up @@ -688,3 +688,128 @@ test every_rule_row_is_filled {
assert RULE_TEXT_LENS[i] > 0;
}
}

// The tests below were written against a mutation sweep of this file (#10717): each one kills
// a single-operator mutant the tests above let through.

test a_clipped_document_writes_nothing_at_or_past_cap {
// put_byte's clip is `w < cap`. With `<=` the byte at cap is written. The buffer is longer
// than cap and zeroed, so a stray write past cap shows.
var t : [256]u8 = undefined;
const w : usize = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\t1\tboom\n", 39);
var out : [200]u8 = undefined;
for i in 0..200 { out[i] = 0; }
const n : usize = sarif_render(&t, w, DEFAULT_MAX_RESULTS, &out, 128);
assert n > 128;
assert out[127] != 0;
var stray : u32 = 0;
for i in 128..200 { if (out[i] != 0) { stray += 1; } }
assert stray == 0;
// Which writer lands on byte cap depends on the document's layout, so pin put_byte itself:
// a write at w == cap advances the cursor and stores nothing.
var small : [4]u8 = undefined;
for i in 0..4 { small[i] = 0; }
assert put_byte(&small, 3, 3, 'x') == 4;
assert small[3] == 0;
assert put_byte(&small, 3, 2, 'y') == 3;
assert small[2] == 'y';
}

test the_printable_edges_survive_in_messages_and_paths {
// `~` (126) and `!` (33) are the last and first printable bytes after space: a message keeps
// them, and a path may hold them.
var t : [256]u8 = undefined;
const w : usize = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\t1\ta~b\n", 38);
var out : [4096]u8 = undefined;
const n : usize = sarif_render(&t, w, DEFAULT_MAX_RESULTS, &out, 4096);
assert buf_has(&out, n, "\"text\":\"a~b\"}", 13) == true;
var b : [64]u8 = undefined;
const p : usize = put_str(&b, 64, 0, "specs/a!b~c.t27", 15);
assert path_ok(&b, 0, p) == true;
}

test a_trailing_dot_dot_is_refused_and_a_trailing_dot_is_not {
var b : [64]u8 = undefined;
const p : usize = put_str(&b, 64, 0, "specs/a..", 9);
// `..` as the last two bytes is still `..`.
assert path_ok(&b, 0, p) == false;
// The field ends at the first dot; the dot after it is outside the field and is not read.
assert path_ok(&b, 0, p - 1) == true;
}

test parse_num_bounds_empty_and_nine_digits {
var b : [16]u8 = undefined;
var p : usize = put_str(&b, 16, 0, "123456789", 9);
assert parse_num(&b, 0, p) == 123456789;
assert parse_num(&b, 3, 3) == -1;
p = put_str(&b, 16, 0, "1234567890", 10);
assert parse_num(&b, 0, p) == -1;
}

test a_reversed_field_is_no_severity {
var b : [16]u8 = undefined;
const p : usize = put_str(&b, 16, 0, "error", 5);
assert p == 5;
// e < s is no field at all, never the empty word and never a match.
assert sev_of(&b, 5, 3) == SEV_NONE;
}

test each_field_check_rejects_its_own_line {
// One test per field: a line that fails only that field's check is invalid.
var t : [256]u8 = undefined;
// missing the message field
var w : usize = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\t1", 33);
assert sarif_valid(&t, w) == 0;
assert sarif_invalid(&t, w) == 1;
// unknown rule
w = put_str(&t, 256, 0, "error\tno-such-rule\tspecs/a.t27\t3\t1\tm", 36);
assert sarif_valid(&t, w) == 0;
// path outside the repository
w = put_str(&t, 256, 0, "error\tparse-error\t../a.t27\t3\t1\tm", 32);
assert sarif_valid(&t, w) == 0;
// column not a number
w = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\tx\tm", 35);
assert sarif_valid(&t, w) == 0;
// empty message
w = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\t1\t", 34);
assert sarif_valid(&t, w) == 0;
assert sarif_invalid(&t, w) == 1;
}

test a_line_ends_at_len_not_at_the_next_newline {
// The buffer holds one byte past len. A line reader that looked at text[len] would take it.
var t : [256]u8 = undefined;
const w : usize = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\t1\tboomX", 39);
var out : [4096]u8 = undefined;
const n : usize = sarif_render(&t, w - 1, DEFAULT_MAX_RESULTS, &out, 4096);
assert buf_has(&out, n, "\"text\":\"boom\"}", 14) == true;
assert buf_has(&out, n, "boomX", 5) == false;
}

test the_first_rule_and_the_first_result_have_no_comma_before_them {
var t : [256]u8 = undefined;
const w : usize = put_str(&t, 256, 0, "error\tparse-error\tspecs/a.t27\t3\t1\tboom\n", 39);
var out : [4096]u8 = undefined;
const n : usize = sarif_render(&t, w, DEFAULT_MAX_RESULTS, &out, 4096);
assert buf_has(&out, n, "\"rules\":[{\"id\":\"T27C001\"", 24) == true;
assert buf_has(&out, n, "\"results\":[{\"ruleId\"", 20) == true;
assert buf_has(&out, n, "[,", 2) == false;
}

test balanced_refuses_what_is_not_closed {
// The structural check every render test leans on had only ever been shown balanced input.
var b : [8]u8 = undefined;
var p : usize = put_str(&b, 8, 0, "{}", 2);
assert balanced(&b, p) == true;
// nothing written
assert balanced(&b, 0) == false;
// opened, never closed
p = put_str(&b, 8, 0, "{", 1);
assert balanced(&b, p) == false;
// closed before it was opened
p = put_str(&b, 8, 0, "}{", 2);
assert balanced(&b, p) == false;
// a brace inside a string does not count
p = put_str(&b, 8, 0, "{\"}\"}", 5);
assert balanced(&b, p) == true;
}
Loading