Commit e12f6ee0 authored by Daniel Theophanes's avatar Daniel Theophanes Committed by Brad Fitzpatrick

database/sql: fix TestPendingConnsAfterErr

TestPendingConnsAfterErr showed a failure on slower systems.
Wait and check for the database to close all connections
before pronouncing failure.

A more careful method was attempted but the connection pool
behavior is too dependent on the scheduler behavior to be
predictable.

Fixes #15684

Change-Id: Iafdbc90ba51170c76a079db04c3d5452047433a4
Reviewed-on: https://go-review.googlesource.com/33418Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 199d410d
...@@ -1438,7 +1438,11 @@ func TestPendingConnsAfterErr(t *testing.T) { ...@@ -1438,7 +1438,11 @@ func TestPendingConnsAfterErr(t *testing.T) {
tryOpen = maxOpen*2 + 2 tryOpen = maxOpen*2 + 2
) )
db := newTestDB(t, "people") // No queries will be run.
db, err := Open("test", fakeDBName)
if err != nil {
t.Fatalf("Open: %v", err)
}
defer closeDB(t, db) defer closeDB(t, db)
defer func() { defer func() {
for k, v := range db.lastPut { for k, v := range db.lastPut {
...@@ -1450,29 +1454,29 @@ func TestPendingConnsAfterErr(t *testing.T) { ...@@ -1450,29 +1454,29 @@ func TestPendingConnsAfterErr(t *testing.T) {
db.SetMaxIdleConns(0) db.SetMaxIdleConns(0)
errOffline := errors.New("db offline") errOffline := errors.New("db offline")
defer func() { setHookOpenErr(nil) }() defer func() { setHookOpenErr(nil) }()
errs := make(chan error, tryOpen) errs := make(chan error, tryOpen)
unblock := make(chan struct{}) var opening sync.WaitGroup
opening.Add(tryOpen)
setHookOpenErr(func() error { setHookOpenErr(func() error {
<-unblock // block until all connections are in flight // Wait for all connections to enqueue.
opening.Wait()
return errOffline return errOffline
}) })
var opening sync.WaitGroup
opening.Add(tryOpen)
for i := 0; i < tryOpen; i++ { for i := 0; i < tryOpen; i++ {
go func() { go func() {
opening.Done() // signal one connection is in flight opening.Done() // signal one connection is in flight
_, err := db.Exec("INSERT|people|name=Julia,age=19") _, err := db.Exec("will never run")
errs <- err errs <- err
}() }()
} }
opening.Wait() // wait for all workers to begin running opening.Wait() // wait for all workers to begin running
time.Sleep(10 * time.Millisecond) // make extra sure all workers are blocked
close(unblock) // let all workers proceed
const timeout = 5 * time.Second const timeout = 5 * time.Second
to := time.NewTimer(timeout) to := time.NewTimer(timeout)
...@@ -1489,6 +1493,24 @@ func TestPendingConnsAfterErr(t *testing.T) { ...@@ -1489,6 +1493,24 @@ func TestPendingConnsAfterErr(t *testing.T) {
t.Fatalf("orphaned connection request(s), still waiting after %v", timeout) t.Fatalf("orphaned connection request(s), still waiting after %v", timeout)
} }
} }
// Wait a reasonable time for the database to close all connections.
tick := time.NewTicker(3 * time.Millisecond)
defer tick.Stop()
for {
select {
case <-tick.C:
db.mu.Lock()
if db.numOpen == 0 {
db.mu.Unlock()
return
}
db.mu.Unlock()
case <-to.C:
// Closing the database will check for numOpen and fail the test.
return
}
}
} }
func TestSingleOpenConn(t *testing.T) { func TestSingleOpenConn(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment