(t *testing.T)
| 494 | } |
| 495 | |
| 496 | func TestTracker_ConcurrentFlushAndTrack(t *testing.T) { |
| 497 | t.Parallel() |
| 498 | |
| 499 | db, _ := dbtestutil.NewDB(t) |
| 500 | ctx := testutil.Context(t, testutil.WaitMedium) |
| 501 | |
| 502 | tracker := boundaryusage.NewTracker() |
| 503 | replicaID := uuid.New() |
| 504 | |
| 505 | const numOperations = 50 |
| 506 | |
| 507 | var wg sync.WaitGroup |
| 508 | |
| 509 | // Goroutine 1: Continuously track. |
| 510 | wg.Add(1) |
| 511 | go func() { |
| 512 | defer wg.Done() |
| 513 | for i := 0; i < numOperations; i++ { |
| 514 | tracker.Track(uuid.New(), uuid.New(), 1, 1) |
| 515 | } |
| 516 | }() |
| 517 | |
| 518 | // Goroutine 2: Continuously flush. |
| 519 | wg.Add(1) |
| 520 | go func() { |
| 521 | defer wg.Done() |
| 522 | for i := 0; i < numOperations; i++ { |
| 523 | _ = tracker.FlushToDB(ctx, db, replicaID) |
| 524 | } |
| 525 | }() |
| 526 | |
| 527 | wg.Wait() |
| 528 | |
| 529 | // Final flush to capture any remaining data. |
| 530 | require.NoError(t, tracker.FlushToDB(ctx, db, replicaID)) |
| 531 | |
| 532 | // Verify stats are non-negative. |
| 533 | boundaryCtx := dbauthz.AsBoundaryUsageTracker(ctx) |
| 534 | summary, err := db.GetAndResetBoundaryUsageSummary(boundaryCtx, 60000) |
| 535 | require.NoError(t, err) |
| 536 | require.GreaterOrEqual(t, summary.AllowedRequests, int64(0)) |
| 537 | require.GreaterOrEqual(t, summary.DeniedRequests, int64(0)) |
| 538 | } |
| 539 | |
| 540 | // trackDuringUpsertDB wraps a database.Store to call Track() during the |
| 541 | // UpsertBoundaryUsageStats operation, simulating a concurrent Track() call. |
nothing calls this directly
no test coverage detected