--------------------------------------------------------------------------- Property: thread-safety — concurrent reads are panic-free and deterministic --------------------------------------------------------------------------- The parser must be safe for concurrent use (no shared mutable state). T
(t *testing.T)
| 939 | // reqproof:proptest Get |
| 940 | // Verifies: SYS-REQ-001 [property] |
| 941 | func TestPropertyConcurrentReadsSafe(t *testing.T) { |
| 942 | r := newRNG(jsonSeed + 16) |
| 943 | // Pre-generate a stable corpus so all goroutines share the same inputs. |
| 944 | const corpus = 200 |
| 945 | inputs := make([][]byte, corpus) |
| 946 | for i := range inputs { |
| 947 | inputs[i] = randomJSONBytes(r, 2) |
| 948 | } |
| 949 | keys := []string{"a", "b", "c", "test", "name"} |
| 950 | |
| 951 | const goroutines = 16 |
| 952 | var wg sync.WaitGroup |
| 953 | wg.Add(goroutines) |
| 954 | errs := make(chan error, goroutines) |
| 955 | for g := 0; g < goroutines; g++ { |
| 956 | go func(seed int64) { |
| 957 | defer wg.Done() |
| 958 | gr := newRNG(seed) |
| 959 | for i := 0; i < 500; i++ { |
| 960 | raw := inputs[gr.Intn(corpus)] |
| 961 | key := keys[gr.Intn(len(keys))] |
| 962 | if !recoverNoPanic(func() { |
| 963 | _, _, _, _ = Get(raw, key) |
| 964 | }) { |
| 965 | errs <- fmt.Errorf("Get panicked under concurrency on %q key=%q", raw, key) |
| 966 | return |
| 967 | } |
| 968 | } |
| 969 | }(jsonSeed + int64(g)) |
| 970 | } |
| 971 | wg.Wait() |
| 972 | close(errs) |
| 973 | for e := range errs { |
| 974 | t.Fatal(e) |
| 975 | } |
| 976 | } |
| 977 | |
| 978 | // closeEnough reports whether two floats agree to within a relative tolerance |
| 979 | // suitable for decimal round-trip comparisons. |
nothing calls this directly
no test coverage detected