github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/database/sql/sql_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sql 6 7 import ( 8 "database/sql/driver" 9 "errors" 10 "fmt" 11 "math/rand" 12 "reflect" 13 "runtime" 14 "strings" 15 "sync" 16 "testing" 17 "time" 18 ) 19 20 func init() { 21 type dbConn struct { 22 db *DB 23 c *driverConn 24 } 25 freedFrom := make(map[dbConn]string) 26 putConnHook = func(db *DB, c *driverConn) { 27 idx := -1 28 for i, v := range db.freeConn { 29 if v == c { 30 idx = i 31 break 32 } 33 } 34 if idx >= 0 { 35 // print before panic, as panic may get lost due to conflicting panic 36 // (all goroutines asleep) elsewhere, since we might not unlock 37 // the mutex in freeConn here. 38 println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack()) 39 panic("double free of conn.") 40 } 41 freedFrom[dbConn{db, c}] = stack() 42 } 43 } 44 45 const fakeDBName = "foo" 46 47 var chrisBirthday = time.Unix(123456789, 0) 48 49 func newTestDB(t testing.TB, name string) *DB { 50 db, err := Open("test", fakeDBName) 51 if err != nil { 52 t.Fatalf("Open: %v", err) 53 } 54 if _, err := db.Exec("WIPE"); err != nil { 55 t.Fatalf("exec wipe: %v", err) 56 } 57 if name == "people" { 58 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime") 59 exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1) 60 exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2) 61 exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 62 } 63 if name == "magicquery" { 64 // Magic table name and column, known by fakedb_test.go. 65 exec(t, db, "CREATE|magicquery|op=string,millis=int32") 66 exec(t, db, "INSERT|magicquery|op=sleep,millis=10") 67 } 68 return db 69 } 70 71 func exec(t testing.TB, db *DB, query string, args ...interface{}) { 72 _, err := db.Exec(query, args...) 73 if err != nil { 74 t.Fatalf("Exec of %q: %v", query, err) 75 } 76 } 77 78 func closeDB(t testing.TB, db *DB) { 79 if e := recover(); e != nil { 80 fmt.Printf("Panic: %v\n", e) 81 panic(e) 82 } 83 defer setHookpostCloseConn(nil) 84 setHookpostCloseConn(func(_ *fakeConn, err error) { 85 if err != nil { 86 t.Errorf("Error closing fakeConn: %v", err) 87 } 88 }) 89 for i, dc := range db.freeConn { 90 if n := len(dc.openStmt); n > 0 { 91 // Just a sanity check. This is legal in 92 // general, but if we make the tests clean up 93 // their statements first, then we can safely 94 // verify this is always zero here, and any 95 // other value is a leak. 96 t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n) 97 } 98 } 99 err := db.Close() 100 if err != nil { 101 t.Fatalf("error closing DB: %v", err) 102 } 103 db.mu.Lock() 104 count := db.numOpen 105 db.mu.Unlock() 106 if count != 0 { 107 t.Fatalf("%d connections still open after closing DB", db.numOpen) 108 } 109 } 110 111 // numPrepares assumes that db has exactly 1 idle conn and returns 112 // its count of calls to Prepare 113 func numPrepares(t *testing.T, db *DB) int { 114 if n := len(db.freeConn); n != 1 { 115 t.Fatalf("free conns = %d; want 1", n) 116 } 117 return db.freeConn[0].ci.(*fakeConn).numPrepare 118 } 119 120 func (db *DB) numDeps() int { 121 db.mu.Lock() 122 defer db.mu.Unlock() 123 return len(db.dep) 124 } 125 126 // Dependencies are closed via a goroutine, so this polls waiting for 127 // numDeps to fall to want, waiting up to d. 128 func (db *DB) numDepsPollUntil(want int, d time.Duration) int { 129 deadline := time.Now().Add(d) 130 for { 131 n := db.numDeps() 132 if n <= want || time.Now().After(deadline) { 133 return n 134 } 135 time.Sleep(50 * time.Millisecond) 136 } 137 } 138 139 func (db *DB) numFreeConns() int { 140 db.mu.Lock() 141 defer db.mu.Unlock() 142 return len(db.freeConn) 143 } 144 145 // clearAllConns closes all connections in db. 146 func (db *DB) clearAllConns(t *testing.T) { 147 db.SetMaxIdleConns(0) 148 149 if g, w := db.numFreeConns(), 0; g != w { 150 t.Errorf("free conns = %d; want %d", g, w) 151 } 152 153 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 154 t.Errorf("number of dependencies = %d; expected 0", n) 155 db.dumpDeps(t) 156 } 157 } 158 159 func (db *DB) dumpDeps(t *testing.T) { 160 for fc := range db.dep { 161 db.dumpDep(t, 0, fc, map[finalCloser]bool{}) 162 } 163 } 164 165 func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) { 166 seen[dep] = true 167 indent := strings.Repeat(" ", depth) 168 ds := db.dep[dep] 169 for k := range ds { 170 t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k) 171 if fc, ok := k.(finalCloser); ok { 172 if !seen[fc] { 173 db.dumpDep(t, depth+1, fc, seen) 174 } 175 } 176 } 177 } 178 179 func TestQuery(t *testing.T) { 180 db := newTestDB(t, "people") 181 defer closeDB(t, db) 182 prepares0 := numPrepares(t, db) 183 rows, err := db.Query("SELECT|people|age,name|") 184 if err != nil { 185 t.Fatalf("Query: %v", err) 186 } 187 type row struct { 188 age int 189 name string 190 } 191 got := []row{} 192 for rows.Next() { 193 var r row 194 err = rows.Scan(&r.age, &r.name) 195 if err != nil { 196 t.Fatalf("Scan: %v", err) 197 } 198 got = append(got, r) 199 } 200 err = rows.Err() 201 if err != nil { 202 t.Fatalf("Err: %v", err) 203 } 204 want := []row{ 205 {age: 1, name: "Alice"}, 206 {age: 2, name: "Bob"}, 207 {age: 3, name: "Chris"}, 208 } 209 if !reflect.DeepEqual(got, want) { 210 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 211 } 212 213 // And verify that the final rows.Next() call, which hit EOF, 214 // also closed the rows connection. 215 if n := db.numFreeConns(); n != 1 { 216 t.Fatalf("free conns after query hitting EOF = %d; want 1", n) 217 } 218 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 219 t.Errorf("executed %d Prepare statements; want 1", prepares) 220 } 221 } 222 223 func TestByteOwnership(t *testing.T) { 224 db := newTestDB(t, "people") 225 defer closeDB(t, db) 226 rows, err := db.Query("SELECT|people|name,photo|") 227 if err != nil { 228 t.Fatalf("Query: %v", err) 229 } 230 type row struct { 231 name []byte 232 photo RawBytes 233 } 234 got := []row{} 235 for rows.Next() { 236 var r row 237 err = rows.Scan(&r.name, &r.photo) 238 if err != nil { 239 t.Fatalf("Scan: %v", err) 240 } 241 got = append(got, r) 242 } 243 corruptMemory := []byte("\xffPHOTO") 244 want := []row{ 245 {name: []byte("Alice"), photo: corruptMemory}, 246 {name: []byte("Bob"), photo: corruptMemory}, 247 {name: []byte("Chris"), photo: corruptMemory}, 248 } 249 if !reflect.DeepEqual(got, want) { 250 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 251 } 252 253 var photo RawBytes 254 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 255 if err == nil { 256 t.Error("want error scanning into RawBytes from QueryRow") 257 } 258 } 259 260 func TestRowsColumns(t *testing.T) { 261 db := newTestDB(t, "people") 262 defer closeDB(t, db) 263 rows, err := db.Query("SELECT|people|age,name|") 264 if err != nil { 265 t.Fatalf("Query: %v", err) 266 } 267 cols, err := rows.Columns() 268 if err != nil { 269 t.Fatalf("Columns: %v", err) 270 } 271 want := []string{"age", "name"} 272 if !reflect.DeepEqual(cols, want) { 273 t.Errorf("got %#v; want %#v", cols, want) 274 } 275 if err := rows.Close(); err != nil { 276 t.Errorf("error closing rows: %s", err) 277 } 278 } 279 280 func TestQueryRow(t *testing.T) { 281 db := newTestDB(t, "people") 282 defer closeDB(t, db) 283 var name string 284 var age int 285 var birthday time.Time 286 287 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age) 288 if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") { 289 t.Errorf("expected error from wrong number of arguments; actually got: %v", err) 290 } 291 292 err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday) 293 if err != nil || !birthday.Equal(chrisBirthday) { 294 t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday) 295 } 296 297 err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name) 298 if err != nil { 299 t.Fatalf("age QueryRow+Scan: %v", err) 300 } 301 if name != "Bob" { 302 t.Errorf("expected name Bob, got %q", name) 303 } 304 if age != 2 { 305 t.Errorf("expected age 2, got %d", age) 306 } 307 308 err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name) 309 if err != nil { 310 t.Fatalf("name QueryRow+Scan: %v", err) 311 } 312 if name != "Alice" { 313 t.Errorf("expected name Alice, got %q", name) 314 } 315 if age != 1 { 316 t.Errorf("expected age 1, got %d", age) 317 } 318 319 var photo []byte 320 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 321 if err != nil { 322 t.Fatalf("photo QueryRow+Scan: %v", err) 323 } 324 want := []byte("APHOTO") 325 if !reflect.DeepEqual(photo, want) { 326 t.Errorf("photo = %q; want %q", photo, want) 327 } 328 } 329 330 func TestStatementErrorAfterClose(t *testing.T) { 331 db := newTestDB(t, "people") 332 defer closeDB(t, db) 333 stmt, err := db.Prepare("SELECT|people|age|name=?") 334 if err != nil { 335 t.Fatalf("Prepare: %v", err) 336 } 337 err = stmt.Close() 338 if err != nil { 339 t.Fatalf("Close: %v", err) 340 } 341 var name string 342 err = stmt.QueryRow("foo").Scan(&name) 343 if err == nil { 344 t.Errorf("expected error from QueryRow.Scan after Stmt.Close") 345 } 346 } 347 348 func TestStatementQueryRow(t *testing.T) { 349 db := newTestDB(t, "people") 350 defer closeDB(t, db) 351 stmt, err := db.Prepare("SELECT|people|age|name=?") 352 if err != nil { 353 t.Fatalf("Prepare: %v", err) 354 } 355 defer stmt.Close() 356 var age int 357 for n, tt := range []struct { 358 name string 359 want int 360 }{ 361 {"Alice", 1}, 362 {"Bob", 2}, 363 {"Chris", 3}, 364 } { 365 if err := stmt.QueryRow(tt.name).Scan(&age); err != nil { 366 t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err) 367 } else if age != tt.want { 368 t.Errorf("%d: age=%d, want %d", n, age, tt.want) 369 } 370 } 371 } 372 373 type stubDriverStmt struct { 374 err error 375 } 376 377 func (s stubDriverStmt) Close() error { 378 return s.err 379 } 380 381 func (s stubDriverStmt) NumInput() int { 382 return -1 383 } 384 385 func (s stubDriverStmt) Exec(args []driver.Value) (driver.Result, error) { 386 return nil, nil 387 } 388 389 func (s stubDriverStmt) Query(args []driver.Value) (driver.Rows, error) { 390 return nil, nil 391 } 392 393 // golang.org/issue/12798 394 func TestStatementClose(t *testing.T) { 395 want := errors.New("STMT ERROR") 396 397 tests := []struct { 398 stmt *Stmt 399 msg string 400 }{ 401 {&Stmt{stickyErr: want}, "stickyErr not propagated"}, 402 {&Stmt{tx: &Tx{}, txsi: &driverStmt{&sync.Mutex{}, stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"}, 403 } 404 for _, test := range tests { 405 if err := test.stmt.Close(); err != want { 406 t.Errorf("%s. Got stmt.Close() = %v, want = %v", test.msg, err, want) 407 } 408 } 409 } 410 411 // golang.org/issue/3734 412 func TestStatementQueryRowConcurrent(t *testing.T) { 413 db := newTestDB(t, "people") 414 defer closeDB(t, db) 415 stmt, err := db.Prepare("SELECT|people|age|name=?") 416 if err != nil { 417 t.Fatalf("Prepare: %v", err) 418 } 419 defer stmt.Close() 420 421 const n = 10 422 ch := make(chan error, n) 423 for i := 0; i < n; i++ { 424 go func() { 425 var age int 426 err := stmt.QueryRow("Alice").Scan(&age) 427 if err == nil && age != 1 { 428 err = fmt.Errorf("unexpected age %d", age) 429 } 430 ch <- err 431 }() 432 } 433 for i := 0; i < n; i++ { 434 if err := <-ch; err != nil { 435 t.Error(err) 436 } 437 } 438 } 439 440 // just a test of fakedb itself 441 func TestBogusPreboundParameters(t *testing.T) { 442 db := newTestDB(t, "foo") 443 defer closeDB(t, db) 444 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 445 _, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion") 446 if err == nil { 447 t.Fatalf("expected error") 448 } 449 if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` { 450 t.Errorf("unexpected error: %v", err) 451 } 452 } 453 454 func TestExec(t *testing.T) { 455 db := newTestDB(t, "foo") 456 defer closeDB(t, db) 457 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 458 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 459 if err != nil { 460 t.Errorf("Stmt, err = %v, %v", stmt, err) 461 } 462 defer stmt.Close() 463 464 type execTest struct { 465 args []interface{} 466 wantErr string 467 } 468 execTests := []execTest{ 469 // Okay: 470 {[]interface{}{"Brad", 31}, ""}, 471 {[]interface{}{"Brad", int64(31)}, ""}, 472 {[]interface{}{"Bob", "32"}, ""}, 473 {[]interface{}{7, 9}, ""}, 474 475 // Invalid conversions: 476 {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"}, 477 {[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"}, 478 479 // Wrong number of args: 480 {[]interface{}{}, "sql: expected 2 arguments, got 0"}, 481 {[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"}, 482 } 483 for n, et := range execTests { 484 _, err := stmt.Exec(et.args...) 485 errStr := "" 486 if err != nil { 487 errStr = err.Error() 488 } 489 if errStr != et.wantErr { 490 t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q", 491 n, et.args, errStr, et.wantErr) 492 } 493 } 494 } 495 496 func TestTxPrepare(t *testing.T) { 497 db := newTestDB(t, "") 498 defer closeDB(t, db) 499 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 500 tx, err := db.Begin() 501 if err != nil { 502 t.Fatalf("Begin = %v", err) 503 } 504 stmt, err := tx.Prepare("INSERT|t1|name=?,age=?") 505 if err != nil { 506 t.Fatalf("Stmt, err = %v, %v", stmt, err) 507 } 508 defer stmt.Close() 509 _, err = stmt.Exec("Bobby", 7) 510 if err != nil { 511 t.Fatalf("Exec = %v", err) 512 } 513 err = tx.Commit() 514 if err != nil { 515 t.Fatalf("Commit = %v", err) 516 } 517 // Commit() should have closed the statement 518 if !stmt.closed { 519 t.Fatal("Stmt not closed after Commit") 520 } 521 } 522 523 func TestTxStmt(t *testing.T) { 524 db := newTestDB(t, "") 525 defer closeDB(t, db) 526 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 527 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 528 if err != nil { 529 t.Fatalf("Stmt, err = %v, %v", stmt, err) 530 } 531 defer stmt.Close() 532 tx, err := db.Begin() 533 if err != nil { 534 t.Fatalf("Begin = %v", err) 535 } 536 txs := tx.Stmt(stmt) 537 defer txs.Close() 538 _, err = txs.Exec("Bobby", 7) 539 if err != nil { 540 t.Fatalf("Exec = %v", err) 541 } 542 err = tx.Commit() 543 if err != nil { 544 t.Fatalf("Commit = %v", err) 545 } 546 // Commit() should have closed the statement 547 if !txs.closed { 548 t.Fatal("Stmt not closed after Commit") 549 } 550 } 551 552 // Issue: https://golang.org/issue/2784 553 // This test didn't fail before because we got lucky with the fakedb driver. 554 // It was failing, and now not, in github.com/bradfitz/go-sql-test 555 func TestTxQuery(t *testing.T) { 556 db := newTestDB(t, "") 557 defer closeDB(t, db) 558 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 559 exec(t, db, "INSERT|t1|name=Alice") 560 561 tx, err := db.Begin() 562 if err != nil { 563 t.Fatal(err) 564 } 565 defer tx.Rollback() 566 567 r, err := tx.Query("SELECT|t1|name|") 568 if err != nil { 569 t.Fatal(err) 570 } 571 defer r.Close() 572 573 if !r.Next() { 574 if r.Err() != nil { 575 t.Fatal(r.Err()) 576 } 577 t.Fatal("expected one row") 578 } 579 580 var x string 581 err = r.Scan(&x) 582 if err != nil { 583 t.Fatal(err) 584 } 585 } 586 587 func TestTxQueryInvalid(t *testing.T) { 588 db := newTestDB(t, "") 589 defer closeDB(t, db) 590 591 tx, err := db.Begin() 592 if err != nil { 593 t.Fatal(err) 594 } 595 defer tx.Rollback() 596 597 _, err = tx.Query("SELECT|t1|name|") 598 if err == nil { 599 t.Fatal("Error expected") 600 } 601 } 602 603 // Tests fix for issue 4433, that retries in Begin happen when 604 // conn.Begin() returns ErrBadConn 605 func TestTxErrBadConn(t *testing.T) { 606 db, err := Open("test", fakeDBName+";badConn") 607 if err != nil { 608 t.Fatalf("Open: %v", err) 609 } 610 if _, err := db.Exec("WIPE"); err != nil { 611 t.Fatalf("exec wipe: %v", err) 612 } 613 defer closeDB(t, db) 614 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 615 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 616 if err != nil { 617 t.Fatalf("Stmt, err = %v, %v", stmt, err) 618 } 619 defer stmt.Close() 620 tx, err := db.Begin() 621 if err != nil { 622 t.Fatalf("Begin = %v", err) 623 } 624 txs := tx.Stmt(stmt) 625 defer txs.Close() 626 _, err = txs.Exec("Bobby", 7) 627 if err != nil { 628 t.Fatalf("Exec = %v", err) 629 } 630 err = tx.Commit() 631 if err != nil { 632 t.Fatalf("Commit = %v", err) 633 } 634 } 635 636 // Tests fix for issue 2542, that we release a lock when querying on 637 // a closed connection. 638 func TestIssue2542Deadlock(t *testing.T) { 639 db := newTestDB(t, "people") 640 closeDB(t, db) 641 for i := 0; i < 2; i++ { 642 _, err := db.Query("SELECT|people|age,name|") 643 if err == nil { 644 t.Fatalf("expected error") 645 } 646 } 647 } 648 649 // From golang.org/issue/3865 650 func TestCloseStmtBeforeRows(t *testing.T) { 651 db := newTestDB(t, "people") 652 defer closeDB(t, db) 653 654 s, err := db.Prepare("SELECT|people|name|") 655 if err != nil { 656 t.Fatal(err) 657 } 658 659 r, err := s.Query() 660 if err != nil { 661 s.Close() 662 t.Fatal(err) 663 } 664 665 err = s.Close() 666 if err != nil { 667 t.Fatal(err) 668 } 669 670 r.Close() 671 } 672 673 // Tests fix for issue 2788, that we bind nil to a []byte if the 674 // value in the column is sql null 675 func TestNullByteSlice(t *testing.T) { 676 db := newTestDB(t, "") 677 defer closeDB(t, db) 678 exec(t, db, "CREATE|t|id=int32,name=nullstring") 679 exec(t, db, "INSERT|t|id=10,name=?", nil) 680 681 var name []byte 682 683 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 684 if err != nil { 685 t.Fatal(err) 686 } 687 if name != nil { 688 t.Fatalf("name []byte should be nil for null column value, got: %#v", name) 689 } 690 691 exec(t, db, "INSERT|t|id=11,name=?", "bob") 692 err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name) 693 if err != nil { 694 t.Fatal(err) 695 } 696 if string(name) != "bob" { 697 t.Fatalf("name []byte should be bob, got: %q", string(name)) 698 } 699 } 700 701 func TestPointerParamsAndScans(t *testing.T) { 702 db := newTestDB(t, "") 703 defer closeDB(t, db) 704 exec(t, db, "CREATE|t|id=int32,name=nullstring") 705 706 bob := "bob" 707 var name *string 708 709 name = &bob 710 exec(t, db, "INSERT|t|id=10,name=?", name) 711 name = nil 712 exec(t, db, "INSERT|t|id=20,name=?", name) 713 714 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 715 if err != nil { 716 t.Fatalf("querying id 10: %v", err) 717 } 718 if name == nil { 719 t.Errorf("id 10's name = nil; want bob") 720 } else if *name != "bob" { 721 t.Errorf("id 10's name = %q; want bob", *name) 722 } 723 724 err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name) 725 if err != nil { 726 t.Fatalf("querying id 20: %v", err) 727 } 728 if name != nil { 729 t.Errorf("id 20 = %q; want nil", *name) 730 } 731 } 732 733 func TestQueryRowClosingStmt(t *testing.T) { 734 db := newTestDB(t, "people") 735 defer closeDB(t, db) 736 var name string 737 var age int 738 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name) 739 if err != nil { 740 t.Fatal(err) 741 } 742 if len(db.freeConn) != 1 { 743 t.Fatalf("expected 1 free conn") 744 } 745 fakeConn := db.freeConn[0].ci.(*fakeConn) 746 if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed { 747 t.Errorf("statement close mismatch: made %d, closed %d", made, closed) 748 } 749 } 750 751 // Test issue 6651 752 func TestIssue6651(t *testing.T) { 753 db := newTestDB(t, "people") 754 defer closeDB(t, db) 755 756 var v string 757 758 want := "error in rows.Next" 759 rowsCursorNextHook = func(dest []driver.Value) error { 760 return fmt.Errorf(want) 761 } 762 defer func() { rowsCursorNextHook = nil }() 763 err := db.QueryRow("SELECT|people|name|").Scan(&v) 764 if err == nil || err.Error() != want { 765 t.Errorf("error = %q; want %q", err, want) 766 } 767 rowsCursorNextHook = nil 768 769 want = "error in rows.Close" 770 rowsCloseHook = func(rows *Rows, err *error) { 771 *err = fmt.Errorf(want) 772 } 773 defer func() { rowsCloseHook = nil }() 774 err = db.QueryRow("SELECT|people|name|").Scan(&v) 775 if err == nil || err.Error() != want { 776 t.Errorf("error = %q; want %q", err, want) 777 } 778 } 779 780 type nullTestRow struct { 781 nullParam interface{} 782 notNullParam interface{} 783 scanNullVal interface{} 784 } 785 786 type nullTestSpec struct { 787 nullType string 788 notNullType string 789 rows [6]nullTestRow 790 } 791 792 func TestNullStringParam(t *testing.T) { 793 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{ 794 {NullString{"aqua", true}, "", NullString{"aqua", true}}, 795 {NullString{"brown", false}, "", NullString{"", false}}, 796 {"chartreuse", "", NullString{"chartreuse", true}}, 797 {NullString{"darkred", true}, "", NullString{"darkred", true}}, 798 {NullString{"eel", false}, "", NullString{"", false}}, 799 {"foo", NullString{"black", false}, nil}, 800 }} 801 nullTestRun(t, spec) 802 } 803 804 func TestNullInt64Param(t *testing.T) { 805 spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{ 806 {NullInt64{31, true}, 1, NullInt64{31, true}}, 807 {NullInt64{-22, false}, 1, NullInt64{0, false}}, 808 {22, 1, NullInt64{22, true}}, 809 {NullInt64{33, true}, 1, NullInt64{33, true}}, 810 {NullInt64{222, false}, 1, NullInt64{0, false}}, 811 {0, NullInt64{31, false}, nil}, 812 }} 813 nullTestRun(t, spec) 814 } 815 816 func TestNullFloat64Param(t *testing.T) { 817 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{ 818 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}}, 819 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}}, 820 {-22.9, 1, NullFloat64{-22.9, true}}, 821 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}}, 822 {NullFloat64{222, false}, 1, NullFloat64{0, false}}, 823 {10, NullFloat64{31.2, false}, nil}, 824 }} 825 nullTestRun(t, spec) 826 } 827 828 func TestNullBoolParam(t *testing.T) { 829 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{ 830 {NullBool{false, true}, true, NullBool{false, true}}, 831 {NullBool{true, false}, false, NullBool{false, false}}, 832 {true, true, NullBool{true, true}}, 833 {NullBool{true, true}, false, NullBool{true, true}}, 834 {NullBool{true, false}, true, NullBool{false, false}}, 835 {true, NullBool{true, false}, nil}, 836 }} 837 nullTestRun(t, spec) 838 } 839 840 func nullTestRun(t *testing.T, spec nullTestSpec) { 841 db := newTestDB(t, "") 842 defer closeDB(t, db) 843 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType)) 844 845 // Inserts with db.Exec: 846 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam) 847 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam) 848 849 // Inserts with a prepared statement: 850 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?") 851 if err != nil { 852 t.Fatalf("prepare: %v", err) 853 } 854 defer stmt.Close() 855 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil { 856 t.Errorf("exec insert chris: %v", err) 857 } 858 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil { 859 t.Errorf("exec insert dave: %v", err) 860 } 861 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil { 862 t.Errorf("exec insert eleanor: %v", err) 863 } 864 865 // Can't put null val into non-null col 866 if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil { 867 t.Errorf("expected error inserting nil val with prepared statement Exec") 868 } 869 870 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil) 871 if err == nil { 872 // TODO: this test fails, but it's just because 873 // fakeConn implements the optional Execer interface, 874 // so arguably this is the correct behavior. But 875 // maybe I should flesh out the fakeConn.Exec 876 // implementation so this properly fails. 877 // t.Errorf("expected error inserting nil name with Exec") 878 } 879 880 paramtype := reflect.TypeOf(spec.rows[0].nullParam) 881 bindVal := reflect.New(paramtype).Interface() 882 883 for i := 0; i < 5; i++ { 884 id := i + 1 885 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil { 886 t.Errorf("id=%d Scan: %v", id, err) 887 } 888 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface() 889 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) { 890 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal) 891 } 892 } 893 } 894 895 // golang.org/issue/4859 896 func TestQueryRowNilScanDest(t *testing.T) { 897 db := newTestDB(t, "people") 898 defer closeDB(t, db) 899 var name *string // nil pointer 900 err := db.QueryRow("SELECT|people|name|").Scan(name) 901 want := "sql: Scan error on column index 0: destination pointer is nil" 902 if err == nil || err.Error() != want { 903 t.Errorf("error = %q; want %q", err.Error(), want) 904 } 905 } 906 907 func TestIssue4902(t *testing.T) { 908 db := newTestDB(t, "people") 909 defer closeDB(t, db) 910 911 driver := db.driver.(*fakeDriver) 912 opens0 := driver.openCount 913 914 var stmt *Stmt 915 var err error 916 for i := 0; i < 10; i++ { 917 stmt, err = db.Prepare("SELECT|people|name|") 918 if err != nil { 919 t.Fatal(err) 920 } 921 err = stmt.Close() 922 if err != nil { 923 t.Fatal(err) 924 } 925 } 926 927 opens := driver.openCount - opens0 928 if opens > 1 { 929 t.Errorf("opens = %d; want <= 1", opens) 930 t.Logf("db = %#v", db) 931 t.Logf("driver = %#v", driver) 932 t.Logf("stmt = %#v", stmt) 933 } 934 } 935 936 // Issue 3857 937 // This used to deadlock. 938 func TestSimultaneousQueries(t *testing.T) { 939 db := newTestDB(t, "people") 940 defer closeDB(t, db) 941 942 tx, err := db.Begin() 943 if err != nil { 944 t.Fatal(err) 945 } 946 defer tx.Rollback() 947 948 r1, err := tx.Query("SELECT|people|name|") 949 if err != nil { 950 t.Fatal(err) 951 } 952 defer r1.Close() 953 954 r2, err := tx.Query("SELECT|people|name|") 955 if err != nil { 956 t.Fatal(err) 957 } 958 defer r2.Close() 959 } 960 961 func TestMaxIdleConns(t *testing.T) { 962 db := newTestDB(t, "people") 963 defer closeDB(t, db) 964 965 tx, err := db.Begin() 966 if err != nil { 967 t.Fatal(err) 968 } 969 tx.Commit() 970 if got := len(db.freeConn); got != 1 { 971 t.Errorf("freeConns = %d; want 1", got) 972 } 973 974 db.SetMaxIdleConns(0) 975 976 if got := len(db.freeConn); got != 0 { 977 t.Errorf("freeConns after set to zero = %d; want 0", got) 978 } 979 980 tx, err = db.Begin() 981 if err != nil { 982 t.Fatal(err) 983 } 984 tx.Commit() 985 if got := len(db.freeConn); got != 0 { 986 t.Errorf("freeConns = %d; want 0", got) 987 } 988 } 989 990 func TestMaxOpenConns(t *testing.T) { 991 if testing.Short() { 992 t.Skip("skipping in short mode") 993 } 994 defer setHookpostCloseConn(nil) 995 setHookpostCloseConn(func(_ *fakeConn, err error) { 996 if err != nil { 997 t.Errorf("Error closing fakeConn: %v", err) 998 } 999 }) 1000 1001 db := newTestDB(t, "magicquery") 1002 defer closeDB(t, db) 1003 1004 driver := db.driver.(*fakeDriver) 1005 1006 // Force the number of open connections to 0 so we can get an accurate 1007 // count for the test 1008 db.clearAllConns(t) 1009 1010 driver.mu.Lock() 1011 opens0 := driver.openCount 1012 closes0 := driver.closeCount 1013 driver.mu.Unlock() 1014 1015 db.SetMaxIdleConns(10) 1016 db.SetMaxOpenConns(10) 1017 1018 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 1019 if err != nil { 1020 t.Fatal(err) 1021 } 1022 1023 // Start 50 parallel slow queries. 1024 const ( 1025 nquery = 50 1026 sleepMillis = 25 1027 nbatch = 2 1028 ) 1029 var wg sync.WaitGroup 1030 for batch := 0; batch < nbatch; batch++ { 1031 for i := 0; i < nquery; i++ { 1032 wg.Add(1) 1033 go func() { 1034 defer wg.Done() 1035 var op string 1036 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 1037 t.Error(err) 1038 } 1039 }() 1040 } 1041 // Sleep for twice the expected length of time for the 1042 // batch of 50 queries above to finish before starting 1043 // the next round. 1044 time.Sleep(2 * sleepMillis * time.Millisecond) 1045 } 1046 wg.Wait() 1047 1048 if g, w := db.numFreeConns(), 10; g != w { 1049 t.Errorf("free conns = %d; want %d", g, w) 1050 } 1051 1052 if n := db.numDepsPollUntil(20, time.Second); n > 20 { 1053 t.Errorf("number of dependencies = %d; expected <= 20", n) 1054 db.dumpDeps(t) 1055 } 1056 1057 driver.mu.Lock() 1058 opens := driver.openCount - opens0 1059 closes := driver.closeCount - closes0 1060 driver.mu.Unlock() 1061 1062 if opens > 10 { 1063 t.Logf("open calls = %d", opens) 1064 t.Logf("close calls = %d", closes) 1065 t.Errorf("db connections opened = %d; want <= 10", opens) 1066 db.dumpDeps(t) 1067 } 1068 1069 if err := stmt.Close(); err != nil { 1070 t.Fatal(err) 1071 } 1072 1073 if g, w := db.numFreeConns(), 10; g != w { 1074 t.Errorf("free conns = %d; want %d", g, w) 1075 } 1076 1077 if n := db.numDepsPollUntil(10, time.Second); n > 10 { 1078 t.Errorf("number of dependencies = %d; expected <= 10", n) 1079 db.dumpDeps(t) 1080 } 1081 1082 db.SetMaxOpenConns(5) 1083 1084 if g, w := db.numFreeConns(), 5; g != w { 1085 t.Errorf("free conns = %d; want %d", g, w) 1086 } 1087 1088 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 1089 t.Errorf("number of dependencies = %d; expected 0", n) 1090 db.dumpDeps(t) 1091 } 1092 1093 db.SetMaxOpenConns(0) 1094 1095 if g, w := db.numFreeConns(), 5; g != w { 1096 t.Errorf("free conns = %d; want %d", g, w) 1097 } 1098 1099 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 1100 t.Errorf("number of dependencies = %d; expected 0", n) 1101 db.dumpDeps(t) 1102 } 1103 1104 db.clearAllConns(t) 1105 } 1106 1107 // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime 1108 // and affects the subsequent release of connections. 1109 func TestMaxOpenConnsOnBusy(t *testing.T) { 1110 defer setHookpostCloseConn(nil) 1111 setHookpostCloseConn(func(_ *fakeConn, err error) { 1112 if err != nil { 1113 t.Errorf("Error closing fakeConn: %v", err) 1114 } 1115 }) 1116 1117 db := newTestDB(t, "magicquery") 1118 defer closeDB(t, db) 1119 1120 db.SetMaxOpenConns(3) 1121 1122 conn0, err := db.conn(cachedOrNewConn) 1123 if err != nil { 1124 t.Fatalf("db open conn fail: %v", err) 1125 } 1126 1127 conn1, err := db.conn(cachedOrNewConn) 1128 if err != nil { 1129 t.Fatalf("db open conn fail: %v", err) 1130 } 1131 1132 conn2, err := db.conn(cachedOrNewConn) 1133 if err != nil { 1134 t.Fatalf("db open conn fail: %v", err) 1135 } 1136 1137 if g, w := db.numOpen, 3; g != w { 1138 t.Errorf("free conns = %d; want %d", g, w) 1139 } 1140 1141 db.SetMaxOpenConns(2) 1142 if g, w := db.numOpen, 3; g != w { 1143 t.Errorf("free conns = %d; want %d", g, w) 1144 } 1145 1146 conn0.releaseConn(nil) 1147 conn1.releaseConn(nil) 1148 if g, w := db.numOpen, 2; g != w { 1149 t.Errorf("free conns = %d; want %d", g, w) 1150 } 1151 1152 conn2.releaseConn(nil) 1153 if g, w := db.numOpen, 2; g != w { 1154 t.Errorf("free conns = %d; want %d", g, w) 1155 } 1156 } 1157 1158 // Issue 10886: tests that all connection attempts return when more than 1159 // DB.maxOpen connections are in flight and the first DB.maxOpen fail. 1160 func TestPendingConnsAfterErr(t *testing.T) { 1161 const ( 1162 maxOpen = 2 1163 tryOpen = maxOpen*2 + 2 1164 ) 1165 1166 db := newTestDB(t, "people") 1167 defer closeDB(t, db) 1168 defer func() { 1169 for k, v := range db.lastPut { 1170 t.Logf("%p: %v", k, v) 1171 } 1172 }() 1173 1174 db.SetMaxOpenConns(maxOpen) 1175 db.SetMaxIdleConns(0) 1176 1177 errOffline := errors.New("db offline") 1178 defer func() { setHookOpenErr(nil) }() 1179 1180 errs := make(chan error, tryOpen) 1181 1182 unblock := make(chan struct{}) 1183 setHookOpenErr(func() error { 1184 <-unblock // block until all connections are in flight 1185 return errOffline 1186 }) 1187 1188 var opening sync.WaitGroup 1189 opening.Add(tryOpen) 1190 for i := 0; i < tryOpen; i++ { 1191 go func() { 1192 opening.Done() // signal one connection is in flight 1193 _, err := db.Exec("INSERT|people|name=Julia,age=19") 1194 errs <- err 1195 }() 1196 } 1197 1198 opening.Wait() // wait for all workers to begin running 1199 time.Sleep(10 * time.Millisecond) // make extra sure all workers are blocked 1200 close(unblock) // let all workers proceed 1201 1202 const timeout = 100 * time.Millisecond 1203 to := time.NewTimer(timeout) 1204 defer to.Stop() 1205 1206 // check that all connections fail without deadlock 1207 for i := 0; i < tryOpen; i++ { 1208 select { 1209 case err := <-errs: 1210 if got, want := err, errOffline; got != want { 1211 t.Errorf("unexpected err: got %v, want %v", got, want) 1212 } 1213 case <-to.C: 1214 t.Fatalf("orphaned connection request(s), still waiting after %v", timeout) 1215 } 1216 } 1217 } 1218 1219 func TestSingleOpenConn(t *testing.T) { 1220 db := newTestDB(t, "people") 1221 defer closeDB(t, db) 1222 1223 db.SetMaxOpenConns(1) 1224 1225 rows, err := db.Query("SELECT|people|name|") 1226 if err != nil { 1227 t.Fatal(err) 1228 } 1229 if err = rows.Close(); err != nil { 1230 t.Fatal(err) 1231 } 1232 // shouldn't deadlock 1233 rows, err = db.Query("SELECT|people|name|") 1234 if err != nil { 1235 t.Fatal(err) 1236 } 1237 if err = rows.Close(); err != nil { 1238 t.Fatal(err) 1239 } 1240 } 1241 1242 func TestStats(t *testing.T) { 1243 db := newTestDB(t, "people") 1244 stats := db.Stats() 1245 if got := stats.OpenConnections; got != 1 { 1246 t.Errorf("stats.OpenConnections = %d; want 1", got) 1247 } 1248 1249 tx, err := db.Begin() 1250 if err != nil { 1251 t.Fatal(err) 1252 } 1253 tx.Commit() 1254 1255 closeDB(t, db) 1256 stats = db.Stats() 1257 if got := stats.OpenConnections; got != 0 { 1258 t.Errorf("stats.OpenConnections = %d; want 0", got) 1259 } 1260 } 1261 1262 func TestConnMaxLifetime(t *testing.T) { 1263 t0 := time.Unix(1000000, 0) 1264 offset := time.Duration(0) 1265 1266 nowFunc = func() time.Time { return t0.Add(offset) } 1267 defer func() { nowFunc = time.Now }() 1268 1269 db := newTestDB(t, "magicquery") 1270 defer closeDB(t, db) 1271 1272 driver := db.driver.(*fakeDriver) 1273 1274 // Force the number of open connections to 0 so we can get an accurate 1275 // count for the test 1276 db.clearAllConns(t) 1277 1278 driver.mu.Lock() 1279 opens0 := driver.openCount 1280 closes0 := driver.closeCount 1281 driver.mu.Unlock() 1282 1283 db.SetMaxIdleConns(10) 1284 db.SetMaxOpenConns(10) 1285 1286 tx, err := db.Begin() 1287 if err != nil { 1288 t.Fatal(err) 1289 } 1290 1291 offset = time.Second 1292 tx2, err := db.Begin() 1293 if err != nil { 1294 t.Fatal(err) 1295 } 1296 1297 tx.Commit() 1298 tx2.Commit() 1299 1300 driver.mu.Lock() 1301 opens := driver.openCount - opens0 1302 closes := driver.closeCount - closes0 1303 driver.mu.Unlock() 1304 1305 if opens != 2 { 1306 t.Errorf("opens = %d; want 2", opens) 1307 } 1308 if closes != 0 { 1309 t.Errorf("closes = %d; want 0", closes) 1310 } 1311 if g, w := db.numFreeConns(), 2; g != w { 1312 t.Errorf("free conns = %d; want %d", g, w) 1313 } 1314 1315 // Expire first conn 1316 offset = time.Second * 11 1317 db.SetConnMaxLifetime(time.Second * 10) 1318 if err != nil { 1319 t.Fatal(err) 1320 } 1321 1322 tx, err = db.Begin() 1323 if err != nil { 1324 t.Fatal(err) 1325 } 1326 tx2, err = db.Begin() 1327 if err != nil { 1328 t.Fatal(err) 1329 } 1330 tx.Commit() 1331 tx2.Commit() 1332 1333 driver.mu.Lock() 1334 opens = driver.openCount - opens0 1335 closes = driver.closeCount - closes0 1336 driver.mu.Unlock() 1337 1338 if opens != 3 { 1339 t.Errorf("opens = %d; want 3", opens) 1340 } 1341 if closes != 1 { 1342 t.Errorf("closes = %d; want 1", closes) 1343 } 1344 } 1345 1346 // golang.org/issue/5323 1347 func TestStmtCloseDeps(t *testing.T) { 1348 if testing.Short() { 1349 t.Skip("skipping in short mode") 1350 } 1351 defer setHookpostCloseConn(nil) 1352 setHookpostCloseConn(func(_ *fakeConn, err error) { 1353 if err != nil { 1354 t.Errorf("Error closing fakeConn: %v", err) 1355 } 1356 }) 1357 1358 db := newTestDB(t, "magicquery") 1359 defer closeDB(t, db) 1360 1361 driver := db.driver.(*fakeDriver) 1362 1363 driver.mu.Lock() 1364 opens0 := driver.openCount 1365 closes0 := driver.closeCount 1366 driver.mu.Unlock() 1367 openDelta0 := opens0 - closes0 1368 1369 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 1370 if err != nil { 1371 t.Fatal(err) 1372 } 1373 1374 // Start 50 parallel slow queries. 1375 const ( 1376 nquery = 50 1377 sleepMillis = 25 1378 nbatch = 2 1379 ) 1380 var wg sync.WaitGroup 1381 for batch := 0; batch < nbatch; batch++ { 1382 for i := 0; i < nquery; i++ { 1383 wg.Add(1) 1384 go func() { 1385 defer wg.Done() 1386 var op string 1387 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 1388 t.Error(err) 1389 } 1390 }() 1391 } 1392 // Sleep for twice the expected length of time for the 1393 // batch of 50 queries above to finish before starting 1394 // the next round. 1395 time.Sleep(2 * sleepMillis * time.Millisecond) 1396 } 1397 wg.Wait() 1398 1399 if g, w := db.numFreeConns(), 2; g != w { 1400 t.Errorf("free conns = %d; want %d", g, w) 1401 } 1402 1403 if n := db.numDepsPollUntil(4, time.Second); n > 4 { 1404 t.Errorf("number of dependencies = %d; expected <= 4", n) 1405 db.dumpDeps(t) 1406 } 1407 1408 driver.mu.Lock() 1409 opens := driver.openCount - opens0 1410 closes := driver.closeCount - closes0 1411 openDelta := (driver.openCount - driver.closeCount) - openDelta0 1412 driver.mu.Unlock() 1413 1414 if openDelta > 2 { 1415 t.Logf("open calls = %d", opens) 1416 t.Logf("close calls = %d", closes) 1417 t.Logf("open delta = %d", openDelta) 1418 t.Errorf("db connections opened = %d; want <= 2", openDelta) 1419 db.dumpDeps(t) 1420 } 1421 1422 if len(stmt.css) > nquery { 1423 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery) 1424 } 1425 1426 if err := stmt.Close(); err != nil { 1427 t.Fatal(err) 1428 } 1429 1430 if g, w := db.numFreeConns(), 2; g != w { 1431 t.Errorf("free conns = %d; want %d", g, w) 1432 } 1433 1434 if n := db.numDepsPollUntil(2, time.Second); n > 2 { 1435 t.Errorf("number of dependencies = %d; expected <= 2", n) 1436 db.dumpDeps(t) 1437 } 1438 1439 db.clearAllConns(t) 1440 } 1441 1442 // golang.org/issue/5046 1443 func TestCloseConnBeforeStmts(t *testing.T) { 1444 db := newTestDB(t, "people") 1445 defer closeDB(t, db) 1446 1447 defer setHookpostCloseConn(nil) 1448 setHookpostCloseConn(func(_ *fakeConn, err error) { 1449 if err != nil { 1450 t.Errorf("Error closing fakeConn: %v; from %s", err, stack()) 1451 db.dumpDeps(t) 1452 t.Errorf("DB = %#v", db) 1453 } 1454 }) 1455 1456 stmt, err := db.Prepare("SELECT|people|name|") 1457 if err != nil { 1458 t.Fatal(err) 1459 } 1460 1461 if len(db.freeConn) != 1 { 1462 t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn)) 1463 } 1464 dc := db.freeConn[0] 1465 if dc.closed { 1466 t.Errorf("conn shouldn't be closed") 1467 } 1468 1469 if n := len(dc.openStmt); n != 1 { 1470 t.Errorf("driverConn num openStmt = %d; want 1", n) 1471 } 1472 err = db.Close() 1473 if err != nil { 1474 t.Errorf("db Close = %v", err) 1475 } 1476 if !dc.closed { 1477 t.Errorf("after db.Close, driverConn should be closed") 1478 } 1479 if n := len(dc.openStmt); n != 0 { 1480 t.Errorf("driverConn num openStmt = %d; want 0", n) 1481 } 1482 1483 err = stmt.Close() 1484 if err != nil { 1485 t.Errorf("Stmt close = %v", err) 1486 } 1487 1488 if !dc.closed { 1489 t.Errorf("conn should be closed") 1490 } 1491 if dc.ci != nil { 1492 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil") 1493 } 1494 } 1495 1496 // golang.org/issue/5283: don't release the Rows' connection in Close 1497 // before calling Stmt.Close. 1498 func TestRowsCloseOrder(t *testing.T) { 1499 db := newTestDB(t, "people") 1500 defer closeDB(t, db) 1501 1502 db.SetMaxIdleConns(0) 1503 setStrictFakeConnClose(t) 1504 defer setStrictFakeConnClose(nil) 1505 1506 rows, err := db.Query("SELECT|people|age,name|") 1507 if err != nil { 1508 t.Fatal(err) 1509 } 1510 err = rows.Close() 1511 if err != nil { 1512 t.Fatal(err) 1513 } 1514 } 1515 1516 func TestRowsImplicitClose(t *testing.T) { 1517 db := newTestDB(t, "people") 1518 defer closeDB(t, db) 1519 1520 rows, err := db.Query("SELECT|people|age,name|") 1521 if err != nil { 1522 t.Fatal(err) 1523 } 1524 1525 want, fail := 2, errors.New("fail") 1526 r := rows.rowsi.(*rowsCursor) 1527 r.errPos, r.err = want, fail 1528 1529 got := 0 1530 for rows.Next() { 1531 got++ 1532 } 1533 if got != want { 1534 t.Errorf("got %d rows, want %d", got, want) 1535 } 1536 if err := rows.Err(); err != fail { 1537 t.Errorf("got error %v, want %v", err, fail) 1538 } 1539 if !r.closed { 1540 t.Errorf("r.closed is false, want true") 1541 } 1542 } 1543 1544 func TestStmtCloseOrder(t *testing.T) { 1545 db := newTestDB(t, "people") 1546 defer closeDB(t, db) 1547 1548 db.SetMaxIdleConns(0) 1549 setStrictFakeConnClose(t) 1550 defer setStrictFakeConnClose(nil) 1551 1552 _, err := db.Query("SELECT|non_existent|name|") 1553 if err == nil { 1554 t.Fatal("Quering non-existent table should fail") 1555 } 1556 } 1557 1558 // Test cases where there's more than maxBadConnRetries bad connections in the 1559 // pool (issue 8834) 1560 func TestManyErrBadConn(t *testing.T) { 1561 manyErrBadConnSetup := func() *DB { 1562 db := newTestDB(t, "people") 1563 1564 nconn := maxBadConnRetries + 1 1565 db.SetMaxIdleConns(nconn) 1566 db.SetMaxOpenConns(nconn) 1567 // open enough connections 1568 func() { 1569 for i := 0; i < nconn; i++ { 1570 rows, err := db.Query("SELECT|people|age,name|") 1571 if err != nil { 1572 t.Fatal(err) 1573 } 1574 defer rows.Close() 1575 } 1576 }() 1577 1578 if db.numOpen != nconn { 1579 t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn) 1580 } else if len(db.freeConn) != nconn { 1581 t.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db.freeConn), nconn) 1582 } 1583 for _, conn := range db.freeConn { 1584 conn.ci.(*fakeConn).stickyBad = true 1585 } 1586 return db 1587 } 1588 1589 // Query 1590 db := manyErrBadConnSetup() 1591 defer closeDB(t, db) 1592 rows, err := db.Query("SELECT|people|age,name|") 1593 if err != nil { 1594 t.Fatal(err) 1595 } 1596 if err = rows.Close(); err != nil { 1597 t.Fatal(err) 1598 } 1599 1600 // Exec 1601 db = manyErrBadConnSetup() 1602 defer closeDB(t, db) 1603 _, err = db.Exec("INSERT|people|name=Julia,age=19") 1604 if err != nil { 1605 t.Fatal(err) 1606 } 1607 1608 // Begin 1609 db = manyErrBadConnSetup() 1610 defer closeDB(t, db) 1611 tx, err := db.Begin() 1612 if err != nil { 1613 t.Fatal(err) 1614 } 1615 if err = tx.Rollback(); err != nil { 1616 t.Fatal(err) 1617 } 1618 1619 // Prepare 1620 db = manyErrBadConnSetup() 1621 defer closeDB(t, db) 1622 stmt, err := db.Prepare("SELECT|people|age,name|") 1623 if err != nil { 1624 t.Fatal(err) 1625 } 1626 if err = stmt.Close(); err != nil { 1627 t.Fatal(err) 1628 } 1629 } 1630 1631 // golang.org/issue/5718 1632 func TestErrBadConnReconnect(t *testing.T) { 1633 db := newTestDB(t, "foo") 1634 defer closeDB(t, db) 1635 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1636 1637 simulateBadConn := func(name string, hook *func() bool, op func() error) { 1638 broken, retried := false, false 1639 numOpen := db.numOpen 1640 1641 // simulate a broken connection on the first try 1642 *hook = func() bool { 1643 if !broken { 1644 broken = true 1645 return true 1646 } 1647 retried = true 1648 return false 1649 } 1650 1651 if err := op(); err != nil { 1652 t.Errorf(name+": %v", err) 1653 return 1654 } 1655 1656 if !broken || !retried { 1657 t.Error(name + ": Failed to simulate broken connection") 1658 } 1659 *hook = nil 1660 1661 if numOpen != db.numOpen { 1662 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 1663 numOpen = db.numOpen 1664 } 1665 } 1666 1667 // db.Exec 1668 dbExec := func() error { 1669 _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 1670 return err 1671 } 1672 simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec) 1673 simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec) 1674 1675 // db.Query 1676 dbQuery := func() error { 1677 rows, err := db.Query("SELECT|t1|age,name|") 1678 if err == nil { 1679 err = rows.Close() 1680 } 1681 return err 1682 } 1683 simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery) 1684 simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery) 1685 1686 // db.Prepare 1687 simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error { 1688 stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 1689 if err != nil { 1690 return err 1691 } 1692 stmt.Close() 1693 return nil 1694 }) 1695 1696 // Provide a way to force a re-prepare of a statement on next execution 1697 forcePrepare := func(stmt *Stmt) { 1698 stmt.css = nil 1699 } 1700 1701 // stmt.Exec 1702 stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 1703 if err != nil { 1704 t.Fatalf("prepare: %v", err) 1705 } 1706 defer stmt1.Close() 1707 // make sure we must prepare the stmt first 1708 forcePrepare(stmt1) 1709 1710 stmtExec := func() error { 1711 _, err := stmt1.Exec("Gopher", 3, false) 1712 return err 1713 } 1714 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec) 1715 simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec) 1716 1717 // stmt.Query 1718 stmt2, err := db.Prepare("SELECT|t1|age,name|") 1719 if err != nil { 1720 t.Fatalf("prepare: %v", err) 1721 } 1722 defer stmt2.Close() 1723 // make sure we must prepare the stmt first 1724 forcePrepare(stmt2) 1725 1726 stmtQuery := func() error { 1727 rows, err := stmt2.Query() 1728 if err == nil { 1729 err = rows.Close() 1730 } 1731 return err 1732 } 1733 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery) 1734 simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery) 1735 } 1736 1737 // golang.org/issue/11264 1738 func TestTxEndBadConn(t *testing.T) { 1739 db := newTestDB(t, "foo") 1740 defer closeDB(t, db) 1741 db.SetMaxIdleConns(0) 1742 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1743 db.SetMaxIdleConns(1) 1744 1745 simulateBadConn := func(name string, hook *func() bool, op func() error) { 1746 broken := false 1747 numOpen := db.numOpen 1748 1749 *hook = func() bool { 1750 if !broken { 1751 broken = true 1752 } 1753 return broken 1754 } 1755 1756 if err := op(); err != driver.ErrBadConn { 1757 t.Errorf(name+": %v", err) 1758 return 1759 } 1760 1761 if !broken { 1762 t.Error(name + ": Failed to simulate broken connection") 1763 } 1764 *hook = nil 1765 1766 if numOpen != db.numOpen { 1767 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 1768 } 1769 } 1770 1771 // db.Exec 1772 dbExec := func(endTx func(tx *Tx) error) func() error { 1773 return func() error { 1774 tx, err := db.Begin() 1775 if err != nil { 1776 return err 1777 } 1778 _, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 1779 if err != nil { 1780 return err 1781 } 1782 return endTx(tx) 1783 } 1784 } 1785 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit)) 1786 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback)) 1787 1788 // db.Query 1789 dbQuery := func(endTx func(tx *Tx) error) func() error { 1790 return func() error { 1791 tx, err := db.Begin() 1792 if err != nil { 1793 return err 1794 } 1795 rows, err := tx.Query("SELECT|t1|age,name|") 1796 if err == nil { 1797 err = rows.Close() 1798 } else { 1799 return err 1800 } 1801 return endTx(tx) 1802 } 1803 } 1804 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit)) 1805 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback)) 1806 } 1807 1808 type concurrentTest interface { 1809 init(t testing.TB, db *DB) 1810 finish(t testing.TB) 1811 test(t testing.TB) error 1812 } 1813 1814 type concurrentDBQueryTest struct { 1815 db *DB 1816 } 1817 1818 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) { 1819 c.db = db 1820 } 1821 1822 func (c *concurrentDBQueryTest) finish(t testing.TB) { 1823 c.db = nil 1824 } 1825 1826 func (c *concurrentDBQueryTest) test(t testing.TB) error { 1827 rows, err := c.db.Query("SELECT|people|name|") 1828 if err != nil { 1829 t.Error(err) 1830 return err 1831 } 1832 var name string 1833 for rows.Next() { 1834 rows.Scan(&name) 1835 } 1836 rows.Close() 1837 return nil 1838 } 1839 1840 type concurrentDBExecTest struct { 1841 db *DB 1842 } 1843 1844 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) { 1845 c.db = db 1846 } 1847 1848 func (c *concurrentDBExecTest) finish(t testing.TB) { 1849 c.db = nil 1850 } 1851 1852 func (c *concurrentDBExecTest) test(t testing.TB) error { 1853 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 1854 if err != nil { 1855 t.Error(err) 1856 return err 1857 } 1858 return nil 1859 } 1860 1861 type concurrentStmtQueryTest struct { 1862 db *DB 1863 stmt *Stmt 1864 } 1865 1866 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) { 1867 c.db = db 1868 var err error 1869 c.stmt, err = db.Prepare("SELECT|people|name|") 1870 if err != nil { 1871 t.Fatal(err) 1872 } 1873 } 1874 1875 func (c *concurrentStmtQueryTest) finish(t testing.TB) { 1876 if c.stmt != nil { 1877 c.stmt.Close() 1878 c.stmt = nil 1879 } 1880 c.db = nil 1881 } 1882 1883 func (c *concurrentStmtQueryTest) test(t testing.TB) error { 1884 rows, err := c.stmt.Query() 1885 if err != nil { 1886 t.Errorf("error on query: %v", err) 1887 return err 1888 } 1889 1890 var name string 1891 for rows.Next() { 1892 rows.Scan(&name) 1893 } 1894 rows.Close() 1895 return nil 1896 } 1897 1898 type concurrentStmtExecTest struct { 1899 db *DB 1900 stmt *Stmt 1901 } 1902 1903 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) { 1904 c.db = db 1905 var err error 1906 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 1907 if err != nil { 1908 t.Fatal(err) 1909 } 1910 } 1911 1912 func (c *concurrentStmtExecTest) finish(t testing.TB) { 1913 if c.stmt != nil { 1914 c.stmt.Close() 1915 c.stmt = nil 1916 } 1917 c.db = nil 1918 } 1919 1920 func (c *concurrentStmtExecTest) test(t testing.TB) error { 1921 _, err := c.stmt.Exec(3, chrisBirthday) 1922 if err != nil { 1923 t.Errorf("error on exec: %v", err) 1924 return err 1925 } 1926 return nil 1927 } 1928 1929 type concurrentTxQueryTest struct { 1930 db *DB 1931 tx *Tx 1932 } 1933 1934 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) { 1935 c.db = db 1936 var err error 1937 c.tx, err = c.db.Begin() 1938 if err != nil { 1939 t.Fatal(err) 1940 } 1941 } 1942 1943 func (c *concurrentTxQueryTest) finish(t testing.TB) { 1944 if c.tx != nil { 1945 c.tx.Rollback() 1946 c.tx = nil 1947 } 1948 c.db = nil 1949 } 1950 1951 func (c *concurrentTxQueryTest) test(t testing.TB) error { 1952 rows, err := c.db.Query("SELECT|people|name|") 1953 if err != nil { 1954 t.Error(err) 1955 return err 1956 } 1957 var name string 1958 for rows.Next() { 1959 rows.Scan(&name) 1960 } 1961 rows.Close() 1962 return nil 1963 } 1964 1965 type concurrentTxExecTest struct { 1966 db *DB 1967 tx *Tx 1968 } 1969 1970 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) { 1971 c.db = db 1972 var err error 1973 c.tx, err = c.db.Begin() 1974 if err != nil { 1975 t.Fatal(err) 1976 } 1977 } 1978 1979 func (c *concurrentTxExecTest) finish(t testing.TB) { 1980 if c.tx != nil { 1981 c.tx.Rollback() 1982 c.tx = nil 1983 } 1984 c.db = nil 1985 } 1986 1987 func (c *concurrentTxExecTest) test(t testing.TB) error { 1988 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 1989 if err != nil { 1990 t.Error(err) 1991 return err 1992 } 1993 return nil 1994 } 1995 1996 type concurrentTxStmtQueryTest struct { 1997 db *DB 1998 tx *Tx 1999 stmt *Stmt 2000 } 2001 2002 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) { 2003 c.db = db 2004 var err error 2005 c.tx, err = c.db.Begin() 2006 if err != nil { 2007 t.Fatal(err) 2008 } 2009 c.stmt, err = c.tx.Prepare("SELECT|people|name|") 2010 if err != nil { 2011 t.Fatal(err) 2012 } 2013 } 2014 2015 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) { 2016 if c.stmt != nil { 2017 c.stmt.Close() 2018 c.stmt = nil 2019 } 2020 if c.tx != nil { 2021 c.tx.Rollback() 2022 c.tx = nil 2023 } 2024 c.db = nil 2025 } 2026 2027 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error { 2028 rows, err := c.stmt.Query() 2029 if err != nil { 2030 t.Errorf("error on query: %v", err) 2031 return err 2032 } 2033 2034 var name string 2035 for rows.Next() { 2036 rows.Scan(&name) 2037 } 2038 rows.Close() 2039 return nil 2040 } 2041 2042 type concurrentTxStmtExecTest struct { 2043 db *DB 2044 tx *Tx 2045 stmt *Stmt 2046 } 2047 2048 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) { 2049 c.db = db 2050 var err error 2051 c.tx, err = c.db.Begin() 2052 if err != nil { 2053 t.Fatal(err) 2054 } 2055 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 2056 if err != nil { 2057 t.Fatal(err) 2058 } 2059 } 2060 2061 func (c *concurrentTxStmtExecTest) finish(t testing.TB) { 2062 if c.stmt != nil { 2063 c.stmt.Close() 2064 c.stmt = nil 2065 } 2066 if c.tx != nil { 2067 c.tx.Rollback() 2068 c.tx = nil 2069 } 2070 c.db = nil 2071 } 2072 2073 func (c *concurrentTxStmtExecTest) test(t testing.TB) error { 2074 _, err := c.stmt.Exec(3, chrisBirthday) 2075 if err != nil { 2076 t.Errorf("error on exec: %v", err) 2077 return err 2078 } 2079 return nil 2080 } 2081 2082 type concurrentRandomTest struct { 2083 tests []concurrentTest 2084 } 2085 2086 func (c *concurrentRandomTest) init(t testing.TB, db *DB) { 2087 c.tests = []concurrentTest{ 2088 new(concurrentDBQueryTest), 2089 new(concurrentDBExecTest), 2090 new(concurrentStmtQueryTest), 2091 new(concurrentStmtExecTest), 2092 new(concurrentTxQueryTest), 2093 new(concurrentTxExecTest), 2094 new(concurrentTxStmtQueryTest), 2095 new(concurrentTxStmtExecTest), 2096 } 2097 for _, ct := range c.tests { 2098 ct.init(t, db) 2099 } 2100 } 2101 2102 func (c *concurrentRandomTest) finish(t testing.TB) { 2103 for _, ct := range c.tests { 2104 ct.finish(t) 2105 } 2106 } 2107 2108 func (c *concurrentRandomTest) test(t testing.TB) error { 2109 ct := c.tests[rand.Intn(len(c.tests))] 2110 return ct.test(t) 2111 } 2112 2113 func doConcurrentTest(t testing.TB, ct concurrentTest) { 2114 maxProcs, numReqs := 1, 500 2115 if testing.Short() { 2116 maxProcs, numReqs = 4, 50 2117 } 2118 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 2119 2120 db := newTestDB(t, "people") 2121 defer closeDB(t, db) 2122 2123 ct.init(t, db) 2124 defer ct.finish(t) 2125 2126 var wg sync.WaitGroup 2127 wg.Add(numReqs) 2128 2129 reqs := make(chan bool) 2130 defer close(reqs) 2131 2132 for i := 0; i < maxProcs*2; i++ { 2133 go func() { 2134 for range reqs { 2135 err := ct.test(t) 2136 if err != nil { 2137 wg.Done() 2138 continue 2139 } 2140 wg.Done() 2141 } 2142 }() 2143 } 2144 2145 for i := 0; i < numReqs; i++ { 2146 reqs <- true 2147 } 2148 2149 wg.Wait() 2150 } 2151 2152 func TestIssue6081(t *testing.T) { 2153 db := newTestDB(t, "people") 2154 defer closeDB(t, db) 2155 2156 drv := db.driver.(*fakeDriver) 2157 drv.mu.Lock() 2158 opens0 := drv.openCount 2159 closes0 := drv.closeCount 2160 drv.mu.Unlock() 2161 2162 stmt, err := db.Prepare("SELECT|people|name|") 2163 if err != nil { 2164 t.Fatal(err) 2165 } 2166 rowsCloseHook = func(rows *Rows, err *error) { 2167 *err = driver.ErrBadConn 2168 } 2169 defer func() { rowsCloseHook = nil }() 2170 for i := 0; i < 10; i++ { 2171 rows, err := stmt.Query() 2172 if err != nil { 2173 t.Fatal(err) 2174 } 2175 rows.Close() 2176 } 2177 if n := len(stmt.css); n > 1 { 2178 t.Errorf("len(css slice) = %d; want <= 1", n) 2179 } 2180 stmt.Close() 2181 if n := len(stmt.css); n != 0 { 2182 t.Errorf("len(css slice) after Close = %d; want 0", n) 2183 } 2184 2185 drv.mu.Lock() 2186 opens := drv.openCount - opens0 2187 closes := drv.closeCount - closes0 2188 drv.mu.Unlock() 2189 if opens < 9 { 2190 t.Errorf("opens = %d; want >= 9", opens) 2191 } 2192 if closes < 9 { 2193 t.Errorf("closes = %d; want >= 9", closes) 2194 } 2195 } 2196 2197 func TestConcurrency(t *testing.T) { 2198 doConcurrentTest(t, new(concurrentDBQueryTest)) 2199 doConcurrentTest(t, new(concurrentDBExecTest)) 2200 doConcurrentTest(t, new(concurrentStmtQueryTest)) 2201 doConcurrentTest(t, new(concurrentStmtExecTest)) 2202 doConcurrentTest(t, new(concurrentTxQueryTest)) 2203 doConcurrentTest(t, new(concurrentTxExecTest)) 2204 doConcurrentTest(t, new(concurrentTxStmtQueryTest)) 2205 doConcurrentTest(t, new(concurrentTxStmtExecTest)) 2206 doConcurrentTest(t, new(concurrentRandomTest)) 2207 } 2208 2209 func TestConnectionLeak(t *testing.T) { 2210 db := newTestDB(t, "people") 2211 defer closeDB(t, db) 2212 // Start by opening defaultMaxIdleConns 2213 rows := make([]*Rows, defaultMaxIdleConns) 2214 // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open 2215 // a new connection and we can fill the idle queue with the released 2216 // connections. 2217 db.SetMaxOpenConns(len(rows) + 1) 2218 for ii := range rows { 2219 r, err := db.Query("SELECT|people|name|") 2220 if err != nil { 2221 t.Fatal(err) 2222 } 2223 r.Next() 2224 if err := r.Err(); err != nil { 2225 t.Fatal(err) 2226 } 2227 rows[ii] = r 2228 } 2229 // Now we have defaultMaxIdleConns busy connections. Open 2230 // a new one, but wait until the busy connections are released 2231 // before returning control to DB. 2232 drv := db.driver.(*fakeDriver) 2233 drv.waitCh = make(chan struct{}, 1) 2234 drv.waitingCh = make(chan struct{}, 1) 2235 var wg sync.WaitGroup 2236 wg.Add(1) 2237 go func() { 2238 r, err := db.Query("SELECT|people|name|") 2239 if err != nil { 2240 t.Fatal(err) 2241 } 2242 r.Close() 2243 wg.Done() 2244 }() 2245 // Wait until the goroutine we've just created has started waiting. 2246 <-drv.waitingCh 2247 // Now close the busy connections. This provides a connection for 2248 // the blocked goroutine and then fills up the idle queue. 2249 for _, v := range rows { 2250 v.Close() 2251 } 2252 // At this point we give the new connection to DB. This connection is 2253 // now useless, since the idle queue is full and there are no pending 2254 // requests. DB should deal with this situation without leaking the 2255 // connection. 2256 drv.waitCh <- struct{}{} 2257 wg.Wait() 2258 } 2259 2260 func BenchmarkConcurrentDBExec(b *testing.B) { 2261 b.ReportAllocs() 2262 ct := new(concurrentDBExecTest) 2263 for i := 0; i < b.N; i++ { 2264 doConcurrentTest(b, ct) 2265 } 2266 } 2267 2268 func BenchmarkConcurrentStmtQuery(b *testing.B) { 2269 b.ReportAllocs() 2270 ct := new(concurrentStmtQueryTest) 2271 for i := 0; i < b.N; i++ { 2272 doConcurrentTest(b, ct) 2273 } 2274 } 2275 2276 func BenchmarkConcurrentStmtExec(b *testing.B) { 2277 b.ReportAllocs() 2278 ct := new(concurrentStmtExecTest) 2279 for i := 0; i < b.N; i++ { 2280 doConcurrentTest(b, ct) 2281 } 2282 } 2283 2284 func BenchmarkConcurrentTxQuery(b *testing.B) { 2285 b.ReportAllocs() 2286 ct := new(concurrentTxQueryTest) 2287 for i := 0; i < b.N; i++ { 2288 doConcurrentTest(b, ct) 2289 } 2290 } 2291 2292 func BenchmarkConcurrentTxExec(b *testing.B) { 2293 b.ReportAllocs() 2294 ct := new(concurrentTxExecTest) 2295 for i := 0; i < b.N; i++ { 2296 doConcurrentTest(b, ct) 2297 } 2298 } 2299 2300 func BenchmarkConcurrentTxStmtQuery(b *testing.B) { 2301 b.ReportAllocs() 2302 ct := new(concurrentTxStmtQueryTest) 2303 for i := 0; i < b.N; i++ { 2304 doConcurrentTest(b, ct) 2305 } 2306 } 2307 2308 func BenchmarkConcurrentTxStmtExec(b *testing.B) { 2309 b.ReportAllocs() 2310 ct := new(concurrentTxStmtExecTest) 2311 for i := 0; i < b.N; i++ { 2312 doConcurrentTest(b, ct) 2313 } 2314 } 2315 2316 func BenchmarkConcurrentRandom(b *testing.B) { 2317 b.ReportAllocs() 2318 ct := new(concurrentRandomTest) 2319 for i := 0; i < b.N; i++ { 2320 doConcurrentTest(b, ct) 2321 } 2322 } 2323 2324 func BenchmarkManyConcurrentQueries(b *testing.B) { 2325 b.ReportAllocs() 2326 // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required. 2327 const parallelism = 16 2328 2329 db := newTestDB(b, "magicquery") 2330 defer closeDB(b, db) 2331 db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism) 2332 2333 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 2334 if err != nil { 2335 b.Fatal(err) 2336 } 2337 defer stmt.Close() 2338 2339 b.SetParallelism(parallelism) 2340 b.RunParallel(func(pb *testing.PB) { 2341 for pb.Next() { 2342 rows, err := stmt.Query("sleep", 1) 2343 if err != nil { 2344 b.Error(err) 2345 return 2346 } 2347 rows.Close() 2348 } 2349 }) 2350 }