--------------------------------------------------------------------------- Property: token-boundary helpers are deterministic and never panic --------------------------------------------------------------------------- reqproof:proptest findTokenStart, nextToken, lastToken, tokenStart, tokenEnd Ver
(t *testing.T)
| 523 | // reqproof:proptest findTokenStart, nextToken, lastToken, tokenStart, tokenEnd |
| 524 | // Verifies: SYS-REQ-035 [property] |
| 525 | func TestPropertyTokenHelpersNoCrash(t *testing.T) { |
| 526 | r := newRNG(jsonSeed + 9) |
| 527 | const iterations = 3000 |
| 528 | cases := make([][]byte, 0, iterations) |
| 529 | for i := 0; i < iterations; i++ { |
| 530 | cases = append(cases, randomBytes(r, 64)) |
| 531 | } |
| 532 | // Add curated edge cases. |
| 533 | cases = append(cases, |
| 534 | nil, []byte{}, []byte(" "), []byte(" \t\n "), |
| 535 | []byte("a"), []byte("\""), []byte("{}"), []byte("[]"), |
| 536 | bytes.Repeat([]byte{0x80}, 128), |
| 537 | bytes.Repeat([]byte(" "), 256), |
| 538 | ) |
| 539 | for i, raw := range cases { |
| 540 | // findTokenStart over all byte values. |
| 541 | for tok := 0; tok < 256; tok++ { |
| 542 | if !recoverNoPanic(func() { _ = findTokenStart(raw, byte(tok)) }) { |
| 543 | t.Fatalf("findTokenStart panicked on case %d tok=%d input=%q", i, tok, raw) |
| 544 | } |
| 545 | } |
| 546 | // nextToken / lastToken / tokenStart / tokenEnd: determinism. |
| 547 | nA := nextToken(raw) |
| 548 | nB := nextToken(raw) |
| 549 | if nA != nB { |
| 550 | t.Fatalf("nextToken non-deterministic on %q: %d vs %d", raw, nA, nB) |
| 551 | } |
| 552 | lA := lastToken(raw) |
| 553 | lB := lastToken(raw) |
| 554 | if lA != lB { |
| 555 | t.Fatalf("lastToken non-deterministic on %q: %d vs %d", raw, lA, lB) |
| 556 | } |
| 557 | if !recoverNoPanic(func() { _ = tokenStart(raw) }) { |
| 558 | t.Fatalf("tokenStart panicked on %q", raw) |
| 559 | } |
| 560 | tsA := tokenStart(raw) |
| 561 | tsB := tokenStart(raw) |
| 562 | if tsA != tsB { |
| 563 | t.Fatalf("tokenStart non-deterministic on %q: %d vs %d", raw, tsA, tsB) |
| 564 | } |
| 565 | teA := tokenEnd(raw) |
| 566 | teB := tokenEnd(raw) |
| 567 | if teA != teB { |
| 568 | t.Fatalf("tokenEnd non-deterministic on %q: %d vs %d", raw, teA, teB) |
| 569 | } |
| 570 | // Bounds: when the helper returns a valid index it must be in [0,len]. |
| 571 | // (tokenEnd/lastToken may legitimately return len(data) to signal |
| 572 | // "scanned past the end"; allow that as a sentinel value.) |
| 573 | if nA != -1 && (nA < 0 || nA > len(raw)) { |
| 574 | t.Fatalf("nextToken out-of-range %d on %q (len=%d)", nA, raw, len(raw)) |
| 575 | } |
| 576 | if lA != -1 && (lA < 0 || lA > len(raw)) { |
| 577 | t.Fatalf("lastToken out-of-range %d on %q (len=%d)", lA, raw, len(raw)) |
| 578 | } |
| 579 | if tsA != -1 && (tsA < 0 || tsA > len(raw)) { |
| 580 | t.Fatalf("tokenStart out-of-range %d on %q (len=%d)", tsA, raw, len(raw)) |
| 581 | } |
| 582 | if teA != -1 && (teA < 0 || teA > len(raw)) { |
nothing calls this directly
no test coverage detected