--------------------------------------------------------------------------- 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)
| 1060 | // reqproof:proptest parser.Get |
| 1061 | // Verifies: SYS-REQ-001 [property] |
| 1062 | func TestPropertyConcurrentReadsSafe(t *testing.T) { |
| 1063 | r := newRNG(jsonSeed + 16) |
| 1064 | // Pre-generate a stable corpus so all goroutines share the same inputs. |
| 1065 | const corpus = 200 |
| 1066 | inputs := make([][]byte, corpus) |
| 1067 | for i := range inputs { |
| 1068 | inputs[i] = randomJSONBytes(r, 2) |
| 1069 | } |
| 1070 | keys := []string{"a", "b", "c", "test", "name"} |
| 1071 | |
| 1072 | const goroutines = 16 |
| 1073 | var wg sync.WaitGroup |
| 1074 | wg.Add(goroutines) |
| 1075 | errs := make(chan error, goroutines) |
| 1076 | for g := 0; g < goroutines; g++ { |
| 1077 | go func(seed int64) { |
| 1078 | defer wg.Done() |
| 1079 | gr := newRNG(seed) |
| 1080 | for i := 0; i < 500; i++ { |
| 1081 | raw := inputs[gr.Intn(corpus)] |
| 1082 | key := keys[gr.Intn(len(keys))] |
| 1083 | if !recoverNoPanic(func() { |
| 1084 | _, _, _, _ = Get(raw, key) |
| 1085 | }) { |
| 1086 | errs <- fmt.Errorf("Get panicked under concurrency on %q key=%q", raw, key) |
| 1087 | return |
| 1088 | } |
| 1089 | } |
| 1090 | }(jsonSeed + int64(g)) |
| 1091 | } |
| 1092 | wg.Wait() |
| 1093 | close(errs) |
| 1094 | for e := range errs { |
| 1095 | t.Fatal(e) |
| 1096 | } |
| 1097 | } |
| 1098 | |
| 1099 | // closeEnough reports whether two floats agree to within a relative tolerance |
| 1100 | // suitable for decimal round-trip comparisons. |
nothing calls this directly
no test coverage detected