1
2
3
4
5 package sql
6
7 import (
8 "context"
9 "database/sql/driver"
10 "errors"
11 "fmt"
12 "internal/race"
13 "internal/testenv"
14 "math/rand"
15 "reflect"
16 "runtime"
17 "slices"
18 "strings"
19 "sync"
20 "sync/atomic"
21 "testing"
22 "time"
23 )
24
25 func init() {
26 type dbConn struct {
27 db *DB
28 c *driverConn
29 }
30 freedFrom := make(map[dbConn]string)
31 var mu sync.Mutex
32 getFreedFrom := func(c dbConn) string {
33 mu.Lock()
34 defer mu.Unlock()
35 return freedFrom[c]
36 }
37 setFreedFrom := func(c dbConn, s string) {
38 mu.Lock()
39 defer mu.Unlock()
40 freedFrom[c] = s
41 }
42 putConnHook = func(db *DB, c *driverConn) {
43 if slices.Contains(db.freeConn, c) {
44
45
46
47 println("double free of conn. conflicts are:\nA) " + getFreedFrom(dbConn{db, c}) + "\n\nand\nB) " + stack())
48 panic("double free of conn.")
49 }
50 setFreedFrom(dbConn{db, c}, stack())
51 }
52 }
53
54
55
56 const pollDuration = 5 * time.Millisecond
57
58 const fakeDBName = "foo"
59
60 var chrisBirthday = time.Unix(123456789, 0)
61
62 func newTestDB(t testing.TB, name string) *DB {
63 return newTestDBConnector(t, &fakeConnector{name: fakeDBName}, name)
64 }
65
66 func newTestDBConnector(t testing.TB, fc *fakeConnector, name string) *DB {
67 fc.name = fakeDBName
68 db := OpenDB(fc)
69 if _, err := db.Exec("WIPE"); err != nil {
70 t.Fatalf("exec wipe: %v", err)
71 }
72 if name == "people" {
73 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
74 exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1)
75 exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2)
76 exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
77 }
78 if name == "magicquery" {
79
80 exec(t, db, "CREATE|magicquery|op=string,millis=int32")
81 exec(t, db, "INSERT|magicquery|op=sleep,millis=10")
82 }
83 if name == "tx_status" {
84
85 exec(t, db, "CREATE|tx_status|tx_status=string")
86 exec(t, db, "INSERT|tx_status|tx_status=invalid")
87 }
88 return db
89 }
90
91 func TestOpenDB(t *testing.T) {
92 db := OpenDB(dsnConnector{dsn: fakeDBName, driver: fdriver})
93 if db.Driver() != fdriver {
94 t.Fatalf("OpenDB should return the driver of the Connector")
95 }
96 }
97
98 func TestDriverPanic(t *testing.T) {
99
100 db, err := Open("test", fakeDBName)
101 if err != nil {
102 t.Fatalf("Open: %v", err)
103 }
104 expectPanic := func(name string, f func()) {
105 defer func() {
106 err := recover()
107 if err == nil {
108 t.Fatalf("%s did not panic", name)
109 }
110 }()
111 f()
112 }
113
114 expectPanic("Exec Exec", func() { db.Exec("PANIC|Exec|WIPE") })
115 exec(t, db, "WIPE")
116 expectPanic("Exec NumInput", func() { db.Exec("PANIC|NumInput|WIPE") })
117 exec(t, db, "WIPE")
118 expectPanic("Exec Close", func() { db.Exec("PANIC|Close|WIPE") })
119 exec(t, db, "WIPE")
120 exec(t, db, "PANIC|Query|WIPE")
121 exec(t, db, "WIPE")
122
123 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
124
125 expectPanic("Query Query", func() { db.Query("PANIC|Query|SELECT|people|age,name|") })
126 expectPanic("Query NumInput", func() { db.Query("PANIC|NumInput|SELECT|people|age,name|") })
127 expectPanic("Query Close", func() {
128 rows, err := db.Query("PANIC|Close|SELECT|people|age,name|")
129 if err != nil {
130 t.Fatal(err)
131 }
132 rows.Close()
133 })
134 db.Query("PANIC|Exec|SELECT|people|age,name|")
135 exec(t, db, "WIPE")
136 }
137
138 func exec(t testing.TB, db *DB, query string, args ...any) {
139 t.Helper()
140 _, err := db.Exec(query, args...)
141 if err != nil {
142 t.Fatalf("Exec of %q: %v", query, err)
143 }
144 }
145
146 func closeDB(t testing.TB, db *DB) {
147 if e := recover(); e != nil {
148 fmt.Printf("Panic: %v\n", e)
149 panic(e)
150 }
151 defer setHookpostCloseConn(nil)
152 setHookpostCloseConn(func(_ *fakeConn, err error) {
153 if err != nil {
154 t.Errorf("Error closing fakeConn: %v", err)
155 }
156 })
157 db.mu.Lock()
158 for i, dc := range db.freeConn {
159 if n := len(dc.openStmt); n > 0 {
160
161
162
163
164
165 t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n)
166 }
167 }
168 db.mu.Unlock()
169
170 err := db.Close()
171 if err != nil {
172 t.Fatalf("error closing DB: %v", err)
173 }
174
175 var numOpen int
176 if !waitCondition(t, func() bool {
177 numOpen = db.numOpenConns()
178 return numOpen == 0
179 }) {
180 t.Fatalf("%d connections still open after closing DB", numOpen)
181 }
182 }
183
184
185
186 func numPrepares(t *testing.T, db *DB) int {
187 if n := len(db.freeConn); n != 1 {
188 t.Fatalf("free conns = %d; want 1", n)
189 }
190 return db.freeConn[0].ci.(*fakeConn).numPrepare
191 }
192
193 func (db *DB) numDeps() int {
194 db.mu.Lock()
195 defer db.mu.Unlock()
196 return len(db.dep)
197 }
198
199
200
201 func (db *DB) numDepsPoll(t *testing.T, want int) int {
202 var n int
203 waitCondition(t, func() bool {
204 n = db.numDeps()
205 return n <= want
206 })
207 return n
208 }
209
210 func (db *DB) numFreeConns() int {
211 db.mu.Lock()
212 defer db.mu.Unlock()
213 return len(db.freeConn)
214 }
215
216 func (db *DB) numOpenConns() int {
217 db.mu.Lock()
218 defer db.mu.Unlock()
219 return db.numOpen
220 }
221
222
223 func (db *DB) clearAllConns(t *testing.T) {
224 db.SetMaxIdleConns(0)
225
226 if g, w := db.numFreeConns(), 0; g != w {
227 t.Errorf("free conns = %d; want %d", g, w)
228 }
229
230 if n := db.numDepsPoll(t, 0); n > 0 {
231 t.Errorf("number of dependencies = %d; expected 0", n)
232 db.dumpDeps(t)
233 }
234 }
235
236 func (db *DB) dumpDeps(t *testing.T) {
237 for fc := range db.dep {
238 db.dumpDep(t, 0, fc, map[finalCloser]bool{})
239 }
240 }
241
242 func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) {
243 seen[dep] = true
244 indent := strings.Repeat(" ", depth)
245 ds := db.dep[dep]
246 for k := range ds {
247 t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k)
248 if fc, ok := k.(finalCloser); ok {
249 if !seen[fc] {
250 db.dumpDep(t, depth+1, fc, seen)
251 }
252 }
253 }
254 }
255
256 func TestQuery(t *testing.T) {
257 db := newTestDB(t, "people")
258 defer closeDB(t, db)
259 prepares0 := numPrepares(t, db)
260 rows, err := db.Query("SELECT|people|age,name|")
261 if err != nil {
262 t.Fatalf("Query: %v", err)
263 }
264 defer rows.Close()
265 type row struct {
266 age int
267 name string
268 }
269 got := []row{}
270 for rows.Next() {
271 var r row
272 err = rows.Scan(&r.age, &r.name)
273 if err != nil {
274 t.Fatalf("Scan: %v", err)
275 }
276 got = append(got, r)
277 }
278 err = rows.Err()
279 if err != nil {
280 t.Fatalf("Err: %v", err)
281 }
282 want := []row{
283 {age: 1, name: "Alice"},
284 {age: 2, name: "Bob"},
285 {age: 3, name: "Chris"},
286 }
287 if !slices.Equal(got, want) {
288 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
289 }
290
291
292
293 if n := db.numFreeConns(); n != 1 {
294 t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
295 }
296 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
297 t.Errorf("executed %d Prepare statements; want 1", prepares)
298 }
299 }
300
301
302 func TestQueryContext(t *testing.T) {
303 db := newTestDB(t, "people")
304 defer closeDB(t, db)
305 prepares0 := numPrepares(t, db)
306
307 ctx, cancel := context.WithCancel(context.Background())
308 defer cancel()
309
310 rows, err := db.QueryContext(ctx, "SELECT|people|age,name|")
311 if err != nil {
312 t.Fatalf("Query: %v", err)
313 }
314 type row struct {
315 age int
316 name string
317 }
318 got := []row{}
319 index := 0
320 for rows.Next() {
321 if index == 2 {
322 cancel()
323 waitForRowsClose(t, rows)
324 }
325 var r row
326 err = rows.Scan(&r.age, &r.name)
327 if err != nil {
328 if index == 2 {
329 break
330 }
331 t.Fatalf("Scan: %v", err)
332 }
333 if index == 2 && err != context.Canceled {
334 t.Fatalf("Scan: %v; want context.Canceled", err)
335 }
336 got = append(got, r)
337 index++
338 }
339 select {
340 case <-ctx.Done():
341 if err := ctx.Err(); err != context.Canceled {
342 t.Fatalf("context err = %v; want context.Canceled", err)
343 }
344 default:
345 t.Fatalf("context err = nil; want context.Canceled")
346 }
347 want := []row{
348 {age: 1, name: "Alice"},
349 {age: 2, name: "Bob"},
350 }
351 if !slices.Equal(got, want) {
352 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
353 }
354
355
356
357 waitForRowsClose(t, rows)
358 waitForFree(t, db, 1)
359 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
360 t.Errorf("executed %d Prepare statements; want 1", prepares)
361 }
362 }
363
364 func waitCondition(t testing.TB, fn func() bool) bool {
365 timeout := 5 * time.Second
366
367 type deadliner interface {
368 Deadline() (time.Time, bool)
369 }
370 if td, ok := t.(deadliner); ok {
371 if deadline, ok := td.Deadline(); ok {
372 timeout = time.Until(deadline)
373 timeout = timeout * 19 / 20
374 }
375 }
376
377 deadline := time.Now().Add(timeout)
378 for {
379 if fn() {
380 return true
381 }
382 if time.Until(deadline) < pollDuration {
383 return false
384 }
385 time.Sleep(pollDuration)
386 }
387 }
388
389
390
391 func waitForFree(t *testing.T, db *DB, want int) {
392 var numFree int
393 if !waitCondition(t, func() bool {
394 numFree = db.numFreeConns()
395 return numFree == want
396 }) {
397 t.Fatalf("free conns after hitting EOF = %d; want %d", numFree, want)
398 }
399 }
400
401 func waitForRowsClose(t *testing.T, rows *Rows) {
402 if !waitCondition(t, func() bool {
403 rows.closemu.RLock()
404 defer rows.closemu.RUnlock()
405 return rows.closed
406 }) {
407 t.Fatal("failed to close rows")
408 }
409 }
410
411
412
413 func TestQueryContextWait(t *testing.T) {
414 db := newTestDB(t, "people")
415 defer closeDB(t, db)
416 prepares0 := numPrepares(t, db)
417
418 ctx, cancel := context.WithCancel(context.Background())
419 defer cancel()
420
421
422
423
424 c, err := db.Conn(ctx)
425 if err != nil {
426 t.Fatal(err)
427 }
428
429 c.dc.ci.(*fakeConn).waiter = func(c context.Context) {
430 cancel()
431 <-ctx.Done()
432 }
433 _, err = c.QueryContext(ctx, "SELECT|people|age,name|")
434 c.Close()
435 if err != context.Canceled {
436 t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
437 }
438
439
440 waitForFree(t, db, 1)
441 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
442 t.Fatalf("executed %d Prepare statements; want 1", prepares)
443 }
444 }
445
446
447
448 func TestTxContextWait(t *testing.T) {
449 testContextWait(t, false)
450 }
451
452
453
454 func TestTxContextWaitNoDiscard(t *testing.T) {
455 testContextWait(t, true)
456 }
457
458 func testContextWait(t *testing.T, keepConnOnRollback bool) {
459 db := newTestDB(t, "people")
460 defer closeDB(t, db)
461
462 ctx, cancel := context.WithCancel(context.Background())
463
464 tx, err := db.BeginTx(ctx, nil)
465 if err != nil {
466 t.Fatal(err)
467 }
468 tx.keepConnOnRollback = keepConnOnRollback
469
470 tx.dc.ci.(*fakeConn).waiter = func(c context.Context) {
471 cancel()
472 <-ctx.Done()
473 }
474
475
476
477 _, err = tx.QueryContext(ctx, "SELECT|people|age,name|")
478 if err != context.Canceled {
479 t.Fatalf("expected QueryContext to error with context canceled but returned %v", err)
480 }
481
482 if keepConnOnRollback {
483 waitForFree(t, db, 1)
484 } else {
485 waitForFree(t, db, 0)
486 }
487 }
488
489
490
491
492 func TestUnsupportedOptions(t *testing.T) {
493 db := newTestDB(t, "people")
494 defer closeDB(t, db)
495 _, err := db.BeginTx(context.Background(), &TxOptions{
496 Isolation: LevelSerializable, ReadOnly: true,
497 })
498 if err == nil {
499 t.Fatal("expected error when using unsupported options, got nil")
500 }
501 }
502
503 func TestMultiResultSetQuery(t *testing.T) {
504 db := newTestDB(t, "people")
505 defer closeDB(t, db)
506 prepares0 := numPrepares(t, db)
507 rows, err := db.Query("SELECT|people|age,name|;SELECT|people|name|")
508 if err != nil {
509 t.Fatalf("Query: %v", err)
510 }
511 type row1 struct {
512 age int
513 name string
514 }
515 type row2 struct {
516 name string
517 }
518 got1 := []row1{}
519 for rows.Next() {
520 var r row1
521 err = rows.Scan(&r.age, &r.name)
522 if err != nil {
523 t.Fatalf("Scan: %v", err)
524 }
525 got1 = append(got1, r)
526 }
527 err = rows.Err()
528 if err != nil {
529 t.Fatalf("Err: %v", err)
530 }
531 want1 := []row1{
532 {age: 1, name: "Alice"},
533 {age: 2, name: "Bob"},
534 {age: 3, name: "Chris"},
535 }
536 if !slices.Equal(got1, want1) {
537 t.Errorf("mismatch.\n got1: %#v\nwant: %#v", got1, want1)
538 }
539
540 if !rows.NextResultSet() {
541 t.Errorf("expected another result set")
542 }
543
544 got2 := []row2{}
545 for rows.Next() {
546 var r row2
547 err = rows.Scan(&r.name)
548 if err != nil {
549 t.Fatalf("Scan: %v", err)
550 }
551 got2 = append(got2, r)
552 }
553 err = rows.Err()
554 if err != nil {
555 t.Fatalf("Err: %v", err)
556 }
557 want2 := []row2{
558 {name: "Alice"},
559 {name: "Bob"},
560 {name: "Chris"},
561 }
562 if !slices.Equal(got2, want2) {
563 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got2, want2)
564 }
565 if rows.NextResultSet() {
566 t.Errorf("expected no more result sets")
567 }
568
569
570
571 waitForFree(t, db, 1)
572 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
573 t.Errorf("executed %d Prepare statements; want 1", prepares)
574 }
575 }
576
577 func TestQueryNamedArg(t *testing.T) {
578 db := newTestDB(t, "people")
579 defer closeDB(t, db)
580 prepares0 := numPrepares(t, db)
581 rows, err := db.Query(
582
583 "SELECT|people|age,name|name=?name,age=?age",
584 Named("age", 2),
585 Named("name", "Bob"),
586 )
587 if err != nil {
588 t.Fatalf("Query: %v", err)
589 }
590 type row struct {
591 age int
592 name string
593 }
594 got := []row{}
595 for rows.Next() {
596 var r row
597 err = rows.Scan(&r.age, &r.name)
598 if err != nil {
599 t.Fatalf("Scan: %v", err)
600 }
601 got = append(got, r)
602 }
603 err = rows.Err()
604 if err != nil {
605 t.Fatalf("Err: %v", err)
606 }
607 want := []row{
608 {age: 2, name: "Bob"},
609 }
610 if !slices.Equal(got, want) {
611 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
612 }
613
614
615
616 if n := db.numFreeConns(); n != 1 {
617 t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
618 }
619 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
620 t.Errorf("executed %d Prepare statements; want 1", prepares)
621 }
622 }
623
624 func TestPoolExhaustOnCancel(t *testing.T) {
625 if testing.Short() {
626 t.Skip("long test")
627 }
628
629 max := 3
630 var saturate, saturateDone sync.WaitGroup
631 saturate.Add(max)
632 saturateDone.Add(max)
633
634 donePing := make(chan bool)
635 state := 0
636
637
638
639
640
641
642
643 waiter := func(ctx context.Context) {
644 switch state {
645 case 0:
646
647 case 1:
648 saturate.Done()
649 select {
650 case <-ctx.Done():
651 case <-donePing:
652 }
653 case 2:
654 }
655 }
656 db := newTestDBConnector(t, &fakeConnector{waiter: waiter}, "people")
657 defer closeDB(t, db)
658
659 db.SetMaxOpenConns(max)
660
661
662
663
664 state = 1
665 for i := 0; i < max; i++ {
666 go func() {
667 rows, err := db.Query("SELECT|people|name,photo|")
668 if err != nil {
669 t.Errorf("Query: %v", err)
670 return
671 }
672 rows.Close()
673 saturateDone.Done()
674 }()
675 }
676
677 saturate.Wait()
678 if t.Failed() {
679 t.FailNow()
680 }
681 state = 2
682
683
684 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
685 defer cancel()
686
687 for i := 0; i < max; i++ {
688 ctxReq, cancelReq := context.WithCancel(ctx)
689 go func() {
690 time.Sleep(100 * time.Millisecond)
691 cancelReq()
692 }()
693 err := db.PingContext(ctxReq)
694 if err != context.Canceled {
695 t.Fatalf("PingContext (Exhaust): %v", err)
696 }
697 }
698 close(donePing)
699 saturateDone.Wait()
700
701
702 err := db.PingContext(ctx)
703 if err != nil {
704 t.Fatalf("PingContext (Normal): %v", err)
705 }
706 }
707
708 func TestRowsColumns(t *testing.T) {
709 db := newTestDB(t, "people")
710 defer closeDB(t, db)
711 rows, err := db.Query("SELECT|people|age,name|")
712 if err != nil {
713 t.Fatalf("Query: %v", err)
714 }
715 cols, err := rows.Columns()
716 if err != nil {
717 t.Fatalf("Columns: %v", err)
718 }
719 want := []string{"age", "name"}
720 if !slices.Equal(cols, want) {
721 t.Errorf("got %#v; want %#v", cols, want)
722 }
723 if err := rows.Close(); err != nil {
724 t.Errorf("error closing rows: %s", err)
725 }
726 }
727
728 func TestRowsColumnTypes(t *testing.T) {
729 db := newTestDB(t, "people")
730 defer closeDB(t, db)
731 rows, err := db.Query("SELECT|people|age,name|")
732 if err != nil {
733 t.Fatalf("Query: %v", err)
734 }
735 tt, err := rows.ColumnTypes()
736 if err != nil {
737 t.Fatalf("ColumnTypes: %v", err)
738 }
739
740 types := make([]reflect.Type, len(tt))
741 for i, tp := range tt {
742 st := tp.ScanType()
743 if st == nil {
744 t.Errorf("scantype is null for column %q", tp.Name())
745 continue
746 }
747 types[i] = st
748 }
749 values := make([]any, len(tt))
750 for i := range values {
751 values[i] = reflect.New(types[i]).Interface()
752 }
753 ct := 0
754 for rows.Next() {
755 err = rows.Scan(values...)
756 if err != nil {
757 t.Fatalf("failed to scan values in %v", err)
758 }
759 if ct == 1 {
760 if age := *values[0].(*int32); age != 2 {
761 t.Errorf("Expected 2, got %v", age)
762 }
763 if name := *values[1].(*string); name != "Bob" {
764 t.Errorf("Expected Bob, got %v", name)
765 }
766 }
767 ct++
768 }
769 if ct != 3 {
770 t.Errorf("expected 3 rows, got %d", ct)
771 }
772
773 if err := rows.Close(); err != nil {
774 t.Errorf("error closing rows: %s", err)
775 }
776 }
777
778 func TestQueryRow(t *testing.T) {
779 db := newTestDB(t, "people")
780 defer closeDB(t, db)
781 var name string
782 var age int
783 var birthday time.Time
784
785 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age)
786 if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") {
787 t.Errorf("expected error from wrong number of arguments; actually got: %v", err)
788 }
789
790 err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday)
791 if err != nil || !birthday.Equal(chrisBirthday) {
792 t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday)
793 }
794
795 err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name)
796 if err != nil {
797 t.Fatalf("age QueryRow+Scan: %v", err)
798 }
799 if name != "Bob" {
800 t.Errorf("expected name Bob, got %q", name)
801 }
802 if age != 2 {
803 t.Errorf("expected age 2, got %d", age)
804 }
805
806 err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name)
807 if err != nil {
808 t.Fatalf("name QueryRow+Scan: %v", err)
809 }
810 if name != "Alice" {
811 t.Errorf("expected name Alice, got %q", name)
812 }
813 if age != 1 {
814 t.Errorf("expected age 1, got %d", age)
815 }
816
817 var photo []byte
818 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
819 if err != nil {
820 t.Fatalf("photo QueryRow+Scan: %v", err)
821 }
822 want := []byte("APHOTO")
823 if !slices.Equal(photo, want) {
824 t.Errorf("photo = %q; want %q", photo, want)
825 }
826 }
827
828 func TestRowErr(t *testing.T) {
829 db := newTestDB(t, "people")
830
831 err := db.QueryRowContext(context.Background(), "SELECT|people|bdate|age=?", 3).Err()
832 if err != nil {
833 t.Errorf("Unexpected err = %v; want %v", err, nil)
834 }
835
836 ctx, cancel := context.WithCancel(context.Background())
837 cancel()
838
839 err = db.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 3).Err()
840 exp := "context canceled"
841 if err == nil || !strings.Contains(err.Error(), exp) {
842 t.Errorf("Expected err = %v; got %v", exp, err)
843 }
844 }
845
846 func TestTxRollbackCommitErr(t *testing.T) {
847 db := newTestDB(t, "people")
848 defer closeDB(t, db)
849
850 tx, err := db.Begin()
851 if err != nil {
852 t.Fatal(err)
853 }
854 err = tx.Rollback()
855 if err != nil {
856 t.Errorf("expected nil error from Rollback; got %v", err)
857 }
858 err = tx.Commit()
859 if err != ErrTxDone {
860 t.Errorf("expected %q from Commit; got %q", ErrTxDone, err)
861 }
862
863 tx, err = db.Begin()
864 if err != nil {
865 t.Fatal(err)
866 }
867 err = tx.Commit()
868 if err != nil {
869 t.Errorf("expected nil error from Commit; got %v", err)
870 }
871 err = tx.Rollback()
872 if err != ErrTxDone {
873 t.Errorf("expected %q from Rollback; got %q", ErrTxDone, err)
874 }
875 }
876
877 func TestStatementErrorAfterClose(t *testing.T) {
878 db := newTestDB(t, "people")
879 defer closeDB(t, db)
880 stmt, err := db.Prepare("SELECT|people|age|name=?")
881 if err != nil {
882 t.Fatalf("Prepare: %v", err)
883 }
884 err = stmt.Close()
885 if err != nil {
886 t.Fatalf("Close: %v", err)
887 }
888 var name string
889 err = stmt.QueryRow("foo").Scan(&name)
890 if err == nil {
891 t.Errorf("expected error from QueryRow.Scan after Stmt.Close")
892 }
893 }
894
895 func TestStatementQueryRow(t *testing.T) {
896 db := newTestDB(t, "people")
897 defer closeDB(t, db)
898 stmt, err := db.Prepare("SELECT|people|age|name=?")
899 if err != nil {
900 t.Fatalf("Prepare: %v", err)
901 }
902 defer stmt.Close()
903 var age int
904 for n, tt := range []struct {
905 name string
906 want int
907 }{
908 {"Alice", 1},
909 {"Bob", 2},
910 {"Chris", 3},
911 } {
912 if err := stmt.QueryRow(tt.name).Scan(&age); err != nil {
913 t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err)
914 } else if age != tt.want {
915 t.Errorf("%d: age=%d, want %d", n, age, tt.want)
916 }
917 }
918 }
919
920 type stubDriverStmt struct {
921 err error
922 }
923
924 func (s stubDriverStmt) Close() error {
925 return s.err
926 }
927
928 func (s stubDriverStmt) NumInput() int {
929 return -1
930 }
931
932 func (s stubDriverStmt) Exec(args []driver.Value) (driver.Result, error) {
933 return nil, nil
934 }
935
936 func (s stubDriverStmt) Query(args []driver.Value) (driver.Rows, error) {
937 return nil, nil
938 }
939
940
941 func TestStatementClose(t *testing.T) {
942 want := errors.New("STMT ERROR")
943
944 tests := []struct {
945 stmt *Stmt
946 msg string
947 }{
948 {&Stmt{stickyErr: want}, "stickyErr not propagated"},
949 {&Stmt{cg: &Tx{}, cgds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
950 }
951 for _, test := range tests {
952 if err := test.stmt.Close(); err != want {
953 t.Errorf("%s. Got stmt.Close() = %v, want = %v", test.msg, err, want)
954 }
955 }
956 }
957
958
959 func TestStatementQueryRowConcurrent(t *testing.T) {
960 db := newTestDB(t, "people")
961 defer closeDB(t, db)
962 stmt, err := db.Prepare("SELECT|people|age|name=?")
963 if err != nil {
964 t.Fatalf("Prepare: %v", err)
965 }
966 defer stmt.Close()
967
968 const n = 10
969 ch := make(chan error, n)
970 for i := 0; i < n; i++ {
971 go func() {
972 var age int
973 err := stmt.QueryRow("Alice").Scan(&age)
974 if err == nil && age != 1 {
975 err = fmt.Errorf("unexpected age %d", age)
976 }
977 ch <- err
978 }()
979 }
980 for i := 0; i < n; i++ {
981 if err := <-ch; err != nil {
982 t.Error(err)
983 }
984 }
985 }
986
987
988 func TestBogusPreboundParameters(t *testing.T) {
989 db := newTestDB(t, "foo")
990 defer closeDB(t, db)
991 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
992 _, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion")
993 if err == nil {
994 t.Fatalf("expected error")
995 }
996 if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` {
997 t.Errorf("unexpected error: %v", err)
998 }
999 }
1000
1001 func TestExec(t *testing.T) {
1002 db := newTestDB(t, "foo")
1003 defer closeDB(t, db)
1004 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
1005 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1006 if err != nil {
1007 t.Errorf("Stmt, err = %v, %v", stmt, err)
1008 }
1009 defer stmt.Close()
1010
1011 type execTest struct {
1012 args []any
1013 wantErr string
1014 }
1015 execTests := []execTest{
1016
1017 {[]any{"Brad", 31}, ""},
1018 {[]any{"Brad", int64(31)}, ""},
1019 {[]any{"Bob", "32"}, ""},
1020 {[]any{7, 9}, ""},
1021
1022
1023 {[]any{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument $2 type: sql/driver: value 4294967295 overflows int32"},
1024 {[]any{"Brad", "strconv fail"}, `sql: converting argument $2 type: sql/driver: value "strconv fail" can't be converted to int32`},
1025
1026
1027 {[]any{}, "sql: expected 2 arguments, got 0"},
1028 {[]any{1, 2, 3}, "sql: expected 2 arguments, got 3"},
1029 }
1030 for n, et := range execTests {
1031 _, err := stmt.Exec(et.args...)
1032 errStr := ""
1033 if err != nil {
1034 errStr = err.Error()
1035 }
1036 if errStr != et.wantErr {
1037 t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q",
1038 n, et.args, errStr, et.wantErr)
1039 }
1040 }
1041 }
1042
1043 func TestTxPrepare(t *testing.T) {
1044 db := newTestDB(t, "")
1045 defer closeDB(t, db)
1046 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
1047 tx, err := db.Begin()
1048 if err != nil {
1049 t.Fatalf("Begin = %v", err)
1050 }
1051 stmt, err := tx.Prepare("INSERT|t1|name=?,age=?")
1052 if err != nil {
1053 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1054 }
1055 defer stmt.Close()
1056 _, err = stmt.Exec("Bobby", 7)
1057 if err != nil {
1058 t.Fatalf("Exec = %v", err)
1059 }
1060 err = tx.Commit()
1061 if err != nil {
1062 t.Fatalf("Commit = %v", err)
1063 }
1064
1065 if !stmt.closed {
1066 t.Fatal("Stmt not closed after Commit")
1067 }
1068 }
1069
1070 func TestTxStmt(t *testing.T) {
1071 db := newTestDB(t, "")
1072 defer closeDB(t, db)
1073 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
1074 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1075 if err != nil {
1076 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1077 }
1078 defer stmt.Close()
1079 tx, err := db.Begin()
1080 if err != nil {
1081 t.Fatalf("Begin = %v", err)
1082 }
1083 txs := tx.Stmt(stmt)
1084 defer txs.Close()
1085 _, err = txs.Exec("Bobby", 7)
1086 if err != nil {
1087 t.Fatalf("Exec = %v", err)
1088 }
1089 err = tx.Commit()
1090 if err != nil {
1091 t.Fatalf("Commit = %v", err)
1092 }
1093
1094 if !txs.closed {
1095 t.Fatal("Stmt not closed after Commit")
1096 }
1097 }
1098
1099 func TestTxStmtPreparedOnce(t *testing.T) {
1100 db := newTestDB(t, "")
1101 defer closeDB(t, db)
1102 exec(t, db, "CREATE|t1|name=string,age=int32")
1103
1104 prepares0 := numPrepares(t, db)
1105
1106
1107 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1108 if err != nil {
1109 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1110 }
1111 defer stmt.Close()
1112
1113 tx, err := db.Begin()
1114 if err != nil {
1115 t.Fatalf("Begin = %v", err)
1116 }
1117
1118 txs1 := tx.Stmt(stmt)
1119 txs2 := tx.Stmt(stmt)
1120
1121 _, err = txs1.Exec("Go", 7)
1122 if err != nil {
1123 t.Fatalf("Exec = %v", err)
1124 }
1125 txs1.Close()
1126
1127 _, err = txs2.Exec("Gopher", 8)
1128 if err != nil {
1129 t.Fatalf("Exec = %v", err)
1130 }
1131 txs2.Close()
1132
1133 err = tx.Commit()
1134 if err != nil {
1135 t.Fatalf("Commit = %v", err)
1136 }
1137
1138 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
1139 t.Errorf("executed %d Prepare statements; want 1", prepares)
1140 }
1141 }
1142
1143 func TestTxStmtClosedRePrepares(t *testing.T) {
1144 db := newTestDB(t, "")
1145 defer closeDB(t, db)
1146 exec(t, db, "CREATE|t1|name=string,age=int32")
1147
1148 prepares0 := numPrepares(t, db)
1149
1150
1151 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1152 if err != nil {
1153 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1154 }
1155 tx, err := db.Begin()
1156 if err != nil {
1157 t.Fatalf("Begin = %v", err)
1158 }
1159 err = stmt.Close()
1160 if err != nil {
1161 t.Fatalf("stmt.Close() = %v", err)
1162 }
1163
1164 txs := tx.Stmt(stmt)
1165 if txs.stickyErr != nil {
1166 t.Fatal(txs.stickyErr)
1167 }
1168 if txs.parentStmt != nil {
1169 t.Fatal("expected nil parentStmt")
1170 }
1171 _, err = txs.Exec(`Eric`, 82)
1172 if err != nil {
1173 t.Fatalf("txs.Exec = %v", err)
1174 }
1175
1176 err = txs.Close()
1177 if err != nil {
1178 t.Fatalf("txs.Close = %v", err)
1179 }
1180
1181 tx.Rollback()
1182
1183 if prepares := numPrepares(t, db) - prepares0; prepares != 2 {
1184 t.Errorf("executed %d Prepare statements; want 2", prepares)
1185 }
1186 }
1187
1188 func TestParentStmtOutlivesTxStmt(t *testing.T) {
1189 db := newTestDB(t, "")
1190 defer closeDB(t, db)
1191 exec(t, db, "CREATE|t1|name=string,age=int32")
1192
1193
1194 db.SetMaxOpenConns(1)
1195
1196 prepares0 := numPrepares(t, db)
1197
1198
1199 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1200 if err != nil {
1201 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1202 }
1203 defer stmt.Close()
1204 tx, err := db.Begin()
1205 if err != nil {
1206 t.Fatalf("Begin = %v", err)
1207 }
1208 txs := tx.Stmt(stmt)
1209 if len(stmt.css) != 1 {
1210 t.Fatalf("len(stmt.css) = %v; want 1", len(stmt.css))
1211 }
1212 err = txs.Close()
1213 if err != nil {
1214 t.Fatalf("txs.Close() = %v", err)
1215 }
1216 err = tx.Rollback()
1217 if err != nil {
1218 t.Fatalf("tx.Rollback() = %v", err)
1219 }
1220
1221 _, err = txs.Exec("Suzan", 30)
1222 if err == nil {
1223 t.Fatalf("txs.Exec(), expected err")
1224 }
1225
1226 _, err = stmt.Exec("Janina", 25)
1227 if err != nil {
1228 t.Fatalf("stmt.Exec() = %v", err)
1229 }
1230
1231 if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
1232 t.Errorf("executed %d Prepare statements; want 1", prepares)
1233 }
1234 }
1235
1236
1237
1238
1239 func TestTxStmtFromTxStmtRePrepares(t *testing.T) {
1240 db := newTestDB(t, "")
1241 defer closeDB(t, db)
1242 exec(t, db, "CREATE|t1|name=string,age=int32")
1243 prepares0 := numPrepares(t, db)
1244
1245 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1246 if err != nil {
1247 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1248 }
1249 defer stmt.Close()
1250
1251 tx, err := db.Begin()
1252 if err != nil {
1253 t.Fatalf("Begin = %v", err)
1254 }
1255 txs1 := tx.Stmt(stmt)
1256
1257
1258
1259 txs2 := tx.Stmt(txs1)
1260 if txs2.stickyErr != nil {
1261 t.Fatal(txs2.stickyErr)
1262 }
1263 if txs2.parentStmt != nil {
1264 t.Fatal("expected nil parentStmt")
1265 }
1266 _, err = txs2.Exec(`Eric`, 82)
1267 if err != nil {
1268 t.Fatal(err)
1269 }
1270
1271 err = txs1.Close()
1272 if err != nil {
1273 t.Fatalf("txs1.Close = %v", err)
1274 }
1275 err = txs2.Close()
1276 if err != nil {
1277 t.Fatalf("txs1.Close = %v", err)
1278 }
1279 err = tx.Rollback()
1280 if err != nil {
1281 t.Fatalf("tx.Rollback = %v", err)
1282 }
1283
1284 if prepares := numPrepares(t, db) - prepares0; prepares != 2 {
1285 t.Errorf("executed %d Prepare statements; want 2", prepares)
1286 }
1287 }
1288
1289
1290
1291
1292 func TestTxQuery(t *testing.T) {
1293 db := newTestDB(t, "")
1294 defer closeDB(t, db)
1295 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
1296 exec(t, db, "INSERT|t1|name=Alice")
1297
1298 tx, err := db.Begin()
1299 if err != nil {
1300 t.Fatal(err)
1301 }
1302 defer tx.Rollback()
1303
1304 r, err := tx.Query("SELECT|t1|name|")
1305 if err != nil {
1306 t.Fatal(err)
1307 }
1308 defer r.Close()
1309
1310 if !r.Next() {
1311 if r.Err() != nil {
1312 t.Fatal(r.Err())
1313 }
1314 t.Fatal("expected one row")
1315 }
1316
1317 var x string
1318 err = r.Scan(&x)
1319 if err != nil {
1320 t.Fatal(err)
1321 }
1322 }
1323
1324 func TestTxQueryInvalid(t *testing.T) {
1325 db := newTestDB(t, "")
1326 defer closeDB(t, db)
1327
1328 tx, err := db.Begin()
1329 if err != nil {
1330 t.Fatal(err)
1331 }
1332 defer tx.Rollback()
1333
1334 _, err = tx.Query("SELECT|t1|name|")
1335 if err == nil {
1336 t.Fatal("Error expected")
1337 }
1338 }
1339
1340
1341
1342 func TestTxErrBadConn(t *testing.T) {
1343 db, err := Open("test", fakeDBName+";badConn")
1344 if err != nil {
1345 t.Fatalf("Open: %v", err)
1346 }
1347 if _, err := db.Exec("WIPE"); err != nil {
1348 t.Fatalf("exec wipe: %v", err)
1349 }
1350 defer closeDB(t, db)
1351 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
1352 stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
1353 if err != nil {
1354 t.Fatalf("Stmt, err = %v, %v", stmt, err)
1355 }
1356 defer stmt.Close()
1357 tx, err := db.Begin()
1358 if err != nil {
1359 t.Fatalf("Begin = %v", err)
1360 }
1361 txs := tx.Stmt(stmt)
1362 defer txs.Close()
1363 _, err = txs.Exec("Bobby", 7)
1364 if err != nil {
1365 t.Fatalf("Exec = %v", err)
1366 }
1367 err = tx.Commit()
1368 if err != nil {
1369 t.Fatalf("Commit = %v", err)
1370 }
1371 }
1372
1373 func TestConnQuery(t *testing.T) {
1374 db := newTestDB(t, "people")
1375 defer closeDB(t, db)
1376
1377 ctx, cancel := context.WithCancel(context.Background())
1378 defer cancel()
1379 conn, err := db.Conn(ctx)
1380 if err != nil {
1381 t.Fatal(err)
1382 }
1383 conn.dc.ci.(*fakeConn).skipDirtySession = true
1384 defer conn.Close()
1385
1386 var name string
1387 err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", 3).Scan(&name)
1388 if err != nil {
1389 t.Fatal(err)
1390 }
1391 if name != "Chris" {
1392 t.Fatalf("unexpected result, got %q want Chris", name)
1393 }
1394
1395 err = conn.PingContext(ctx)
1396 if err != nil {
1397 t.Fatal(err)
1398 }
1399 }
1400
1401 func TestConnRaw(t *testing.T) {
1402 db := newTestDB(t, "people")
1403 defer closeDB(t, db)
1404
1405 ctx, cancel := context.WithCancel(context.Background())
1406 defer cancel()
1407 conn, err := db.Conn(ctx)
1408 if err != nil {
1409 t.Fatal(err)
1410 }
1411 conn.dc.ci.(*fakeConn).skipDirtySession = true
1412 defer conn.Close()
1413
1414 sawFunc := false
1415 err = conn.Raw(func(dc any) error {
1416 sawFunc = true
1417 if _, ok := dc.(*fakeConn); !ok {
1418 return fmt.Errorf("got %T want *fakeConn", dc)
1419 }
1420 return nil
1421 })
1422 if err != nil {
1423 t.Fatal(err)
1424 }
1425 if !sawFunc {
1426 t.Fatal("Raw func not called")
1427 }
1428
1429 func() {
1430 defer func() {
1431 x := recover()
1432 if x == nil {
1433 t.Fatal("expected panic")
1434 }
1435 conn.closemu.Lock()
1436 closed := conn.dc == nil
1437 conn.closemu.Unlock()
1438 if !closed {
1439 t.Fatal("expected connection to be closed after panic")
1440 }
1441 }()
1442 err = conn.Raw(func(dc any) error {
1443 panic("Conn.Raw panic should return an error")
1444 })
1445 t.Fatal("expected panic from Raw func")
1446 }()
1447 }
1448
1449 func TestCursorFake(t *testing.T) {
1450 db := newTestDB(t, "people")
1451 defer closeDB(t, db)
1452
1453 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
1454 defer cancel()
1455
1456 exec(t, db, "CREATE|peoplecursor|list=table")
1457 exec(t, db, "INSERT|peoplecursor|list=people!name!age")
1458
1459 rows, err := db.QueryContext(ctx, `SELECT|peoplecursor|list|`)
1460 if err != nil {
1461 t.Fatal(err)
1462 }
1463 defer rows.Close()
1464
1465 if !rows.Next() {
1466 t.Fatal("no rows")
1467 }
1468 var cursor = &Rows{}
1469 err = rows.Scan(cursor)
1470 if err != nil {
1471 t.Fatal(err)
1472 }
1473 defer cursor.Close()
1474
1475 const expectedRows = 3
1476 var currentRow int64
1477
1478 var n int64
1479 var s string
1480 for cursor.Next() {
1481 currentRow++
1482 err = cursor.Scan(&s, &n)
1483 if err != nil {
1484 t.Fatal(err)
1485 }
1486 if n != currentRow {
1487 t.Errorf("expected number(Age)=%d, got %d", currentRow, n)
1488 }
1489 }
1490 if currentRow != expectedRows {
1491 t.Errorf("expected %d rows, got %d rows", expectedRows, currentRow)
1492 }
1493 }
1494
1495 func TestInvalidNilValues(t *testing.T) {
1496 var date1 time.Time
1497 var date2 int
1498
1499 tests := []struct {
1500 name string
1501 input any
1502 expectedError string
1503 }{
1504 {
1505 name: "time.Time",
1506 input: &date1,
1507 expectedError: `sql: Scan error on column index 0, name "bdate": unsupported Scan, storing driver.Value type <nil> into type *time.Time`,
1508 },
1509 {
1510 name: "int",
1511 input: &date2,
1512 expectedError: `sql: Scan error on column index 0, name "bdate": converting NULL to int is unsupported`,
1513 },
1514 }
1515
1516 for _, tt := range tests {
1517 t.Run(tt.name, func(t *testing.T) {
1518 db := newTestDB(t, "people")
1519 defer closeDB(t, db)
1520
1521 ctx, cancel := context.WithCancel(context.Background())
1522 defer cancel()
1523 conn, err := db.Conn(ctx)
1524 if err != nil {
1525 t.Fatal(err)
1526 }
1527 conn.dc.ci.(*fakeConn).skipDirtySession = true
1528 defer conn.Close()
1529
1530 err = conn.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 1).Scan(tt.input)
1531 if err == nil {
1532 t.Fatal("expected error when querying nil column, but succeeded")
1533 }
1534 if err.Error() != tt.expectedError {
1535 t.Fatalf("Expected error: %s\nReceived: %s", tt.expectedError, err.Error())
1536 }
1537
1538 err = conn.PingContext(ctx)
1539 if err != nil {
1540 t.Fatal(err)
1541 }
1542 })
1543 }
1544 }
1545
1546 func TestConnTx(t *testing.T) {
1547 db := newTestDB(t, "people")
1548 defer closeDB(t, db)
1549
1550 ctx, cancel := context.WithCancel(context.Background())
1551 defer cancel()
1552 conn, err := db.Conn(ctx)
1553 if err != nil {
1554 t.Fatal(err)
1555 }
1556 conn.dc.ci.(*fakeConn).skipDirtySession = true
1557 defer conn.Close()
1558
1559 tx, err := conn.BeginTx(ctx, nil)
1560 if err != nil {
1561 t.Fatal(err)
1562 }
1563 insertName, insertAge := "Nancy", 33
1564 _, err = tx.ExecContext(ctx, "INSERT|people|name=?,age=?,photo=APHOTO", insertName, insertAge)
1565 if err != nil {
1566 t.Fatal(err)
1567 }
1568 err = tx.Commit()
1569 if err != nil {
1570 t.Fatal(err)
1571 }
1572
1573 var selectName string
1574 err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", insertAge).Scan(&selectName)
1575 if err != nil {
1576 t.Fatal(err)
1577 }
1578 if selectName != insertName {
1579 t.Fatalf("got %q want %q", selectName, insertName)
1580 }
1581 }
1582
1583
1584
1585
1586 func TestConnIsValid(t *testing.T) {
1587 db := newTestDB(t, "people")
1588 defer closeDB(t, db)
1589
1590 db.SetMaxOpenConns(1)
1591
1592 ctx := context.Background()
1593
1594 c, err := db.Conn(ctx)
1595 if err != nil {
1596 t.Fatal(err)
1597 }
1598
1599 err = c.Raw(func(raw any) error {
1600 dc := raw.(*fakeConn)
1601 dc.stickyBad = true
1602 return nil
1603 })
1604 if err != nil {
1605 t.Fatal(err)
1606 }
1607 c.Close()
1608
1609 if len(db.freeConn) > 0 && db.freeConn[0].ci.(*fakeConn).stickyBad {
1610 t.Fatal("bad connection returned to pool; expected bad connection to be discarded")
1611 }
1612 }
1613
1614
1615
1616 func TestIssue2542Deadlock(t *testing.T) {
1617 db := newTestDB(t, "people")
1618 closeDB(t, db)
1619 for i := 0; i < 2; i++ {
1620 _, err := db.Query("SELECT|people|age,name|")
1621 if err == nil {
1622 t.Fatalf("expected error")
1623 }
1624 }
1625 }
1626
1627
1628 func TestCloseStmtBeforeRows(t *testing.T) {
1629 db := newTestDB(t, "people")
1630 defer closeDB(t, db)
1631
1632 s, err := db.Prepare("SELECT|people|name|")
1633 if err != nil {
1634 t.Fatal(err)
1635 }
1636
1637 r, err := s.Query()
1638 if err != nil {
1639 s.Close()
1640 t.Fatal(err)
1641 }
1642
1643 err = s.Close()
1644 if err != nil {
1645 t.Fatal(err)
1646 }
1647
1648 r.Close()
1649 }
1650
1651
1652
1653 func TestNullByteSlice(t *testing.T) {
1654 db := newTestDB(t, "")
1655 defer closeDB(t, db)
1656 exec(t, db, "CREATE|t|id=int32,name=nullstring")
1657 exec(t, db, "INSERT|t|id=10,name=?", nil)
1658
1659 var name []byte
1660
1661 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
1662 if err != nil {
1663 t.Fatal(err)
1664 }
1665 if name != nil {
1666 t.Fatalf("name []byte should be nil for null column value, got: %#v", name)
1667 }
1668
1669 exec(t, db, "INSERT|t|id=11,name=?", "bob")
1670 err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name)
1671 if err != nil {
1672 t.Fatal(err)
1673 }
1674 if string(name) != "bob" {
1675 t.Fatalf("name []byte should be bob, got: %q", string(name))
1676 }
1677 }
1678
1679 func TestPointerParamsAndScans(t *testing.T) {
1680 db := newTestDB(t, "")
1681 defer closeDB(t, db)
1682 exec(t, db, "CREATE|t|id=int32,name=nullstring")
1683
1684 bob := "bob"
1685 var name *string
1686
1687 name = &bob
1688 exec(t, db, "INSERT|t|id=10,name=?", name)
1689 name = nil
1690 exec(t, db, "INSERT|t|id=20,name=?", name)
1691
1692 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
1693 if err != nil {
1694 t.Fatalf("querying id 10: %v", err)
1695 }
1696 if name == nil {
1697 t.Errorf("id 10's name = nil; want bob")
1698 } else if *name != "bob" {
1699 t.Errorf("id 10's name = %q; want bob", *name)
1700 }
1701
1702 err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name)
1703 if err != nil {
1704 t.Fatalf("querying id 20: %v", err)
1705 }
1706 if name != nil {
1707 t.Errorf("id 20 = %q; want nil", *name)
1708 }
1709 }
1710
1711 func TestQueryRowClosingStmt(t *testing.T) {
1712 db := newTestDB(t, "people")
1713 defer closeDB(t, db)
1714 var name string
1715 var age int
1716 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name)
1717 if err != nil {
1718 t.Fatal(err)
1719 }
1720 if len(db.freeConn) != 1 {
1721 t.Fatalf("expected 1 free conn")
1722 }
1723 fakeConn := db.freeConn[0].ci.(*fakeConn)
1724 if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
1725 t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
1726 }
1727 }
1728
1729 var atomicRowsCloseHook atomic.Value
1730
1731 func init() {
1732 rowsCloseHook = func() func(*Rows, *error) {
1733 fn, _ := atomicRowsCloseHook.Load().(func(*Rows, *error))
1734 return fn
1735 }
1736 }
1737
1738 func setRowsCloseHook(fn func(*Rows, *error)) {
1739 if fn == nil {
1740
1741
1742 fn = func(*Rows, *error) {}
1743 }
1744 atomicRowsCloseHook.Store(fn)
1745 }
1746
1747
1748 func TestIssue6651(t *testing.T) {
1749 db := newTestDB(t, "people")
1750 defer closeDB(t, db)
1751
1752 var v string
1753
1754 want := "error in rows.Next"
1755 rowsCursorNextHook = func(dest []driver.Value) error {
1756 return errors.New(want)
1757 }
1758 defer func() { rowsCursorNextHook = nil }()
1759
1760 err := db.QueryRow("SELECT|people|name|").Scan(&v)
1761 if err == nil || err.Error() != want {
1762 t.Errorf("error = %q; want %q", err, want)
1763 }
1764 rowsCursorNextHook = nil
1765
1766 want = "error in rows.Close"
1767 setRowsCloseHook(func(rows *Rows, err *error) {
1768 *err = errors.New(want)
1769 })
1770 defer setRowsCloseHook(nil)
1771 err = db.QueryRow("SELECT|people|name|").Scan(&v)
1772 if err == nil || err.Error() != want {
1773 t.Errorf("error = %q; want %q", err, want)
1774 }
1775 }
1776
1777 type nullTestRow struct {
1778 nullParam any
1779 notNullParam any
1780 scanNullVal any
1781 }
1782
1783 type nullTestSpec struct {
1784 nullType string
1785 notNullType string
1786 rows [6]nullTestRow
1787 }
1788
1789 func TestNullStringParam(t *testing.T) {
1790 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
1791 {NullString{"aqua", true}, "", NullString{"aqua", true}},
1792 {NullString{"brown", false}, "", NullString{"", false}},
1793 {"chartreuse", "", NullString{"chartreuse", true}},
1794 {NullString{"darkred", true}, "", NullString{"darkred", true}},
1795 {NullString{"eel", false}, "", NullString{"", false}},
1796 {"foo", NullString{"black", false}, nil},
1797 }}
1798 nullTestRun(t, spec)
1799 }
1800
1801 func TestGenericNullStringParam(t *testing.T) {
1802 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
1803 {Null[string]{"aqua", true}, "", Null[string]{"aqua", true}},
1804 {Null[string]{"brown", false}, "", Null[string]{"", false}},
1805 {"chartreuse", "", Null[string]{"chartreuse", true}},
1806 {Null[string]{"darkred", true}, "", Null[string]{"darkred", true}},
1807 {Null[string]{"eel", false}, "", Null[string]{"", false}},
1808 {"foo", Null[string]{"black", false}, nil},
1809 }}
1810 nullTestRun(t, spec)
1811 }
1812
1813 func TestNullInt64Param(t *testing.T) {
1814 spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{
1815 {NullInt64{31, true}, 1, NullInt64{31, true}},
1816 {NullInt64{-22, false}, 1, NullInt64{0, false}},
1817 {22, 1, NullInt64{22, true}},
1818 {NullInt64{33, true}, 1, NullInt64{33, true}},
1819 {NullInt64{222, false}, 1, NullInt64{0, false}},
1820 {0, NullInt64{31, false}, nil},
1821 }}
1822 nullTestRun(t, spec)
1823 }
1824
1825 func TestNullInt32Param(t *testing.T) {
1826 spec := nullTestSpec{"nullint32", "int32", [6]nullTestRow{
1827 {NullInt32{31, true}, 1, NullInt32{31, true}},
1828 {NullInt32{-22, false}, 1, NullInt32{0, false}},
1829 {22, 1, NullInt32{22, true}},
1830 {NullInt32{33, true}, 1, NullInt32{33, true}},
1831 {NullInt32{222, false}, 1, NullInt32{0, false}},
1832 {0, NullInt32{31, false}, nil},
1833 }}
1834 nullTestRun(t, spec)
1835 }
1836
1837 func TestNullInt16Param(t *testing.T) {
1838 spec := nullTestSpec{"nullint16", "int16", [6]nullTestRow{
1839 {NullInt16{31, true}, 1, NullInt16{31, true}},
1840 {NullInt16{-22, false}, 1, NullInt16{0, false}},
1841 {22, 1, NullInt16{22, true}},
1842 {NullInt16{33, true}, 1, NullInt16{33, true}},
1843 {NullInt16{222, false}, 1, NullInt16{0, false}},
1844 {0, NullInt16{31, false}, nil},
1845 }}
1846 nullTestRun(t, spec)
1847 }
1848
1849 func TestNullByteParam(t *testing.T) {
1850 spec := nullTestSpec{"nullbyte", "byte", [6]nullTestRow{
1851 {NullByte{31, true}, 1, NullByte{31, true}},
1852 {NullByte{0, false}, 1, NullByte{0, false}},
1853 {22, 1, NullByte{22, true}},
1854 {NullByte{33, true}, 1, NullByte{33, true}},
1855 {NullByte{222, false}, 1, NullByte{0, false}},
1856 {0, NullByte{31, false}, nil},
1857 }}
1858 nullTestRun(t, spec)
1859 }
1860
1861 func TestNullFloat64Param(t *testing.T) {
1862 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
1863 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
1864 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}},
1865 {-22.9, 1, NullFloat64{-22.9, true}},
1866 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}},
1867 {NullFloat64{222, false}, 1, NullFloat64{0, false}},
1868 {10, NullFloat64{31.2, false}, nil},
1869 }}
1870 nullTestRun(t, spec)
1871 }
1872
1873 func TestNullBoolParam(t *testing.T) {
1874 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{
1875 {NullBool{false, true}, true, NullBool{false, true}},
1876 {NullBool{true, false}, false, NullBool{false, false}},
1877 {true, true, NullBool{true, true}},
1878 {NullBool{true, true}, false, NullBool{true, true}},
1879 {NullBool{true, false}, true, NullBool{false, false}},
1880 {true, NullBool{true, false}, nil},
1881 }}
1882 nullTestRun(t, spec)
1883 }
1884
1885 func TestNullTimeParam(t *testing.T) {
1886 t0 := time.Time{}
1887 t1 := time.Date(2000, 1, 1, 8, 9, 10, 11, time.UTC)
1888 t2 := time.Date(2010, 1, 1, 8, 9, 10, 11, time.UTC)
1889 spec := nullTestSpec{"nulldatetime", "datetime", [6]nullTestRow{
1890 {NullTime{t1, true}, t2, NullTime{t1, true}},
1891 {NullTime{t1, false}, t2, NullTime{t0, false}},
1892 {t1, t2, NullTime{t1, true}},
1893 {NullTime{t1, true}, t2, NullTime{t1, true}},
1894 {NullTime{t1, false}, t2, NullTime{t0, false}},
1895 {t2, NullTime{t1, false}, nil},
1896 }}
1897 nullTestRun(t, spec)
1898 }
1899
1900 func nullTestRun(t *testing.T, spec nullTestSpec) {
1901 db := newTestDB(t, "")
1902 defer closeDB(t, db)
1903 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType))
1904
1905
1906 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam)
1907 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam)
1908
1909
1910 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
1911 if err != nil {
1912 t.Fatalf("prepare: %v", err)
1913 }
1914 defer stmt.Close()
1915 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil {
1916 t.Errorf("exec insert chris: %v", err)
1917 }
1918 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil {
1919 t.Errorf("exec insert dave: %v", err)
1920 }
1921 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil {
1922 t.Errorf("exec insert eleanor: %v", err)
1923 }
1924
1925
1926 row5 := spec.rows[5]
1927 if _, err := stmt.Exec(6, "bob", row5.nullParam, row5.notNullParam); err == nil {
1928 t.Errorf("expected error inserting nil val with prepared statement Exec: NULL=%#v, NOT-NULL=%#v", row5.nullParam, row5.notNullParam)
1929 }
1930
1931 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
1932 if err == nil {
1933
1934
1935
1936
1937
1938
1939 }
1940
1941 paramtype := reflect.TypeOf(spec.rows[0].nullParam)
1942 bindVal := reflect.New(paramtype).Interface()
1943
1944 for i := 0; i < 5; i++ {
1945 id := i + 1
1946 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil {
1947 t.Errorf("id=%d Scan: %v", id, err)
1948 }
1949 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface()
1950 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) {
1951 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal)
1952 }
1953 }
1954 }
1955
1956
1957 func TestQueryRowNilScanDest(t *testing.T) {
1958 db := newTestDB(t, "people")
1959 defer closeDB(t, db)
1960 var name *string
1961 err := db.QueryRow("SELECT|people|name|").Scan(name)
1962 want := `sql: Scan error on column index 0, name "name": destination pointer is nil`
1963 if err == nil || err.Error() != want {
1964 t.Errorf("error = %q; want %q", err.Error(), want)
1965 }
1966 }
1967
1968 func TestIssue4902(t *testing.T) {
1969 db := newTestDB(t, "people")
1970 defer closeDB(t, db)
1971
1972 driver := db.Driver().(*fakeDriver)
1973 opens0 := driver.openCount
1974
1975 var stmt *Stmt
1976 var err error
1977 for i := 0; i < 10; i++ {
1978 stmt, err = db.Prepare("SELECT|people|name|")
1979 if err != nil {
1980 t.Fatal(err)
1981 }
1982 err = stmt.Close()
1983 if err != nil {
1984 t.Fatal(err)
1985 }
1986 }
1987
1988 opens := driver.openCount - opens0
1989 if opens > 1 {
1990 t.Errorf("opens = %d; want <= 1", opens)
1991 t.Logf("db = %#v", db)
1992 t.Logf("driver = %#v", driver)
1993 t.Logf("stmt = %#v", stmt)
1994 }
1995 }
1996
1997
1998
1999 func TestSimultaneousQueries(t *testing.T) {
2000 db := newTestDB(t, "people")
2001 defer closeDB(t, db)
2002
2003 tx, err := db.Begin()
2004 if err != nil {
2005 t.Fatal(err)
2006 }
2007 defer tx.Rollback()
2008
2009 r1, err := tx.Query("SELECT|people|name|")
2010 if err != nil {
2011 t.Fatal(err)
2012 }
2013 defer r1.Close()
2014
2015 r2, err := tx.Query("SELECT|people|name|")
2016 if err != nil {
2017 t.Fatal(err)
2018 }
2019 defer r2.Close()
2020 }
2021
2022 func TestMaxIdleConns(t *testing.T) {
2023 db := newTestDB(t, "people")
2024 defer closeDB(t, db)
2025
2026 tx, err := db.Begin()
2027 if err != nil {
2028 t.Fatal(err)
2029 }
2030 tx.Commit()
2031 if got := len(db.freeConn); got != 1 {
2032 t.Errorf("freeConns = %d; want 1", got)
2033 }
2034
2035 db.SetMaxIdleConns(0)
2036
2037 if got := len(db.freeConn); got != 0 {
2038 t.Errorf("freeConns after set to zero = %d; want 0", got)
2039 }
2040
2041 tx, err = db.Begin()
2042 if err != nil {
2043 t.Fatal(err)
2044 }
2045 tx.Commit()
2046 if got := len(db.freeConn); got != 0 {
2047 t.Errorf("freeConns = %d; want 0", got)
2048 }
2049 }
2050
2051 func TestMaxOpenConns(t *testing.T) {
2052 if testing.Short() {
2053 t.Skip("skipping in short mode")
2054 }
2055 defer setHookpostCloseConn(nil)
2056 setHookpostCloseConn(func(_ *fakeConn, err error) {
2057 if err != nil {
2058 t.Errorf("Error closing fakeConn: %v", err)
2059 }
2060 })
2061
2062 db := newTestDB(t, "magicquery")
2063 defer closeDB(t, db)
2064
2065 driver := db.Driver().(*fakeDriver)
2066
2067
2068
2069 db.clearAllConns(t)
2070
2071 driver.mu.Lock()
2072 opens0 := driver.openCount
2073 closes0 := driver.closeCount
2074 driver.mu.Unlock()
2075
2076 db.SetMaxIdleConns(10)
2077 db.SetMaxOpenConns(10)
2078
2079 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
2080 if err != nil {
2081 t.Fatal(err)
2082 }
2083
2084
2085 const (
2086 nquery = 50
2087 sleepMillis = 25
2088 nbatch = 2
2089 )
2090 var wg sync.WaitGroup
2091 for batch := 0; batch < nbatch; batch++ {
2092 for i := 0; i < nquery; i++ {
2093 wg.Add(1)
2094 go func() {
2095 defer wg.Done()
2096 var op string
2097 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
2098 t.Error(err)
2099 }
2100 }()
2101 }
2102
2103 wg.Wait()
2104 }
2105
2106 if g, w := db.numFreeConns(), 10; g != w {
2107 t.Errorf("free conns = %d; want %d", g, w)
2108 }
2109
2110 if n := db.numDepsPoll(t, 20); n > 20 {
2111 t.Errorf("number of dependencies = %d; expected <= 20", n)
2112 db.dumpDeps(t)
2113 }
2114
2115 driver.mu.Lock()
2116 opens := driver.openCount - opens0
2117 closes := driver.closeCount - closes0
2118 driver.mu.Unlock()
2119
2120 if opens > 10 {
2121 t.Logf("open calls = %d", opens)
2122 t.Logf("close calls = %d", closes)
2123 t.Errorf("db connections opened = %d; want <= 10", opens)
2124 db.dumpDeps(t)
2125 }
2126
2127 if err := stmt.Close(); err != nil {
2128 t.Fatal(err)
2129 }
2130
2131 if g, w := db.numFreeConns(), 10; g != w {
2132 t.Errorf("free conns = %d; want %d", g, w)
2133 }
2134
2135 if n := db.numDepsPoll(t, 10); n > 10 {
2136 t.Errorf("number of dependencies = %d; expected <= 10", n)
2137 db.dumpDeps(t)
2138 }
2139
2140 db.SetMaxOpenConns(5)
2141
2142 if g, w := db.numFreeConns(), 5; g != w {
2143 t.Errorf("free conns = %d; want %d", g, w)
2144 }
2145
2146 if n := db.numDepsPoll(t, 5); n > 5 {
2147 t.Errorf("number of dependencies = %d; expected 0", n)
2148 db.dumpDeps(t)
2149 }
2150
2151 db.SetMaxOpenConns(0)
2152
2153 if g, w := db.numFreeConns(), 5; g != w {
2154 t.Errorf("free conns = %d; want %d", g, w)
2155 }
2156
2157 if n := db.numDepsPoll(t, 5); n > 5 {
2158 t.Errorf("number of dependencies = %d; expected 0", n)
2159 db.dumpDeps(t)
2160 }
2161
2162 db.clearAllConns(t)
2163 }
2164
2165
2166
2167 func TestMaxOpenConnsOnBusy(t *testing.T) {
2168 defer setHookpostCloseConn(nil)
2169 setHookpostCloseConn(func(_ *fakeConn, err error) {
2170 if err != nil {
2171 t.Errorf("Error closing fakeConn: %v", err)
2172 }
2173 })
2174
2175 db := newTestDB(t, "magicquery")
2176 defer closeDB(t, db)
2177
2178 db.SetMaxOpenConns(3)
2179
2180 ctx := context.Background()
2181
2182 conn0, err := db.conn(ctx, cachedOrNewConn)
2183 if err != nil {
2184 t.Fatalf("db open conn fail: %v", err)
2185 }
2186
2187 conn1, err := db.conn(ctx, cachedOrNewConn)
2188 if err != nil {
2189 t.Fatalf("db open conn fail: %v", err)
2190 }
2191
2192 conn2, err := db.conn(ctx, cachedOrNewConn)
2193 if err != nil {
2194 t.Fatalf("db open conn fail: %v", err)
2195 }
2196
2197 if g, w := db.numOpen, 3; g != w {
2198 t.Errorf("free conns = %d; want %d", g, w)
2199 }
2200
2201 db.SetMaxOpenConns(2)
2202 if g, w := db.numOpen, 3; g != w {
2203 t.Errorf("free conns = %d; want %d", g, w)
2204 }
2205
2206 conn0.releaseConn(nil)
2207 conn1.releaseConn(nil)
2208 if g, w := db.numOpen, 2; g != w {
2209 t.Errorf("free conns = %d; want %d", g, w)
2210 }
2211
2212 conn2.releaseConn(nil)
2213 if g, w := db.numOpen, 2; g != w {
2214 t.Errorf("free conns = %d; want %d", g, w)
2215 }
2216 }
2217
2218
2219
2220 func TestPendingConnsAfterErr(t *testing.T) {
2221 const (
2222 maxOpen = 2
2223 tryOpen = maxOpen*2 + 2
2224 )
2225
2226
2227 db, err := Open("test", fakeDBName)
2228 if err != nil {
2229 t.Fatalf("Open: %v", err)
2230 }
2231 defer closeDB(t, db)
2232 defer func() {
2233 for k, v := range db.lastPut {
2234 t.Logf("%p: %v", k, v)
2235 }
2236 }()
2237
2238 db.SetMaxOpenConns(maxOpen)
2239 db.SetMaxIdleConns(0)
2240
2241 errOffline := errors.New("db offline")
2242
2243 defer func() { setHookOpenErr(nil) }()
2244
2245 errs := make(chan error, tryOpen)
2246
2247 var opening sync.WaitGroup
2248 opening.Add(tryOpen)
2249
2250 setHookOpenErr(func() error {
2251
2252 opening.Wait()
2253 return errOffline
2254 })
2255
2256 for i := 0; i < tryOpen; i++ {
2257 go func() {
2258 opening.Done()
2259 _, err := db.Exec("will never run")
2260 errs <- err
2261 }()
2262 }
2263
2264 opening.Wait()
2265
2266 const timeout = 5 * time.Second
2267 to := time.NewTimer(timeout)
2268 defer to.Stop()
2269
2270
2271 for i := 0; i < tryOpen; i++ {
2272 select {
2273 case err := <-errs:
2274 if got, want := err, errOffline; got != want {
2275 t.Errorf("unexpected err: got %v, want %v", got, want)
2276 }
2277 case <-to.C:
2278 t.Fatalf("orphaned connection request(s), still waiting after %v", timeout)
2279 }
2280 }
2281
2282
2283 tick := time.NewTicker(3 * time.Millisecond)
2284 defer tick.Stop()
2285 for {
2286 select {
2287 case <-tick.C:
2288 db.mu.Lock()
2289 if db.numOpen == 0 {
2290 db.mu.Unlock()
2291 return
2292 }
2293 db.mu.Unlock()
2294 case <-to.C:
2295
2296 return
2297 }
2298 }
2299 }
2300
2301 func TestSingleOpenConn(t *testing.T) {
2302 db := newTestDB(t, "people")
2303 defer closeDB(t, db)
2304
2305 db.SetMaxOpenConns(1)
2306
2307 rows, err := db.Query("SELECT|people|name|")
2308 if err != nil {
2309 t.Fatal(err)
2310 }
2311 if err = rows.Close(); err != nil {
2312 t.Fatal(err)
2313 }
2314
2315 rows, err = db.Query("SELECT|people|name|")
2316 if err != nil {
2317 t.Fatal(err)
2318 }
2319 if err = rows.Close(); err != nil {
2320 t.Fatal(err)
2321 }
2322 }
2323
2324 func TestStats(t *testing.T) {
2325 db := newTestDB(t, "people")
2326 stats := db.Stats()
2327 if got := stats.OpenConnections; got != 1 {
2328 t.Errorf("stats.OpenConnections = %d; want 1", got)
2329 }
2330
2331 tx, err := db.Begin()
2332 if err != nil {
2333 t.Fatal(err)
2334 }
2335 tx.Commit()
2336
2337 closeDB(t, db)
2338 stats = db.Stats()
2339 if got := stats.OpenConnections; got != 0 {
2340 t.Errorf("stats.OpenConnections = %d; want 0", got)
2341 }
2342 }
2343
2344 func TestConnMaxLifetime(t *testing.T) {
2345 t0 := time.Unix(1000000, 0)
2346 offset := time.Duration(0)
2347
2348 nowFunc = func() time.Time { return t0.Add(offset) }
2349 defer func() { nowFunc = time.Now }()
2350
2351 db := newTestDB(t, "magicquery")
2352 defer closeDB(t, db)
2353
2354 driver := db.Driver().(*fakeDriver)
2355
2356
2357
2358 db.clearAllConns(t)
2359
2360 driver.mu.Lock()
2361 opens0 := driver.openCount
2362 closes0 := driver.closeCount
2363 driver.mu.Unlock()
2364
2365 db.SetMaxIdleConns(10)
2366 db.SetMaxOpenConns(10)
2367
2368 tx, err := db.Begin()
2369 if err != nil {
2370 t.Fatal(err)
2371 }
2372
2373 offset = time.Second
2374 tx2, err := db.Begin()
2375 if err != nil {
2376 t.Fatal(err)
2377 }
2378
2379 tx.Commit()
2380 tx2.Commit()
2381
2382 driver.mu.Lock()
2383 opens := driver.openCount - opens0
2384 closes := driver.closeCount - closes0
2385 driver.mu.Unlock()
2386
2387 if opens != 2 {
2388 t.Errorf("opens = %d; want 2", opens)
2389 }
2390 if closes != 0 {
2391 t.Errorf("closes = %d; want 0", closes)
2392 }
2393 if g, w := db.numFreeConns(), 2; g != w {
2394 t.Errorf("free conns = %d; want %d", g, w)
2395 }
2396
2397
2398 offset = 11 * time.Second
2399 db.SetConnMaxLifetime(10 * time.Second)
2400
2401 tx, err = db.Begin()
2402 if err != nil {
2403 t.Fatal(err)
2404 }
2405 tx2, err = db.Begin()
2406 if err != nil {
2407 t.Fatal(err)
2408 }
2409 tx.Commit()
2410 tx2.Commit()
2411
2412
2413 waitCondition(t, func() bool {
2414 driver.mu.Lock()
2415 opens = driver.openCount - opens0
2416 closes = driver.closeCount - closes0
2417 driver.mu.Unlock()
2418
2419 return closes == 1
2420 })
2421
2422 if opens != 3 {
2423 t.Errorf("opens = %d; want 3", opens)
2424 }
2425 if closes != 1 {
2426 t.Errorf("closes = %d; want 1", closes)
2427 }
2428
2429 if s := db.Stats(); s.MaxLifetimeClosed != 1 {
2430 t.Errorf("MaxLifetimeClosed = %d; want 1 %#v", s.MaxLifetimeClosed, s)
2431 }
2432 }
2433
2434
2435 func TestStmtCloseDeps(t *testing.T) {
2436 if testing.Short() {
2437 t.Skip("skipping in short mode")
2438 }
2439 defer setHookpostCloseConn(nil)
2440 setHookpostCloseConn(func(_ *fakeConn, err error) {
2441 if err != nil {
2442 t.Errorf("Error closing fakeConn: %v", err)
2443 }
2444 })
2445
2446 db := newTestDB(t, "magicquery")
2447 defer closeDB(t, db)
2448
2449 driver := db.Driver().(*fakeDriver)
2450
2451 driver.mu.Lock()
2452 opens0 := driver.openCount
2453 closes0 := driver.closeCount
2454 driver.mu.Unlock()
2455 openDelta0 := opens0 - closes0
2456
2457 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
2458 if err != nil {
2459 t.Fatal(err)
2460 }
2461
2462
2463 const (
2464 nquery = 50
2465 sleepMillis = 25
2466 nbatch = 2
2467 )
2468 var wg sync.WaitGroup
2469 for batch := 0; batch < nbatch; batch++ {
2470 for i := 0; i < nquery; i++ {
2471 wg.Add(1)
2472 go func() {
2473 defer wg.Done()
2474 var op string
2475 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
2476 t.Error(err)
2477 }
2478 }()
2479 }
2480
2481 wg.Wait()
2482 }
2483
2484 if g, w := db.numFreeConns(), 2; g != w {
2485 t.Errorf("free conns = %d; want %d", g, w)
2486 }
2487
2488 if n := db.numDepsPoll(t, 4); n > 4 {
2489 t.Errorf("number of dependencies = %d; expected <= 4", n)
2490 db.dumpDeps(t)
2491 }
2492
2493 driver.mu.Lock()
2494 opens := driver.openCount - opens0
2495 closes := driver.closeCount - closes0
2496 openDelta := (driver.openCount - driver.closeCount) - openDelta0
2497 driver.mu.Unlock()
2498
2499 if openDelta > 2 {
2500 t.Logf("open calls = %d", opens)
2501 t.Logf("close calls = %d", closes)
2502 t.Logf("open delta = %d", openDelta)
2503 t.Errorf("db connections opened = %d; want <= 2", openDelta)
2504 db.dumpDeps(t)
2505 }
2506
2507 if !waitCondition(t, func() bool {
2508 return len(stmt.css) <= nquery
2509 }) {
2510 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery)
2511 }
2512
2513 if err := stmt.Close(); err != nil {
2514 t.Fatal(err)
2515 }
2516
2517 if g, w := db.numFreeConns(), 2; g != w {
2518 t.Errorf("free conns = %d; want %d", g, w)
2519 }
2520
2521 if n := db.numDepsPoll(t, 2); n > 2 {
2522 t.Errorf("number of dependencies = %d; expected <= 2", n)
2523 db.dumpDeps(t)
2524 }
2525
2526 db.clearAllConns(t)
2527 }
2528
2529
2530 func TestCloseConnBeforeStmts(t *testing.T) {
2531 db := newTestDB(t, "people")
2532 defer closeDB(t, db)
2533
2534 defer setHookpostCloseConn(nil)
2535 setHookpostCloseConn(func(_ *fakeConn, err error) {
2536 if err != nil {
2537 t.Errorf("Error closing fakeConn: %v; from %s", err, stack())
2538 db.dumpDeps(t)
2539 t.Errorf("DB = %#v", db)
2540 }
2541 })
2542
2543 stmt, err := db.Prepare("SELECT|people|name|")
2544 if err != nil {
2545 t.Fatal(err)
2546 }
2547
2548 if len(db.freeConn) != 1 {
2549 t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn))
2550 }
2551 dc := db.freeConn[0]
2552 if dc.closed {
2553 t.Errorf("conn shouldn't be closed")
2554 }
2555
2556 if n := len(dc.openStmt); n != 1 {
2557 t.Errorf("driverConn num openStmt = %d; want 1", n)
2558 }
2559 err = db.Close()
2560 if err != nil {
2561 t.Errorf("db Close = %v", err)
2562 }
2563 if !dc.closed {
2564 t.Errorf("after db.Close, driverConn should be closed")
2565 }
2566 if n := len(dc.openStmt); n != 0 {
2567 t.Errorf("driverConn num openStmt = %d; want 0", n)
2568 }
2569
2570 err = stmt.Close()
2571 if err != nil {
2572 t.Errorf("Stmt close = %v", err)
2573 }
2574
2575 if !dc.closed {
2576 t.Errorf("conn should be closed")
2577 }
2578 if dc.ci != nil {
2579 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil")
2580 }
2581 }
2582
2583
2584
2585 func TestRowsCloseOrder(t *testing.T) {
2586 db := newTestDB(t, "people")
2587 defer closeDB(t, db)
2588
2589 db.SetMaxIdleConns(0)
2590 setStrictFakeConnClose(t)
2591 defer setStrictFakeConnClose(nil)
2592
2593 rows, err := db.Query("SELECT|people|age,name|")
2594 if err != nil {
2595 t.Fatal(err)
2596 }
2597 err = rows.Close()
2598 if err != nil {
2599 t.Fatal(err)
2600 }
2601 }
2602
2603 func TestRowsImplicitClose(t *testing.T) {
2604 db := newTestDB(t, "people")
2605 defer closeDB(t, db)
2606
2607 rows, err := db.Query("SELECT|people|age,name|")
2608 if err != nil {
2609 t.Fatal(err)
2610 }
2611
2612 want, fail := 2, errors.New("fail")
2613 r := rows.rowsi.(*rowsCursor)
2614 r.errPos, r.err = want, fail
2615
2616 got := 0
2617 for rows.Next() {
2618 got++
2619 }
2620 if got != want {
2621 t.Errorf("got %d rows, want %d", got, want)
2622 }
2623 if err := rows.Err(); err != fail {
2624 t.Errorf("got error %v, want %v", err, fail)
2625 }
2626 if !r.closed {
2627 t.Errorf("r.closed is false, want true")
2628 }
2629 }
2630
2631 func TestRowsCloseError(t *testing.T) {
2632 db := newTestDB(t, "people")
2633 defer db.Close()
2634 rows, err := db.Query("SELECT|people|age,name|")
2635 if err != nil {
2636 t.Fatalf("Query: %v", err)
2637 }
2638 type row struct {
2639 age int
2640 name string
2641 }
2642 got := []row{}
2643
2644 rc, ok := rows.rowsi.(*rowsCursor)
2645 if !ok {
2646 t.Fatal("not using *rowsCursor")
2647 }
2648 rc.closeErr = errors.New("rowsCursor: failed to close")
2649
2650 for rows.Next() {
2651 var r row
2652 err = rows.Scan(&r.age, &r.name)
2653 if err != nil {
2654 t.Fatalf("Scan: %v", err)
2655 }
2656 got = append(got, r)
2657 }
2658 err = rows.Err()
2659 if err != rc.closeErr {
2660 t.Fatalf("unexpected err: got %v, want %v", err, rc.closeErr)
2661 }
2662 }
2663
2664 func TestStmtCloseOrder(t *testing.T) {
2665 db := newTestDB(t, "people")
2666 defer closeDB(t, db)
2667
2668 db.SetMaxIdleConns(0)
2669 setStrictFakeConnClose(t)
2670 defer setStrictFakeConnClose(nil)
2671
2672 _, err := db.Query("SELECT|non_existent|name|")
2673 if err == nil {
2674 t.Fatal("Querying non-existent table should fail")
2675 }
2676 }
2677
2678
2679
2680 func TestManyErrBadConn(t *testing.T) {
2681 manyErrBadConnSetup := func(first ...func(db *DB)) *DB {
2682 db := newTestDB(t, "people")
2683
2684 for _, f := range first {
2685 f(db)
2686 }
2687
2688 nconn := maxBadConnRetries + 1
2689 db.SetMaxIdleConns(nconn)
2690 db.SetMaxOpenConns(nconn)
2691
2692 func() {
2693 for i := 0; i < nconn; i++ {
2694 rows, err := db.Query("SELECT|people|age,name|")
2695 if err != nil {
2696 t.Fatal(err)
2697 }
2698 defer rows.Close()
2699 }
2700 }()
2701
2702 db.mu.Lock()
2703 defer db.mu.Unlock()
2704 if db.numOpen != nconn {
2705 t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn)
2706 } else if len(db.freeConn) != nconn {
2707 t.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db.freeConn), nconn)
2708 }
2709 for _, conn := range db.freeConn {
2710 conn.Lock()
2711 conn.ci.(*fakeConn).stickyBad = true
2712 conn.Unlock()
2713 }
2714 return db
2715 }
2716
2717
2718 db := manyErrBadConnSetup()
2719 defer closeDB(t, db)
2720 rows, err := db.Query("SELECT|people|age,name|")
2721 if err != nil {
2722 t.Fatal(err)
2723 }
2724 if err = rows.Close(); err != nil {
2725 t.Fatal(err)
2726 }
2727
2728
2729 db = manyErrBadConnSetup()
2730 defer closeDB(t, db)
2731 _, err = db.Exec("INSERT|people|name=Julia,age=19")
2732 if err != nil {
2733 t.Fatal(err)
2734 }
2735
2736
2737 db = manyErrBadConnSetup()
2738 defer closeDB(t, db)
2739 tx, err := db.Begin()
2740 if err != nil {
2741 t.Fatal(err)
2742 }
2743 if err = tx.Rollback(); err != nil {
2744 t.Fatal(err)
2745 }
2746
2747
2748 db = manyErrBadConnSetup()
2749 defer closeDB(t, db)
2750 stmt, err := db.Prepare("SELECT|people|age,name|")
2751 if err != nil {
2752 t.Fatal(err)
2753 }
2754 if err = stmt.Close(); err != nil {
2755 t.Fatal(err)
2756 }
2757
2758
2759 db = manyErrBadConnSetup(func(db *DB) {
2760 stmt, err = db.Prepare("INSERT|people|name=Julia,age=19")
2761 if err != nil {
2762 t.Fatal(err)
2763 }
2764 })
2765 defer closeDB(t, db)
2766 _, err = stmt.Exec()
2767 if err != nil {
2768 t.Fatal(err)
2769 }
2770 if err = stmt.Close(); err != nil {
2771 t.Fatal(err)
2772 }
2773
2774
2775 db = manyErrBadConnSetup(func(db *DB) {
2776 stmt, err = db.Prepare("SELECT|people|age,name|")
2777 if err != nil {
2778 t.Fatal(err)
2779 }
2780 })
2781 defer closeDB(t, db)
2782 rows, err = stmt.Query()
2783 if err != nil {
2784 t.Fatal(err)
2785 }
2786 if err = rows.Close(); err != nil {
2787 t.Fatal(err)
2788 }
2789 if err = stmt.Close(); err != nil {
2790 t.Fatal(err)
2791 }
2792
2793
2794 db = manyErrBadConnSetup()
2795 defer closeDB(t, db)
2796 ctx, cancel := context.WithCancel(context.Background())
2797 defer cancel()
2798 conn, err := db.Conn(ctx)
2799 if err != nil {
2800 t.Fatal(err)
2801 }
2802 conn.dc.ci.(*fakeConn).skipDirtySession = true
2803 err = conn.Close()
2804 if err != nil {
2805 t.Fatal(err)
2806 }
2807
2808
2809 db = manyErrBadConnSetup()
2810 defer closeDB(t, db)
2811 err = db.PingContext(ctx)
2812 if err != nil {
2813 t.Fatal(err)
2814 }
2815 }
2816
2817
2818 func TestTxCannotCommitAfterRollback(t *testing.T) {
2819 db := newTestDB(t, "tx_status")
2820 defer closeDB(t, db)
2821
2822
2823 var txStatus string
2824 err := db.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
2825 if err != nil {
2826 t.Fatal(err)
2827 }
2828 if g, w := txStatus, "autocommit"; g != w {
2829 t.Fatalf("tx_status=%q, wanted %q", g, w)
2830 }
2831
2832 ctx, cancel := context.WithCancel(context.Background())
2833 defer cancel()
2834
2835 tx, err := db.BeginTx(ctx, nil)
2836 if err != nil {
2837 t.Fatal(err)
2838 }
2839
2840
2841
2842
2843 tx.txi.(*fakeTx).c.skipDirtySession = true
2844
2845 defer tx.Rollback()
2846
2847 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
2848 if err != nil {
2849 t.Fatal(err)
2850 }
2851 if g, w := txStatus, "transaction"; g != w {
2852 t.Fatalf("tx_status=%q, wanted %q", g, w)
2853 }
2854
2855
2856
2857
2858 sendQuery := make(chan struct{})
2859
2860
2861 bypassRowsAwaitDone = true
2862 hookTxGrabConn = func() {
2863 cancel()
2864 <-sendQuery
2865 }
2866 rollbackHook = func() {
2867 close(sendQuery)
2868 }
2869 defer func() {
2870 hookTxGrabConn = nil
2871 rollbackHook = nil
2872 bypassRowsAwaitDone = false
2873 }()
2874
2875 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
2876 if err != nil {
2877
2878 t.Fatal(err)
2879 }
2880 if g, w := txStatus, "transaction"; g != w {
2881 t.Fatalf("tx_status=%q, wanted %q", g, w)
2882 }
2883 }
2884
2885
2886 func TestTxStmtDeadlock(t *testing.T) {
2887 db := newTestDB(t, "people")
2888 defer closeDB(t, db)
2889
2890 ctx, cancel := context.WithCancel(context.Background())
2891 defer cancel()
2892 tx, err := db.BeginTx(ctx, nil)
2893 if err != nil {
2894 t.Fatal(err)
2895 }
2896
2897 stmt, err := tx.Prepare("SELECT|people|name,age|age=?")
2898 if err != nil {
2899 t.Fatal(err)
2900 }
2901 cancel()
2902
2903 for i := 0; i < 1e3; i++ {
2904
2905
2906 _, err = stmt.Query(1)
2907 if err != nil {
2908 break
2909 }
2910 }
2911 _ = tx.Rollback()
2912 }
2913
2914
2915
2916
2917 func TestConnExpiresFreshOutOfPool(t *testing.T) {
2918 execCases := []struct {
2919 expired bool
2920 badReset bool
2921 }{
2922 {false, false},
2923 {true, false},
2924 {false, true},
2925 }
2926
2927 t0 := time.Unix(1000000, 0)
2928 offset := time.Duration(0)
2929 offsetMu := sync.RWMutex{}
2930
2931 nowFunc = func() time.Time {
2932 offsetMu.RLock()
2933 defer offsetMu.RUnlock()
2934 return t0.Add(offset)
2935 }
2936 defer func() { nowFunc = time.Now }()
2937
2938 ctx, cancel := context.WithCancel(context.Background())
2939 defer cancel()
2940
2941 db := newTestDB(t, "magicquery")
2942 defer closeDB(t, db)
2943
2944 db.SetMaxOpenConns(1)
2945
2946 for _, ec := range execCases {
2947 ec := ec
2948 name := fmt.Sprintf("expired=%t,badReset=%t", ec.expired, ec.badReset)
2949 t.Run(name, func(t *testing.T) {
2950 db.clearAllConns(t)
2951
2952 db.SetMaxIdleConns(1)
2953 db.SetConnMaxLifetime(10 * time.Second)
2954
2955 conn, err := db.conn(ctx, alwaysNewConn)
2956 if err != nil {
2957 t.Fatal(err)
2958 }
2959
2960 afterPutConn := make(chan struct{})
2961 waitingForConn := make(chan struct{})
2962
2963 go func() {
2964 defer close(afterPutConn)
2965
2966 conn, err := db.conn(ctx, alwaysNewConn)
2967 if err == nil {
2968 db.putConn(conn, err, false)
2969 } else {
2970 t.Errorf("db.conn: %v", err)
2971 }
2972 }()
2973 go func() {
2974 defer close(waitingForConn)
2975
2976 for {
2977 if t.Failed() {
2978 return
2979 }
2980 db.mu.Lock()
2981 ct := db.connRequests.Len()
2982 db.mu.Unlock()
2983 if ct > 0 {
2984 return
2985 }
2986 time.Sleep(pollDuration)
2987 }
2988 }()
2989
2990 <-waitingForConn
2991
2992 if t.Failed() {
2993 return
2994 }
2995
2996 offsetMu.Lock()
2997 if ec.expired {
2998 offset = 11 * time.Second
2999 } else {
3000 offset = time.Duration(0)
3001 }
3002 offsetMu.Unlock()
3003
3004 conn.ci.(*fakeConn).stickyBad = ec.badReset
3005
3006 db.putConn(conn, err, true)
3007
3008 <-afterPutConn
3009 })
3010 }
3011 }
3012
3013
3014
3015 func TestIssue20575(t *testing.T) {
3016 db := newTestDB(t, "people")
3017 defer closeDB(t, db)
3018
3019 tx, err := db.Begin()
3020 if err != nil {
3021 t.Fatal(err)
3022 }
3023 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
3024 defer cancel()
3025 _, err = tx.QueryContext(ctx, "SELECT|people|age,name|")
3026 if err != nil {
3027 t.Fatal(err)
3028 }
3029
3030 err = tx.Rollback()
3031 if err != nil {
3032 t.Fatal(err)
3033 }
3034 select {
3035 default:
3036 case <-ctx.Done():
3037 t.Fatal("timeout: failed to rollback query without closing rows:", ctx.Err())
3038 }
3039 }
3040
3041
3042
3043 func TestIssue20622(t *testing.T) {
3044 db := newTestDB(t, "people")
3045 defer closeDB(t, db)
3046
3047 ctx, cancel := context.WithCancel(context.Background())
3048 defer cancel()
3049
3050 tx, err := db.BeginTx(ctx, nil)
3051 if err != nil {
3052 t.Fatal(err)
3053 }
3054
3055 rows, err := tx.Query("SELECT|people|age,name|")
3056 if err != nil {
3057 t.Fatal(err)
3058 }
3059
3060 count := 0
3061 for rows.Next() {
3062 count++
3063 var age int
3064 var name string
3065 if err := rows.Scan(&age, &name); err != nil {
3066 t.Fatal("scan failed", err)
3067 }
3068
3069 if count == 1 {
3070 cancel()
3071 }
3072 time.Sleep(100 * time.Millisecond)
3073 }
3074 rows.Close()
3075 tx.Commit()
3076 }
3077
3078
3079 func TestErrBadConnReconnect(t *testing.T) {
3080 db := newTestDB(t, "foo")
3081 defer closeDB(t, db)
3082 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
3083
3084 simulateBadConn := func(name string, hook *func() bool, op func() error) {
3085 broken, retried := false, false
3086 numOpen := db.numOpen
3087
3088
3089 *hook = func() bool {
3090 if !broken {
3091 broken = true
3092 return true
3093 }
3094 retried = true
3095 return false
3096 }
3097
3098 if err := op(); err != nil {
3099 t.Errorf(name+": %v", err)
3100 return
3101 }
3102
3103 if !broken || !retried {
3104 t.Error(name + ": Failed to simulate broken connection")
3105 }
3106 *hook = nil
3107
3108 if numOpen != db.numOpen {
3109 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen)
3110 numOpen = db.numOpen
3111 }
3112 }
3113
3114
3115 dbExec := func() error {
3116 _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
3117 return err
3118 }
3119 simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec)
3120 simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec)
3121
3122
3123 dbQuery := func() error {
3124 rows, err := db.Query("SELECT|t1|age,name|")
3125 if err == nil {
3126 err = rows.Close()
3127 }
3128 return err
3129 }
3130 simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery)
3131 simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery)
3132
3133
3134 simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error {
3135 stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
3136 if err != nil {
3137 return err
3138 }
3139 stmt.Close()
3140 return nil
3141 })
3142
3143
3144 forcePrepare := func(stmt *Stmt) {
3145 stmt.css = nil
3146 }
3147
3148
3149 stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
3150 if err != nil {
3151 t.Fatalf("prepare: %v", err)
3152 }
3153 defer stmt1.Close()
3154
3155 forcePrepare(stmt1)
3156
3157 stmtExec := func() error {
3158 _, err := stmt1.Exec("Gopher", 3, false)
3159 return err
3160 }
3161 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec)
3162 simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec)
3163
3164
3165 stmt2, err := db.Prepare("SELECT|t1|age,name|")
3166 if err != nil {
3167 t.Fatalf("prepare: %v", err)
3168 }
3169 defer stmt2.Close()
3170
3171 forcePrepare(stmt2)
3172
3173 stmtQuery := func() error {
3174 rows, err := stmt2.Query()
3175 if err == nil {
3176 err = rows.Close()
3177 }
3178 return err
3179 }
3180 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery)
3181 simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery)
3182 }
3183
3184
3185 func TestTxEndBadConn(t *testing.T) {
3186 db := newTestDB(t, "foo")
3187 defer closeDB(t, db)
3188 db.SetMaxIdleConns(0)
3189 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
3190 db.SetMaxIdleConns(1)
3191
3192 simulateBadConn := func(name string, hook *func() bool, op func() error) {
3193 broken := false
3194 numOpen := db.numOpen
3195
3196 *hook = func() bool {
3197 if !broken {
3198 broken = true
3199 }
3200 return broken
3201 }
3202
3203 if err := op(); !errors.Is(err, driver.ErrBadConn) {
3204 t.Errorf(name+": %v", err)
3205 return
3206 }
3207
3208 if !broken {
3209 t.Error(name + ": Failed to simulate broken connection")
3210 }
3211 *hook = nil
3212
3213 if numOpen != db.numOpen {
3214 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen)
3215 }
3216 }
3217
3218
3219 dbExec := func(endTx func(tx *Tx) error) func() error {
3220 return func() error {
3221 tx, err := db.Begin()
3222 if err != nil {
3223 return err
3224 }
3225 _, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
3226 if err != nil {
3227 return err
3228 }
3229 return endTx(tx)
3230 }
3231 }
3232 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit))
3233 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback))
3234
3235
3236 dbQuery := func(endTx func(tx *Tx) error) func() error {
3237 return func() error {
3238 tx, err := db.Begin()
3239 if err != nil {
3240 return err
3241 }
3242 rows, err := tx.Query("SELECT|t1|age,name|")
3243 if err == nil {
3244 err = rows.Close()
3245 } else {
3246 return err
3247 }
3248 return endTx(tx)
3249 }
3250 }
3251 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit))
3252 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback))
3253 }
3254
3255 type concurrentTest interface {
3256 init(t testing.TB, db *DB)
3257 finish(t testing.TB)
3258 test(t testing.TB) error
3259 }
3260
3261 type concurrentDBQueryTest struct {
3262 db *DB
3263 }
3264
3265 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) {
3266 c.db = db
3267 }
3268
3269 func (c *concurrentDBQueryTest) finish(t testing.TB) {
3270 c.db = nil
3271 }
3272
3273 func (c *concurrentDBQueryTest) test(t testing.TB) error {
3274 rows, err := c.db.Query("SELECT|people|name|")
3275 if err != nil {
3276 t.Error(err)
3277 return err
3278 }
3279 var name string
3280 for rows.Next() {
3281 rows.Scan(&name)
3282 }
3283 rows.Close()
3284 return nil
3285 }
3286
3287 type concurrentDBExecTest struct {
3288 db *DB
3289 }
3290
3291 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) {
3292 c.db = db
3293 }
3294
3295 func (c *concurrentDBExecTest) finish(t testing.TB) {
3296 c.db = nil
3297 }
3298
3299 func (c *concurrentDBExecTest) test(t testing.TB) error {
3300 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
3301 if err != nil {
3302 t.Error(err)
3303 return err
3304 }
3305 return nil
3306 }
3307
3308 type concurrentStmtQueryTest struct {
3309 db *DB
3310 stmt *Stmt
3311 }
3312
3313 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) {
3314 c.db = db
3315 var err error
3316 c.stmt, err = db.Prepare("SELECT|people|name|")
3317 if err != nil {
3318 t.Fatal(err)
3319 }
3320 }
3321
3322 func (c *concurrentStmtQueryTest) finish(t testing.TB) {
3323 if c.stmt != nil {
3324 c.stmt.Close()
3325 c.stmt = nil
3326 }
3327 c.db = nil
3328 }
3329
3330 func (c *concurrentStmtQueryTest) test(t testing.TB) error {
3331 rows, err := c.stmt.Query()
3332 if err != nil {
3333 t.Errorf("error on query: %v", err)
3334 return err
3335 }
3336
3337 var name string
3338 for rows.Next() {
3339 rows.Scan(&name)
3340 }
3341 rows.Close()
3342 return nil
3343 }
3344
3345 type concurrentStmtExecTest struct {
3346 db *DB
3347 stmt *Stmt
3348 }
3349
3350 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) {
3351 c.db = db
3352 var err error
3353 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
3354 if err != nil {
3355 t.Fatal(err)
3356 }
3357 }
3358
3359 func (c *concurrentStmtExecTest) finish(t testing.TB) {
3360 if c.stmt != nil {
3361 c.stmt.Close()
3362 c.stmt = nil
3363 }
3364 c.db = nil
3365 }
3366
3367 func (c *concurrentStmtExecTest) test(t testing.TB) error {
3368 _, err := c.stmt.Exec(3, chrisBirthday)
3369 if err != nil {
3370 t.Errorf("error on exec: %v", err)
3371 return err
3372 }
3373 return nil
3374 }
3375
3376 type concurrentTxQueryTest struct {
3377 db *DB
3378 tx *Tx
3379 }
3380
3381 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) {
3382 c.db = db
3383 var err error
3384 c.tx, err = c.db.Begin()
3385 if err != nil {
3386 t.Fatal(err)
3387 }
3388 }
3389
3390 func (c *concurrentTxQueryTest) finish(t testing.TB) {
3391 if c.tx != nil {
3392 c.tx.Rollback()
3393 c.tx = nil
3394 }
3395 c.db = nil
3396 }
3397
3398 func (c *concurrentTxQueryTest) test(t testing.TB) error {
3399 rows, err := c.db.Query("SELECT|people|name|")
3400 if err != nil {
3401 t.Error(err)
3402 return err
3403 }
3404 var name string
3405 for rows.Next() {
3406 rows.Scan(&name)
3407 }
3408 rows.Close()
3409 return nil
3410 }
3411
3412 type concurrentTxExecTest struct {
3413 db *DB
3414 tx *Tx
3415 }
3416
3417 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) {
3418 c.db = db
3419 var err error
3420 c.tx, err = c.db.Begin()
3421 if err != nil {
3422 t.Fatal(err)
3423 }
3424 }
3425
3426 func (c *concurrentTxExecTest) finish(t testing.TB) {
3427 if c.tx != nil {
3428 c.tx.Rollback()
3429 c.tx = nil
3430 }
3431 c.db = nil
3432 }
3433
3434 func (c *concurrentTxExecTest) test(t testing.TB) error {
3435 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
3436 if err != nil {
3437 t.Error(err)
3438 return err
3439 }
3440 return nil
3441 }
3442
3443 type concurrentTxStmtQueryTest struct {
3444 db *DB
3445 tx *Tx
3446 stmt *Stmt
3447 }
3448
3449 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) {
3450 c.db = db
3451 var err error
3452 c.tx, err = c.db.Begin()
3453 if err != nil {
3454 t.Fatal(err)
3455 }
3456 c.stmt, err = c.tx.Prepare("SELECT|people|name|")
3457 if err != nil {
3458 t.Fatal(err)
3459 }
3460 }
3461
3462 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) {
3463 if c.stmt != nil {
3464 c.stmt.Close()
3465 c.stmt = nil
3466 }
3467 if c.tx != nil {
3468 c.tx.Rollback()
3469 c.tx = nil
3470 }
3471 c.db = nil
3472 }
3473
3474 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error {
3475 rows, err := c.stmt.Query()
3476 if err != nil {
3477 t.Errorf("error on query: %v", err)
3478 return err
3479 }
3480
3481 var name string
3482 for rows.Next() {
3483 rows.Scan(&name)
3484 }
3485 rows.Close()
3486 return nil
3487 }
3488
3489 type concurrentTxStmtExecTest struct {
3490 db *DB
3491 tx *Tx
3492 stmt *Stmt
3493 }
3494
3495 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) {
3496 c.db = db
3497 var err error
3498 c.tx, err = c.db.Begin()
3499 if err != nil {
3500 t.Fatal(err)
3501 }
3502 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
3503 if err != nil {
3504 t.Fatal(err)
3505 }
3506 }
3507
3508 func (c *concurrentTxStmtExecTest) finish(t testing.TB) {
3509 if c.stmt != nil {
3510 c.stmt.Close()
3511 c.stmt = nil
3512 }
3513 if c.tx != nil {
3514 c.tx.Rollback()
3515 c.tx = nil
3516 }
3517 c.db = nil
3518 }
3519
3520 func (c *concurrentTxStmtExecTest) test(t testing.TB) error {
3521 _, err := c.stmt.Exec(3, chrisBirthday)
3522 if err != nil {
3523 t.Errorf("error on exec: %v", err)
3524 return err
3525 }
3526 return nil
3527 }
3528
3529 type concurrentRandomTest struct {
3530 tests []concurrentTest
3531 }
3532
3533 func (c *concurrentRandomTest) init(t testing.TB, db *DB) {
3534 c.tests = []concurrentTest{
3535 new(concurrentDBQueryTest),
3536 new(concurrentDBExecTest),
3537 new(concurrentStmtQueryTest),
3538 new(concurrentStmtExecTest),
3539 new(concurrentTxQueryTest),
3540 new(concurrentTxExecTest),
3541 new(concurrentTxStmtQueryTest),
3542 new(concurrentTxStmtExecTest),
3543 }
3544 for _, ct := range c.tests {
3545 ct.init(t, db)
3546 }
3547 }
3548
3549 func (c *concurrentRandomTest) finish(t testing.TB) {
3550 for _, ct := range c.tests {
3551 ct.finish(t)
3552 }
3553 }
3554
3555 func (c *concurrentRandomTest) test(t testing.TB) error {
3556 ct := c.tests[rand.Intn(len(c.tests))]
3557 return ct.test(t)
3558 }
3559
3560 func doConcurrentTest(t testing.TB, ct concurrentTest) {
3561 maxProcs, numReqs := 1, 500
3562 if testing.Short() {
3563 maxProcs, numReqs = 4, 50
3564 }
3565 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
3566
3567 db := newTestDB(t, "people")
3568 defer closeDB(t, db)
3569
3570 ct.init(t, db)
3571 defer ct.finish(t)
3572
3573 var wg sync.WaitGroup
3574 wg.Add(numReqs)
3575
3576 reqs := make(chan bool)
3577 defer close(reqs)
3578
3579 for i := 0; i < maxProcs*2; i++ {
3580 go func() {
3581 for range reqs {
3582 err := ct.test(t)
3583 if err != nil {
3584 wg.Done()
3585 continue
3586 }
3587 wg.Done()
3588 }
3589 }()
3590 }
3591
3592 for i := 0; i < numReqs; i++ {
3593 reqs <- true
3594 }
3595
3596 wg.Wait()
3597 }
3598
3599 func TestIssue6081(t *testing.T) {
3600 db := newTestDB(t, "people")
3601 defer closeDB(t, db)
3602
3603 drv := db.Driver().(*fakeDriver)
3604 drv.mu.Lock()
3605 opens0 := drv.openCount
3606 closes0 := drv.closeCount
3607 drv.mu.Unlock()
3608
3609 stmt, err := db.Prepare("SELECT|people|name|")
3610 if err != nil {
3611 t.Fatal(err)
3612 }
3613 setRowsCloseHook(func(rows *Rows, err *error) {
3614 *err = driver.ErrBadConn
3615 })
3616 defer setRowsCloseHook(nil)
3617 for i := 0; i < 10; i++ {
3618 rows, err := stmt.Query()
3619 if err != nil {
3620 t.Fatal(err)
3621 }
3622 rows.Close()
3623 }
3624 if n := len(stmt.css); n > 1 {
3625 t.Errorf("len(css slice) = %d; want <= 1", n)
3626 }
3627 stmt.Close()
3628 if n := len(stmt.css); n != 0 {
3629 t.Errorf("len(css slice) after Close = %d; want 0", n)
3630 }
3631
3632 drv.mu.Lock()
3633 opens := drv.openCount - opens0
3634 closes := drv.closeCount - closes0
3635 drv.mu.Unlock()
3636 if opens < 9 {
3637 t.Errorf("opens = %d; want >= 9", opens)
3638 }
3639 if closes < 9 {
3640 t.Errorf("closes = %d; want >= 9", closes)
3641 }
3642 }
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655 func TestIssue18429(t *testing.T) {
3656 db := newTestDB(t, "people")
3657 defer closeDB(t, db)
3658
3659 ctx := context.Background()
3660 sem := make(chan bool, 20)
3661 var wg sync.WaitGroup
3662
3663 const milliWait = 30
3664
3665 for i := 0; i < 100; i++ {
3666 sem <- true
3667 wg.Add(1)
3668 go func() {
3669 defer func() {
3670 <-sem
3671 wg.Done()
3672 }()
3673 qwait := (time.Duration(rand.Intn(milliWait)) * time.Millisecond).String()
3674
3675 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
3676 defer cancel()
3677
3678 tx, err := db.BeginTx(ctx, nil)
3679 if err != nil {
3680 return
3681 }
3682
3683
3684
3685 rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
3686 if rows != nil {
3687 var name string
3688
3689 for rows.Next() {
3690
3691 rows.Scan(&name)
3692 }
3693 rows.Close()
3694 }
3695
3696
3697 tx.Rollback()
3698 }()
3699 }
3700 wg.Wait()
3701 }
3702
3703
3704 func TestIssue20160(t *testing.T) {
3705 db := newTestDB(t, "people")
3706 defer closeDB(t, db)
3707
3708 ctx := context.Background()
3709 sem := make(chan bool, 20)
3710 var wg sync.WaitGroup
3711
3712 const milliWait = 30
3713
3714 stmt, err := db.PrepareContext(ctx, "SELECT|people|name|")
3715 if err != nil {
3716 t.Fatal(err)
3717 }
3718 defer stmt.Close()
3719
3720 for i := 0; i < 100; i++ {
3721 sem <- true
3722 wg.Add(1)
3723 go func() {
3724 defer func() {
3725 <-sem
3726 wg.Done()
3727 }()
3728 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
3729 defer cancel()
3730
3731
3732
3733
3734 rows, _ := stmt.QueryContext(ctx)
3735 if rows != nil {
3736 rows.Close()
3737 }
3738 }()
3739 }
3740 wg.Wait()
3741 }
3742
3743
3744
3745
3746
3747
3748 func TestIssue18719(t *testing.T) {
3749 db := newTestDB(t, "people")
3750 defer closeDB(t, db)
3751
3752 ctx, cancel := context.WithCancel(context.Background())
3753 defer cancel()
3754
3755 tx, err := db.BeginTx(ctx, nil)
3756 if err != nil {
3757 t.Fatal(err)
3758 }
3759
3760 hookTxGrabConn = func() {
3761 cancel()
3762
3763
3764 for !tx.isDone() {
3765 time.Sleep(pollDuration)
3766 }
3767 }
3768 defer func() { hookTxGrabConn = nil }()
3769
3770
3771
3772 _, err = tx.QueryContext(ctx, "SELECT|people|name|")
3773 if err != nil {
3774 t.Fatalf("expected error %v but got %v", nil, err)
3775 }
3776
3777
3778
3779
3780
3781
3782 cancel()
3783 }
3784
3785 func TestIssue20647(t *testing.T) {
3786 db := newTestDB(t, "people")
3787 defer closeDB(t, db)
3788
3789 ctx, cancel := context.WithCancel(context.Background())
3790 defer cancel()
3791
3792 conn, err := db.Conn(ctx)
3793 if err != nil {
3794 t.Fatal(err)
3795 }
3796 conn.dc.ci.(*fakeConn).skipDirtySession = true
3797 defer conn.Close()
3798
3799 stmt, err := conn.PrepareContext(ctx, "SELECT|people|name|")
3800 if err != nil {
3801 t.Fatal(err)
3802 }
3803 defer stmt.Close()
3804
3805 rows1, err := stmt.QueryContext(ctx)
3806 if err != nil {
3807 t.Fatal("rows1", err)
3808 }
3809 defer rows1.Close()
3810
3811 rows2, err := stmt.QueryContext(ctx)
3812 if err != nil {
3813 t.Fatal("rows2", err)
3814 }
3815 defer rows2.Close()
3816
3817 if rows1.dc != rows2.dc {
3818 t.Fatal("stmt prepared on Conn does not use same connection")
3819 }
3820 }
3821
3822 func TestConcurrency(t *testing.T) {
3823 list := []struct {
3824 name string
3825 ct concurrentTest
3826 }{
3827 {"Query", new(concurrentDBQueryTest)},
3828 {"Exec", new(concurrentDBExecTest)},
3829 {"StmtQuery", new(concurrentStmtQueryTest)},
3830 {"StmtExec", new(concurrentStmtExecTest)},
3831 {"TxQuery", new(concurrentTxQueryTest)},
3832 {"TxExec", new(concurrentTxExecTest)},
3833 {"TxStmtQuery", new(concurrentTxStmtQueryTest)},
3834 {"TxStmtExec", new(concurrentTxStmtExecTest)},
3835 {"Random", new(concurrentRandomTest)},
3836 }
3837 for _, item := range list {
3838 t.Run(item.name, func(t *testing.T) {
3839 doConcurrentTest(t, item.ct)
3840 })
3841 }
3842 }
3843
3844 func TestConnectionLeak(t *testing.T) {
3845 db := newTestDB(t, "people")
3846 defer closeDB(t, db)
3847
3848 rows := make([]*Rows, defaultMaxIdleConns)
3849
3850
3851
3852 db.SetMaxOpenConns(len(rows) + 1)
3853 for ii := range rows {
3854 r, err := db.Query("SELECT|people|name|")
3855 if err != nil {
3856 t.Fatal(err)
3857 }
3858 r.Next()
3859 if err := r.Err(); err != nil {
3860 t.Fatal(err)
3861 }
3862 rows[ii] = r
3863 }
3864
3865
3866
3867 drv := db.Driver().(*fakeDriver)
3868 drv.waitCh = make(chan struct{}, 1)
3869 drv.waitingCh = make(chan struct{}, 1)
3870 var wg sync.WaitGroup
3871 wg.Add(1)
3872 go func() {
3873 r, err := db.Query("SELECT|people|name|")
3874 if err != nil {
3875 t.Error(err)
3876 return
3877 }
3878 r.Close()
3879 wg.Done()
3880 }()
3881
3882 <-drv.waitingCh
3883
3884
3885 for _, v := range rows {
3886 v.Close()
3887 }
3888
3889
3890
3891
3892 drv.waitCh <- struct{}{}
3893 wg.Wait()
3894 }
3895
3896 func TestStatsMaxIdleClosedZero(t *testing.T) {
3897 db := newTestDB(t, "people")
3898 defer closeDB(t, db)
3899
3900 db.SetMaxOpenConns(1)
3901 db.SetMaxIdleConns(1)
3902 db.SetConnMaxLifetime(0)
3903
3904 preMaxIdleClosed := db.Stats().MaxIdleClosed
3905
3906 for i := 0; i < 10; i++ {
3907 rows, err := db.Query("SELECT|people|name|")
3908 if err != nil {
3909 t.Fatal(err)
3910 }
3911 rows.Close()
3912 }
3913
3914 st := db.Stats()
3915 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
3916 t.Logf("MaxIdleClosed: %d", maxIdleClosed)
3917 if maxIdleClosed != 0 {
3918 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
3919 }
3920 }
3921
3922 func TestStatsMaxIdleClosedTen(t *testing.T) {
3923 db := newTestDB(t, "people")
3924 defer closeDB(t, db)
3925
3926 db.SetMaxOpenConns(1)
3927 db.SetMaxIdleConns(0)
3928 db.SetConnMaxLifetime(0)
3929
3930 preMaxIdleClosed := db.Stats().MaxIdleClosed
3931
3932 for i := 0; i < 10; i++ {
3933 rows, err := db.Query("SELECT|people|name|")
3934 if err != nil {
3935 t.Fatal(err)
3936 }
3937 rows.Close()
3938 }
3939
3940 st := db.Stats()
3941 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
3942 t.Logf("MaxIdleClosed: %d", maxIdleClosed)
3943 if maxIdleClosed != 10 {
3944 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
3945 }
3946 }
3947
3948
3949
3950 func testUseConns(t *testing.T, count int, tm time.Time, db *DB) time.Time {
3951 conns := make([]*Conn, count)
3952 ctx := context.Background()
3953 for i := range conns {
3954 tm = tm.Add(time.Nanosecond)
3955 nowFunc = func() time.Time {
3956 return tm
3957 }
3958 c, err := db.Conn(ctx)
3959 if err != nil {
3960 t.Error(err)
3961 }
3962 conns[i] = c
3963 }
3964
3965 for i := len(conns) - 1; i >= 0; i-- {
3966 tm = tm.Add(time.Nanosecond)
3967 nowFunc = func() time.Time {
3968 return tm
3969 }
3970 if err := conns[i].Close(); err != nil {
3971 t.Error(err)
3972 }
3973 }
3974
3975 return tm
3976 }
3977
3978 func TestMaxIdleTime(t *testing.T) {
3979 usedConns := 5
3980 reusedConns := 2
3981 list := []struct {
3982 wantMaxIdleTime time.Duration
3983 wantMaxLifetime time.Duration
3984 wantNextCheck time.Duration
3985 wantIdleClosed int64
3986 wantMaxIdleClosed int64
3987 timeOffset time.Duration
3988 secondTimeOffset time.Duration
3989 }{
3990 {
3991 time.Millisecond,
3992 0,
3993 time.Millisecond - time.Nanosecond,
3994 int64(usedConns - reusedConns),
3995 int64(usedConns - reusedConns),
3996 10 * time.Millisecond,
3997 0,
3998 },
3999 {
4000
4001 time.Millisecond,
4002
4003
4004
4005 10*time.Millisecond + 100*time.Nanosecond + 3*time.Nanosecond,
4006 time.Nanosecond,
4007
4008 int64(usedConns - reusedConns + 1),
4009 int64(usedConns - reusedConns),
4010 10 * time.Millisecond,
4011
4012 100 * time.Nanosecond,
4013 },
4014 {
4015 time.Hour,
4016 0,
4017 time.Second,
4018 0,
4019 0,
4020 10 * time.Millisecond,
4021 0},
4022 }
4023 baseTime := time.Unix(0, 0)
4024 defer func() {
4025 nowFunc = time.Now
4026 }()
4027 for _, item := range list {
4028 nowFunc = func() time.Time {
4029 return baseTime
4030 }
4031 t.Run(fmt.Sprintf("%v", item.wantMaxIdleTime), func(t *testing.T) {
4032 db := newTestDB(t, "people")
4033 defer closeDB(t, db)
4034
4035 db.SetMaxOpenConns(usedConns)
4036 db.SetMaxIdleConns(usedConns)
4037 db.SetConnMaxIdleTime(item.wantMaxIdleTime)
4038 db.SetConnMaxLifetime(item.wantMaxLifetime)
4039
4040 preMaxIdleClosed := db.Stats().MaxIdleTimeClosed
4041
4042
4043 testUseConns(t, usedConns, baseTime, db)
4044
4045 tm := baseTime.Add(item.timeOffset)
4046
4047
4048
4049 tm = testUseConns(t, reusedConns, tm, db)
4050
4051 tm = tm.Add(item.secondTimeOffset)
4052 nowFunc = func() time.Time {
4053 return tm
4054 }
4055
4056 db.mu.Lock()
4057 nc, closing := db.connectionCleanerRunLocked(time.Second)
4058 if nc != item.wantNextCheck {
4059 t.Errorf("got %v; want %v next check duration", nc, item.wantNextCheck)
4060 }
4061
4062
4063 var last time.Time
4064 for _, c := range db.freeConn {
4065 if last.After(c.returnedAt) {
4066 t.Error("freeConn is not ordered by returnedAt")
4067 break
4068 }
4069 last = c.returnedAt
4070 }
4071
4072 db.mu.Unlock()
4073 for _, c := range closing {
4074 c.Close()
4075 }
4076 if g, w := int64(len(closing)), item.wantIdleClosed; g != w {
4077 t.Errorf("got: %d; want %d closed conns", g, w)
4078 }
4079
4080 st := db.Stats()
4081 maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed
4082 if g, w := maxIdleClosed, item.wantMaxIdleClosed; g != w {
4083 t.Errorf("got: %d; want %d max idle closed conns", g, w)
4084 }
4085 })
4086 }
4087 }
4088
4089 type nvcDriver struct {
4090 fakeDriver
4091 skipNamedValueCheck bool
4092 }
4093
4094 func (d *nvcDriver) Open(dsn string) (driver.Conn, error) {
4095 c, err := d.fakeDriver.Open(dsn)
4096 fc := c.(*fakeConn)
4097 fc.db.allowAny = true
4098 return &nvcConn{fc, d.skipNamedValueCheck}, err
4099 }
4100
4101 type nvcConn struct {
4102 *fakeConn
4103 skipNamedValueCheck bool
4104 }
4105
4106 type decimalInt struct {
4107 value int
4108 }
4109
4110 type doNotInclude struct{}
4111
4112 var _ driver.NamedValueChecker = &nvcConn{}
4113
4114 func (c *nvcConn) CheckNamedValue(nv *driver.NamedValue) error {
4115 if c.skipNamedValueCheck {
4116 return driver.ErrSkip
4117 }
4118 switch v := nv.Value.(type) {
4119 default:
4120 return driver.ErrSkip
4121 case Out:
4122 switch ov := v.Dest.(type) {
4123 default:
4124 return errors.New("unknown NameValueCheck OUTPUT type")
4125 case *string:
4126 *ov = "from-server"
4127 nv.Value = "OUT:*string"
4128 }
4129 return nil
4130 case decimalInt, []int64:
4131 return nil
4132 case doNotInclude:
4133 return driver.ErrRemoveArgument
4134 }
4135 }
4136
4137 func TestNamedValueChecker(t *testing.T) {
4138 Register("NamedValueCheck", &nvcDriver{})
4139 db, err := Open("NamedValueCheck", "")
4140 if err != nil {
4141 t.Fatal(err)
4142 }
4143 defer db.Close()
4144
4145 ctx, cancel := context.WithCancel(context.Background())
4146 defer cancel()
4147
4148 _, err = db.ExecContext(ctx, "WIPE")
4149 if err != nil {
4150 t.Fatal("exec wipe", err)
4151 }
4152
4153 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any")
4154 if err != nil {
4155 t.Fatal("exec create", err)
4156 }
4157
4158 o1 := ""
4159 _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A,str1=?,out1=?O1,array1=?", Named("A", decimalInt{123}), "hello", Named("O1", Out{Dest: &o1}), []int64{42, 128, 707}, doNotInclude{})
4160 if err != nil {
4161 t.Fatal("exec insert", err)
4162 }
4163 var (
4164 str1 string
4165 dec1 decimalInt
4166 arr1 []int64
4167 )
4168 err = db.QueryRowContext(ctx, "SELECT|keys|dec1,str1,array1|").Scan(&dec1, &str1, &arr1)
4169 if err != nil {
4170 t.Fatal("select", err)
4171 }
4172
4173 list := []struct{ got, want any }{
4174 {o1, "from-server"},
4175 {dec1, decimalInt{123}},
4176 {str1, "hello"},
4177 {arr1, []int64{42, 128, 707}},
4178 }
4179
4180 for index, item := range list {
4181 if !reflect.DeepEqual(item.got, item.want) {
4182 t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index)
4183 }
4184 }
4185 }
4186
4187 func TestNamedValueCheckerSkip(t *testing.T) {
4188 Register("NamedValueCheckSkip", &nvcDriver{skipNamedValueCheck: true})
4189 db, err := Open("NamedValueCheckSkip", "")
4190 if err != nil {
4191 t.Fatal(err)
4192 }
4193 defer db.Close()
4194
4195 ctx, cancel := context.WithCancel(context.Background())
4196 defer cancel()
4197
4198 _, err = db.ExecContext(ctx, "WIPE")
4199 if err != nil {
4200 t.Fatal("exec wipe", err)
4201 }
4202
4203 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any")
4204 if err != nil {
4205 t.Fatal("exec create", err)
4206 }
4207
4208 _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A", Named("A", decimalInt{123}))
4209 if err == nil {
4210 t.Fatalf("expected error with bad argument, got %v", err)
4211 }
4212 }
4213
4214 func TestOpenConnector(t *testing.T) {
4215 Register("testctx", &fakeDriverCtx{})
4216 db, err := Open("testctx", "people")
4217 if err != nil {
4218 t.Fatal(err)
4219 }
4220 defer db.Close()
4221
4222 c, ok := db.connector.(*fakeConnector)
4223 if !ok {
4224 t.Fatal("not using *fakeConnector")
4225 }
4226
4227 if err := db.Close(); err != nil {
4228 t.Fatal(err)
4229 }
4230
4231 if !c.closed {
4232 t.Fatal("connector is not closed")
4233 }
4234 }
4235
4236 type ctxOnlyDriver struct {
4237 fakeDriver
4238 }
4239
4240 func (d *ctxOnlyDriver) Open(dsn string) (driver.Conn, error) {
4241 conn, err := d.fakeDriver.Open(dsn)
4242 if err != nil {
4243 return nil, err
4244 }
4245 return &ctxOnlyConn{fc: conn.(*fakeConn)}, nil
4246 }
4247
4248 var (
4249 _ driver.Conn = &ctxOnlyConn{}
4250 _ driver.QueryerContext = &ctxOnlyConn{}
4251 _ driver.ExecerContext = &ctxOnlyConn{}
4252 )
4253
4254 type ctxOnlyConn struct {
4255 fc *fakeConn
4256
4257 queryCtxCalled bool
4258 execCtxCalled bool
4259 }
4260
4261 func (c *ctxOnlyConn) Begin() (driver.Tx, error) {
4262 return c.fc.Begin()
4263 }
4264
4265 func (c *ctxOnlyConn) Close() error {
4266 return c.fc.Close()
4267 }
4268
4269
4270
4271 func (c *ctxOnlyConn) Prepare(q string) (driver.Stmt, error) {
4272 panic("not used")
4273 }
4274
4275 func (c *ctxOnlyConn) PrepareContext(ctx context.Context, q string) (driver.Stmt, error) {
4276 return c.fc.PrepareContext(ctx, q)
4277 }
4278
4279 func (c *ctxOnlyConn) QueryContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Rows, error) {
4280 c.queryCtxCalled = true
4281 return c.fc.QueryContext(ctx, q, args)
4282 }
4283
4284 func (c *ctxOnlyConn) ExecContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Result, error) {
4285 c.execCtxCalled = true
4286 return c.fc.ExecContext(ctx, q, args)
4287 }
4288
4289
4290
4291 func TestQueryExecContextOnly(t *testing.T) {
4292
4293 var connType driver.Conn = &ctxOnlyConn{}
4294 if _, ok := connType.(driver.Execer); ok {
4295 t.Fatalf("%T must not implement driver.Execer", connType)
4296 }
4297 if _, ok := connType.(driver.Queryer); ok {
4298 t.Fatalf("%T must not implement driver.Queryer", connType)
4299 }
4300
4301 Register("ContextOnly", &ctxOnlyDriver{})
4302 db, err := Open("ContextOnly", "")
4303 if err != nil {
4304 t.Fatal(err)
4305 }
4306 defer db.Close()
4307
4308 ctx, cancel := context.WithCancel(context.Background())
4309 defer cancel()
4310
4311 conn, err := db.Conn(ctx)
4312 if err != nil {
4313 t.Fatal("db.Conn", err)
4314 }
4315 defer conn.Close()
4316 coc := conn.dc.ci.(*ctxOnlyConn)
4317 coc.fc.skipDirtySession = true
4318
4319 _, err = conn.ExecContext(ctx, "WIPE")
4320 if err != nil {
4321 t.Fatal("exec wipe", err)
4322 }
4323
4324 _, err = conn.ExecContext(ctx, "CREATE|keys|v1=string")
4325 if err != nil {
4326 t.Fatal("exec create", err)
4327 }
4328 expectedValue := "value1"
4329 _, err = conn.ExecContext(ctx, "INSERT|keys|v1=?", expectedValue)
4330 if err != nil {
4331 t.Fatal("exec insert", err)
4332 }
4333 rows, err := conn.QueryContext(ctx, "SELECT|keys|v1|")
4334 if err != nil {
4335 t.Fatal("query select", err)
4336 }
4337 v1 := ""
4338 for rows.Next() {
4339 err = rows.Scan(&v1)
4340 if err != nil {
4341 t.Fatal("rows scan", err)
4342 }
4343 }
4344 rows.Close()
4345
4346 if v1 != expectedValue {
4347 t.Fatalf("expected %q, got %q", expectedValue, v1)
4348 }
4349
4350 if !coc.execCtxCalled {
4351 t.Error("ExecContext not called")
4352 }
4353 if !coc.queryCtxCalled {
4354 t.Error("QueryContext not called")
4355 }
4356 }
4357
4358 type alwaysErrScanner struct{}
4359
4360 var errTestScanWrap = errors.New("errTestScanWrap")
4361
4362 func (alwaysErrScanner) Scan(any) error {
4363 return errTestScanWrap
4364 }
4365
4366
4367 func TestRowsScanProperlyWrapsErrors(t *testing.T) {
4368 db := newTestDB(t, "people")
4369 defer closeDB(t, db)
4370
4371 rows, err := db.Query("SELECT|people|age|")
4372 if err != nil {
4373 t.Fatalf("Query: %v", err)
4374 }
4375
4376 var res alwaysErrScanner
4377
4378 for rows.Next() {
4379 err = rows.Scan(&res)
4380 if err == nil {
4381 t.Fatal("expecting back an error")
4382 }
4383 if !errors.Is(err, errTestScanWrap) {
4384 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errTestScanWrap)
4385 }
4386
4387 if !strings.Contains(err.Error(), errTestScanWrap.Error()) {
4388 t.Fatalf("Error %v does not contain %v", err, errTestScanWrap)
4389 }
4390 }
4391 }
4392
4393 type alwaysErrValuer struct{}
4394
4395
4396 var errEmpty = errors.New("empty value")
4397
4398 func (v alwaysErrValuer) Value() (driver.Value, error) {
4399 return nil, errEmpty
4400 }
4401
4402
4403 func TestDriverArgsWrapsErrors(t *testing.T) {
4404 db := newTestDB(t, "people")
4405 defer closeDB(t, db)
4406
4407 t.Run("exec", func(t *testing.T) {
4408 _, err := db.Exec("INSERT|keys|dec1=?", alwaysErrValuer{})
4409 if err == nil {
4410 t.Fatal("expecting back an error")
4411 }
4412 if !errors.Is(err, errEmpty) {
4413 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errEmpty)
4414 }
4415
4416 if !strings.Contains(err.Error(), errEmpty.Error()) {
4417 t.Fatalf("Error %v does not contain %v", err, errEmpty)
4418 }
4419 })
4420
4421 t.Run("query", func(t *testing.T) {
4422 _, err := db.Query("INSERT|keys|dec1=?", alwaysErrValuer{})
4423 if err == nil {
4424 t.Fatal("expecting back an error")
4425 }
4426 if !errors.Is(err, errEmpty) {
4427 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errEmpty)
4428 }
4429
4430 if !strings.Contains(err.Error(), errEmpty.Error()) {
4431 t.Fatalf("Error %v does not contain %v", err, errEmpty)
4432 }
4433 })
4434 }
4435
4436 func TestContextCancelDuringRawBytesScan(t *testing.T) {
4437 for _, mode := range []string{"nocancel", "top", "bottom", "go"} {
4438 t.Run(mode, func(t *testing.T) {
4439 testContextCancelDuringRawBytesScan(t, mode)
4440 })
4441 }
4442 }
4443
4444
4445 func testContextCancelDuringRawBytesScan(t *testing.T, mode string) {
4446 db := newTestDB(t, "people")
4447 defer closeDB(t, db)
4448
4449 if _, err := db.Exec("USE_RAWBYTES"); err != nil {
4450 t.Fatal(err)
4451 }
4452
4453
4454
4455 ctx, cancel := context.WithCancel(context.Background())
4456 defer cancel()
4457
4458 r, err := db.QueryContext(ctx, "SELECT|people|name|")
4459 if err != nil {
4460 t.Fatal(err)
4461 }
4462 numRows := 0
4463 var sink byte
4464 for r.Next() {
4465 if mode == "top" && numRows == 2 {
4466
4467
4468
4469 cancel()
4470 time.Sleep(100 * time.Millisecond)
4471 }
4472 numRows++
4473 var s RawBytes
4474 err = r.Scan(&s)
4475 if numRows == 3 && err == context.Canceled {
4476 if r.closemuScanHold {
4477 t.Errorf("expected closemu NOT to be held")
4478 }
4479 break
4480 }
4481 if !r.closemuScanHold {
4482 t.Errorf("expected closemu to be held")
4483 }
4484 if err != nil {
4485 t.Fatal(err)
4486 }
4487 t.Logf("read %q", s)
4488 if mode == "bottom" && numRows == 2 {
4489
4490
4491
4492 cancel()
4493 time.Sleep(100 * time.Millisecond)
4494 }
4495 if mode == "go" && numRows == 2 {
4496
4497 go cancel()
4498 }
4499 for _, b := range s {
4500 sink += b
4501 }
4502 }
4503 if r.closemuScanHold {
4504 t.Errorf("closemu held; should not be")
4505 }
4506
4507
4508
4509 switch numRows {
4510 case 0, 1:
4511 t.Errorf("got %d rows; want 2+", numRows)
4512 case 2:
4513 if err := r.Err(); err != context.Canceled {
4514 t.Errorf("unexpected error: %v (%T)", err, err)
4515 }
4516 default:
4517
4518 }
4519
4520 if err := r.Close(); err != nil {
4521 t.Fatal(err)
4522 }
4523 }
4524
4525 func TestContextCancelBetweenNextAndErr(t *testing.T) {
4526 db := newTestDB(t, "people")
4527 defer closeDB(t, db)
4528 ctx, cancel := context.WithCancel(context.Background())
4529 defer cancel()
4530
4531 r, err := db.QueryContext(ctx, "SELECT|people|name|")
4532 if err != nil {
4533 t.Fatal(err)
4534 }
4535 for r.Next() {
4536 }
4537 cancel()
4538 time.Sleep(10 * time.Millisecond)
4539 if err := r.Err(); err != nil {
4540 t.Fatal(err)
4541 }
4542 }
4543
4544 func TestNilErrorAfterClose(t *testing.T) {
4545 db := newTestDB(t, "people")
4546 defer closeDB(t, db)
4547
4548
4549
4550
4551 ctx, cancel := context.WithCancel(context.Background())
4552 defer cancel()
4553
4554 r, err := db.QueryContext(ctx, "SELECT|people|name|")
4555 if err != nil {
4556 t.Fatal(err)
4557 }
4558
4559 if err := r.Close(); err != nil {
4560 t.Fatal(err)
4561 }
4562
4563 time.Sleep(10 * time.Millisecond)
4564 if err := r.Err(); err != nil {
4565 t.Fatal(err)
4566 }
4567 }
4568
4569
4570
4571
4572
4573 func TestRawBytesReuse(t *testing.T) {
4574 db := newTestDB(t, "people")
4575 defer closeDB(t, db)
4576
4577 if _, err := db.Exec("USE_RAWBYTES"); err != nil {
4578 t.Fatal(err)
4579 }
4580
4581 var raw RawBytes
4582
4583
4584 rows, err := db.Query("SELECT|people|name|")
4585 if err != nil {
4586 t.Fatal(err)
4587 }
4588 rows.Next()
4589 rows.Scan(&raw)
4590 name1 := string(raw)
4591 rows.Close()
4592
4593
4594 rows, err = db.Query("SELECT|people|age|")
4595 if err != nil {
4596 t.Fatal(err)
4597 }
4598 rows.Next()
4599 rows.Scan(&raw)
4600 rows.Close()
4601
4602
4603 rows, err = db.Query("SELECT|people|name|")
4604 if err != nil {
4605 t.Fatal(err)
4606 }
4607 rows.Next()
4608 rows.Scan(&raw)
4609 name2 := string(raw)
4610 rows.Close()
4611 if name1 != name2 {
4612 t.Fatalf("Scan read name %q, want %q", name2, name1)
4613 }
4614 }
4615
4616
4617
4618 type badConn struct{}
4619
4620 func (bc badConn) Prepare(query string) (driver.Stmt, error) {
4621 return nil, errors.New("badConn Prepare")
4622 }
4623
4624 func (bc badConn) Close() error {
4625 return nil
4626 }
4627
4628 func (bc badConn) Begin() (driver.Tx, error) {
4629 return nil, errors.New("badConn Begin")
4630 }
4631
4632 func (bc badConn) Exec(query string, args []driver.Value) (driver.Result, error) {
4633 panic("badConn.Exec")
4634 }
4635
4636
4637 type badDriver struct{}
4638
4639 func (bd badDriver) Open(name string) (driver.Conn, error) {
4640 return badConn{}, nil
4641 }
4642
4643
4644 func TestBadDriver(t *testing.T) {
4645 Register("bad", badDriver{})
4646 db, err := Open("bad", "ignored")
4647 if err != nil {
4648 t.Fatal(err)
4649 }
4650 defer func() {
4651 if r := recover(); r == nil {
4652 t.Error("expected panic")
4653 } else {
4654 if want := "badConn.Exec"; r.(string) != want {
4655 t.Errorf("panic was %v, expected %v", r, want)
4656 }
4657 }
4658 }()
4659 defer db.Close()
4660 db.Exec("ignored")
4661 }
4662
4663 type pingDriver struct {
4664 fails bool
4665 }
4666
4667 type pingConn struct {
4668 badConn
4669 driver *pingDriver
4670 }
4671
4672 var pingError = errors.New("Ping failed")
4673
4674 func (pc pingConn) Ping(ctx context.Context) error {
4675 if pc.driver.fails {
4676 return pingError
4677 }
4678 return nil
4679 }
4680
4681 var _ driver.Pinger = pingConn{}
4682
4683 func (pd *pingDriver) Open(name string) (driver.Conn, error) {
4684 return pingConn{driver: pd}, nil
4685 }
4686
4687 func TestPing(t *testing.T) {
4688 driver := &pingDriver{}
4689 Register("ping", driver)
4690
4691 db, err := Open("ping", "ignored")
4692 if err != nil {
4693 t.Fatal(err)
4694 }
4695
4696 if err := db.Ping(); err != nil {
4697 t.Errorf("err was %#v, expected nil", err)
4698 return
4699 }
4700
4701 driver.fails = true
4702 if err := db.Ping(); err != pingError {
4703 t.Errorf("err was %#v, expected pingError", err)
4704 }
4705 }
4706
4707
4708 func TestTypedString(t *testing.T) {
4709 db := newTestDB(t, "people")
4710 defer closeDB(t, db)
4711
4712 type Str string
4713 var scanned Str
4714
4715 err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned)
4716 if err != nil {
4717 t.Fatal(err)
4718 }
4719 expected := Str("Alice")
4720 if scanned != expected {
4721 t.Errorf("expected %+v, got %+v", expected, scanned)
4722 }
4723 }
4724
4725 func BenchmarkConcurrentDBExec(b *testing.B) {
4726 b.ReportAllocs()
4727 ct := new(concurrentDBExecTest)
4728 for i := 0; i < b.N; i++ {
4729 doConcurrentTest(b, ct)
4730 }
4731 }
4732
4733 func BenchmarkConcurrentStmtQuery(b *testing.B) {
4734 b.ReportAllocs()
4735 ct := new(concurrentStmtQueryTest)
4736 for i := 0; i < b.N; i++ {
4737 doConcurrentTest(b, ct)
4738 }
4739 }
4740
4741 func BenchmarkConcurrentStmtExec(b *testing.B) {
4742 b.ReportAllocs()
4743 ct := new(concurrentStmtExecTest)
4744 for i := 0; i < b.N; i++ {
4745 doConcurrentTest(b, ct)
4746 }
4747 }
4748
4749 func BenchmarkConcurrentTxQuery(b *testing.B) {
4750 b.ReportAllocs()
4751 ct := new(concurrentTxQueryTest)
4752 for i := 0; i < b.N; i++ {
4753 doConcurrentTest(b, ct)
4754 }
4755 }
4756
4757 func BenchmarkConcurrentTxExec(b *testing.B) {
4758 b.ReportAllocs()
4759 ct := new(concurrentTxExecTest)
4760 for i := 0; i < b.N; i++ {
4761 doConcurrentTest(b, ct)
4762 }
4763 }
4764
4765 func BenchmarkConcurrentTxStmtQuery(b *testing.B) {
4766 b.ReportAllocs()
4767 ct := new(concurrentTxStmtQueryTest)
4768 for i := 0; i < b.N; i++ {
4769 doConcurrentTest(b, ct)
4770 }
4771 }
4772
4773 func BenchmarkConcurrentTxStmtExec(b *testing.B) {
4774 b.ReportAllocs()
4775 ct := new(concurrentTxStmtExecTest)
4776 for i := 0; i < b.N; i++ {
4777 doConcurrentTest(b, ct)
4778 }
4779 }
4780
4781 func BenchmarkConcurrentRandom(b *testing.B) {
4782 b.ReportAllocs()
4783 ct := new(concurrentRandomTest)
4784 for i := 0; i < b.N; i++ {
4785 doConcurrentTest(b, ct)
4786 }
4787 }
4788
4789 func BenchmarkManyConcurrentQueries(b *testing.B) {
4790 b.ReportAllocs()
4791
4792 const parallelism = 16
4793
4794 db := newTestDB(b, "magicquery")
4795 defer closeDB(b, db)
4796 db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism)
4797
4798 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
4799 if err != nil {
4800 b.Fatal(err)
4801 }
4802 defer stmt.Close()
4803
4804 b.SetParallelism(parallelism)
4805 b.RunParallel(func(pb *testing.PB) {
4806 for pb.Next() {
4807 rows, err := stmt.Query("sleep", 1)
4808 if err != nil {
4809 b.Error(err)
4810 return
4811 }
4812 rows.Close()
4813 }
4814 })
4815 }
4816
4817 func TestGrabConnAllocs(t *testing.T) {
4818 testenv.SkipIfOptimizationOff(t)
4819 if race.Enabled {
4820 t.Skip("skipping allocation test when using race detector")
4821 }
4822 c := new(Conn)
4823 ctx := context.Background()
4824 n := int(testing.AllocsPerRun(1000, func() {
4825 _, release, err := c.grabConn(ctx)
4826 if err != nil {
4827 t.Fatal(err)
4828 }
4829 release(nil)
4830 }))
4831 if n > 0 {
4832 t.Fatalf("Conn.grabConn allocated %v objects; want 0", n)
4833 }
4834 }
4835
4836 func BenchmarkGrabConn(b *testing.B) {
4837 b.ReportAllocs()
4838 c := new(Conn)
4839 ctx := context.Background()
4840 for i := 0; i < b.N; i++ {
4841 _, release, err := c.grabConn(ctx)
4842 if err != nil {
4843 b.Fatal(err)
4844 }
4845 release(nil)
4846 }
4847 }
4848
4849 func TestConnRequestSet(t *testing.T) {
4850 var s connRequestSet
4851 wantLen := func(want int) {
4852 t.Helper()
4853 if got := s.Len(); got != want {
4854 t.Errorf("Len = %d; want %d", got, want)
4855 }
4856 if want == 0 && !t.Failed() {
4857 if _, ok := s.TakeRandom(); ok {
4858 t.Fatalf("TakeRandom returned result when empty")
4859 }
4860 }
4861 }
4862 reset := func() { s = connRequestSet{} }
4863
4864 t.Run("add-delete", func(t *testing.T) {
4865 reset()
4866 wantLen(0)
4867 dh := s.Add(nil)
4868 wantLen(1)
4869 if !s.Delete(dh) {
4870 t.Fatal("failed to delete")
4871 }
4872 wantLen(0)
4873 if s.Delete(dh) {
4874 t.Error("delete worked twice")
4875 }
4876 wantLen(0)
4877 })
4878 t.Run("take-before-delete", func(t *testing.T) {
4879 reset()
4880 ch1 := make(chan connRequest)
4881 dh := s.Add(ch1)
4882 wantLen(1)
4883 if got, ok := s.TakeRandom(); !ok || got != ch1 {
4884 t.Fatalf("wrong take; ok=%v", ok)
4885 }
4886 wantLen(0)
4887 if s.Delete(dh) {
4888 t.Error("unexpected delete after take")
4889 }
4890 })
4891 t.Run("get-take-many", func(t *testing.T) {
4892 reset()
4893 m := map[chan connRequest]bool{}
4894 const N = 100
4895 var inOrder, backOut []chan connRequest
4896 for range N {
4897 c := make(chan connRequest)
4898 m[c] = true
4899 s.Add(c)
4900 inOrder = append(inOrder, c)
4901 }
4902 if s.Len() != N {
4903 t.Fatalf("Len = %v; want %v", s.Len(), N)
4904 }
4905 for s.Len() > 0 {
4906 c, ok := s.TakeRandom()
4907 if !ok {
4908 t.Fatal("failed to take when non-empty")
4909 }
4910 if !m[c] {
4911 t.Fatal("returned item not in remaining set")
4912 }
4913 delete(m, c)
4914 backOut = append(backOut, c)
4915 }
4916 if len(m) > 0 {
4917 t.Error("items remain in expected map")
4918 }
4919 if slices.Equal(inOrder, backOut) {
4920 t.Error("wasn't random")
4921 }
4922 })
4923 t.Run("close-delete", func(t *testing.T) {
4924 reset()
4925 ch := make(chan connRequest)
4926 dh := s.Add(ch)
4927 wantLen(1)
4928 s.CloseAndRemoveAll()
4929 wantLen(0)
4930 if s.Delete(dh) {
4931 t.Error("unexpected delete after CloseAndRemoveAll")
4932 }
4933 })
4934 }
4935
4936 func BenchmarkConnRequestSet(b *testing.B) {
4937 var s connRequestSet
4938 for range b.N {
4939 for range 16 {
4940 s.Add(nil)
4941 }
4942 for range 8 {
4943 if _, ok := s.TakeRandom(); !ok {
4944 b.Fatal("want ok")
4945 }
4946 }
4947 for range 8 {
4948 s.Add(nil)
4949 }
4950 for range 16 {
4951 if _, ok := s.TakeRandom(); !ok {
4952 b.Fatal("want ok")
4953 }
4954 }
4955 if _, ok := s.TakeRandom(); ok {
4956 b.Fatal("unexpected ok")
4957 }
4958 }
4959 }
4960
View as plain text