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