| 1 | package migrations |
| 2 | |
| 3 | // NOTE: These concurrent migration tests require the local Kubo binary (built with 'make build') to be in PATH. |
| 4 | // |
| 5 | // To run these tests successfully: |
| 6 | // export PATH="$(pwd)/cmd/ipfs:$PATH" |
| 7 | // go test ./test/cli/migrations/ |
| 8 | |
| 9 | import ( |
| 10 | "context" |
| 11 | "testing" |
| 12 | "time" |
| 13 | |
| 14 | "github.com/stretchr/testify/require" |
| 15 | ) |
| 16 | |
| 17 | const daemonStartupWait = 2 * time.Second |
| 18 | |
| 19 | // TestConcurrentMigrations tests concurrent daemon --migrate attempts |
| 20 | func TestConcurrentMigrations(t *testing.T) { |
| 21 | t.Parallel() |
| 22 | |
| 23 | t.Run("concurrent daemon migrations prevented by lock", testConcurrentDaemonMigrations) |
| 24 | } |
| 25 | |
| 26 | func testConcurrentDaemonMigrations(t *testing.T) { |
| 27 | node := setupStaticV16Repo(t) |
| 28 | |
| 29 | // Start first daemon --migrate in background (holds repo.lock) |
| 30 | ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
| 31 | defer cancel() |
| 32 | |
| 33 | firstDaemon := setupDaemonCmd(ctx, node, "daemon", "--migrate") |
| 34 | require.NoError(t, firstDaemon.Start()) |
| 35 | defer func() { |
| 36 | // Shutdown first daemon |
| 37 | shutdownCmd := setupDaemonCmd(context.Background(), node, "shutdown") |
| 38 | _ = shutdownCmd.Run() |
| 39 | _ = firstDaemon.Wait() |
| 40 | }() |
| 41 | |
| 42 | // Wait for first daemon to start and acquire lock |
| 43 | time.Sleep(daemonStartupWait) |
| 44 | |
| 45 | // Attempt second daemon --migrate (should fail due to lock) |
| 46 | secondDaemon := setupDaemonCmd(context.Background(), node, "daemon", "--migrate") |
| 47 | output, err := secondDaemon.CombinedOutput() |
| 48 | t.Logf("Second daemon output: %s", output) |
| 49 | |
| 50 | // Should fail with lock error |
| 51 | require.Error(t, err, "second daemon should fail when first daemon holds lock") |
| 52 | require.Contains(t, string(output), "lock", "error should mention lock") |
| 53 | |
| 54 | assertNoTempFiles(t, node.Dir, "no temp files should be created when lock fails") |
| 55 | } |