TestNoteboxConcurrencyBugDemo demonstrates the specific bug: Multiple goroutines calling OpenNotebox/Close on the same endpoint:localStorage can cause race conditions due to insufficient concurrency protection
(t *testing.T)
| 12 | // Multiple goroutines calling OpenNotebox/Close on the same endpoint:localStorage |
| 13 | // can cause race conditions due to insufficient concurrency protection |
| 14 | func TestNoteboxConcurrencyBugDemo(t *testing.T) { |
| 15 | longRunningTest(t) |
| 16 | ctx := context.Background() |
| 17 | |
| 18 | // Clean up any leftover noteboxes from previous tests |
| 19 | _ = Purge(ctx) |
| 20 | forceCleanupAllNoteboxes() // Force cleanup to ensure test isolation |
| 21 | |
| 22 | // Create temp directory for test |
| 23 | tmpDir := t.TempDir() |
| 24 | |
| 25 | // Set file storage directory |
| 26 | FileSetStorageLocation(tmpDir) |
| 27 | |
| 28 | const ( |
| 29 | endpoint = "bug-demo-endpoint" |
| 30 | numGoroutines = 20 |
| 31 | numOperations = 50 |
| 32 | ) |
| 33 | |
| 34 | // Create a single storage location that all goroutines will share |
| 35 | testStorage := FileStorageObject("shared_notebox_storage") |
| 36 | |
| 37 | // Create the notebox once |
| 38 | err := CreateNotebox(ctx, endpoint, testStorage) |
| 39 | if err != nil { |
| 40 | t.Fatalf("Failed to create notebox: %v", err) |
| 41 | } |
| 42 | |
| 43 | // Track errors and panics |
| 44 | var ( |
| 45 | errors sync.Map |
| 46 | panics sync.Map |
| 47 | wg sync.WaitGroup |
| 48 | ) |
| 49 | |
| 50 | wg.Add(numGoroutines) |
| 51 | |
| 52 | // Launch N goroutines that all try to open/work/close the same notebox |
| 53 | for i := 0; i < numGoroutines; i++ { |
| 54 | go func(id int) { |
| 55 | defer wg.Done() |
| 56 | |
| 57 | for op := 0; op < numOperations; op++ { |
| 58 | // Catch panics |
| 59 | func() { |
| 60 | defer func() { |
| 61 | if r := recover(); r != nil { |
| 62 | panics.Store(fmt.Sprintf("goroutine-%d-op-%d", id, op), r) |
| 63 | } |
| 64 | }() |
| 65 | |
| 66 | // Open the notebox |
| 67 | box, err := OpenNotebox(ctx, endpoint, testStorage) |
| 68 | if err != nil { |
| 69 | errors.Store(fmt.Sprintf("open-%d-%d", id, op), err) |
| 70 | return |
| 71 | } |
nothing calls this directly
no test coverage detected