| 219 | } |
| 220 | |
| 221 | func TestPathStore_ConcurrentSafety(t *testing.T) { |
| 222 | t.Parallel() |
| 223 | |
| 224 | ps := agentgit.NewPathStore() |
| 225 | const goroutines = 20 |
| 226 | const iterations = 50 |
| 227 | |
| 228 | chatIDs := make([]uuid.UUID, goroutines) |
| 229 | for i := range chatIDs { |
| 230 | chatIDs[i] = uuid.New() |
| 231 | } |
| 232 | |
| 233 | var wg sync.WaitGroup |
| 234 | wg.Add(goroutines * 2) // writers + readers |
| 235 | |
| 236 | // Writers. |
| 237 | for i := range goroutines { |
| 238 | go func(idx int) { |
| 239 | defer wg.Done() |
| 240 | for j := range iterations { |
| 241 | ancestors := []uuid.UUID{chatIDs[(idx+1)%goroutines]} |
| 242 | path := []string{ |
| 243 | "/file-" + chatIDs[idx].String() + "-" + time.Now().Format(time.RFC3339Nano), |
| 244 | "/iter-" + string(rune('0'+j%10)), |
| 245 | } |
| 246 | ps.AddPaths(append([]uuid.UUID{chatIDs[idx]}, ancestors...), path) |
| 247 | } |
| 248 | }(i) |
| 249 | } |
| 250 | |
| 251 | // Readers. |
| 252 | for i := range goroutines { |
| 253 | go func(idx int) { |
| 254 | defer wg.Done() |
| 255 | for range iterations { |
| 256 | _ = ps.GetPaths(chatIDs[idx]) |
| 257 | } |
| 258 | }(i) |
| 259 | } |
| 260 | |
| 261 | wg.Wait() |
| 262 | |
| 263 | // Verify every chat has at least the paths it wrote. |
| 264 | for _, id := range chatIDs { |
| 265 | paths := ps.GetPaths(id) |
| 266 | require.NotEmpty(t, paths, "chat %s should have paths", id) |
| 267 | } |
| 268 | } |