1
0
mirror of https://github.com/golang/go synced 2024-11-18 00:44:47 -07:00

database/sql: deflake query cancel tests

Rather then using a sleep in the fake DB, go to a channel
select and wait for the context to be done.

Fixes #18115

Change-Id: I6bc3a29db58c568d0a7ea06c2a354c18c9e798b2
Reviewed-on: https://go-review.googlesource.com/33712
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Daniel Theophanes 2016-11-30 09:30:31 -08:00 committed by Brad Fitzpatrick
parent f6bff1d587
commit 2a64ebfc6d
2 changed files with 26 additions and 5 deletions

View File

@ -511,6 +511,10 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (*fakeStmt, err
var hookPrepareBadConn func() bool var hookPrepareBadConn func() bool
func (c *fakeConn) Prepare(query string) (driver.Stmt, error) { func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
panic("use PrepareContext")
}
func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
c.numPrepare++ c.numPrepare++
if c.db == nil { if c.db == nil {
panic("nil c.db; conn = " + fmt.Sprintf("%#v", c)) panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
@ -549,7 +553,13 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
parts = parts[1:] parts = parts[1:]
if stmt.wait > 0 { if stmt.wait > 0 {
time.Sleep(stmt.wait) wait := time.NewTimer(stmt.wait)
select {
case <-wait.C:
case <-ctx.Done():
wait.Stop()
return nil, ctx.Err()
}
} }
c.incrStat(&c.stmtsMade) c.incrStat(&c.stmtsMade)

View File

@ -24,6 +24,17 @@ func init() {
c *driverConn c *driverConn
} }
freedFrom := make(map[dbConn]string) freedFrom := make(map[dbConn]string)
var mu sync.Mutex
getFreedFrom := func(c dbConn) string {
mu.Lock()
defer mu.Unlock()
return freedFrom[c]
}
setFreedFrom := func(c dbConn, s string) {
mu.Lock()
defer mu.Unlock()
freedFrom[c] = s
}
putConnHook = func(db *DB, c *driverConn) { putConnHook = func(db *DB, c *driverConn) {
idx := -1 idx := -1
for i, v := range db.freeConn { for i, v := range db.freeConn {
@ -36,10 +47,10 @@ func init() {
// print before panic, as panic may get lost due to conflicting panic // print before panic, as panic may get lost due to conflicting panic
// (all goroutines asleep) elsewhere, since we might not unlock // (all goroutines asleep) elsewhere, since we might not unlock
// the mutex in freeConn here. // the mutex in freeConn here.
println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack()) println("double free of conn. conflicts are:\nA) " + getFreedFrom(dbConn{db, c}) + "\n\nand\nB) " + stack())
panic("double free of conn.") panic("double free of conn.")
} }
freedFrom[dbConn{db, c}] = stack() setFreedFrom(dbConn{db, c}, stack())
} }
} }
@ -344,7 +355,7 @@ func TestQueryContextWait(t *testing.T) {
// This will trigger the *fakeConn.Prepare method which will take time // This will trigger the *fakeConn.Prepare method which will take time
// performing the query. The ctxDriverPrepare func will check the context // performing the query. The ctxDriverPrepare func will check the context
// after this and close the rows and return an error. // after this and close the rows and return an error.
_, err := db.QueryContext(ctx, "WAIT|30ms|SELECT|people|age,name|") _, err := db.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
if err != context.DeadlineExceeded { if err != context.DeadlineExceeded {
t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err) t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
} }
@ -372,7 +383,7 @@ func TestTxContextWait(t *testing.T) {
// This will trigger the *fakeConn.Prepare method which will take time // This will trigger the *fakeConn.Prepare method which will take time
// performing the query. The ctxDriverPrepare func will check the context // performing the query. The ctxDriverPrepare func will check the context
// after this and close the rows and return an error. // after this and close the rows and return an error.
_, err = tx.QueryContext(ctx, "WAIT|30ms|SELECT|people|age,name|") _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
if err != context.DeadlineExceeded { if err != context.DeadlineExceeded {
t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err) t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
} }