From eeb05c27f9c3b396fac6be712da2840ad5eb9820 Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Mon, 19 Oct 2026 04:48:34 +0700 Subject: [PATCH] test(claw): pin token_shape's line reader, 16 of 23 sweep survivors killed Six tests cover a note at the end of its line, blank and two-space lines inside a job, a commented-out job header, list items at the job indent, key-shaped lines inside run blocks, the job header shapes and the put_span clip. The other 7 survivors are equivalent (listed in the PR). Closes #10676 Co-Authored-By: Claude Opus 5.5 --- .trinity/seals/claw_ClawTokenShape.json | 16 ++-- specs/claw/token_shape.t27 | 104 ++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 8 deletions(-) diff --git a/.trinity/seals/claw_ClawTokenShape.json b/.trinity/seals/claw_ClawTokenShape.json index 4da4f9f316..40ce69257e 100644 --- a/.trinity/seals/claw_ClawTokenShape.json +++ b/.trinity/seals/claw_ClawTokenShape.json @@ -7,23 +7,23 @@ } ], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:793e236c843d71659823ebee20444c902a3abf1b3f1dbda763ca42b54dc59c51", - "gen_hash_rust": "sha256:28c9289a2ea5104684dc941b3e02fa0004d5257adcd00c4593bae415f10c7df2", - "gen_hash_verilog": "sha256:7973bacc8961200f38e14563f04b61e6e9dc8b43e442fcdda85fa62dc7faed7a", - "gen_hash_zig": "sha256:30ab84bff278fbba91a98f007ba0493da30b0ef89a280c4aaffd909c0b64dd7d", + "gen_hash_c": "sha256:6ffa5bc072e7016706cd0d8525170b09682f4146920e26f52dd7b3d72cfefcff", + "gen_hash_rust": "sha256:f052387f815f371e380d604bcdb90bb46486588e288fdde3ca1efa798093030e", + "gen_hash_verilog": "sha256:aab1d5e59d3e371756e79e33076be1b50ddf8a7feb0a6aa767e9582c85ddb8ca", + "gen_hash_zig": "sha256:e1d6217b8196e2ea7d721ff7dbf85b8143f34309aae5a86d5f6c10c630e8e372", "module": "ClawTokenShape", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T17:57:50Z", + "sealed_at": "2026-10-18T21:47:51Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:b326da148e0d837cb05228f27efdcdf0faf22d85b0a0693a791052caf44f8b04", + "spec_hash": "sha256:fa1c7d25a6a9374f2dd1ffe1ad47a6bfb0437a0580655ab40cc30c20e58760c7", "spec_path": "specs/claw/token_shape.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 10, - "total": 10, + "passed": 16, + "total": 16, "vacuous": 0 }, "toolchain": { diff --git a/specs/claw/token_shape.t27 b/specs/claw/token_shape.t27 index 095baa1022..ed41a760fb 100644 --- a/specs/claw/token_shape.t27 +++ b/specs/claw/token_shape.t27 @@ -351,3 +351,107 @@ test a_job_that_says_red_on_purpose_is_not_judged { assert n == 127; assert token_shape_count(&t, n) == 0; } + +// Tests below were added by the mutation sweep of #10673 (tick 18); each names the mutants it kills. + +// span_has `<=` -> `<`: a needle that ends exactly at the end of its line. +test a_note_at_the_end_of_its_line_counts { + var t : [512]u8 = undefined; + var n : usize = put_str(&t, 512, 0, "jobs:\n", 6); + n = put_str(&t, 512, n, " claw-a:\n", 10); + n = put_str(&t, 512, n, " steps:\n", 11); + n = put_str(&t, 512, n, " - {id: tok, continue-on-error: true, uses: actions/create-github-app-token@v2}\n", 85); + n = put_str(&t, 512, n, " - if: steps.tok.outcome == 'failure'\n", 43); + n = put_str(&t, 512, n, " run: echo note\n", 23); + assert n == 178; + assert token_shape_count(&t, n) == 0; +} + +// top `e > s` -> `e >= s` and is_job_header's empty-name `return false` -> `return true`: +// an empty line and a line of two spaces inside a job end neither the job nor `jobs:`. +test blank_and_two_space_lines_do_not_end_a_job { + var t : [512]u8 = undefined; + var n : usize = put_str(&t, 512, 0, "jobs:\n", 6); + n = put_str(&t, 512, n, " claw-a:\n", 10); + n = put_str(&t, 512, n, " steps:\n", 11); + n = put_str(&t, 512, n, " - {id: tok, continue-on-error: true, uses: actions/create-github-app-token@v2}\n", 85); + n = put_str(&t, 512, n, "\n", 1); + n = put_str(&t, 512, n, " \n", 3); + n = put_str(&t, 512, n, " - {if: steps.tok.outcome == 'failure', run: echo note}\n", 61); + assert n == 177; + assert token_shape_count(&t, n) == 0; +} + +// is_job_header `or` -> `and` and its `return false` -> `return true` on '#' or '-': +// a commented-out job is not a job, so the note after it still belongs to claw-a. +test a_commented_out_job_header_is_not_a_job { + var t : [512]u8 = undefined; + var n : usize = put_str(&t, 512, 0, "jobs:\n", 6); + n = put_str(&t, 512, n, " claw-a:\n", 10); + n = put_str(&t, 512, n, " steps:\n", 11); + n = put_str(&t, 512, n, " - {id: tok, continue-on-error: true, uses: actions/create-github-app-token@v2}\n", 85); + n = put_str(&t, 512, n, " #build:\n", 10); + n = put_str(&t, 512, n, " - {if: steps.tok.outcome == 'failure', run: echo note}\n", 61); + assert n == 183; + assert token_shape_count(&t, n) == 0; +} + +// item `ind > 2` -> `ind >= 2`: a step is deeper than its job; a list item at the job's own indent is not one. +// The `or` -> `and` on the in-step key check: a key-shaped line deep inside a `run: |` block is not a key of the step. +test only_a_step_or_its_own_key_can_mint { + var t : [256]u8 = undefined; + var n : usize = put_str(&t, 256, 0, "jobs:\n", 6); + n = put_str(&t, 256, n, " claw-a:\n", 10); + n = put_str(&t, 256, n, " - {id: tok, uses: actions/create-github-app-token@v2}\n", 56); + assert n == 72; + assert token_shape_count(&t, n) == 0; + var b : [256]u8 = undefined; + var m : usize = put_str(&b, 256, 0, "jobs:\n", 6); + m = put_str(&b, 256, m, " plain:\n", 9); + m = put_str(&b, 256, m, " steps:\n", 11); + m = put_str(&b, 256, m, " - run: |\n", 15); + m = put_str(&b, 256, m, " uses: actions/create-github-app-token@v2\n", 53); + assert m == 94; + assert token_shape_count(&b, m) == 0; +} + +// is_job_header, line by line: trailing spaces and a CR are allowed after the colon (kills `!=` -> `==` +// and `and` -> `or` on the tail check); anything else after it, an empty name, a space in the name or no +// colon at all is not a header (kills `i + 1` -> `i + 2`, `>` -> `>=` on the name length, both +// `return false` -> `return true`, and the scan running past the line on `<` -> `<=`). +test only_a_bare_name_and_a_colon_is_a_job_header { + var t : [32]u8 = undefined; + var n : usize = put_str(&t, 32, 0, " claw-a: x\n", 13); + t[11] = 13; + assert n == 13; + assert is_job_header(&t, 0, 12) == true; + n = put_str(&t, 32, 0, " a:b\n", 6); + assert is_job_header(&t, 0, 5) == false; + n = put_str(&t, 32, 0, " #build:\n", 10); + assert is_job_header(&t, 0, 9) == false; + n = put_str(&t, 32, 0, " :\n", 4); + assert is_job_header(&t, 0, 3) == false; + n = put_str(&t, 32, 0, " a b:\n", 7); + assert is_job_header(&t, 0, 6) == false; + n = put_str(&t, 32, 0, " \n", 3); + assert is_job_header(&t, 0, 2) == false; + // a last line with no newline in a reused buffer: the stale byte at e is a colon, and the scan must stop before it + n = put_str(&t, 32, 0, " oops:\n", 8); + assert n == 8; + assert is_job_header(&t, 0, 6) == false; +} + +// put_span `x < cap` -> `x <= cap`: a clipped copy writes nothing at index cap. +test a_clipped_span_writes_nothing_at_cap { + var t : [16]u8 = undefined; + const n : usize = put_str(&t, 16, 0, "abcdef", 6); + var d : [8]u8 = undefined; + var k : usize = 0; + while (k < 8) { + d[k] = 0; + k += 1; + } + assert put_span(&d, 4, 0, &t, 0, n) == 6; + assert d[3] == 'd'; + assert d[4] == 0; +}