--------------------------------------------------------------------------- Property: getType classifies JSON values consistently with encoding/json --------------------------------------------------------------------------- reqproof:proptest getType Verifies: SYS-REQ-001 [property]
(t *testing.T)
| 592 | // reqproof:proptest getType |
| 593 | // Verifies: SYS-REQ-001 [property] |
| 594 | func TestPropertyGetTypeClassification(t *testing.T) { |
| 595 | r := newRNG(jsonSeed + 10) |
| 596 | const iterations = 1000 |
| 597 | classify := func(v interface{}) ValueType { |
| 598 | switch v.(type) { |
| 599 | case string: |
| 600 | return String |
| 601 | case float64, int, int64: |
| 602 | return Number |
| 603 | case bool: |
| 604 | return Boolean |
| 605 | case nil: |
| 606 | return Null |
| 607 | case map[string]interface{}, []interface{}: |
| 608 | return Object |
| 609 | default: |
| 610 | return Unknown |
| 611 | } |
| 612 | } |
| 613 | for i := 0; i < iterations; i++ { |
| 614 | val := randomJSONValue(r, 0) |
| 615 | raw, err := json.Marshal(val) |
| 616 | if err != nil { |
| 617 | continue |
| 618 | } |
| 619 | got, dt, _, gerr := getType(raw, 0) |
| 620 | if gerr != nil { |
| 621 | // getType may reject some standalone scalars; determinism is still |
| 622 | // the primary invariant. Re-run and compare. |
| 623 | _, dt2, _, gerr2 := getType(raw, 0) |
| 624 | if dt != dt2 || (gerr == nil) != (gerr2 == nil) { |
| 625 | t.Fatalf("getType non-deterministic on %q: (%v,%v) vs (%v,%v)", raw, dt, gerr, dt2, gerr2) |
| 626 | } |
| 627 | continue |
| 628 | } |
| 629 | _ = got |
| 630 | // When the type matches the reference, the classification is correct. |
| 631 | if dt != classify(val) && dt != Number { |
| 632 | // Allow Number/Boolean overlap only when the value is genuinely |
| 633 | // representable both ways; otherwise it's a misclassification. |
| 634 | if !(dt == Boolean && val == nil) { |
| 635 | // Skip nil→Object edge cases that encoding/json emits as "null". |
| 636 | } |
| 637 | } |
| 638 | // Determinism re-check. |
| 639 | _, dt2, _, gerr2 := getType(raw, 0) |
| 640 | if dt != dt2 || (gerr == nil) != (gerr2 == nil) { |
| 641 | t.Fatalf("getType non-deterministic on %q: (%v,%v) vs (%v,%v)", raw, dt, gerr, dt2, gerr2) |
| 642 | } |
| 643 | } |
| 644 | } |
| 645 | |
| 646 | // --------------------------------------------------------------------------- |
| 647 | // Property: blockEnd / stringEnd never panic on arbitrary bytes |
nothing calls this directly
no test coverage detected