github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/database/sql/sql_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sql 6 7 import ( 8 "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 canceled 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 TestNullInt16Param(t *testing.T) { 1823 spec := nullTestSpec{"nullint16", "int16", [6]nullTestRow{ 1824 {NullInt16{31, true}, 1, NullInt16{31, true}}, 1825 {NullInt16{-22, false}, 1, NullInt16{0, false}}, 1826 {22, 1, NullInt16{22, true}}, 1827 {NullInt16{33, true}, 1, NullInt16{33, true}}, 1828 {NullInt16{222, false}, 1, NullInt16{0, false}}, 1829 {0, NullInt16{31, false}, nil}, 1830 }} 1831 nullTestRun(t, spec) 1832 } 1833 1834 func TestNullByteParam(t *testing.T) { 1835 spec := nullTestSpec{"nullbyte", "byte", [6]nullTestRow{ 1836 {NullByte{31, true}, 1, NullByte{31, true}}, 1837 {NullByte{0, false}, 1, NullByte{0, false}}, 1838 {22, 1, NullByte{22, true}}, 1839 {NullByte{33, true}, 1, NullByte{33, true}}, 1840 {NullByte{222, false}, 1, NullByte{0, false}}, 1841 {0, NullByte{31, false}, nil}, 1842 }} 1843 nullTestRun(t, spec) 1844 } 1845 1846 func TestNullFloat64Param(t *testing.T) { 1847 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{ 1848 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}}, 1849 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}}, 1850 {-22.9, 1, NullFloat64{-22.9, true}}, 1851 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}}, 1852 {NullFloat64{222, false}, 1, NullFloat64{0, false}}, 1853 {10, NullFloat64{31.2, false}, nil}, 1854 }} 1855 nullTestRun(t, spec) 1856 } 1857 1858 func TestNullBoolParam(t *testing.T) { 1859 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{ 1860 {NullBool{false, true}, true, NullBool{false, true}}, 1861 {NullBool{true, false}, false, NullBool{false, false}}, 1862 {true, true, NullBool{true, true}}, 1863 {NullBool{true, true}, false, NullBool{true, true}}, 1864 {NullBool{true, false}, true, NullBool{false, false}}, 1865 {true, NullBool{true, false}, nil}, 1866 }} 1867 nullTestRun(t, spec) 1868 } 1869 1870 func TestNullTimeParam(t *testing.T) { 1871 t0 := time.Time{} 1872 t1 := time.Date(2000, 1, 1, 8, 9, 10, 11, time.UTC) 1873 t2 := time.Date(2010, 1, 1, 8, 9, 10, 11, time.UTC) 1874 spec := nullTestSpec{"nulldatetime", "datetime", [6]nullTestRow{ 1875 {NullTime{t1, true}, t2, NullTime{t1, true}}, 1876 {NullTime{t1, false}, t2, NullTime{t0, false}}, 1877 {t1, t2, NullTime{t1, true}}, 1878 {NullTime{t1, true}, t2, NullTime{t1, true}}, 1879 {NullTime{t1, false}, t2, NullTime{t0, false}}, 1880 {t2, NullTime{t1, false}, nil}, 1881 }} 1882 nullTestRun(t, spec) 1883 } 1884 1885 func nullTestRun(t *testing.T, spec nullTestSpec) { 1886 db := newTestDB(t, "") 1887 defer closeDB(t, db) 1888 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType)) 1889 1890 // Inserts with db.Exec: 1891 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam) 1892 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam) 1893 1894 // Inserts with a prepared statement: 1895 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?") 1896 if err != nil { 1897 t.Fatalf("prepare: %v", err) 1898 } 1899 defer stmt.Close() 1900 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil { 1901 t.Errorf("exec insert chris: %v", err) 1902 } 1903 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil { 1904 t.Errorf("exec insert dave: %v", err) 1905 } 1906 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil { 1907 t.Errorf("exec insert eleanor: %v", err) 1908 } 1909 1910 // Can't put null val into non-null col 1911 if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil { 1912 t.Errorf("expected error inserting nil val with prepared statement Exec") 1913 } 1914 1915 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil) 1916 if err == nil { 1917 // TODO: this test fails, but it's just because 1918 // fakeConn implements the optional Execer interface, 1919 // so arguably this is the correct behavior. But 1920 // maybe I should flesh out the fakeConn.Exec 1921 // implementation so this properly fails. 1922 // t.Errorf("expected error inserting nil name with Exec") 1923 } 1924 1925 paramtype := reflect.TypeOf(spec.rows[0].nullParam) 1926 bindVal := reflect.New(paramtype).Interface() 1927 1928 for i := 0; i < 5; i++ { 1929 id := i + 1 1930 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil { 1931 t.Errorf("id=%d Scan: %v", id, err) 1932 } 1933 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface() 1934 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) { 1935 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal) 1936 } 1937 } 1938 } 1939 1940 // golang.org/issue/4859 1941 func TestQueryRowNilScanDest(t *testing.T) { 1942 db := newTestDB(t, "people") 1943 defer closeDB(t, db) 1944 var name *string // nil pointer 1945 err := db.QueryRow("SELECT|people|name|").Scan(name) 1946 want := `sql: Scan error on column index 0, name "name": destination pointer is nil` 1947 if err == nil || err.Error() != want { 1948 t.Errorf("error = %q; want %q", err.Error(), want) 1949 } 1950 } 1951 1952 func TestIssue4902(t *testing.T) { 1953 db := newTestDB(t, "people") 1954 defer closeDB(t, db) 1955 1956 driver := db.Driver().(*fakeDriver) 1957 opens0 := driver.openCount 1958 1959 var stmt *Stmt 1960 var err error 1961 for i := 0; i < 10; i++ { 1962 stmt, err = db.Prepare("SELECT|people|name|") 1963 if err != nil { 1964 t.Fatal(err) 1965 } 1966 err = stmt.Close() 1967 if err != nil { 1968 t.Fatal(err) 1969 } 1970 } 1971 1972 opens := driver.openCount - opens0 1973 if opens > 1 { 1974 t.Errorf("opens = %d; want <= 1", opens) 1975 t.Logf("db = %#v", db) 1976 t.Logf("driver = %#v", driver) 1977 t.Logf("stmt = %#v", stmt) 1978 } 1979 } 1980 1981 // Issue 3857 1982 // This used to deadlock. 1983 func TestSimultaneousQueries(t *testing.T) { 1984 db := newTestDB(t, "people") 1985 defer closeDB(t, db) 1986 1987 tx, err := db.Begin() 1988 if err != nil { 1989 t.Fatal(err) 1990 } 1991 defer tx.Rollback() 1992 1993 r1, err := tx.Query("SELECT|people|name|") 1994 if err != nil { 1995 t.Fatal(err) 1996 } 1997 defer r1.Close() 1998 1999 r2, err := tx.Query("SELECT|people|name|") 2000 if err != nil { 2001 t.Fatal(err) 2002 } 2003 defer r2.Close() 2004 } 2005 2006 func TestMaxIdleConns(t *testing.T) { 2007 db := newTestDB(t, "people") 2008 defer closeDB(t, db) 2009 2010 tx, err := db.Begin() 2011 if err != nil { 2012 t.Fatal(err) 2013 } 2014 tx.Commit() 2015 if got := len(db.freeConn); got != 1 { 2016 t.Errorf("freeConns = %d; want 1", got) 2017 } 2018 2019 db.SetMaxIdleConns(0) 2020 2021 if got := len(db.freeConn); got != 0 { 2022 t.Errorf("freeConns after set to zero = %d; want 0", got) 2023 } 2024 2025 tx, err = db.Begin() 2026 if err != nil { 2027 t.Fatal(err) 2028 } 2029 tx.Commit() 2030 if got := len(db.freeConn); got != 0 { 2031 t.Errorf("freeConns = %d; want 0", got) 2032 } 2033 } 2034 2035 func TestMaxOpenConns(t *testing.T) { 2036 if testing.Short() { 2037 t.Skip("skipping in short mode") 2038 } 2039 defer setHookpostCloseConn(nil) 2040 setHookpostCloseConn(func(_ *fakeConn, err error) { 2041 if err != nil { 2042 t.Errorf("Error closing fakeConn: %v", err) 2043 } 2044 }) 2045 2046 db := newTestDB(t, "magicquery") 2047 defer closeDB(t, db) 2048 2049 driver := db.Driver().(*fakeDriver) 2050 2051 // Force the number of open connections to 0 so we can get an accurate 2052 // count for the test 2053 db.clearAllConns(t) 2054 2055 driver.mu.Lock() 2056 opens0 := driver.openCount 2057 closes0 := driver.closeCount 2058 driver.mu.Unlock() 2059 2060 db.SetMaxIdleConns(10) 2061 db.SetMaxOpenConns(10) 2062 2063 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 2064 if err != nil { 2065 t.Fatal(err) 2066 } 2067 2068 // Start 50 parallel slow queries. 2069 const ( 2070 nquery = 50 2071 sleepMillis = 25 2072 nbatch = 2 2073 ) 2074 var wg sync.WaitGroup 2075 for batch := 0; batch < nbatch; batch++ { 2076 for i := 0; i < nquery; i++ { 2077 wg.Add(1) 2078 go func() { 2079 defer wg.Done() 2080 var op string 2081 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 2082 t.Error(err) 2083 } 2084 }() 2085 } 2086 // Sleep for twice the expected length of time for the 2087 // batch of 50 queries above to finish before starting 2088 // the next round. 2089 time.Sleep(2 * sleepMillis * time.Millisecond) 2090 } 2091 wg.Wait() 2092 2093 if g, w := db.numFreeConns(), 10; g != w { 2094 t.Errorf("free conns = %d; want %d", g, w) 2095 } 2096 2097 if n := db.numDepsPollUntil(20, time.Second); n > 20 { 2098 t.Errorf("number of dependencies = %d; expected <= 20", n) 2099 db.dumpDeps(t) 2100 } 2101 2102 driver.mu.Lock() 2103 opens := driver.openCount - opens0 2104 closes := driver.closeCount - closes0 2105 driver.mu.Unlock() 2106 2107 if opens > 10 { 2108 t.Logf("open calls = %d", opens) 2109 t.Logf("close calls = %d", closes) 2110 t.Errorf("db connections opened = %d; want <= 10", opens) 2111 db.dumpDeps(t) 2112 } 2113 2114 if err := stmt.Close(); err != nil { 2115 t.Fatal(err) 2116 } 2117 2118 if g, w := db.numFreeConns(), 10; g != w { 2119 t.Errorf("free conns = %d; want %d", g, w) 2120 } 2121 2122 if n := db.numDepsPollUntil(10, time.Second); n > 10 { 2123 t.Errorf("number of dependencies = %d; expected <= 10", n) 2124 db.dumpDeps(t) 2125 } 2126 2127 db.SetMaxOpenConns(5) 2128 2129 if g, w := db.numFreeConns(), 5; g != w { 2130 t.Errorf("free conns = %d; want %d", g, w) 2131 } 2132 2133 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 2134 t.Errorf("number of dependencies = %d; expected 0", n) 2135 db.dumpDeps(t) 2136 } 2137 2138 db.SetMaxOpenConns(0) 2139 2140 if g, w := db.numFreeConns(), 5; g != w { 2141 t.Errorf("free conns = %d; want %d", g, w) 2142 } 2143 2144 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 2145 t.Errorf("number of dependencies = %d; expected 0", n) 2146 db.dumpDeps(t) 2147 } 2148 2149 db.clearAllConns(t) 2150 } 2151 2152 // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime 2153 // and affects the subsequent release of connections. 2154 func TestMaxOpenConnsOnBusy(t *testing.T) { 2155 defer setHookpostCloseConn(nil) 2156 setHookpostCloseConn(func(_ *fakeConn, err error) { 2157 if err != nil { 2158 t.Errorf("Error closing fakeConn: %v", err) 2159 } 2160 }) 2161 2162 db := newTestDB(t, "magicquery") 2163 defer closeDB(t, db) 2164 2165 db.SetMaxOpenConns(3) 2166 2167 ctx := context.Background() 2168 2169 conn0, err := db.conn(ctx, cachedOrNewConn) 2170 if err != nil { 2171 t.Fatalf("db open conn fail: %v", err) 2172 } 2173 2174 conn1, err := db.conn(ctx, cachedOrNewConn) 2175 if err != nil { 2176 t.Fatalf("db open conn fail: %v", err) 2177 } 2178 2179 conn2, err := db.conn(ctx, cachedOrNewConn) 2180 if err != nil { 2181 t.Fatalf("db open conn fail: %v", err) 2182 } 2183 2184 if g, w := db.numOpen, 3; g != w { 2185 t.Errorf("free conns = %d; want %d", g, w) 2186 } 2187 2188 db.SetMaxOpenConns(2) 2189 if g, w := db.numOpen, 3; g != w { 2190 t.Errorf("free conns = %d; want %d", g, w) 2191 } 2192 2193 conn0.releaseConn(nil) 2194 conn1.releaseConn(nil) 2195 if g, w := db.numOpen, 2; g != w { 2196 t.Errorf("free conns = %d; want %d", g, w) 2197 } 2198 2199 conn2.releaseConn(nil) 2200 if g, w := db.numOpen, 2; g != w { 2201 t.Errorf("free conns = %d; want %d", g, w) 2202 } 2203 } 2204 2205 // Issue 10886: tests that all connection attempts return when more than 2206 // DB.maxOpen connections are in flight and the first DB.maxOpen fail. 2207 func TestPendingConnsAfterErr(t *testing.T) { 2208 const ( 2209 maxOpen = 2 2210 tryOpen = maxOpen*2 + 2 2211 ) 2212 2213 // No queries will be run. 2214 db, err := Open("test", fakeDBName) 2215 if err != nil { 2216 t.Fatalf("Open: %v", err) 2217 } 2218 defer closeDB(t, db) 2219 defer func() { 2220 for k, v := range db.lastPut { 2221 t.Logf("%p: %v", k, v) 2222 } 2223 }() 2224 2225 db.SetMaxOpenConns(maxOpen) 2226 db.SetMaxIdleConns(0) 2227 2228 errOffline := errors.New("db offline") 2229 2230 defer func() { setHookOpenErr(nil) }() 2231 2232 errs := make(chan error, tryOpen) 2233 2234 var opening sync.WaitGroup 2235 opening.Add(tryOpen) 2236 2237 setHookOpenErr(func() error { 2238 // Wait for all connections to enqueue. 2239 opening.Wait() 2240 return errOffline 2241 }) 2242 2243 for i := 0; i < tryOpen; i++ { 2244 go func() { 2245 opening.Done() // signal one connection is in flight 2246 _, err := db.Exec("will never run") 2247 errs <- err 2248 }() 2249 } 2250 2251 opening.Wait() // wait for all workers to begin running 2252 2253 const timeout = 5 * time.Second 2254 to := time.NewTimer(timeout) 2255 defer to.Stop() 2256 2257 // check that all connections fail without deadlock 2258 for i := 0; i < tryOpen; i++ { 2259 select { 2260 case err := <-errs: 2261 if got, want := err, errOffline; got != want { 2262 t.Errorf("unexpected err: got %v, want %v", got, want) 2263 } 2264 case <-to.C: 2265 t.Fatalf("orphaned connection request(s), still waiting after %v", timeout) 2266 } 2267 } 2268 2269 // Wait a reasonable time for the database to close all connections. 2270 tick := time.NewTicker(3 * time.Millisecond) 2271 defer tick.Stop() 2272 for { 2273 select { 2274 case <-tick.C: 2275 db.mu.Lock() 2276 if db.numOpen == 0 { 2277 db.mu.Unlock() 2278 return 2279 } 2280 db.mu.Unlock() 2281 case <-to.C: 2282 // Closing the database will check for numOpen and fail the test. 2283 return 2284 } 2285 } 2286 } 2287 2288 func TestSingleOpenConn(t *testing.T) { 2289 db := newTestDB(t, "people") 2290 defer closeDB(t, db) 2291 2292 db.SetMaxOpenConns(1) 2293 2294 rows, err := db.Query("SELECT|people|name|") 2295 if err != nil { 2296 t.Fatal(err) 2297 } 2298 if err = rows.Close(); err != nil { 2299 t.Fatal(err) 2300 } 2301 // shouldn't deadlock 2302 rows, err = db.Query("SELECT|people|name|") 2303 if err != nil { 2304 t.Fatal(err) 2305 } 2306 if err = rows.Close(); err != nil { 2307 t.Fatal(err) 2308 } 2309 } 2310 2311 func TestStats(t *testing.T) { 2312 db := newTestDB(t, "people") 2313 stats := db.Stats() 2314 if got := stats.OpenConnections; got != 1 { 2315 t.Errorf("stats.OpenConnections = %d; want 1", got) 2316 } 2317 2318 tx, err := db.Begin() 2319 if err != nil { 2320 t.Fatal(err) 2321 } 2322 tx.Commit() 2323 2324 closeDB(t, db) 2325 stats = db.Stats() 2326 if got := stats.OpenConnections; got != 0 { 2327 t.Errorf("stats.OpenConnections = %d; want 0", got) 2328 } 2329 } 2330 2331 func TestConnMaxLifetime(t *testing.T) { 2332 t0 := time.Unix(1000000, 0) 2333 offset := time.Duration(0) 2334 2335 nowFunc = func() time.Time { return t0.Add(offset) } 2336 defer func() { nowFunc = time.Now }() 2337 2338 db := newTestDB(t, "magicquery") 2339 defer closeDB(t, db) 2340 2341 driver := db.Driver().(*fakeDriver) 2342 2343 // Force the number of open connections to 0 so we can get an accurate 2344 // count for the test 2345 db.clearAllConns(t) 2346 2347 driver.mu.Lock() 2348 opens0 := driver.openCount 2349 closes0 := driver.closeCount 2350 driver.mu.Unlock() 2351 2352 db.SetMaxIdleConns(10) 2353 db.SetMaxOpenConns(10) 2354 2355 tx, err := db.Begin() 2356 if err != nil { 2357 t.Fatal(err) 2358 } 2359 2360 offset = time.Second 2361 tx2, err := db.Begin() 2362 if err != nil { 2363 t.Fatal(err) 2364 } 2365 2366 tx.Commit() 2367 tx2.Commit() 2368 2369 driver.mu.Lock() 2370 opens := driver.openCount - opens0 2371 closes := driver.closeCount - closes0 2372 driver.mu.Unlock() 2373 2374 if opens != 2 { 2375 t.Errorf("opens = %d; want 2", opens) 2376 } 2377 if closes != 0 { 2378 t.Errorf("closes = %d; want 0", closes) 2379 } 2380 if g, w := db.numFreeConns(), 2; g != w { 2381 t.Errorf("free conns = %d; want %d", g, w) 2382 } 2383 2384 // Expire first conn 2385 offset = 11 * time.Second 2386 db.SetConnMaxLifetime(10 * time.Second) 2387 if err != nil { 2388 t.Fatal(err) 2389 } 2390 2391 tx, err = db.Begin() 2392 if err != nil { 2393 t.Fatal(err) 2394 } 2395 tx2, err = db.Begin() 2396 if err != nil { 2397 t.Fatal(err) 2398 } 2399 tx.Commit() 2400 tx2.Commit() 2401 2402 driver.mu.Lock() 2403 opens = driver.openCount - opens0 2404 closes = driver.closeCount - closes0 2405 driver.mu.Unlock() 2406 2407 if opens != 3 { 2408 t.Errorf("opens = %d; want 3", opens) 2409 } 2410 if closes != 1 { 2411 t.Errorf("closes = %d; want 1", closes) 2412 } 2413 } 2414 2415 // golang.org/issue/5323 2416 func TestStmtCloseDeps(t *testing.T) { 2417 if testing.Short() { 2418 t.Skip("skipping in short mode") 2419 } 2420 defer setHookpostCloseConn(nil) 2421 setHookpostCloseConn(func(_ *fakeConn, err error) { 2422 if err != nil { 2423 t.Errorf("Error closing fakeConn: %v", err) 2424 } 2425 }) 2426 2427 db := newTestDB(t, "magicquery") 2428 defer closeDB(t, db) 2429 2430 driver := db.Driver().(*fakeDriver) 2431 2432 driver.mu.Lock() 2433 opens0 := driver.openCount 2434 closes0 := driver.closeCount 2435 driver.mu.Unlock() 2436 openDelta0 := opens0 - closes0 2437 2438 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 2439 if err != nil { 2440 t.Fatal(err) 2441 } 2442 2443 // Start 50 parallel slow queries. 2444 const ( 2445 nquery = 50 2446 sleepMillis = 25 2447 nbatch = 2 2448 ) 2449 var wg sync.WaitGroup 2450 for batch := 0; batch < nbatch; batch++ { 2451 for i := 0; i < nquery; i++ { 2452 wg.Add(1) 2453 go func() { 2454 defer wg.Done() 2455 var op string 2456 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 2457 t.Error(err) 2458 } 2459 }() 2460 } 2461 // Sleep for twice the expected length of time for the 2462 // batch of 50 queries above to finish before starting 2463 // the next round. 2464 time.Sleep(2 * sleepMillis * time.Millisecond) 2465 } 2466 wg.Wait() 2467 2468 if g, w := db.numFreeConns(), 2; g != w { 2469 t.Errorf("free conns = %d; want %d", g, w) 2470 } 2471 2472 if n := db.numDepsPollUntil(4, time.Second); n > 4 { 2473 t.Errorf("number of dependencies = %d; expected <= 4", n) 2474 db.dumpDeps(t) 2475 } 2476 2477 driver.mu.Lock() 2478 opens := driver.openCount - opens0 2479 closes := driver.closeCount - closes0 2480 openDelta := (driver.openCount - driver.closeCount) - openDelta0 2481 driver.mu.Unlock() 2482 2483 if openDelta > 2 { 2484 t.Logf("open calls = %d", opens) 2485 t.Logf("close calls = %d", closes) 2486 t.Logf("open delta = %d", openDelta) 2487 t.Errorf("db connections opened = %d; want <= 2", openDelta) 2488 db.dumpDeps(t) 2489 } 2490 2491 if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool { 2492 return len(stmt.css) <= nquery 2493 }) { 2494 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery) 2495 } 2496 2497 if err := stmt.Close(); err != nil { 2498 t.Fatal(err) 2499 } 2500 2501 if g, w := db.numFreeConns(), 2; g != w { 2502 t.Errorf("free conns = %d; want %d", g, w) 2503 } 2504 2505 if n := db.numDepsPollUntil(2, time.Second); n > 2 { 2506 t.Errorf("number of dependencies = %d; expected <= 2", n) 2507 db.dumpDeps(t) 2508 } 2509 2510 db.clearAllConns(t) 2511 } 2512 2513 // golang.org/issue/5046 2514 func TestCloseConnBeforeStmts(t *testing.T) { 2515 db := newTestDB(t, "people") 2516 defer closeDB(t, db) 2517 2518 defer setHookpostCloseConn(nil) 2519 setHookpostCloseConn(func(_ *fakeConn, err error) { 2520 if err != nil { 2521 t.Errorf("Error closing fakeConn: %v; from %s", err, stack()) 2522 db.dumpDeps(t) 2523 t.Errorf("DB = %#v", db) 2524 } 2525 }) 2526 2527 stmt, err := db.Prepare("SELECT|people|name|") 2528 if err != nil { 2529 t.Fatal(err) 2530 } 2531 2532 if len(db.freeConn) != 1 { 2533 t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn)) 2534 } 2535 dc := db.freeConn[0] 2536 if dc.closed { 2537 t.Errorf("conn shouldn't be closed") 2538 } 2539 2540 if n := len(dc.openStmt); n != 1 { 2541 t.Errorf("driverConn num openStmt = %d; want 1", n) 2542 } 2543 err = db.Close() 2544 if err != nil { 2545 t.Errorf("db Close = %v", err) 2546 } 2547 if !dc.closed { 2548 t.Errorf("after db.Close, driverConn should be closed") 2549 } 2550 if n := len(dc.openStmt); n != 0 { 2551 t.Errorf("driverConn num openStmt = %d; want 0", n) 2552 } 2553 2554 err = stmt.Close() 2555 if err != nil { 2556 t.Errorf("Stmt close = %v", err) 2557 } 2558 2559 if !dc.closed { 2560 t.Errorf("conn should be closed") 2561 } 2562 if dc.ci != nil { 2563 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil") 2564 } 2565 } 2566 2567 // golang.org/issue/5283: don't release the Rows' connection in Close 2568 // before calling Stmt.Close. 2569 func TestRowsCloseOrder(t *testing.T) { 2570 db := newTestDB(t, "people") 2571 defer closeDB(t, db) 2572 2573 db.SetMaxIdleConns(0) 2574 setStrictFakeConnClose(t) 2575 defer setStrictFakeConnClose(nil) 2576 2577 rows, err := db.Query("SELECT|people|age,name|") 2578 if err != nil { 2579 t.Fatal(err) 2580 } 2581 err = rows.Close() 2582 if err != nil { 2583 t.Fatal(err) 2584 } 2585 } 2586 2587 func TestRowsImplicitClose(t *testing.T) { 2588 db := newTestDB(t, "people") 2589 defer closeDB(t, db) 2590 2591 rows, err := db.Query("SELECT|people|age,name|") 2592 if err != nil { 2593 t.Fatal(err) 2594 } 2595 2596 want, fail := 2, errors.New("fail") 2597 r := rows.rowsi.(*rowsCursor) 2598 r.errPos, r.err = want, fail 2599 2600 got := 0 2601 for rows.Next() { 2602 got++ 2603 } 2604 if got != want { 2605 t.Errorf("got %d rows, want %d", got, want) 2606 } 2607 if err := rows.Err(); err != fail { 2608 t.Errorf("got error %v, want %v", err, fail) 2609 } 2610 if !r.closed { 2611 t.Errorf("r.closed is false, want true") 2612 } 2613 } 2614 2615 func TestStmtCloseOrder(t *testing.T) { 2616 db := newTestDB(t, "people") 2617 defer closeDB(t, db) 2618 2619 db.SetMaxIdleConns(0) 2620 setStrictFakeConnClose(t) 2621 defer setStrictFakeConnClose(nil) 2622 2623 _, err := db.Query("SELECT|non_existent|name|") 2624 if err == nil { 2625 t.Fatal("Querying non-existent table should fail") 2626 } 2627 } 2628 2629 // Test cases where there's more than maxBadConnRetries bad connections in the 2630 // pool (issue 8834) 2631 func TestManyErrBadConn(t *testing.T) { 2632 manyErrBadConnSetup := func(first ...func(db *DB)) *DB { 2633 db := newTestDB(t, "people") 2634 2635 for _, f := range first { 2636 f(db) 2637 } 2638 2639 nconn := maxBadConnRetries + 1 2640 db.SetMaxIdleConns(nconn) 2641 db.SetMaxOpenConns(nconn) 2642 // open enough connections 2643 func() { 2644 for i := 0; i < nconn; i++ { 2645 rows, err := db.Query("SELECT|people|age,name|") 2646 if err != nil { 2647 t.Fatal(err) 2648 } 2649 defer rows.Close() 2650 } 2651 }() 2652 2653 db.mu.Lock() 2654 defer db.mu.Unlock() 2655 if db.numOpen != nconn { 2656 t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn) 2657 } else if len(db.freeConn) != nconn { 2658 t.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db.freeConn), nconn) 2659 } 2660 for _, conn := range db.freeConn { 2661 conn.Lock() 2662 conn.ci.(*fakeConn).stickyBad = true 2663 conn.Unlock() 2664 } 2665 return db 2666 } 2667 2668 // Query 2669 db := manyErrBadConnSetup() 2670 defer closeDB(t, db) 2671 rows, err := db.Query("SELECT|people|age,name|") 2672 if err != nil { 2673 t.Fatal(err) 2674 } 2675 if err = rows.Close(); err != nil { 2676 t.Fatal(err) 2677 } 2678 2679 // Exec 2680 db = manyErrBadConnSetup() 2681 defer closeDB(t, db) 2682 _, err = db.Exec("INSERT|people|name=Julia,age=19") 2683 if err != nil { 2684 t.Fatal(err) 2685 } 2686 2687 // Begin 2688 db = manyErrBadConnSetup() 2689 defer closeDB(t, db) 2690 tx, err := db.Begin() 2691 if err != nil { 2692 t.Fatal(err) 2693 } 2694 if err = tx.Rollback(); err != nil { 2695 t.Fatal(err) 2696 } 2697 2698 // Prepare 2699 db = manyErrBadConnSetup() 2700 defer closeDB(t, db) 2701 stmt, err := db.Prepare("SELECT|people|age,name|") 2702 if err != nil { 2703 t.Fatal(err) 2704 } 2705 if err = stmt.Close(); err != nil { 2706 t.Fatal(err) 2707 } 2708 2709 // Stmt.Exec 2710 db = manyErrBadConnSetup(func(db *DB) { 2711 stmt, err = db.Prepare("INSERT|people|name=Julia,age=19") 2712 if err != nil { 2713 t.Fatal(err) 2714 } 2715 }) 2716 defer closeDB(t, db) 2717 _, err = stmt.Exec() 2718 if err != nil { 2719 t.Fatal(err) 2720 } 2721 if err = stmt.Close(); err != nil { 2722 t.Fatal(err) 2723 } 2724 2725 // Stmt.Query 2726 db = manyErrBadConnSetup(func(db *DB) { 2727 stmt, err = db.Prepare("SELECT|people|age,name|") 2728 if err != nil { 2729 t.Fatal(err) 2730 } 2731 }) 2732 defer closeDB(t, db) 2733 rows, err = stmt.Query() 2734 if err != nil { 2735 t.Fatal(err) 2736 } 2737 if err = rows.Close(); err != nil { 2738 t.Fatal(err) 2739 } 2740 if err = stmt.Close(); err != nil { 2741 t.Fatal(err) 2742 } 2743 2744 // Conn 2745 db = manyErrBadConnSetup() 2746 defer closeDB(t, db) 2747 ctx, cancel := context.WithCancel(context.Background()) 2748 defer cancel() 2749 conn, err := db.Conn(ctx) 2750 if err != nil { 2751 t.Fatal(err) 2752 } 2753 conn.dc.ci.(*fakeConn).skipDirtySession = true 2754 err = conn.Close() 2755 if err != nil { 2756 t.Fatal(err) 2757 } 2758 2759 // Ping 2760 db = manyErrBadConnSetup() 2761 defer closeDB(t, db) 2762 err = db.PingContext(ctx) 2763 if err != nil { 2764 t.Fatal(err) 2765 } 2766 } 2767 2768 // Issue 34775: Ensure that a Tx cannot commit after a rollback. 2769 func TestTxCannotCommitAfterRollback(t *testing.T) { 2770 db := newTestDB(t, "tx_status") 2771 defer closeDB(t, db) 2772 2773 // First check query reporting is correct. 2774 var txStatus string 2775 err := db.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus) 2776 if err != nil { 2777 t.Fatal(err) 2778 } 2779 if g, w := txStatus, "autocommit"; g != w { 2780 t.Fatalf("tx_status=%q, wanted %q", g, w) 2781 } 2782 2783 ctx, cancel := context.WithCancel(context.Background()) 2784 defer cancel() 2785 2786 tx, err := db.BeginTx(ctx, nil) 2787 if err != nil { 2788 t.Fatal(err) 2789 } 2790 2791 // Ignore dirty session for this test. 2792 // A failing test should trigger the dirty session flag as well, 2793 // but that isn't exactly what this should test for. 2794 tx.txi.(*fakeTx).c.skipDirtySession = true 2795 2796 defer tx.Rollback() 2797 2798 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus) 2799 if err != nil { 2800 t.Fatal(err) 2801 } 2802 if g, w := txStatus, "transaction"; g != w { 2803 t.Fatalf("tx_status=%q, wanted %q", g, w) 2804 } 2805 2806 // 1. Begin a transaction. 2807 // 2. (A) Start a query, (B) begin Tx rollback through a ctx cancel. 2808 // 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail). 2809 sendQuery := make(chan struct{}) 2810 // The Tx status is returned through the row results, ensure 2811 // that the rows results are not canceled. 2812 bypassRowsAwaitDone = true 2813 hookTxGrabConn = func() { 2814 cancel() 2815 <-sendQuery 2816 } 2817 rollbackHook = func() { 2818 close(sendQuery) 2819 } 2820 defer func() { 2821 hookTxGrabConn = nil 2822 rollbackHook = nil 2823 bypassRowsAwaitDone = false 2824 }() 2825 2826 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus) 2827 if err != nil { 2828 // A failure here would be expected if skipDirtySession was not set to true above. 2829 t.Fatal(err) 2830 } 2831 if g, w := txStatus, "transaction"; g != w { 2832 t.Fatalf("tx_status=%q, wanted %q", g, w) 2833 } 2834 } 2835 2836 // Issue 40985 transaction statement deadlock while context cancel. 2837 func TestTxStmtDeadlock(t *testing.T) { 2838 db := newTestDB(t, "people") 2839 defer closeDB(t, db) 2840 2841 ctx, cancel := context.WithCancel(context.Background()) 2842 defer cancel() 2843 tx, err := db.BeginTx(ctx, nil) 2844 if err != nil { 2845 t.Fatal(err) 2846 } 2847 2848 stmt, err := tx.Prepare("SELECT|people|name,age|age=?") 2849 if err != nil { 2850 t.Fatal(err) 2851 } 2852 cancel() 2853 // Run number of stmt queries to reproduce deadlock from context cancel 2854 for i := 0; i < 1e3; i++ { 2855 // Encounter any close related errors (e.g. ErrTxDone, stmt is closed) 2856 // is expected due to context cancel. 2857 _, err = stmt.Query(1) 2858 if err != nil { 2859 break 2860 } 2861 } 2862 _ = tx.Rollback() 2863 } 2864 2865 // Issue32530 encounters an issue where a connection may 2866 // expire right after it comes out of a used connection pool 2867 // even when a new connection is requested. 2868 func TestConnExpiresFreshOutOfPool(t *testing.T) { 2869 execCases := []struct { 2870 expired bool 2871 badReset bool 2872 }{ 2873 {false, false}, 2874 {true, false}, 2875 {false, true}, 2876 } 2877 2878 t0 := time.Unix(1000000, 0) 2879 offset := time.Duration(0) 2880 offsetMu := sync.RWMutex{} 2881 2882 nowFunc = func() time.Time { 2883 offsetMu.RLock() 2884 defer offsetMu.RUnlock() 2885 return t0.Add(offset) 2886 } 2887 defer func() { nowFunc = time.Now }() 2888 2889 ctx, cancel := context.WithCancel(context.Background()) 2890 defer cancel() 2891 2892 db := newTestDB(t, "magicquery") 2893 defer closeDB(t, db) 2894 2895 db.SetMaxOpenConns(1) 2896 2897 for _, ec := range execCases { 2898 ec := ec 2899 name := fmt.Sprintf("expired=%t,badReset=%t", ec.expired, ec.badReset) 2900 t.Run(name, func(t *testing.T) { 2901 db.clearAllConns(t) 2902 2903 db.SetMaxIdleConns(1) 2904 db.SetConnMaxLifetime(10 * time.Second) 2905 2906 conn, err := db.conn(ctx, alwaysNewConn) 2907 if err != nil { 2908 t.Fatal(err) 2909 } 2910 2911 afterPutConn := make(chan struct{}) 2912 waitingForConn := make(chan struct{}) 2913 2914 go func() { 2915 defer close(afterPutConn) 2916 2917 conn, err := db.conn(ctx, alwaysNewConn) 2918 if err == nil { 2919 db.putConn(conn, err, false) 2920 } else { 2921 t.Errorf("db.conn: %v", err) 2922 } 2923 }() 2924 go func() { 2925 defer close(waitingForConn) 2926 2927 for { 2928 if t.Failed() { 2929 return 2930 } 2931 db.mu.Lock() 2932 ct := len(db.connRequests) 2933 db.mu.Unlock() 2934 if ct > 0 { 2935 return 2936 } 2937 time.Sleep(10 * time.Millisecond) 2938 } 2939 }() 2940 2941 <-waitingForConn 2942 2943 if t.Failed() { 2944 return 2945 } 2946 2947 offsetMu.Lock() 2948 if ec.expired { 2949 offset = 11 * time.Second 2950 } else { 2951 offset = time.Duration(0) 2952 } 2953 offsetMu.Unlock() 2954 2955 conn.ci.(*fakeConn).stickyBad = ec.badReset 2956 2957 db.putConn(conn, err, true) 2958 2959 <-afterPutConn 2960 }) 2961 } 2962 } 2963 2964 // TestIssue20575 ensures the Rows from query does not block 2965 // closing a transaction. Ensure Rows is closed while closing a trasaction. 2966 func TestIssue20575(t *testing.T) { 2967 db := newTestDB(t, "people") 2968 defer closeDB(t, db) 2969 2970 tx, err := db.Begin() 2971 if err != nil { 2972 t.Fatal(err) 2973 } 2974 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 2975 defer cancel() 2976 _, err = tx.QueryContext(ctx, "SELECT|people|age,name|") 2977 if err != nil { 2978 t.Fatal(err) 2979 } 2980 // Do not close Rows from QueryContext. 2981 err = tx.Rollback() 2982 if err != nil { 2983 t.Fatal(err) 2984 } 2985 select { 2986 default: 2987 case <-ctx.Done(): 2988 t.Fatal("timeout: failed to rollback query without closing rows:", ctx.Err()) 2989 } 2990 } 2991 2992 // TestIssue20622 tests closing the transaction before rows is closed, requires 2993 // the race detector to fail. 2994 func TestIssue20622(t *testing.T) { 2995 db := newTestDB(t, "people") 2996 defer closeDB(t, db) 2997 2998 ctx, cancel := context.WithCancel(context.Background()) 2999 defer cancel() 3000 3001 tx, err := db.BeginTx(ctx, nil) 3002 if err != nil { 3003 t.Fatal(err) 3004 } 3005 3006 rows, err := tx.Query("SELECT|people|age,name|") 3007 if err != nil { 3008 t.Fatal(err) 3009 } 3010 3011 count := 0 3012 for rows.Next() { 3013 count++ 3014 var age int 3015 var name string 3016 if err := rows.Scan(&age, &name); err != nil { 3017 t.Fatal("scan failed", err) 3018 } 3019 3020 if count == 1 { 3021 cancel() 3022 } 3023 time.Sleep(100 * time.Millisecond) 3024 } 3025 rows.Close() 3026 tx.Commit() 3027 } 3028 3029 // golang.org/issue/5718 3030 func TestErrBadConnReconnect(t *testing.T) { 3031 db := newTestDB(t, "foo") 3032 defer closeDB(t, db) 3033 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 3034 3035 simulateBadConn := func(name string, hook *func() bool, op func() error) { 3036 broken, retried := false, false 3037 numOpen := db.numOpen 3038 3039 // simulate a broken connection on the first try 3040 *hook = func() bool { 3041 if !broken { 3042 broken = true 3043 return true 3044 } 3045 retried = true 3046 return false 3047 } 3048 3049 if err := op(); err != nil { 3050 t.Errorf(name+": %v", err) 3051 return 3052 } 3053 3054 if !broken || !retried { 3055 t.Error(name + ": Failed to simulate broken connection") 3056 } 3057 *hook = nil 3058 3059 if numOpen != db.numOpen { 3060 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 3061 numOpen = db.numOpen 3062 } 3063 } 3064 3065 // db.Exec 3066 dbExec := func() error { 3067 _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 3068 return err 3069 } 3070 simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec) 3071 simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec) 3072 3073 // db.Query 3074 dbQuery := func() error { 3075 rows, err := db.Query("SELECT|t1|age,name|") 3076 if err == nil { 3077 err = rows.Close() 3078 } 3079 return err 3080 } 3081 simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery) 3082 simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery) 3083 3084 // db.Prepare 3085 simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error { 3086 stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 3087 if err != nil { 3088 return err 3089 } 3090 stmt.Close() 3091 return nil 3092 }) 3093 3094 // Provide a way to force a re-prepare of a statement on next execution 3095 forcePrepare := func(stmt *Stmt) { 3096 stmt.css = nil 3097 } 3098 3099 // stmt.Exec 3100 stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 3101 if err != nil { 3102 t.Fatalf("prepare: %v", err) 3103 } 3104 defer stmt1.Close() 3105 // make sure we must prepare the stmt first 3106 forcePrepare(stmt1) 3107 3108 stmtExec := func() error { 3109 _, err := stmt1.Exec("Gopher", 3, false) 3110 return err 3111 } 3112 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec) 3113 simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec) 3114 3115 // stmt.Query 3116 stmt2, err := db.Prepare("SELECT|t1|age,name|") 3117 if err != nil { 3118 t.Fatalf("prepare: %v", err) 3119 } 3120 defer stmt2.Close() 3121 // make sure we must prepare the stmt first 3122 forcePrepare(stmt2) 3123 3124 stmtQuery := func() error { 3125 rows, err := stmt2.Query() 3126 if err == nil { 3127 err = rows.Close() 3128 } 3129 return err 3130 } 3131 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery) 3132 simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery) 3133 } 3134 3135 // golang.org/issue/11264 3136 func TestTxEndBadConn(t *testing.T) { 3137 db := newTestDB(t, "foo") 3138 defer closeDB(t, db) 3139 db.SetMaxIdleConns(0) 3140 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 3141 db.SetMaxIdleConns(1) 3142 3143 simulateBadConn := func(name string, hook *func() bool, op func() error) { 3144 broken := false 3145 numOpen := db.numOpen 3146 3147 *hook = func() bool { 3148 if !broken { 3149 broken = true 3150 } 3151 return broken 3152 } 3153 3154 if err := op(); err != driver.ErrBadConn { 3155 t.Errorf(name+": %v", err) 3156 return 3157 } 3158 3159 if !broken { 3160 t.Error(name + ": Failed to simulate broken connection") 3161 } 3162 *hook = nil 3163 3164 if numOpen != db.numOpen { 3165 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 3166 } 3167 } 3168 3169 // db.Exec 3170 dbExec := func(endTx func(tx *Tx) error) func() error { 3171 return func() error { 3172 tx, err := db.Begin() 3173 if err != nil { 3174 return err 3175 } 3176 _, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 3177 if err != nil { 3178 return err 3179 } 3180 return endTx(tx) 3181 } 3182 } 3183 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit)) 3184 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback)) 3185 3186 // db.Query 3187 dbQuery := func(endTx func(tx *Tx) error) func() error { 3188 return func() error { 3189 tx, err := db.Begin() 3190 if err != nil { 3191 return err 3192 } 3193 rows, err := tx.Query("SELECT|t1|age,name|") 3194 if err == nil { 3195 err = rows.Close() 3196 } else { 3197 return err 3198 } 3199 return endTx(tx) 3200 } 3201 } 3202 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit)) 3203 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback)) 3204 } 3205 3206 type concurrentTest interface { 3207 init(t testing.TB, db *DB) 3208 finish(t testing.TB) 3209 test(t testing.TB) error 3210 } 3211 3212 type concurrentDBQueryTest struct { 3213 db *DB 3214 } 3215 3216 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) { 3217 c.db = db 3218 } 3219 3220 func (c *concurrentDBQueryTest) finish(t testing.TB) { 3221 c.db = nil 3222 } 3223 3224 func (c *concurrentDBQueryTest) test(t testing.TB) error { 3225 rows, err := c.db.Query("SELECT|people|name|") 3226 if err != nil { 3227 t.Error(err) 3228 return err 3229 } 3230 var name string 3231 for rows.Next() { 3232 rows.Scan(&name) 3233 } 3234 rows.Close() 3235 return nil 3236 } 3237 3238 type concurrentDBExecTest struct { 3239 db *DB 3240 } 3241 3242 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) { 3243 c.db = db 3244 } 3245 3246 func (c *concurrentDBExecTest) finish(t testing.TB) { 3247 c.db = nil 3248 } 3249 3250 func (c *concurrentDBExecTest) test(t testing.TB) error { 3251 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 3252 if err != nil { 3253 t.Error(err) 3254 return err 3255 } 3256 return nil 3257 } 3258 3259 type concurrentStmtQueryTest struct { 3260 db *DB 3261 stmt *Stmt 3262 } 3263 3264 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) { 3265 c.db = db 3266 var err error 3267 c.stmt, err = db.Prepare("SELECT|people|name|") 3268 if err != nil { 3269 t.Fatal(err) 3270 } 3271 } 3272 3273 func (c *concurrentStmtQueryTest) finish(t testing.TB) { 3274 if c.stmt != nil { 3275 c.stmt.Close() 3276 c.stmt = nil 3277 } 3278 c.db = nil 3279 } 3280 3281 func (c *concurrentStmtQueryTest) test(t testing.TB) error { 3282 rows, err := c.stmt.Query() 3283 if err != nil { 3284 t.Errorf("error on query: %v", err) 3285 return err 3286 } 3287 3288 var name string 3289 for rows.Next() { 3290 rows.Scan(&name) 3291 } 3292 rows.Close() 3293 return nil 3294 } 3295 3296 type concurrentStmtExecTest struct { 3297 db *DB 3298 stmt *Stmt 3299 } 3300 3301 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) { 3302 c.db = db 3303 var err error 3304 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 3305 if err != nil { 3306 t.Fatal(err) 3307 } 3308 } 3309 3310 func (c *concurrentStmtExecTest) finish(t testing.TB) { 3311 if c.stmt != nil { 3312 c.stmt.Close() 3313 c.stmt = nil 3314 } 3315 c.db = nil 3316 } 3317 3318 func (c *concurrentStmtExecTest) test(t testing.TB) error { 3319 _, err := c.stmt.Exec(3, chrisBirthday) 3320 if err != nil { 3321 t.Errorf("error on exec: %v", err) 3322 return err 3323 } 3324 return nil 3325 } 3326 3327 type concurrentTxQueryTest struct { 3328 db *DB 3329 tx *Tx 3330 } 3331 3332 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) { 3333 c.db = db 3334 var err error 3335 c.tx, err = c.db.Begin() 3336 if err != nil { 3337 t.Fatal(err) 3338 } 3339 } 3340 3341 func (c *concurrentTxQueryTest) finish(t testing.TB) { 3342 if c.tx != nil { 3343 c.tx.Rollback() 3344 c.tx = nil 3345 } 3346 c.db = nil 3347 } 3348 3349 func (c *concurrentTxQueryTest) test(t testing.TB) error { 3350 rows, err := c.db.Query("SELECT|people|name|") 3351 if err != nil { 3352 t.Error(err) 3353 return err 3354 } 3355 var name string 3356 for rows.Next() { 3357 rows.Scan(&name) 3358 } 3359 rows.Close() 3360 return nil 3361 } 3362 3363 type concurrentTxExecTest struct { 3364 db *DB 3365 tx *Tx 3366 } 3367 3368 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) { 3369 c.db = db 3370 var err error 3371 c.tx, err = c.db.Begin() 3372 if err != nil { 3373 t.Fatal(err) 3374 } 3375 } 3376 3377 func (c *concurrentTxExecTest) finish(t testing.TB) { 3378 if c.tx != nil { 3379 c.tx.Rollback() 3380 c.tx = nil 3381 } 3382 c.db = nil 3383 } 3384 3385 func (c *concurrentTxExecTest) test(t testing.TB) error { 3386 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 3387 if err != nil { 3388 t.Error(err) 3389 return err 3390 } 3391 return nil 3392 } 3393 3394 type concurrentTxStmtQueryTest struct { 3395 db *DB 3396 tx *Tx 3397 stmt *Stmt 3398 } 3399 3400 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) { 3401 c.db = db 3402 var err error 3403 c.tx, err = c.db.Begin() 3404 if err != nil { 3405 t.Fatal(err) 3406 } 3407 c.stmt, err = c.tx.Prepare("SELECT|people|name|") 3408 if err != nil { 3409 t.Fatal(err) 3410 } 3411 } 3412 3413 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) { 3414 if c.stmt != nil { 3415 c.stmt.Close() 3416 c.stmt = nil 3417 } 3418 if c.tx != nil { 3419 c.tx.Rollback() 3420 c.tx = nil 3421 } 3422 c.db = nil 3423 } 3424 3425 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error { 3426 rows, err := c.stmt.Query() 3427 if err != nil { 3428 t.Errorf("error on query: %v", err) 3429 return err 3430 } 3431 3432 var name string 3433 for rows.Next() { 3434 rows.Scan(&name) 3435 } 3436 rows.Close() 3437 return nil 3438 } 3439 3440 type concurrentTxStmtExecTest struct { 3441 db *DB 3442 tx *Tx 3443 stmt *Stmt 3444 } 3445 3446 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) { 3447 c.db = db 3448 var err error 3449 c.tx, err = c.db.Begin() 3450 if err != nil { 3451 t.Fatal(err) 3452 } 3453 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 3454 if err != nil { 3455 t.Fatal(err) 3456 } 3457 } 3458 3459 func (c *concurrentTxStmtExecTest) finish(t testing.TB) { 3460 if c.stmt != nil { 3461 c.stmt.Close() 3462 c.stmt = nil 3463 } 3464 if c.tx != nil { 3465 c.tx.Rollback() 3466 c.tx = nil 3467 } 3468 c.db = nil 3469 } 3470 3471 func (c *concurrentTxStmtExecTest) test(t testing.TB) error { 3472 _, err := c.stmt.Exec(3, chrisBirthday) 3473 if err != nil { 3474 t.Errorf("error on exec: %v", err) 3475 return err 3476 } 3477 return nil 3478 } 3479 3480 type concurrentRandomTest struct { 3481 tests []concurrentTest 3482 } 3483 3484 func (c *concurrentRandomTest) init(t testing.TB, db *DB) { 3485 c.tests = []concurrentTest{ 3486 new(concurrentDBQueryTest), 3487 new(concurrentDBExecTest), 3488 new(concurrentStmtQueryTest), 3489 new(concurrentStmtExecTest), 3490 new(concurrentTxQueryTest), 3491 new(concurrentTxExecTest), 3492 new(concurrentTxStmtQueryTest), 3493 new(concurrentTxStmtExecTest), 3494 } 3495 for _, ct := range c.tests { 3496 ct.init(t, db) 3497 } 3498 } 3499 3500 func (c *concurrentRandomTest) finish(t testing.TB) { 3501 for _, ct := range c.tests { 3502 ct.finish(t) 3503 } 3504 } 3505 3506 func (c *concurrentRandomTest) test(t testing.TB) error { 3507 ct := c.tests[rand.Intn(len(c.tests))] 3508 return ct.test(t) 3509 } 3510 3511 func doConcurrentTest(t testing.TB, ct concurrentTest) { 3512 maxProcs, numReqs := 1, 500 3513 if testing.Short() { 3514 maxProcs, numReqs = 4, 50 3515 } 3516 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 3517 3518 db := newTestDB(t, "people") 3519 defer closeDB(t, db) 3520 3521 ct.init(t, db) 3522 defer ct.finish(t) 3523 3524 var wg sync.WaitGroup 3525 wg.Add(numReqs) 3526 3527 reqs := make(chan bool) 3528 defer close(reqs) 3529 3530 for i := 0; i < maxProcs*2; i++ { 3531 go func() { 3532 for range reqs { 3533 err := ct.test(t) 3534 if err != nil { 3535 wg.Done() 3536 continue 3537 } 3538 wg.Done() 3539 } 3540 }() 3541 } 3542 3543 for i := 0; i < numReqs; i++ { 3544 reqs <- true 3545 } 3546 3547 wg.Wait() 3548 } 3549 3550 func TestIssue6081(t *testing.T) { 3551 db := newTestDB(t, "people") 3552 defer closeDB(t, db) 3553 3554 drv := db.Driver().(*fakeDriver) 3555 drv.mu.Lock() 3556 opens0 := drv.openCount 3557 closes0 := drv.closeCount 3558 drv.mu.Unlock() 3559 3560 stmt, err := db.Prepare("SELECT|people|name|") 3561 if err != nil { 3562 t.Fatal(err) 3563 } 3564 setRowsCloseHook(func(rows *Rows, err *error) { 3565 *err = driver.ErrBadConn 3566 }) 3567 defer setRowsCloseHook(nil) 3568 for i := 0; i < 10; i++ { 3569 rows, err := stmt.Query() 3570 if err != nil { 3571 t.Fatal(err) 3572 } 3573 rows.Close() 3574 } 3575 if n := len(stmt.css); n > 1 { 3576 t.Errorf("len(css slice) = %d; want <= 1", n) 3577 } 3578 stmt.Close() 3579 if n := len(stmt.css); n != 0 { 3580 t.Errorf("len(css slice) after Close = %d; want 0", n) 3581 } 3582 3583 drv.mu.Lock() 3584 opens := drv.openCount - opens0 3585 closes := drv.closeCount - closes0 3586 drv.mu.Unlock() 3587 if opens < 9 { 3588 t.Errorf("opens = %d; want >= 9", opens) 3589 } 3590 if closes < 9 { 3591 t.Errorf("closes = %d; want >= 9", closes) 3592 } 3593 } 3594 3595 // TestIssue18429 attempts to stress rolling back the transaction from a 3596 // context cancel while simultaneously calling Tx.Rollback. Rolling back from a 3597 // context happens concurrently so tx.rollback and tx.Commit must guard against 3598 // double entry. 3599 // 3600 // In the test, a context is canceled while the query is in process so 3601 // the internal rollback will run concurrently with the explicitly called 3602 // Tx.Rollback. 3603 // 3604 // The addition of calling rows.Next also tests 3605 // Issue 21117. 3606 func TestIssue18429(t *testing.T) { 3607 db := newTestDB(t, "people") 3608 defer closeDB(t, db) 3609 3610 ctx := context.Background() 3611 sem := make(chan bool, 20) 3612 var wg sync.WaitGroup 3613 3614 const milliWait = 30 3615 3616 for i := 0; i < 100; i++ { 3617 sem <- true 3618 wg.Add(1) 3619 go func() { 3620 defer func() { 3621 <-sem 3622 wg.Done() 3623 }() 3624 qwait := (time.Duration(rand.Intn(milliWait)) * time.Millisecond).String() 3625 3626 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond) 3627 defer cancel() 3628 3629 tx, err := db.BeginTx(ctx, nil) 3630 if err != nil { 3631 return 3632 } 3633 // This is expected to give a cancel error most, but not all the time. 3634 // Test failure will happen with a panic or other race condition being 3635 // reported. 3636 rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|") 3637 if rows != nil { 3638 var name string 3639 // Call Next to test Issue 21117 and check for races. 3640 for rows.Next() { 3641 // Scan the buffer so it is read and checked for races. 3642 rows.Scan(&name) 3643 } 3644 rows.Close() 3645 } 3646 // This call will race with the context cancel rollback to complete 3647 // if the rollback itself isn't guarded. 3648 tx.Rollback() 3649 }() 3650 } 3651 wg.Wait() 3652 } 3653 3654 // TestIssue20160 attempts to test a short context life on a stmt Query. 3655 func TestIssue20160(t *testing.T) { 3656 db := newTestDB(t, "people") 3657 defer closeDB(t, db) 3658 3659 ctx := context.Background() 3660 sem := make(chan bool, 20) 3661 var wg sync.WaitGroup 3662 3663 const milliWait = 30 3664 3665 stmt, err := db.PrepareContext(ctx, "SELECT|people|name|") 3666 if err != nil { 3667 t.Fatal(err) 3668 } 3669 defer stmt.Close() 3670 3671 for i := 0; i < 100; i++ { 3672 sem <- true 3673 wg.Add(1) 3674 go func() { 3675 defer func() { 3676 <-sem 3677 wg.Done() 3678 }() 3679 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond) 3680 defer cancel() 3681 3682 // This is expected to give a cancel error most, but not all the time. 3683 // Test failure will happen with a panic or other race condition being 3684 // reported. 3685 rows, _ := stmt.QueryContext(ctx) 3686 if rows != nil { 3687 rows.Close() 3688 } 3689 }() 3690 } 3691 wg.Wait() 3692 } 3693 3694 // TestIssue18719 closes the context right before use. The sql.driverConn 3695 // will nil out the ci on close in a lock, but if another process uses it right after 3696 // it will panic with on the nil ref. 3697 // 3698 // See https://golang.org/cl/35550 . 3699 func TestIssue18719(t *testing.T) { 3700 db := newTestDB(t, "people") 3701 defer closeDB(t, db) 3702 3703 ctx, cancel := context.WithCancel(context.Background()) 3704 defer cancel() 3705 3706 tx, err := db.BeginTx(ctx, nil) 3707 if err != nil { 3708 t.Fatal(err) 3709 } 3710 3711 hookTxGrabConn = func() { 3712 cancel() 3713 3714 // Wait for the context to cancel and tx to rollback. 3715 for tx.isDone() == false { 3716 time.Sleep(3 * time.Millisecond) 3717 } 3718 } 3719 defer func() { hookTxGrabConn = nil }() 3720 3721 // This call will grab the connection and cancel the context 3722 // after it has done so. Code after must deal with the canceled state. 3723 _, err = tx.QueryContext(ctx, "SELECT|people|name|") 3724 if err != nil { 3725 t.Fatalf("expected error %v but got %v", nil, err) 3726 } 3727 3728 // Rows may be ignored because it will be closed when the context is canceled. 3729 3730 // Do not explicitly rollback. The rollback will happen from the 3731 // canceled context. 3732 3733 cancel() 3734 } 3735 3736 func TestIssue20647(t *testing.T) { 3737 db := newTestDB(t, "people") 3738 defer closeDB(t, db) 3739 3740 ctx, cancel := context.WithCancel(context.Background()) 3741 defer cancel() 3742 3743 conn, err := db.Conn(ctx) 3744 if err != nil { 3745 t.Fatal(err) 3746 } 3747 conn.dc.ci.(*fakeConn).skipDirtySession = true 3748 defer conn.Close() 3749 3750 stmt, err := conn.PrepareContext(ctx, "SELECT|people|name|") 3751 if err != nil { 3752 t.Fatal(err) 3753 } 3754 defer stmt.Close() 3755 3756 rows1, err := stmt.QueryContext(ctx) 3757 if err != nil { 3758 t.Fatal("rows1", err) 3759 } 3760 defer rows1.Close() 3761 3762 rows2, err := stmt.QueryContext(ctx) 3763 if err != nil { 3764 t.Fatal("rows2", err) 3765 } 3766 defer rows2.Close() 3767 3768 if rows1.dc != rows2.dc { 3769 t.Fatal("stmt prepared on Conn does not use same connection") 3770 } 3771 } 3772 3773 func TestConcurrency(t *testing.T) { 3774 list := []struct { 3775 name string 3776 ct concurrentTest 3777 }{ 3778 {"Query", new(concurrentDBQueryTest)}, 3779 {"Exec", new(concurrentDBExecTest)}, 3780 {"StmtQuery", new(concurrentStmtQueryTest)}, 3781 {"StmtExec", new(concurrentStmtExecTest)}, 3782 {"TxQuery", new(concurrentTxQueryTest)}, 3783 {"TxExec", new(concurrentTxExecTest)}, 3784 {"TxStmtQuery", new(concurrentTxStmtQueryTest)}, 3785 {"TxStmtExec", new(concurrentTxStmtExecTest)}, 3786 {"Random", new(concurrentRandomTest)}, 3787 } 3788 for _, item := range list { 3789 t.Run(item.name, func(t *testing.T) { 3790 doConcurrentTest(t, item.ct) 3791 }) 3792 } 3793 } 3794 3795 func TestConnectionLeak(t *testing.T) { 3796 db := newTestDB(t, "people") 3797 defer closeDB(t, db) 3798 // Start by opening defaultMaxIdleConns 3799 rows := make([]*Rows, defaultMaxIdleConns) 3800 // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open 3801 // a new connection and we can fill the idle queue with the released 3802 // connections. 3803 db.SetMaxOpenConns(len(rows) + 1) 3804 for ii := range rows { 3805 r, err := db.Query("SELECT|people|name|") 3806 if err != nil { 3807 t.Fatal(err) 3808 } 3809 r.Next() 3810 if err := r.Err(); err != nil { 3811 t.Fatal(err) 3812 } 3813 rows[ii] = r 3814 } 3815 // Now we have defaultMaxIdleConns busy connections. Open 3816 // a new one, but wait until the busy connections are released 3817 // before returning control to DB. 3818 drv := db.Driver().(*fakeDriver) 3819 drv.waitCh = make(chan struct{}, 1) 3820 drv.waitingCh = make(chan struct{}, 1) 3821 var wg sync.WaitGroup 3822 wg.Add(1) 3823 go func() { 3824 r, err := db.Query("SELECT|people|name|") 3825 if err != nil { 3826 t.Error(err) 3827 return 3828 } 3829 r.Close() 3830 wg.Done() 3831 }() 3832 // Wait until the goroutine we've just created has started waiting. 3833 <-drv.waitingCh 3834 // Now close the busy connections. This provides a connection for 3835 // the blocked goroutine and then fills up the idle queue. 3836 for _, v := range rows { 3837 v.Close() 3838 } 3839 // At this point we give the new connection to DB. This connection is 3840 // now useless, since the idle queue is full and there are no pending 3841 // requests. DB should deal with this situation without leaking the 3842 // connection. 3843 drv.waitCh <- struct{}{} 3844 wg.Wait() 3845 } 3846 3847 func TestStatsMaxIdleClosedZero(t *testing.T) { 3848 db := newTestDB(t, "people") 3849 defer closeDB(t, db) 3850 3851 db.SetMaxOpenConns(1) 3852 db.SetMaxIdleConns(1) 3853 db.SetConnMaxLifetime(0) 3854 3855 preMaxIdleClosed := db.Stats().MaxIdleClosed 3856 3857 for i := 0; i < 10; i++ { 3858 rows, err := db.Query("SELECT|people|name|") 3859 if err != nil { 3860 t.Fatal(err) 3861 } 3862 rows.Close() 3863 } 3864 3865 st := db.Stats() 3866 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed 3867 t.Logf("MaxIdleClosed: %d", maxIdleClosed) 3868 if maxIdleClosed != 0 { 3869 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed) 3870 } 3871 } 3872 3873 func TestStatsMaxIdleClosedTen(t *testing.T) { 3874 db := newTestDB(t, "people") 3875 defer closeDB(t, db) 3876 3877 db.SetMaxOpenConns(1) 3878 db.SetMaxIdleConns(0) 3879 db.SetConnMaxLifetime(0) 3880 3881 preMaxIdleClosed := db.Stats().MaxIdleClosed 3882 3883 for i := 0; i < 10; i++ { 3884 rows, err := db.Query("SELECT|people|name|") 3885 if err != nil { 3886 t.Fatal(err) 3887 } 3888 rows.Close() 3889 } 3890 3891 st := db.Stats() 3892 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed 3893 t.Logf("MaxIdleClosed: %d", maxIdleClosed) 3894 if maxIdleClosed != 10 { 3895 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed) 3896 } 3897 } 3898 3899 func TestMaxIdleTime(t *testing.T) { 3900 list := []struct { 3901 wantMaxIdleTime time.Duration 3902 wantIdleClosed int64 3903 timeOffset time.Duration 3904 }{ 3905 {time.Nanosecond, 1, 10 * time.Millisecond}, 3906 {time.Hour, 0, 10 * time.Millisecond}, 3907 } 3908 baseTime := time.Unix(0, 0) 3909 defer func() { 3910 nowFunc = time.Now 3911 }() 3912 for _, item := range list { 3913 nowFunc = func() time.Time { 3914 return baseTime 3915 } 3916 t.Run(fmt.Sprintf("%v", item.wantMaxIdleTime), func(t *testing.T) { 3917 db := newTestDB(t, "people") 3918 defer closeDB(t, db) 3919 3920 db.SetMaxOpenConns(1) 3921 db.SetMaxIdleConns(1) 3922 db.SetConnMaxIdleTime(item.wantMaxIdleTime) 3923 db.SetConnMaxLifetime(0) 3924 3925 preMaxIdleClosed := db.Stats().MaxIdleTimeClosed 3926 3927 if err := db.Ping(); err != nil { 3928 t.Fatal(err) 3929 } 3930 3931 nowFunc = func() time.Time { 3932 return baseTime.Add(item.timeOffset) 3933 } 3934 3935 db.mu.Lock() 3936 closing := db.connectionCleanerRunLocked() 3937 db.mu.Unlock() 3938 for _, c := range closing { 3939 c.Close() 3940 } 3941 if g, w := int64(len(closing)), item.wantIdleClosed; g != w { 3942 t.Errorf("got: %d; want %d closed conns", g, w) 3943 } 3944 3945 st := db.Stats() 3946 maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed 3947 if g, w := maxIdleClosed, item.wantIdleClosed; g != w { 3948 t.Errorf(" got: %d; want %d max idle closed conns", g, w) 3949 } 3950 }) 3951 } 3952 } 3953 3954 type nvcDriver struct { 3955 fakeDriver 3956 skipNamedValueCheck bool 3957 } 3958 3959 func (d *nvcDriver) Open(dsn string) (driver.Conn, error) { 3960 c, err := d.fakeDriver.Open(dsn) 3961 fc := c.(*fakeConn) 3962 fc.db.allowAny = true 3963 return &nvcConn{fc, d.skipNamedValueCheck}, err 3964 } 3965 3966 type nvcConn struct { 3967 *fakeConn 3968 skipNamedValueCheck bool 3969 } 3970 3971 type decimalInt struct { 3972 value int 3973 } 3974 3975 type doNotInclude struct{} 3976 3977 var _ driver.NamedValueChecker = &nvcConn{} 3978 3979 func (c *nvcConn) CheckNamedValue(nv *driver.NamedValue) error { 3980 if c.skipNamedValueCheck { 3981 return driver.ErrSkip 3982 } 3983 switch v := nv.Value.(type) { 3984 default: 3985 return driver.ErrSkip 3986 case Out: 3987 switch ov := v.Dest.(type) { 3988 default: 3989 return errors.New("unknown NameValueCheck OUTPUT type") 3990 case *string: 3991 *ov = "from-server" 3992 nv.Value = "OUT:*string" 3993 } 3994 return nil 3995 case decimalInt, []int64: 3996 return nil 3997 case doNotInclude: 3998 return driver.ErrRemoveArgument 3999 } 4000 } 4001 4002 func TestNamedValueChecker(t *testing.T) { 4003 Register("NamedValueCheck", &nvcDriver{}) 4004 db, err := Open("NamedValueCheck", "") 4005 if err != nil { 4006 t.Fatal(err) 4007 } 4008 defer db.Close() 4009 4010 ctx, cancel := context.WithCancel(context.Background()) 4011 defer cancel() 4012 4013 _, err = db.ExecContext(ctx, "WIPE") 4014 if err != nil { 4015 t.Fatal("exec wipe", err) 4016 } 4017 4018 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any") 4019 if err != nil { 4020 t.Fatal("exec create", err) 4021 } 4022 4023 o1 := "" 4024 _, 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{}) 4025 if err != nil { 4026 t.Fatal("exec insert", err) 4027 } 4028 var ( 4029 str1 string 4030 dec1 decimalInt 4031 arr1 []int64 4032 ) 4033 err = db.QueryRowContext(ctx, "SELECT|keys|dec1,str1,array1|").Scan(&dec1, &str1, &arr1) 4034 if err != nil { 4035 t.Fatal("select", err) 4036 } 4037 4038 list := []struct{ got, want interface{} }{ 4039 {o1, "from-server"}, 4040 {dec1, decimalInt{123}}, 4041 {str1, "hello"}, 4042 {arr1, []int64{42, 128, 707}}, 4043 } 4044 4045 for index, item := range list { 4046 if !reflect.DeepEqual(item.got, item.want) { 4047 t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index) 4048 } 4049 } 4050 } 4051 4052 func TestNamedValueCheckerSkip(t *testing.T) { 4053 Register("NamedValueCheckSkip", &nvcDriver{skipNamedValueCheck: true}) 4054 db, err := Open("NamedValueCheckSkip", "") 4055 if err != nil { 4056 t.Fatal(err) 4057 } 4058 defer db.Close() 4059 4060 ctx, cancel := context.WithCancel(context.Background()) 4061 defer cancel() 4062 4063 _, err = db.ExecContext(ctx, "WIPE") 4064 if err != nil { 4065 t.Fatal("exec wipe", err) 4066 } 4067 4068 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any") 4069 if err != nil { 4070 t.Fatal("exec create", err) 4071 } 4072 4073 _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A", Named("A", decimalInt{123})) 4074 if err == nil { 4075 t.Fatalf("expected error with bad argument, got %v", err) 4076 } 4077 } 4078 4079 func TestOpenConnector(t *testing.T) { 4080 Register("testctx", &fakeDriverCtx{}) 4081 db, err := Open("testctx", "people") 4082 if err != nil { 4083 t.Fatal(err) 4084 } 4085 defer db.Close() 4086 4087 c, ok := db.connector.(*fakeConnector) 4088 if !ok { 4089 t.Fatal("not using *fakeConnector") 4090 } 4091 4092 if err := db.Close(); err != nil { 4093 t.Fatal(err) 4094 } 4095 4096 if !c.closed { 4097 t.Fatal("connector is not closed") 4098 } 4099 } 4100 4101 type ctxOnlyDriver struct { 4102 fakeDriver 4103 } 4104 4105 func (d *ctxOnlyDriver) Open(dsn string) (driver.Conn, error) { 4106 conn, err := d.fakeDriver.Open(dsn) 4107 if err != nil { 4108 return nil, err 4109 } 4110 return &ctxOnlyConn{fc: conn.(*fakeConn)}, nil 4111 } 4112 4113 var ( 4114 _ driver.Conn = &ctxOnlyConn{} 4115 _ driver.QueryerContext = &ctxOnlyConn{} 4116 _ driver.ExecerContext = &ctxOnlyConn{} 4117 ) 4118 4119 type ctxOnlyConn struct { 4120 fc *fakeConn 4121 4122 queryCtxCalled bool 4123 execCtxCalled bool 4124 } 4125 4126 func (c *ctxOnlyConn) Begin() (driver.Tx, error) { 4127 return c.fc.Begin() 4128 } 4129 4130 func (c *ctxOnlyConn) Close() error { 4131 return c.fc.Close() 4132 } 4133 4134 // Prepare is still part of the Conn interface, so while it isn't used 4135 // must be defined for compatibility. 4136 func (c *ctxOnlyConn) Prepare(q string) (driver.Stmt, error) { 4137 panic("not used") 4138 } 4139 4140 func (c *ctxOnlyConn) PrepareContext(ctx context.Context, q string) (driver.Stmt, error) { 4141 return c.fc.PrepareContext(ctx, q) 4142 } 4143 4144 func (c *ctxOnlyConn) QueryContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Rows, error) { 4145 c.queryCtxCalled = true 4146 return c.fc.QueryContext(ctx, q, args) 4147 } 4148 4149 func (c *ctxOnlyConn) ExecContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Result, error) { 4150 c.execCtxCalled = true 4151 return c.fc.ExecContext(ctx, q, args) 4152 } 4153 4154 // TestQueryExecContextOnly ensures drivers only need to implement QueryContext 4155 // and ExecContext methods. 4156 func TestQueryExecContextOnly(t *testing.T) { 4157 // Ensure connection does not implement non-context interfaces. 4158 var connType driver.Conn = &ctxOnlyConn{} 4159 if _, ok := connType.(driver.Execer); ok { 4160 t.Fatalf("%T must not implement driver.Execer", connType) 4161 } 4162 if _, ok := connType.(driver.Queryer); ok { 4163 t.Fatalf("%T must not implement driver.Queryer", connType) 4164 } 4165 4166 Register("ContextOnly", &ctxOnlyDriver{}) 4167 db, err := Open("ContextOnly", "") 4168 if err != nil { 4169 t.Fatal(err) 4170 } 4171 defer db.Close() 4172 4173 ctx, cancel := context.WithCancel(context.Background()) 4174 defer cancel() 4175 4176 conn, err := db.Conn(ctx) 4177 if err != nil { 4178 t.Fatal("db.Conn", err) 4179 } 4180 defer conn.Close() 4181 coc := conn.dc.ci.(*ctxOnlyConn) 4182 coc.fc.skipDirtySession = true 4183 4184 _, err = conn.ExecContext(ctx, "WIPE") 4185 if err != nil { 4186 t.Fatal("exec wipe", err) 4187 } 4188 4189 _, err = conn.ExecContext(ctx, "CREATE|keys|v1=string") 4190 if err != nil { 4191 t.Fatal("exec create", err) 4192 } 4193 expectedValue := "value1" 4194 _, err = conn.ExecContext(ctx, "INSERT|keys|v1=?", expectedValue) 4195 if err != nil { 4196 t.Fatal("exec insert", err) 4197 } 4198 rows, err := conn.QueryContext(ctx, "SELECT|keys|v1|") 4199 if err != nil { 4200 t.Fatal("query select", err) 4201 } 4202 v1 := "" 4203 for rows.Next() { 4204 err = rows.Scan(&v1) 4205 if err != nil { 4206 t.Fatal("rows scan", err) 4207 } 4208 } 4209 rows.Close() 4210 4211 if v1 != expectedValue { 4212 t.Fatalf("expected %q, got %q", expectedValue, v1) 4213 } 4214 4215 if !coc.execCtxCalled { 4216 t.Error("ExecContext not called") 4217 } 4218 if !coc.queryCtxCalled { 4219 t.Error("QueryContext not called") 4220 } 4221 } 4222 4223 type alwaysErrScanner struct{} 4224 4225 var errTestScanWrap = errors.New("errTestScanWrap") 4226 4227 func (alwaysErrScanner) Scan(interface{}) error { 4228 return errTestScanWrap 4229 } 4230 4231 // Issue 38099: Ensure that Rows.Scan properly wraps underlying errors. 4232 func TestRowsScanProperlyWrapsErrors(t *testing.T) { 4233 db := newTestDB(t, "people") 4234 defer closeDB(t, db) 4235 4236 rows, err := db.Query("SELECT|people|age|") 4237 if err != nil { 4238 t.Fatalf("Query: %v", err) 4239 } 4240 4241 var res alwaysErrScanner 4242 4243 for rows.Next() { 4244 err = rows.Scan(&res) 4245 if err == nil { 4246 t.Fatal("expecting back an error") 4247 } 4248 if !errors.Is(err, errTestScanWrap) { 4249 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errTestScanWrap) 4250 } 4251 // Ensure that error substring matching still correctly works. 4252 if !strings.Contains(err.Error(), errTestScanWrap.Error()) { 4253 t.Fatalf("Error %v does not contain %v", err, errTestScanWrap) 4254 } 4255 } 4256 } 4257 4258 // badConn implements a bad driver.Conn, for TestBadDriver. 4259 // The Exec method panics. 4260 type badConn struct{} 4261 4262 func (bc badConn) Prepare(query string) (driver.Stmt, error) { 4263 return nil, errors.New("badConn Prepare") 4264 } 4265 4266 func (bc badConn) Close() error { 4267 return nil 4268 } 4269 4270 func (bc badConn) Begin() (driver.Tx, error) { 4271 return nil, errors.New("badConn Begin") 4272 } 4273 4274 func (bc badConn) Exec(query string, args []driver.Value) (driver.Result, error) { 4275 panic("badConn.Exec") 4276 } 4277 4278 // badDriver is a driver.Driver that uses badConn. 4279 type badDriver struct{} 4280 4281 func (bd badDriver) Open(name string) (driver.Conn, error) { 4282 return badConn{}, nil 4283 } 4284 4285 // Issue 15901. 4286 func TestBadDriver(t *testing.T) { 4287 Register("bad", badDriver{}) 4288 db, err := Open("bad", "ignored") 4289 if err != nil { 4290 t.Fatal(err) 4291 } 4292 defer func() { 4293 if r := recover(); r == nil { 4294 t.Error("expected panic") 4295 } else { 4296 if want := "badConn.Exec"; r.(string) != want { 4297 t.Errorf("panic was %v, expected %v", r, want) 4298 } 4299 } 4300 }() 4301 defer db.Close() 4302 db.Exec("ignored") 4303 } 4304 4305 type pingDriver struct { 4306 fails bool 4307 } 4308 4309 type pingConn struct { 4310 badConn 4311 driver *pingDriver 4312 } 4313 4314 var pingError = errors.New("Ping failed") 4315 4316 func (pc pingConn) Ping(ctx context.Context) error { 4317 if pc.driver.fails { 4318 return pingError 4319 } 4320 return nil 4321 } 4322 4323 var _ driver.Pinger = pingConn{} 4324 4325 func (pd *pingDriver) Open(name string) (driver.Conn, error) { 4326 return pingConn{driver: pd}, nil 4327 } 4328 4329 func TestPing(t *testing.T) { 4330 driver := &pingDriver{} 4331 Register("ping", driver) 4332 4333 db, err := Open("ping", "ignored") 4334 if err != nil { 4335 t.Fatal(err) 4336 } 4337 4338 if err := db.Ping(); err != nil { 4339 t.Errorf("err was %#v, expected nil", err) 4340 return 4341 } 4342 4343 driver.fails = true 4344 if err := db.Ping(); err != pingError { 4345 t.Errorf("err was %#v, expected pingError", err) 4346 } 4347 } 4348 4349 // Issue 18101. 4350 func TestTypedString(t *testing.T) { 4351 db := newTestDB(t, "people") 4352 defer closeDB(t, db) 4353 4354 type Str string 4355 var scanned Str 4356 4357 err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned) 4358 if err != nil { 4359 t.Fatal(err) 4360 } 4361 expected := Str("Alice") 4362 if scanned != expected { 4363 t.Errorf("expected %+v, got %+v", expected, scanned) 4364 } 4365 } 4366 4367 func BenchmarkConcurrentDBExec(b *testing.B) { 4368 b.ReportAllocs() 4369 ct := new(concurrentDBExecTest) 4370 for i := 0; i < b.N; i++ { 4371 doConcurrentTest(b, ct) 4372 } 4373 } 4374 4375 func BenchmarkConcurrentStmtQuery(b *testing.B) { 4376 b.ReportAllocs() 4377 ct := new(concurrentStmtQueryTest) 4378 for i := 0; i < b.N; i++ { 4379 doConcurrentTest(b, ct) 4380 } 4381 } 4382 4383 func BenchmarkConcurrentStmtExec(b *testing.B) { 4384 b.ReportAllocs() 4385 ct := new(concurrentStmtExecTest) 4386 for i := 0; i < b.N; i++ { 4387 doConcurrentTest(b, ct) 4388 } 4389 } 4390 4391 func BenchmarkConcurrentTxQuery(b *testing.B) { 4392 b.ReportAllocs() 4393 ct := new(concurrentTxQueryTest) 4394 for i := 0; i < b.N; i++ { 4395 doConcurrentTest(b, ct) 4396 } 4397 } 4398 4399 func BenchmarkConcurrentTxExec(b *testing.B) { 4400 b.ReportAllocs() 4401 ct := new(concurrentTxExecTest) 4402 for i := 0; i < b.N; i++ { 4403 doConcurrentTest(b, ct) 4404 } 4405 } 4406 4407 func BenchmarkConcurrentTxStmtQuery(b *testing.B) { 4408 b.ReportAllocs() 4409 ct := new(concurrentTxStmtQueryTest) 4410 for i := 0; i < b.N; i++ { 4411 doConcurrentTest(b, ct) 4412 } 4413 } 4414 4415 func BenchmarkConcurrentTxStmtExec(b *testing.B) { 4416 b.ReportAllocs() 4417 ct := new(concurrentTxStmtExecTest) 4418 for i := 0; i < b.N; i++ { 4419 doConcurrentTest(b, ct) 4420 } 4421 } 4422 4423 func BenchmarkConcurrentRandom(b *testing.B) { 4424 b.ReportAllocs() 4425 ct := new(concurrentRandomTest) 4426 for i := 0; i < b.N; i++ { 4427 doConcurrentTest(b, ct) 4428 } 4429 } 4430 4431 func BenchmarkManyConcurrentQueries(b *testing.B) { 4432 b.ReportAllocs() 4433 // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required. 4434 const parallelism = 16 4435 4436 db := newTestDB(b, "magicquery") 4437 defer closeDB(b, db) 4438 db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism) 4439 4440 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 4441 if err != nil { 4442 b.Fatal(err) 4443 } 4444 defer stmt.Close() 4445 4446 b.SetParallelism(parallelism) 4447 b.RunParallel(func(pb *testing.PB) { 4448 for pb.Next() { 4449 rows, err := stmt.Query("sleep", 1) 4450 if err != nil { 4451 b.Error(err) 4452 return 4453 } 4454 rows.Close() 4455 } 4456 }) 4457 }