@@ -19,6 +19,7 @@ import (
19
19
"io/ioutil"
20
20
"log"
21
21
"math"
22
+ "math/rand"
22
23
"net"
23
24
"net/url"
24
25
"os"
@@ -2938,3 +2939,55 @@ func TestValuerWithValueReceiverGivenNilValue(t *testing.T) {
2938
2939
// This test will panic on the INSERT if ConvertValue() does not check for typed nil before calling Value()
2939
2940
})
2940
2941
}
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