Skip to content

Commit 60e730f

Browse files
committed
test: Implement TestContextCancelQueryWhileScan
1 parent c0f6b44 commit 60e730f

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

driver_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"io/ioutil"
2020
"log"
2121
"math"
22+
"math/rand"
2223
"net"
2324
"net/url"
2425
"os"
@@ -2938,3 +2939,55 @@ func TestValuerWithValueReceiverGivenNilValue(t *testing.T) {
29382939
// This test will panic on the INSERT if ConvertValue() does not check for typed nil before calling Value()
29392940
})
29402941
}
2942+
2943+
// TestContextCancelQueryWhileScan checks for race conditions that arise when
2944+
// a query context is canceled while a user is calling rows.Scan(). The code
2945+
// is based on database/sql TestIssue18429.
2946+
// See https://github.com/golang/go/issues/23519
2947+
func TestContextCancelQueryWhileScan(t *testing.T) {
2948+
const blob = "0123456789abcdef"
2949+
const contextRaceIterations = 1000
2950+
const milliWait = 5
2951+
const blobSize = 64 * 1024
2952+
const insertRows = 64
2953+
2954+
largeBlob := strings.Repeat(blob, blobSize/len(blob))
2955+
2956+
runTests(t, dsn, func(dbt *DBTest) {
2957+
dbt.mustExec("CREATE TABLE test (id int, value MEDIUMBLOB) CHARACTER SET utf8")
2958+
for i := 0; i < insertRows; i++ {
2959+
dbt.mustExec("INSERT INTO test VALUES (?, ?)", i+1, largeBlob)
2960+
}
2961+
2962+
sem := make(chan bool, 20)
2963+
var wg sync.WaitGroup
2964+
for i := 0; i < contextRaceIterations; i++ {
2965+
sem <- true
2966+
wg.Add(1)
2967+
go func() {
2968+
defer func() {
2969+
<-sem
2970+
wg.Done()
2971+
}()
2972+
2973+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(rand.Intn(milliWait))*time.Millisecond)
2974+
defer cancel()
2975+
2976+
rows, _ := dbt.db.QueryContext(ctx, `SELECT id, value FROM test`)
2977+
if rows != nil {
2978+
var b int
2979+
var s string
2980+
for rows.Next() {
2981+
if rows.Scan(&b, &s) == nil {
2982+
if len(s) != blobSize {
2983+
t.Fatal("mismatch in read buffer")
2984+
}
2985+
}
2986+
}
2987+
rows.Close()
2988+
}
2989+
}()
2990+
}
2991+
wg.Wait()
2992+
})
2993+
}

0 commit comments

Comments
 (0)