1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
25 freedFrom
:= make(map[dbConn
]string)
26 putConnHook
= func(db
*DB
, c
*driverConn
) {
27 if c
.listElem
!= nil {
28 // print before panic, as panic may get lost due to conflicting panic
29 // (all goroutines asleep) elsewhere, since we might not unlock
30 // the mutex in freeConn here.
31 println("double free of conn. conflicts are:\nA) " + freedFrom
[dbConn
{db
, c
}] + "\n\nand\nB) " + stack())
32 panic("double free of conn.")
34 freedFrom
[dbConn
{db
, c
}] = stack()
38 const fakeDBName
= "foo"
40 var chrisBirthday
= time
.Unix(123456789, 0)
42 func newTestDB(t testing
.TB
, name
string) *DB
{
43 db
, err
:= Open("test", fakeDBName
)
45 t
.Fatalf("Open: %v", err
)
47 if _
, err
:= db
.Exec("WIPE"); err
!= nil {
48 t
.Fatalf("exec wipe: %v", err
)
51 exec(t
, db
, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
52 exec(t
, db
, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1)
53 exec(t
, db
, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2)
54 exec(t
, db
, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday
)
56 if name
== "magicquery" {
57 // Magic table name and column, known by fakedb_test.go.
58 exec(t
, db
, "CREATE|magicquery|op=string,millis=int32")
59 exec(t
, db
, "INSERT|magicquery|op=sleep,millis=10")
64 func exec(t testing
.TB
, db
*DB
, query
string, args
...interface{}) {
65 _
, err
:= db
.Exec(query
, args
...)
67 t
.Fatalf("Exec of %q: %v", query
, err
)
71 func closeDB(t testing
.TB
, db
*DB
) {
72 if e
:= recover(); e
!= nil {
73 fmt
.Printf("Panic: %v\n", e
)
76 defer setHookpostCloseConn(nil)
77 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
79 t
.Errorf("Error closing fakeConn: %v", err
)
82 for node
, i
:= db
.freeConn
.Front(), 0; node
!= nil; node
, i
= node
.Next(), i
+1 {
83 dc
:= node
.Value
.(*driverConn
)
84 if n
:= len(dc
.openStmt
); n
> 0 {
85 // Just a sanity check. This is legal in
86 // general, but if we make the tests clean up
87 // their statements first, then we can safely
88 // verify this is always zero here, and any
89 // other value is a leak.
90 t
.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i
, db
.freeConn
.Len(), n
)
95 t
.Fatalf("error closing DB: %v", err
)
101 t
.Fatalf("%d connections still open after closing DB", db
.numOpen
)
105 // numPrepares assumes that db has exactly 1 idle conn and returns
106 // its count of calls to Prepare
107 func numPrepares(t
*testing
.T
, db
*DB
) int {
108 if n
:= db
.freeConn
.Len(); n
!= 1 {
109 t
.Fatalf("free conns = %d; want 1", n
)
111 return (db
.freeConn
.Front().Value
.(*driverConn
)).ci
.(*fakeConn
).numPrepare
114 func (db
*DB
) numDeps() int {
120 // Dependencies are closed via a goroutine, so this polls waiting for
121 // numDeps to fall to want, waiting up to d.
122 func (db
*DB
) numDepsPollUntil(want
int, d time
.Duration
) int {
123 deadline
:= time
.Now().Add(d
)
126 if n
<= want || time
.Now().After(deadline
) {
129 time
.Sleep(50 * time
.Millisecond
)
133 func (db
*DB
) numFreeConns() int {
136 return db
.freeConn
.Len()
139 func (db
*DB
) dumpDeps(t
*testing
.T
) {
140 for fc
:= range db
.dep
{
141 db
.dumpDep(t
, 0, fc
, map[finalCloser
]bool{})
145 func (db
*DB
) dumpDep(t
*testing
.T
, depth
int, dep finalCloser
, seen
map[finalCloser
]bool) {
147 indent
:= strings
.Repeat(" ", depth
)
150 t
.Logf("%s%T (%p) waiting for -> %T (%p)", indent
, dep
, dep
, k
, k
)
151 if fc
, ok
:= k
.(finalCloser
); ok
{
153 db
.dumpDep(t
, depth
+1, fc
, seen
)
159 func TestQuery(t
*testing
.T
) {
160 db
:= newTestDB(t
, "people")
162 prepares0
:= numPrepares(t
, db
)
163 rows
, err
:= db
.Query("SELECT|people|age,name|")
165 t
.Fatalf("Query: %v", err
)
174 err
= rows
.Scan(&r
.age
, &r
.name
)
176 t
.Fatalf("Scan: %v", err
)
182 t
.Fatalf("Err: %v", err
)
185 {age
: 1, name
: "Alice"},
186 {age
: 2, name
: "Bob"},
187 {age
: 3, name
: "Chris"},
189 if !reflect
.DeepEqual(got
, want
) {
190 t
.Errorf("mismatch.\n got: %#v\nwant: %#v", got
, want
)
193 // And verify that the final rows.Next() call, which hit EOF,
194 // also closed the rows connection.
195 if n
:= db
.numFreeConns(); n
!= 1 {
196 t
.Fatalf("free conns after query hitting EOF = %d; want 1", n
)
198 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
199 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
203 func TestByteOwnership(t
*testing
.T
) {
204 db
:= newTestDB(t
, "people")
206 rows
, err
:= db
.Query("SELECT|people|name,photo|")
208 t
.Fatalf("Query: %v", err
)
217 err
= rows
.Scan(&r
.name
, &r
.photo
)
219 t
.Fatalf("Scan: %v", err
)
223 corruptMemory
:= []byte("\xffPHOTO")
225 {name
: []byte("Alice"), photo
: corruptMemory
},
226 {name
: []byte("Bob"), photo
: corruptMemory
},
227 {name
: []byte("Chris"), photo
: corruptMemory
},
229 if !reflect
.DeepEqual(got
, want
) {
230 t
.Errorf("mismatch.\n got: %#v\nwant: %#v", got
, want
)
234 err
= db
.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo
)
236 t
.Error("want error scanning into RawBytes from QueryRow")
240 func TestRowsColumns(t
*testing
.T
) {
241 db
:= newTestDB(t
, "people")
243 rows
, err
:= db
.Query("SELECT|people|age,name|")
245 t
.Fatalf("Query: %v", err
)
247 cols
, err
:= rows
.Columns()
249 t
.Fatalf("Columns: %v", err
)
251 want
:= []string{"age", "name"}
252 if !reflect
.DeepEqual(cols
, want
) {
253 t
.Errorf("got %#v; want %#v", cols
, want
)
255 if err
:= rows
.Close(); err
!= nil {
256 t
.Errorf("error closing rows: %s", err
)
260 func TestQueryRow(t
*testing
.T
) {
261 db
:= newTestDB(t
, "people")
265 var birthday time
.Time
267 err
:= db
.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age
)
268 if err
== nil ||
!strings
.Contains(err
.Error(), "expected 2 destination arguments") {
269 t
.Errorf("expected error from wrong number of arguments; actually got: %v", err
)
272 err
= db
.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday
)
273 if err
!= nil ||
!birthday
.Equal(chrisBirthday
) {
274 t
.Errorf("chris birthday = %v, err = %v; want %v", birthday
, err
, chrisBirthday
)
277 err
= db
.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age
, &name
)
279 t
.Fatalf("age QueryRow+Scan: %v", err
)
282 t
.Errorf("expected name Bob, got %q", name
)
285 t
.Errorf("expected age 2, got %d", age
)
288 err
= db
.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age
, &name
)
290 t
.Fatalf("name QueryRow+Scan: %v", err
)
293 t
.Errorf("expected name Alice, got %q", name
)
296 t
.Errorf("expected age 1, got %d", age
)
300 err
= db
.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo
)
302 t
.Fatalf("photo QueryRow+Scan: %v", err
)
304 want
:= []byte("APHOTO")
305 if !reflect
.DeepEqual(photo
, want
) {
306 t
.Errorf("photo = %q; want %q", photo
, want
)
310 func TestStatementErrorAfterClose(t
*testing
.T
) {
311 db
:= newTestDB(t
, "people")
313 stmt
, err
:= db
.Prepare("SELECT|people|age|name=?")
315 t
.Fatalf("Prepare: %v", err
)
319 t
.Fatalf("Close: %v", err
)
322 err
= stmt
.QueryRow("foo").Scan(&name
)
324 t
.Errorf("expected error from QueryRow.Scan after Stmt.Close")
328 func TestStatementQueryRow(t
*testing
.T
) {
329 db
:= newTestDB(t
, "people")
331 stmt
, err
:= db
.Prepare("SELECT|people|age|name=?")
333 t
.Fatalf("Prepare: %v", err
)
337 for n
, tt
:= range []struct {
345 if err
:= stmt
.QueryRow(tt
.name
).Scan(&age
); err
!= nil {
346 t
.Errorf("%d: on %q, QueryRow/Scan: %v", n
, tt
.name
, err
)
347 } else if age
!= tt
.want
{
348 t
.Errorf("%d: age=%d, want %d", n
, age
, tt
.want
)
353 // golang.org/issue/3734
354 func TestStatementQueryRowConcurrent(t
*testing
.T
) {
355 db
:= newTestDB(t
, "people")
357 stmt
, err
:= db
.Prepare("SELECT|people|age|name=?")
359 t
.Fatalf("Prepare: %v", err
)
364 ch
:= make(chan error
, n
)
365 for i
:= 0; i
< n
; i
++ {
368 err
:= stmt
.QueryRow("Alice").Scan(&age
)
369 if err
== nil && age
!= 1 {
370 err
= fmt
.Errorf("unexpected age %d", age
)
375 for i
:= 0; i
< n
; i
++ {
376 if err
:= <-ch
; err
!= nil {
382 // just a test of fakedb itself
383 func TestBogusPreboundParameters(t
*testing
.T
) {
384 db
:= newTestDB(t
, "foo")
386 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
387 _
, err
:= db
.Prepare("INSERT|t1|name=?,age=bogusconversion")
389 t
.Fatalf("expected error")
391 if err
.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` {
392 t
.Errorf("unexpected error: %v", err
)
396 func TestExec(t
*testing
.T
) {
397 db
:= newTestDB(t
, "foo")
399 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
400 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
402 t
.Errorf("Stmt, err = %v, %v", stmt
, err
)
406 type execTest
struct {
410 execTests
:= []execTest
{
412 {[]interface{}{"Brad", 31}, ""},
413 {[]interface{}{"Brad", int64(31)}, ""},
414 {[]interface{}{"Bob", "32"}, ""},
415 {[]interface{}{7, 9}, ""},
417 // Invalid conversions:
418 {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"},
419 {[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
421 // Wrong number of args:
422 {[]interface{}{}, "sql: expected 2 arguments, got 0"},
423 {[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"},
425 for n
, et
:= range execTests
{
426 _
, err
:= stmt
.Exec(et
.args
...)
431 if errStr
!= et
.wantErr
{
432 t
.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q",
433 n
, et
.args
, errStr
, et
.wantErr
)
438 func TestTxStmt(t
*testing
.T
) {
439 db
:= newTestDB(t
, "")
441 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
442 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
444 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
447 tx
, err
:= db
.Begin()
449 t
.Fatalf("Begin = %v", err
)
453 _
, err
= txs
.Exec("Bobby", 7)
455 t
.Fatalf("Exec = %v", err
)
459 t
.Fatalf("Commit = %v", err
)
463 // Issue: http://golang.org/issue/2784
464 // This test didn't fail before because we got lucky with the fakedb driver.
465 // It was failing, and now not, in github.com/bradfitz/go-sql-test
466 func TestTxQuery(t
*testing
.T
) {
467 db
:= newTestDB(t
, "")
469 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
470 exec(t
, db
, "INSERT|t1|name=Alice")
472 tx
, err
:= db
.Begin()
478 r
, err
:= tx
.Query("SELECT|t1|name|")
488 t
.Fatal("expected one row")
498 func TestTxQueryInvalid(t
*testing
.T
) {
499 db
:= newTestDB(t
, "")
502 tx
, err
:= db
.Begin()
508 _
, err
= tx
.Query("SELECT|t1|name|")
510 t
.Fatal("Error expected")
514 // Tests fix for issue 4433, that retries in Begin happen when
515 // conn.Begin() returns ErrBadConn
516 func TestTxErrBadConn(t
*testing
.T
) {
517 db
, err
:= Open("test", fakeDBName
+";badConn")
519 t
.Fatalf("Open: %v", err
)
521 if _
, err
:= db
.Exec("WIPE"); err
!= nil {
522 t
.Fatalf("exec wipe: %v", err
)
525 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
526 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
528 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
531 tx
, err
:= db
.Begin()
533 t
.Fatalf("Begin = %v", err
)
537 _
, err
= txs
.Exec("Bobby", 7)
539 t
.Fatalf("Exec = %v", err
)
543 t
.Fatalf("Commit = %v", err
)
547 // Tests fix for issue 2542, that we release a lock when querying on
548 // a closed connection.
549 func TestIssue2542Deadlock(t
*testing
.T
) {
550 db
:= newTestDB(t
, "people")
552 for i
:= 0; i
< 2; i
++ {
553 _
, err
:= db
.Query("SELECT|people|age,name|")
555 t
.Fatalf("expected error")
560 // From golang.org/issue/3865
561 func TestCloseStmtBeforeRows(t
*testing
.T
) {
562 db
:= newTestDB(t
, "people")
565 s
, err
:= db
.Prepare("SELECT|people|name|")
584 // Tests fix for issue 2788, that we bind nil to a []byte if the
585 // value in the column is sql null
586 func TestNullByteSlice(t
*testing
.T
) {
587 db
:= newTestDB(t
, "")
589 exec(t
, db
, "CREATE|t|id=int32,name=nullstring")
590 exec(t
, db
, "INSERT|t|id=10,name=?", nil)
594 err
:= db
.QueryRow("SELECT|t|name|id=?", 10).Scan(&name
)
599 t
.Fatalf("name []byte should be nil for null column value, got: %#v", name
)
602 exec(t
, db
, "INSERT|t|id=11,name=?", "bob")
603 err
= db
.QueryRow("SELECT|t|name|id=?", 11).Scan(&name
)
607 if string(name
) != "bob" {
608 t
.Fatalf("name []byte should be bob, got: %q", string(name
))
612 func TestPointerParamsAndScans(t
*testing
.T
) {
613 db
:= newTestDB(t
, "")
615 exec(t
, db
, "CREATE|t|id=int32,name=nullstring")
621 exec(t
, db
, "INSERT|t|id=10,name=?", name
)
623 exec(t
, db
, "INSERT|t|id=20,name=?", name
)
625 err
:= db
.QueryRow("SELECT|t|name|id=?", 10).Scan(&name
)
627 t
.Fatalf("querying id 10: %v", err
)
630 t
.Errorf("id 10's name = nil; want bob")
631 } else if *name
!= "bob" {
632 t
.Errorf("id 10's name = %q; want bob", *name
)
635 err
= db
.QueryRow("SELECT|t|name|id=?", 20).Scan(&name
)
637 t
.Fatalf("querying id 20: %v", err
)
640 t
.Errorf("id 20 = %q; want nil", *name
)
644 func TestQueryRowClosingStmt(t
*testing
.T
) {
645 db
:= newTestDB(t
, "people")
649 err
:= db
.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age
, &name
)
653 if db
.freeConn
.Len() != 1 {
654 t
.Fatalf("expected 1 free conn")
656 fakeConn
:= (db
.freeConn
.Front().Value
.(*driverConn
)).ci
.(*fakeConn
)
657 if made
, closed := fakeConn
.stmtsMade
, fakeConn
.stmtsClosed
; made
!= closed {
658 t
.Errorf("statement close mismatch: made %d, closed %d", made
, closed)
663 func TestIssue6651(t
*testing
.T
) {
664 db
:= newTestDB(t
, "people")
669 want
:= "error in rows.Next"
670 rowsCursorNextHook
= func(dest
[]driver
.Value
) error
{
671 return fmt
.Errorf(want
)
673 defer func() { rowsCursorNextHook
= nil }()
674 err
:= db
.QueryRow("SELECT|people|name|").Scan(&v
)
675 if err
== nil || err
.Error() != want
{
676 t
.Errorf("error = %q; want %q", err
, want
)
678 rowsCursorNextHook
= nil
680 want
= "error in rows.Close"
681 rowsCloseHook
= func(rows
*Rows
, err
*error
) {
682 *err
= fmt
.Errorf(want
)
684 defer func() { rowsCloseHook
= nil }()
685 err
= db
.QueryRow("SELECT|people|name|").Scan(&v
)
686 if err
== nil || err
.Error() != want
{
687 t
.Errorf("error = %q; want %q", err
, want
)
691 type nullTestRow
struct {
692 nullParam
interface{}
693 notNullParam
interface{}
694 scanNullVal
interface{}
697 type nullTestSpec
struct {
703 func TestNullStringParam(t
*testing
.T
) {
704 spec
:= nullTestSpec
{"nullstring", "string", [6]nullTestRow
{
705 {NullString
{"aqua", true}, "", NullString
{"aqua", true}},
706 {NullString
{"brown", false}, "", NullString
{"", false}},
707 {"chartreuse", "", NullString
{"chartreuse", true}},
708 {NullString
{"darkred", true}, "", NullString
{"darkred", true}},
709 {NullString
{"eel", false}, "", NullString
{"", false}},
710 {"foo", NullString
{"black", false}, nil},
715 func TestNullInt64Param(t
*testing
.T
) {
716 spec
:= nullTestSpec
{"nullint64", "int64", [6]nullTestRow
{
717 {NullInt64
{31, true}, 1, NullInt64
{31, true}},
718 {NullInt64
{-22, false}, 1, NullInt64
{0, false}},
719 {22, 1, NullInt64
{22, true}},
720 {NullInt64
{33, true}, 1, NullInt64
{33, true}},
721 {NullInt64
{222, false}, 1, NullInt64
{0, false}},
722 {0, NullInt64
{31, false}, nil},
727 func TestNullFloat64Param(t
*testing
.T
) {
728 spec
:= nullTestSpec
{"nullfloat64", "float64", [6]nullTestRow
{
729 {NullFloat64
{31.2, true}, 1, NullFloat64
{31.2, true}},
730 {NullFloat64
{13.1, false}, 1, NullFloat64
{0, false}},
731 {-22.9, 1, NullFloat64
{-22.9, true}},
732 {NullFloat64
{33.81, true}, 1, NullFloat64
{33.81, true}},
733 {NullFloat64
{222, false}, 1, NullFloat64
{0, false}},
734 {10, NullFloat64
{31.2, false}, nil},
739 func TestNullBoolParam(t
*testing
.T
) {
740 spec
:= nullTestSpec
{"nullbool", "bool", [6]nullTestRow
{
741 {NullBool
{false, true}, true, NullBool
{false, true}},
742 {NullBool
{true, false}, false, NullBool
{false, false}},
743 {true, true, NullBool
{true, true}},
744 {NullBool
{true, true}, false, NullBool
{true, true}},
745 {NullBool
{true, false}, true, NullBool
{false, false}},
746 {true, NullBool
{true, false}, nil},
751 func nullTestRun(t
*testing
.T
, spec nullTestSpec
) {
752 db
:= newTestDB(t
, "")
754 exec(t
, db
, fmt
.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec
.nullType
, spec
.notNullType
))
756 // Inserts with db.Exec:
757 exec(t
, db
, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec
.rows
[0].nullParam
, spec
.rows
[0].notNullParam
)
758 exec(t
, db
, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec
.rows
[1].nullParam
, spec
.rows
[1].notNullParam
)
760 // Inserts with a prepared statement:
761 stmt
, err
:= db
.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
763 t
.Fatalf("prepare: %v", err
)
766 if _
, err
:= stmt
.Exec(3, "chris", spec
.rows
[2].nullParam
, spec
.rows
[2].notNullParam
); err
!= nil {
767 t
.Errorf("exec insert chris: %v", err
)
769 if _
, err
:= stmt
.Exec(4, "dave", spec
.rows
[3].nullParam
, spec
.rows
[3].notNullParam
); err
!= nil {
770 t
.Errorf("exec insert dave: %v", err
)
772 if _
, err
:= stmt
.Exec(5, "eleanor", spec
.rows
[4].nullParam
, spec
.rows
[4].notNullParam
); err
!= nil {
773 t
.Errorf("exec insert eleanor: %v", err
)
776 // Can't put null val into non-null col
777 if _
, err
:= stmt
.Exec(6, "bob", spec
.rows
[5].nullParam
, spec
.rows
[5].notNullParam
); err
== nil {
778 t
.Errorf("expected error inserting nil val with prepared statement Exec")
781 _
, err
= db
.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
783 // TODO: this test fails, but it's just because
784 // fakeConn implements the optional Execer interface,
785 // so arguably this is the correct behavior. But
786 // maybe I should flesh out the fakeConn.Exec
787 // implementation so this properly fails.
788 // t.Errorf("expected error inserting nil name with Exec")
791 paramtype
:= reflect
.TypeOf(spec
.rows
[0].nullParam
)
792 bindVal
:= reflect
.New(paramtype
).Interface()
794 for i
:= 0; i
< 5; i
++ {
796 if err
:= db
.QueryRow("SELECT|t|nullf|id=?", id
).Scan(bindVal
); err
!= nil {
797 t
.Errorf("id=%d Scan: %v", id
, err
)
799 bindValDeref
:= reflect
.ValueOf(bindVal
).Elem().Interface()
800 if !reflect
.DeepEqual(bindValDeref
, spec
.rows
[i
].scanNullVal
) {
801 t
.Errorf("id=%d got %#v, want %#v", id
, bindValDeref
, spec
.rows
[i
].scanNullVal
)
806 // golang.org/issue/4859
807 func TestQueryRowNilScanDest(t
*testing
.T
) {
808 db
:= newTestDB(t
, "people")
810 var name
*string // nil pointer
811 err
:= db
.QueryRow("SELECT|people|name|").Scan(name
)
812 want
:= "sql: Scan error on column index 0: destination pointer is nil"
813 if err
== nil || err
.Error() != want
{
814 t
.Errorf("error = %q; want %q", err
.Error(), want
)
818 func TestIssue4902(t
*testing
.T
) {
819 db
:= newTestDB(t
, "people")
822 driver
:= db
.driver
.(*fakeDriver
)
823 opens0
:= driver
.openCount
827 for i
:= 0; i
< 10; i
++ {
828 stmt
, err
= db
.Prepare("SELECT|people|name|")
838 opens
:= driver
.openCount
- opens0
840 t
.Errorf("opens = %d; want <= 1", opens
)
841 t
.Logf("db = %#v", db
)
842 t
.Logf("driver = %#v", driver
)
843 t
.Logf("stmt = %#v", stmt
)
848 // This used to deadlock.
849 func TestSimultaneousQueries(t
*testing
.T
) {
850 db
:= newTestDB(t
, "people")
853 tx
, err
:= db
.Begin()
859 r1
, err
:= tx
.Query("SELECT|people|name|")
865 r2
, err
:= tx
.Query("SELECT|people|name|")
872 func TestMaxIdleConns(t
*testing
.T
) {
873 db
:= newTestDB(t
, "people")
876 tx
, err
:= db
.Begin()
881 if got
:= db
.freeConn
.Len(); got
!= 1 {
882 t
.Errorf("freeConns = %d; want 1", got
)
885 db
.SetMaxIdleConns(0)
887 if got
:= db
.freeConn
.Len(); got
!= 0 {
888 t
.Errorf("freeConns after set to zero = %d; want 0", got
)
896 if got
:= db
.freeConn
.Len(); got
!= 0 {
897 t
.Errorf("freeConns = %d; want 0", got
)
901 func TestMaxOpenConns(t
*testing
.T
) {
903 t
.Skip("skipping in short mode")
905 defer setHookpostCloseConn(nil)
906 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
908 t
.Errorf("Error closing fakeConn: %v", err
)
912 db
:= newTestDB(t
, "magicquery")
915 driver
:= db
.driver
.(*fakeDriver
)
917 // Force the number of open connections to 0 so we can get an accurate
918 // count for the test
919 db
.SetMaxIdleConns(0)
921 if g
, w
:= db
.numFreeConns(), 0; g
!= w
{
922 t
.Errorf("free conns = %d; want %d", g
, w
)
925 if n
:= db
.numDepsPollUntil(0, time
.Second
); n
> 0 {
926 t
.Errorf("number of dependencies = %d; expected 0", n
)
931 opens0
:= driver
.openCount
932 closes0
:= driver
.closeCount
935 db
.SetMaxIdleConns(10)
936 db
.SetMaxOpenConns(10)
938 stmt
, err
:= db
.Prepare("SELECT|magicquery|op|op=?,millis=?")
943 // Start 50 parallel slow queries.
949 var wg sync
.WaitGroup
950 for batch
:= 0; batch
< nbatch
; batch
++ {
951 for i
:= 0; i
< nquery
; i
++ {
956 if err
:= stmt
.QueryRow("sleep", sleepMillis
).Scan(&op
); err
!= nil && err
!= ErrNoRows
{
961 // Sleep for twice the expected length of time for the
962 // batch of 50 queries above to finish before starting
964 time
.Sleep(2 * sleepMillis
* time
.Millisecond
)
968 if g
, w
:= db
.numFreeConns(), 10; g
!= w
{
969 t
.Errorf("free conns = %d; want %d", g
, w
)
972 if n
:= db
.numDepsPollUntil(20, time
.Second
); n
> 20 {
973 t
.Errorf("number of dependencies = %d; expected <= 20", n
)
978 opens
:= driver
.openCount
- opens0
979 closes
:= driver
.closeCount
- closes0
983 t
.Logf("open calls = %d", opens
)
984 t
.Logf("close calls = %d", closes
)
985 t
.Errorf("db connections opened = %d; want <= 10", opens
)
989 if err
:= stmt
.Close(); err
!= nil {
993 if g
, w
:= db
.numFreeConns(), 10; g
!= w
{
994 t
.Errorf("free conns = %d; want %d", g
, w
)
997 if n
:= db
.numDepsPollUntil(10, time
.Second
); n
> 10 {
998 t
.Errorf("number of dependencies = %d; expected <= 10", n
)
1002 db
.SetMaxOpenConns(5)
1004 if g
, w
:= db
.numFreeConns(), 5; g
!= w
{
1005 t
.Errorf("free conns = %d; want %d", g
, w
)
1008 if n
:= db
.numDepsPollUntil(5, time
.Second
); n
> 5 {
1009 t
.Errorf("number of dependencies = %d; expected 0", n
)
1013 db
.SetMaxOpenConns(0)
1015 if g
, w
:= db
.numFreeConns(), 5; g
!= w
{
1016 t
.Errorf("free conns = %d; want %d", g
, w
)
1019 if n
:= db
.numDepsPollUntil(5, time
.Second
); n
> 5 {
1020 t
.Errorf("number of dependencies = %d; expected 0", n
)
1024 db
.SetMaxIdleConns(0)
1026 if g
, w
:= db
.numFreeConns(), 0; g
!= w
{
1027 t
.Errorf("free conns = %d; want %d", g
, w
)
1030 if n
:= db
.numDepsPollUntil(0, time
.Second
); n
> 0 {
1031 t
.Errorf("number of dependencies = %d; expected 0", n
)
1036 func TestSingleOpenConn(t
*testing
.T
) {
1037 db
:= newTestDB(t
, "people")
1038 defer closeDB(t
, db
)
1040 db
.SetMaxOpenConns(1)
1042 rows
, err
:= db
.Query("SELECT|people|name|")
1046 if err
= rows
.Close(); err
!= nil {
1049 // shouldn't deadlock
1050 rows
, err
= db
.Query("SELECT|people|name|")
1054 if err
= rows
.Close(); err
!= nil {
1059 // golang.org/issue/5323
1060 func TestStmtCloseDeps(t
*testing
.T
) {
1061 if testing
.Short() {
1062 t
.Skip("skipping in short mode")
1064 defer setHookpostCloseConn(nil)
1065 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
1067 t
.Errorf("Error closing fakeConn: %v", err
)
1071 db
:= newTestDB(t
, "magicquery")
1072 defer closeDB(t
, db
)
1074 driver
:= db
.driver
.(*fakeDriver
)
1077 opens0
:= driver
.openCount
1078 closes0
:= driver
.closeCount
1080 openDelta0
:= opens0
- closes0
1082 stmt
, err
:= db
.Prepare("SELECT|magicquery|op|op=?,millis=?")
1087 // Start 50 parallel slow queries.
1093 var wg sync
.WaitGroup
1094 for batch
:= 0; batch
< nbatch
; batch
++ {
1095 for i
:= 0; i
< nquery
; i
++ {
1100 if err
:= stmt
.QueryRow("sleep", sleepMillis
).Scan(&op
); err
!= nil && err
!= ErrNoRows
{
1105 // Sleep for twice the expected length of time for the
1106 // batch of 50 queries above to finish before starting
1108 time
.Sleep(2 * sleepMillis
* time
.Millisecond
)
1112 if g
, w
:= db
.numFreeConns(), 2; g
!= w
{
1113 t
.Errorf("free conns = %d; want %d", g
, w
)
1116 if n
:= db
.numDepsPollUntil(4, time
.Second
); n
> 4 {
1117 t
.Errorf("number of dependencies = %d; expected <= 4", n
)
1122 opens
:= driver
.openCount
- opens0
1123 closes
:= driver
.closeCount
- closes0
1124 openDelta
:= (driver
.openCount
- driver
.closeCount
) - openDelta0
1128 t
.Logf("open calls = %d", opens
)
1129 t
.Logf("close calls = %d", closes
)
1130 t
.Logf("open delta = %d", openDelta
)
1131 t
.Errorf("db connections opened = %d; want <= 2", openDelta
)
1135 if len(stmt
.css
) > nquery
{
1136 t
.Errorf("len(stmt.css) = %d; want <= %d", len(stmt
.css
), nquery
)
1139 if err
:= stmt
.Close(); err
!= nil {
1143 if g
, w
:= db
.numFreeConns(), 2; g
!= w
{
1144 t
.Errorf("free conns = %d; want %d", g
, w
)
1147 if n
:= db
.numDepsPollUntil(2, time
.Second
); n
> 2 {
1148 t
.Errorf("number of dependencies = %d; expected <= 2", n
)
1152 db
.SetMaxIdleConns(0)
1154 if g
, w
:= db
.numFreeConns(), 0; g
!= w
{
1155 t
.Errorf("free conns = %d; want %d", g
, w
)
1158 if n
:= db
.numDepsPollUntil(0, time
.Second
); n
> 0 {
1159 t
.Errorf("number of dependencies = %d; expected 0", n
)
1164 // golang.org/issue/5046
1165 func TestCloseConnBeforeStmts(t
*testing
.T
) {
1166 db
:= newTestDB(t
, "people")
1167 defer closeDB(t
, db
)
1169 defer setHookpostCloseConn(nil)
1170 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
1172 t
.Errorf("Error closing fakeConn: %v; from %s", err
, stack())
1174 t
.Errorf("DB = %#v", db
)
1178 stmt
, err
:= db
.Prepare("SELECT|people|name|")
1183 if db
.freeConn
.Len() != 1 {
1184 t
.Fatalf("expected 1 freeConn; got %d", db
.freeConn
.Len())
1186 dc
:= db
.freeConn
.Front().Value
.(*driverConn
)
1188 t
.Errorf("conn shouldn't be closed")
1191 if n
:= len(dc
.openStmt
); n
!= 1 {
1192 t
.Errorf("driverConn num openStmt = %d; want 1", n
)
1196 t
.Errorf("db Close = %v", err
)
1199 t
.Errorf("after db.Close, driverConn should be closed")
1201 if n
:= len(dc
.openStmt
); n
!= 0 {
1202 t
.Errorf("driverConn num openStmt = %d; want 0", n
)
1207 t
.Errorf("Stmt close = %v", err
)
1211 t
.Errorf("conn should be closed")
1214 t
.Errorf("after Stmt Close, driverConn's Conn interface should be nil")
1218 // golang.org/issue/5283: don't release the Rows' connection in Close
1219 // before calling Stmt.Close.
1220 func TestRowsCloseOrder(t
*testing
.T
) {
1221 db
:= newTestDB(t
, "people")
1222 defer closeDB(t
, db
)
1224 db
.SetMaxIdleConns(0)
1225 setStrictFakeConnClose(t
)
1226 defer setStrictFakeConnClose(nil)
1228 rows
, err
:= db
.Query("SELECT|people|age,name|")
1238 func TestRowsImplicitClose(t
*testing
.T
) {
1239 db
:= newTestDB(t
, "people")
1240 defer closeDB(t
, db
)
1242 rows
, err
:= db
.Query("SELECT|people|age,name|")
1247 want
, fail
:= 2, errors
.New("fail")
1248 r
:= rows
.rowsi
.(*rowsCursor
)
1249 r
.errPos
, r
.err
= want
, fail
1256 t
.Errorf("got %d rows, want %d", got
, want
)
1258 if err
:= rows
.Err(); err
!= fail
{
1259 t
.Errorf("got error %v, want %v", err
, fail
)
1262 t
.Errorf("r.closed is false, want true")
1266 func TestStmtCloseOrder(t
*testing
.T
) {
1267 db
:= newTestDB(t
, "people")
1268 defer closeDB(t
, db
)
1270 db
.SetMaxIdleConns(0)
1271 setStrictFakeConnClose(t
)
1272 defer setStrictFakeConnClose(nil)
1274 _
, err
:= db
.Query("SELECT|non_existent|name|")
1276 t
.Fatal("Quering non-existent table should fail")
1280 // golang.org/issue/5781
1281 func TestErrBadConnReconnect(t
*testing
.T
) {
1282 db
:= newTestDB(t
, "foo")
1283 defer closeDB(t
, db
)
1284 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1286 simulateBadConn
:= func(name
string, hook
*func() bool, op
func() error
) {
1287 broken
, retried
:= false, false
1288 numOpen
:= db
.numOpen
1290 // simulate a broken connection on the first try
1291 *hook
= func() bool {
1300 if err
:= op(); err
!= nil {
1301 t
.Errorf(name
+": %v", err
)
1305 if !broken ||
!retried
{
1306 t
.Error(name
+ ": Failed to simulate broken connection")
1310 if numOpen
!= db
.numOpen
{
1311 t
.Errorf(name
+": leaked %d connection(s)!", db
.numOpen
-numOpen
)
1312 numOpen
= db
.numOpen
1317 dbExec
:= func() error
{
1318 _
, err
:= db
.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
1321 simulateBadConn("db.Exec prepare", &hookPrepareBadConn
, dbExec
)
1322 simulateBadConn("db.Exec exec", &hookExecBadConn
, dbExec
)
1325 dbQuery
:= func() error
{
1326 rows
, err
:= db
.Query("SELECT|t1|age,name|")
1332 simulateBadConn("db.Query prepare", &hookPrepareBadConn
, dbQuery
)
1333 simulateBadConn("db.Query query", &hookQueryBadConn
, dbQuery
)
1336 simulateBadConn("db.Prepare", &hookPrepareBadConn
, func() error
{
1337 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?,dead=?")
1346 stmt1
, err
:= db
.Prepare("INSERT|t1|name=?,age=?,dead=?")
1348 t
.Fatalf("prepare: %v", err
)
1351 // make sure we must prepare the stmt first
1352 for _
, cs
:= range stmt1
.css
{
1356 stmtExec
:= func() error
{
1357 _
, err
:= stmt1
.Exec("Gopher", 3, false)
1360 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn
, stmtExec
)
1361 simulateBadConn("stmt.Exec exec", &hookExecBadConn
, stmtExec
)
1364 stmt2
, err
:= db
.Prepare("SELECT|t1|age,name|")
1366 t
.Fatalf("prepare: %v", err
)
1369 // make sure we must prepare the stmt first
1370 for _
, cs
:= range stmt2
.css
{
1374 stmtQuery
:= func() error
{
1375 rows
, err
:= stmt2
.Query()
1381 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn
, stmtQuery
)
1382 simulateBadConn("stmt.Query exec", &hookQueryBadConn
, stmtQuery
)
1385 type concurrentTest
interface {
1386 init(t testing
.TB
, db
*DB
)
1387 finish(t testing
.TB
)
1388 test(t testing
.TB
) error
1391 type concurrentDBQueryTest
struct {
1395 func (c
*concurrentDBQueryTest
) init(t testing
.TB
, db
*DB
) {
1399 func (c
*concurrentDBQueryTest
) finish(t testing
.TB
) {
1403 func (c
*concurrentDBQueryTest
) test(t testing
.TB
) error
{
1404 rows
, err
:= c
.db
.Query("SELECT|people|name|")
1417 type concurrentDBExecTest
struct {
1421 func (c
*concurrentDBExecTest
) init(t testing
.TB
, db
*DB
) {
1425 func (c
*concurrentDBExecTest
) finish(t testing
.TB
) {
1429 func (c
*concurrentDBExecTest
) test(t testing
.TB
) error
{
1430 _
, err
:= c
.db
.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday
)
1438 type concurrentStmtQueryTest
struct {
1443 func (c
*concurrentStmtQueryTest
) init(t testing
.TB
, db
*DB
) {
1446 c
.stmt
, err
= db
.Prepare("SELECT|people|name|")
1452 func (c
*concurrentStmtQueryTest
) finish(t testing
.TB
) {
1460 func (c
*concurrentStmtQueryTest
) test(t testing
.TB
) error
{
1461 rows
, err
:= c
.stmt
.Query()
1463 t
.Errorf("error on query: %v", err
)
1475 type concurrentStmtExecTest
struct {
1480 func (c
*concurrentStmtExecTest
) init(t testing
.TB
, db
*DB
) {
1483 c
.stmt
, err
= db
.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
1489 func (c
*concurrentStmtExecTest
) finish(t testing
.TB
) {
1497 func (c
*concurrentStmtExecTest
) test(t testing
.TB
) error
{
1498 _
, err
:= c
.stmt
.Exec(3, chrisBirthday
)
1500 t
.Errorf("error on exec: %v", err
)
1506 type concurrentTxQueryTest
struct {
1511 func (c
*concurrentTxQueryTest
) init(t testing
.TB
, db
*DB
) {
1514 c
.tx
, err
= c
.db
.Begin()
1520 func (c
*concurrentTxQueryTest
) finish(t testing
.TB
) {
1528 func (c
*concurrentTxQueryTest
) test(t testing
.TB
) error
{
1529 rows
, err
:= c
.db
.Query("SELECT|people|name|")
1542 type concurrentTxExecTest
struct {
1547 func (c
*concurrentTxExecTest
) init(t testing
.TB
, db
*DB
) {
1550 c
.tx
, err
= c
.db
.Begin()
1556 func (c
*concurrentTxExecTest
) finish(t testing
.TB
) {
1564 func (c
*concurrentTxExecTest
) test(t testing
.TB
) error
{
1565 _
, err
:= c
.tx
.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday
)
1573 type concurrentTxStmtQueryTest
struct {
1579 func (c
*concurrentTxStmtQueryTest
) init(t testing
.TB
, db
*DB
) {
1582 c
.tx
, err
= c
.db
.Begin()
1586 c
.stmt
, err
= c
.tx
.Prepare("SELECT|people|name|")
1592 func (c
*concurrentTxStmtQueryTest
) finish(t testing
.TB
) {
1604 func (c
*concurrentTxStmtQueryTest
) test(t testing
.TB
) error
{
1605 rows
, err
:= c
.stmt
.Query()
1607 t
.Errorf("error on query: %v", err
)
1619 type concurrentTxStmtExecTest
struct {
1625 func (c
*concurrentTxStmtExecTest
) init(t testing
.TB
, db
*DB
) {
1628 c
.tx
, err
= c
.db
.Begin()
1632 c
.stmt
, err
= c
.tx
.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
1638 func (c
*concurrentTxStmtExecTest
) finish(t testing
.TB
) {
1650 func (c
*concurrentTxStmtExecTest
) test(t testing
.TB
) error
{
1651 _
, err
:= c
.stmt
.Exec(3, chrisBirthday
)
1653 t
.Errorf("error on exec: %v", err
)
1659 type concurrentRandomTest
struct {
1660 tests
[]concurrentTest
1663 func (c
*concurrentRandomTest
) init(t testing
.TB
, db
*DB
) {
1664 c
.tests
= []concurrentTest
{
1665 new(concurrentDBQueryTest
),
1666 new(concurrentDBExecTest
),
1667 new(concurrentStmtQueryTest
),
1668 new(concurrentStmtExecTest
),
1669 new(concurrentTxQueryTest
),
1670 new(concurrentTxExecTest
),
1671 new(concurrentTxStmtQueryTest
),
1672 new(concurrentTxStmtExecTest
),
1674 for _
, ct
:= range c
.tests
{
1679 func (c
*concurrentRandomTest
) finish(t testing
.TB
) {
1680 for _
, ct
:= range c
.tests
{
1685 func (c
*concurrentRandomTest
) test(t testing
.TB
) error
{
1686 ct
:= c
.tests
[rand
.Intn(len(c
.tests
))]
1690 func doConcurrentTest(t testing
.TB
, ct concurrentTest
) {
1691 maxProcs
, numReqs
:= 1, 500
1692 if testing
.Short() {
1693 maxProcs
, numReqs
= 4, 50
1695 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(maxProcs
))
1697 db
:= newTestDB(t
, "people")
1698 defer closeDB(t
, db
)
1703 var wg sync
.WaitGroup
1706 reqs
:= make(chan bool)
1709 for i
:= 0; i
< maxProcs
*2; i
++ {
1711 for _
= range reqs
{
1722 for i
:= 0; i
< numReqs
; i
++ {
1729 func manyConcurrentQueries(t testing
.TB
) {
1730 maxProcs
, numReqs
:= 16, 500
1731 if testing
.Short() {
1732 maxProcs
, numReqs
= 4, 50
1734 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(maxProcs
))
1736 db
:= newTestDB(t
, "people")
1737 defer closeDB(t
, db
)
1739 stmt
, err
:= db
.Prepare("SELECT|people|name|")
1745 var wg sync
.WaitGroup
1748 reqs
:= make(chan bool)
1751 for i
:= 0; i
< maxProcs
*2; i
++ {
1753 for _
= range reqs
{
1754 rows
, err
:= stmt
.Query()
1756 t
.Errorf("error on query: %v", err
)
1772 for i
:= 0; i
< numReqs
; i
++ {
1779 func TestIssue6081(t
*testing
.T
) {
1780 db
:= newTestDB(t
, "people")
1781 defer closeDB(t
, db
)
1783 drv
:= db
.driver
.(*fakeDriver
)
1785 opens0
:= drv
.openCount
1786 closes0
:= drv
.closeCount
1789 stmt
, err
:= db
.Prepare("SELECT|people|name|")
1793 rowsCloseHook
= func(rows
*Rows
, err
*error
) {
1794 *err
= driver
.ErrBadConn
1796 defer func() { rowsCloseHook
= nil }()
1797 for i
:= 0; i
< 10; i
++ {
1798 rows
, err
:= stmt
.Query()
1804 if n
:= len(stmt
.css
); n
> 1 {
1805 t
.Errorf("len(css slice) = %d; want <= 1", n
)
1808 if n
:= len(stmt
.css
); n
!= 0 {
1809 t
.Errorf("len(css slice) after Close = %d; want 0", n
)
1813 opens
:= drv
.openCount
- opens0
1814 closes
:= drv
.closeCount
- closes0
1817 t
.Errorf("opens = %d; want >= 9", opens
)
1820 t
.Errorf("closes = %d; want >= 9", closes
)
1824 func TestConcurrency(t
*testing
.T
) {
1825 doConcurrentTest(t
, new(concurrentDBQueryTest
))
1826 doConcurrentTest(t
, new(concurrentDBExecTest
))
1827 doConcurrentTest(t
, new(concurrentStmtQueryTest
))
1828 doConcurrentTest(t
, new(concurrentStmtExecTest
))
1829 doConcurrentTest(t
, new(concurrentTxQueryTest
))
1830 doConcurrentTest(t
, new(concurrentTxExecTest
))
1831 doConcurrentTest(t
, new(concurrentTxStmtQueryTest
))
1832 doConcurrentTest(t
, new(concurrentTxStmtExecTest
))
1833 doConcurrentTest(t
, new(concurrentRandomTest
))
1836 func TestConnectionLeak(t
*testing
.T
) {
1837 db
:= newTestDB(t
, "people")
1838 defer closeDB(t
, db
)
1839 // Start by opening defaultMaxIdleConns
1840 rows
:= make([]*Rows
, defaultMaxIdleConns
)
1841 // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open
1842 // a new connection and we can fill the idle queue with the released
1844 db
.SetMaxOpenConns(len(rows
) + 1)
1845 for ii
:= range rows
{
1846 r
, err
:= db
.Query("SELECT|people|name|")
1851 if err
:= r
.Err(); err
!= nil {
1856 // Now we have defaultMaxIdleConns busy connections. Open
1857 // a new one, but wait until the busy connections are released
1858 // before returning control to DB.
1859 drv
:= db
.driver
.(*fakeDriver
)
1860 drv
.waitCh
= make(chan struct{}, 1)
1861 drv
.waitingCh
= make(chan struct{}, 1)
1862 var wg sync
.WaitGroup
1865 r
, err
:= db
.Query("SELECT|people|name|")
1872 // Wait until the goroutine we've just created has started waiting.
1874 // Now close the busy connections. This provides a connection for
1875 // the blocked goroutine and then fills up the idle queue.
1876 for _
, v
:= range rows
{
1879 // At this point we give the new connection to DB. This connection is
1880 // now useless, since the idle queue is full and there are no pending
1881 // requests. DB should deal with this situation without leaking the
1883 drv
.waitCh
<- struct{}{}
1887 func BenchmarkConcurrentDBExec(b
*testing
.B
) {
1889 ct
:= new(concurrentDBExecTest
)
1890 for i
:= 0; i
< b
.N
; i
++ {
1891 doConcurrentTest(b
, ct
)
1895 func BenchmarkConcurrentStmtQuery(b
*testing
.B
) {
1897 ct
:= new(concurrentStmtQueryTest
)
1898 for i
:= 0; i
< b
.N
; i
++ {
1899 doConcurrentTest(b
, ct
)
1903 func BenchmarkConcurrentStmtExec(b
*testing
.B
) {
1905 ct
:= new(concurrentStmtExecTest
)
1906 for i
:= 0; i
< b
.N
; i
++ {
1907 doConcurrentTest(b
, ct
)
1911 func BenchmarkConcurrentTxQuery(b
*testing
.B
) {
1913 ct
:= new(concurrentTxQueryTest
)
1914 for i
:= 0; i
< b
.N
; i
++ {
1915 doConcurrentTest(b
, ct
)
1919 func BenchmarkConcurrentTxExec(b
*testing
.B
) {
1921 ct
:= new(concurrentTxExecTest
)
1922 for i
:= 0; i
< b
.N
; i
++ {
1923 doConcurrentTest(b
, ct
)
1927 func BenchmarkConcurrentTxStmtQuery(b
*testing
.B
) {
1929 ct
:= new(concurrentTxStmtQueryTest
)
1930 for i
:= 0; i
< b
.N
; i
++ {
1931 doConcurrentTest(b
, ct
)
1935 func BenchmarkConcurrentTxStmtExec(b
*testing
.B
) {
1937 ct
:= new(concurrentTxStmtExecTest
)
1938 for i
:= 0; i
< b
.N
; i
++ {
1939 doConcurrentTest(b
, ct
)
1943 func BenchmarkConcurrentRandom(b
*testing
.B
) {
1945 ct
:= new(concurrentRandomTest
)
1946 for i
:= 0; i
< b
.N
; i
++ {
1947 doConcurrentTest(b
, ct
)