-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test(store/snapshot): fix flaky test #20078
Changes from 5 commits
9f985c0
0aebb60
358b7a5
db7700d
6f4637d
047dea8
5044de3
27e71ab
46dabc2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -5,6 +5,7 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"errors" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"io" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"sync" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"sync/atomic" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"testing" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -262,6 +263,7 @@ func TestStore_Prune(t *testing.T) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func TestStore_Save(t *testing.T) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
t.Parallel() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
store := setupStore(t) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Saving a snapshot should work | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
snapshot, err := store.Save(4, 1, makeChunks([][]byte{{1}, {2}})) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -318,19 +320,43 @@ func TestStore_Save(t *testing.T) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Saving a snapshot should error if a snapshot is already in progress for the same height, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// regardless of format. However, a different height should succeed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ch = make(chan io.ReadCloser) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mtx := sync.Mutex{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mtx.Lock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
go func() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mtx.Unlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_, err := store.Save(7, 1, ch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mtx.Lock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defer mtx.Unlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_, err = store.Save(7, 2, makeChunks(nil)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.Error(t, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_, err = store.Save(8, 1, makeChunks(nil)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require.NoError(t, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
close(ch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgStart, wgDone sync.WaitGroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
errCount atomic.Uint32 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const n = 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgStart.Add(n + 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgDone.Add(n + 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for i := 0; i <= n; i++ { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ch = make(chan io.ReadCloser, 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ch <- &ReadCloserMock{} // does not block on a buffered channel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
close(ch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
go func(i int) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgStart.Done() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgStart.Wait() // wait for all routines started | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var err error | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if i < n { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_, err = store.Save(7, 1, ch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_, err = store.Save(8, 1, makeChunks(nil)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good intend but this condition on var (
wgStart, wgDone sync.WaitGroup
mu sync.Mutex
gotErrHeights []uint64
)
srcHeights := []uint64{7, 7, 7, 8, 9}
wgStart.Add(len(srcHeights))
wgDone.Add(len(srcHeights))
for _, h := range srcHeights {
ch = make(chan io.ReadCloser, 1)
ch <- &ReadCloserMock{} // does not block on a buffered channel
close(ch)
go func(height uint64) {
wgStart.Done()
wgStart.Wait() // wait for all routines started
if _, err = store.Save(height, 1, ch); err != nil {
mu.Lock()
gotErrHeights = append(gotErrHeights, height)
mu.Unlock()
}
wgDone.Done()
}(h)
}
wgDone.Wait() // wait for all routines completed
assert.Equal(t, []uint64{7, 7}, gotErrHeights) This approach has the benefit that you can identify the failing height rather than relying on the count. WDYT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. great point There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
errCount.Add(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgDone.Done() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}(i) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
wgDone.Wait() // wait for all routines completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert.Equal(t, uint32(n-1), errCount.Load()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type ReadCloserMock struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (r ReadCloserMock) Read(p []byte) (n int, err error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return len(p), io.EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
func (r ReadCloserMock) Close() error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+349
to
+357
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The - func (r ReadCloserMock) Read(p []byte) (n int, err error) {
- return len(p), io.EOF
+ func (r *ReadCloserMock) Read(p []byte) (n int, err error) {
+ if len(r.data) > 0 {
+ n = copy(p, r.data)
+ r.data = r.data[n:]
+ return n, nil
+ }
+ return 0, io.EOF
+ }
+
+ func NewReadCloserMock(data []byte) *ReadCloserMock {
+ return &ReadCloserMock{data: data}
+ } Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the case of
different height should succeed
is missedThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done