Skip to content

Commit 3786c3a

Browse files
authored
Merge pull request #43 from PowerDNS/fix-test-data-race
Fix race in syncer test
2 parents 9353f38 + f1d03ce commit 3786c3a

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

syncer/sync_test.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"os"
88
"strings"
9+
"sync"
910
"testing"
1011
"time"
1112

@@ -60,7 +61,7 @@ func doTest(t *testing.T, withHeader bool) {
6061

6162
// Start syncer A with one key
6263
t.Log("Starting syncer A")
63-
go runSync(ctxA, syncerA)
64+
goRunSync(ctxA, syncerA)
6465

6566
t.Log("----------")
6667

@@ -71,7 +72,7 @@ func doTest(t *testing.T, withHeader bool) {
7172
// Starting with an empty LMDB is a special case that will not trigger any
7273
// local snapshot.
7374
t.Log("Starting syncer B")
74-
go runSync(ctxB, syncerB)
75+
goRunSync(ctxB, syncerB)
7576

7677
t.Log("----------")
7778

@@ -98,7 +99,7 @@ func doTest(t *testing.T, withHeader bool) {
9899
cancelA()
99100
ctxA, cancelA = context.WithCancel(ctx)
100101
t.Log("----------")
101-
go runSync(ctxA, syncerA)
102+
goRunSync(ctxA, syncerA)
102103

103104
t.Log("----------")
104105

@@ -119,7 +120,7 @@ func doTest(t *testing.T, withHeader bool) {
119120
t.Log("----------")
120121
t.Log("Starting syncer A again")
121122
ctxA, cancelA = context.WithCancel(ctx)
122-
go runSync(ctxA, syncerA)
123+
goRunSync(ctxA, syncerA)
123124
t.Log("----------")
124125

125126
// New value in A should get synced to B
@@ -191,6 +192,32 @@ func requireSnapshotsLenWait(t *testing.T, st simpleblob.Interface, expLen int,
191192
require.Len(t, list, expLen, instance)
192193
}
193194

195+
// Ensure that we there are never two Sync goroutines running at the same time,
196+
// because this can cause a data race.
197+
// Protected by mutex, just in case the test is ever run in parallel mode.
198+
var (
199+
runningSyncersMu sync.Mutex
200+
runningSyncers = map[*Syncer]*sync.WaitGroup{}
201+
)
202+
203+
func goRunSync(ctx context.Context, syncer *Syncer) {
204+
runningSyncersMu.Lock()
205+
wg, exists := runningSyncers[syncer]
206+
if !exists {
207+
wg = &sync.WaitGroup{}
208+
runningSyncers[syncer] = wg
209+
}
210+
runningSyncersMu.Unlock()
211+
go func() {
212+
logrus.Info("Wait for any previous Syncer instance to exit")
213+
wg.Wait()
214+
logrus.Info("Wait for any previous Syncer done")
215+
wg.Add(1)
216+
defer wg.Done()
217+
runSync(ctx, syncer)
218+
}()
219+
}
220+
194221
func runSync(ctx context.Context, syncer *Syncer) {
195222
err := syncer.Sync(ctx)
196223
if err != nil && err != context.Canceled {

test.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ go test -count=1 "$@" ./...
1515
go test -count=1 "$@" github.com/PowerDNS/simpleblob/...
1616

1717
# Run again with race detector
18-
go test -race -count=1 "$@" ./...
18+
go test -race -count=5 "$@" ./...
19+
GOMAXPROCS=1 go test -race -count=5 "$@" ./...
1920

2021
# This one used to be flaky, run a few more times
2122
go test -count 20 -run TestSyncer_Sync_startup powerdns.com/platform/lightningstream/syncer

0 commit comments

Comments
 (0)