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