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