Skip to content

Commit f968297

Browse files
authored
test(storage): add test for Writer race (#6862)
Adds a test to detect a potential race condition that can arise if the context is cancelled before writing to GCS. We already have a test that detects a similar condition after we have already started writing the object, but this test looks at the context being cancelled before any writes occur. When run with -race, this test fails in storage/v1.27.0, but it passes when run with the fix in #6817. Updates #6816
1 parent 8b203b8 commit f968297

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

storage/writer_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"crypto/sha256"
2020
"encoding/base64"
21+
"errors"
2122
"net/http"
2223
"strings"
2324
"testing"
@@ -119,7 +120,7 @@ func TestEncryption(t *testing.T) {
119120
// This test demonstrates the data race on Writer.err that can happen when the
120121
// Writer's context is cancelled. To see the race, comment out the w.mu.Lock/Unlock
121122
// lines in writer.go and run this test with -race.
122-
func TestRaceOnCancel(t *testing.T) {
123+
func TestRaceOnCancelAfterWrite(t *testing.T) {
123124
client := mockClient(t, &mockTransport{})
124125
cctx, cancel := context.WithCancel(context.Background())
125126
w := client.Bucket("b").Object("o").NewWriter(cctx)
@@ -136,6 +137,24 @@ func TestRaceOnCancel(t *testing.T) {
136137
w.Write([]byte(nil))
137138
}
138139

140+
// This test checks for the read-write race condition that can occur if
141+
// monitorCancel is launched before the pipe is opened. See
142+
// https://github.com/googleapis/google-cloud-go/issues/6816
143+
func TestRaceOnCancelBeforeWrite(t *testing.T) {
144+
ctx, cancel := context.WithCancel(context.Background())
145+
client := mockClient(t, &mockTransport{})
146+
cancel()
147+
writer := client.Bucket("foo").Object("bar").NewWriter(ctx)
148+
writer.ChunkSize = googleapi.MinUploadChunkSize
149+
writer.Write([]byte("data"))
150+
151+
// We expect Close to return a context cancelled error, and the Writer should
152+
// not open the pipe and avoid triggering a race condition.
153+
if err := writer.Close(); !errors.Is(err, context.Canceled) {
154+
t.Errorf("Writer.Close: got %v, want %v", err, context.Canceled)
155+
}
156+
}
157+
139158
func TestCancelDoesNotLeak(t *testing.T) {
140159
ctx, cancel := context.WithCancel(context.Background())
141160
const contents = "hello world"

0 commit comments

Comments
 (0)