github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/database/sql/sql_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sql 6 7 import ( 8 "database/sql/driver" 9 "errors" 10 "fmt" 11 "math/rand" 12 "reflect" 13 "runtime" 14 "strings" 15 "sync" 16 "testing" 17 "time" 18 ) 19 20 func init() { 21 type dbConn struct { 22 db *DB 23 c *driverConn 24 } 25 freedFrom := make(map[dbConn]string) 26 putConnHook = func(db *DB, c *driverConn) { 27 if c.listElem != nil { 28 // print before panic, as panic may get lost due to conflicting panic 29 // (all goroutines asleep) elsewhere, since we might not unlock 30 // the mutex in freeConn here. 31 println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack()) 32 panic("double free of conn.") 33 } 34 freedFrom[dbConn{db, c}] = stack() 35 } 36 } 37 38 const fakeDBName = "foo" 39 40 var chrisBirthday = time.Unix(123456789, 0) 41 42 func newTestDB(t testing.TB, name string) *DB { 43 db, err := Open("test", fakeDBName) 44 if err != nil { 45 t.Fatalf("Open: %v", err) 46 } 47 if _, err := db.Exec("WIPE"); err != nil { 48 t.Fatalf("exec wipe: %v", err) 49 } 50 if name == "people" { 51 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime") 52 exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1) 53 exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2) 54 exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 55 } 56 if name == "magicquery" { 57 // Magic table name and column, known by fakedb_test.go. 58 exec(t, db, "CREATE|magicquery|op=string,millis=int32") 59 exec(t, db, "INSERT|magicquery|op=sleep,millis=10") 60 } 61 return db 62 } 63 64 func exec(t testing.TB, db *DB, query string, args ...interface{}) { 65 _, err := db.Exec(query, args...) 66 if err != nil { 67 t.Fatalf("Exec of %q: %v", query, err) 68 } 69 } 70 71 func closeDB(t testing.TB, db *DB) { 72 if e := recover(); e != nil { 73 fmt.Printf("Panic: %v\n", e) 74 panic(e) 75 } 76 defer setHookpostCloseConn(nil) 77 setHookpostCloseConn(func(_ *fakeConn, err error) { 78 if err != nil { 79 t.Errorf("Error closing fakeConn: %v", err) 80 } 81 }) 82 for node, i := db.freeConn.Front(), 0; node != nil; node, i = node.Next(), i+1 { 83 dc := node.Value.(*driverConn) 84 if n := len(dc.openStmt); n > 0 { 85 // Just a sanity check. This is legal in 86 // general, but if we make the tests clean up 87 // their statements first, then we can safely 88 // verify this is always zero here, and any 89 // other value is a leak. 90 t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, db.freeConn.Len(), n) 91 } 92 } 93 err := db.Close() 94 if err != nil { 95 t.Fatalf("error closing DB: %v", err) 96 } 97 } 98 99 // numPrepares assumes that db has exactly 1 idle conn and returns 100 // its count of calls to Prepare 101 func numPrepares(t *testing.T, db *DB) int { 102 if n := db.freeConn.Len(); n != 1 { 103 t.Fatalf("free conns = %d; want 1", n) 104 } 105 return (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn).numPrepare 106 } 107 108 func (db *DB) numDeps() int { 109 db.mu.Lock() 110 defer db.mu.Unlock() 111 return len(db.dep) 112 } 113 114 // Dependencies are closed via a goroutine, so this polls waiting for 115 // numDeps to fall to want, waiting up to d. 116 func (db *DB) numDepsPollUntil(want int, d time.Duration) int { 117 deadline := time.Now().Add(d) 118 for { 119 n := db.numDeps() 120 if n <= want || time.Now().After(deadline) { 121 return n 122 } 123 time.Sleep(50 * time.Millisecond) 124 } 125 } 126 127 func (db *DB) numFreeConns() int { 128 db.mu.Lock() 129 defer db.mu.Unlock() 130 return db.freeConn.Len() 131 } 132 133 func (db *DB) dumpDeps(t *testing.T) { 134 for fc := range db.dep { 135 db.dumpDep(t, 0, fc, map[finalCloser]bool{}) 136 } 137 } 138 139 func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) { 140 seen[dep] = true 141 indent := strings.Repeat(" ", depth) 142 ds := db.dep[dep] 143 for k := range ds { 144 t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k) 145 if fc, ok := k.(finalCloser); ok { 146 if !seen[fc] { 147 db.dumpDep(t, depth+1, fc, seen) 148 } 149 } 150 } 151 } 152 153 func TestQuery(t *testing.T) { 154 db := newTestDB(t, "people") 155 defer closeDB(t, db) 156 prepares0 := numPrepares(t, db) 157 rows, err := db.Query("SELECT|people|age,name|") 158 if err != nil { 159 t.Fatalf("Query: %v", err) 160 } 161 type row struct { 162 age int 163 name string 164 } 165 got := []row{} 166 for rows.Next() { 167 var r row 168 err = rows.Scan(&r.age, &r.name) 169 if err != nil { 170 t.Fatalf("Scan: %v", err) 171 } 172 got = append(got, r) 173 } 174 err = rows.Err() 175 if err != nil { 176 t.Fatalf("Err: %v", err) 177 } 178 want := []row{ 179 {age: 1, name: "Alice"}, 180 {age: 2, name: "Bob"}, 181 {age: 3, name: "Chris"}, 182 } 183 if !reflect.DeepEqual(got, want) { 184 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 185 } 186 187 // And verify that the final rows.Next() call, which hit EOF, 188 // also closed the rows connection. 189 if n := db.numFreeConns(); n != 1 { 190 t.Fatalf("free conns after query hitting EOF = %d; want 1", n) 191 } 192 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 193 t.Errorf("executed %d Prepare statements; want 1", prepares) 194 } 195 } 196 197 func TestByteOwnership(t *testing.T) { 198 db := newTestDB(t, "people") 199 defer closeDB(t, db) 200 rows, err := db.Query("SELECT|people|name,photo|") 201 if err != nil { 202 t.Fatalf("Query: %v", err) 203 } 204 type row struct { 205 name []byte 206 photo RawBytes 207 } 208 got := []row{} 209 for rows.Next() { 210 var r row 211 err = rows.Scan(&r.name, &r.photo) 212 if err != nil { 213 t.Fatalf("Scan: %v", err) 214 } 215 got = append(got, r) 216 } 217 corruptMemory := []byte("\xffPHOTO") 218 want := []row{ 219 {name: []byte("Alice"), photo: corruptMemory}, 220 {name: []byte("Bob"), photo: corruptMemory}, 221 {name: []byte("Chris"), photo: corruptMemory}, 222 } 223 if !reflect.DeepEqual(got, want) { 224 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 225 } 226 227 var photo RawBytes 228 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 229 if err == nil { 230 t.Error("want error scanning into RawBytes from QueryRow") 231 } 232 } 233 234 func TestRowsColumns(t *testing.T) { 235 db := newTestDB(t, "people") 236 defer closeDB(t, db) 237 rows, err := db.Query("SELECT|people|age,name|") 238 if err != nil { 239 t.Fatalf("Query: %v", err) 240 } 241 cols, err := rows.Columns() 242 if err != nil { 243 t.Fatalf("Columns: %v", err) 244 } 245 want := []string{"age", "name"} 246 if !reflect.DeepEqual(cols, want) { 247 t.Errorf("got %#v; want %#v", cols, want) 248 } 249 } 250 251 func TestQueryRow(t *testing.T) { 252 db := newTestDB(t, "people") 253 defer closeDB(t, db) 254 var name string 255 var age int 256 var birthday time.Time 257 258 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age) 259 if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") { 260 t.Errorf("expected error from wrong number of arguments; actually got: %v", err) 261 } 262 263 err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday) 264 if err != nil || !birthday.Equal(chrisBirthday) { 265 t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday) 266 } 267 268 err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name) 269 if err != nil { 270 t.Fatalf("age QueryRow+Scan: %v", err) 271 } 272 if name != "Bob" { 273 t.Errorf("expected name Bob, got %q", name) 274 } 275 if age != 2 { 276 t.Errorf("expected age 2, got %d", age) 277 } 278 279 err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name) 280 if err != nil { 281 t.Fatalf("name QueryRow+Scan: %v", err) 282 } 283 if name != "Alice" { 284 t.Errorf("expected name Alice, got %q", name) 285 } 286 if age != 1 { 287 t.Errorf("expected age 1, got %d", age) 288 } 289 290 var photo []byte 291 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 292 if err != nil { 293 t.Fatalf("photo QueryRow+Scan: %v", err) 294 } 295 want := []byte("APHOTO") 296 if !reflect.DeepEqual(photo, want) { 297 t.Errorf("photo = %q; want %q", photo, want) 298 } 299 } 300 301 func TestStatementErrorAfterClose(t *testing.T) { 302 db := newTestDB(t, "people") 303 defer closeDB(t, db) 304 stmt, err := db.Prepare("SELECT|people|age|name=?") 305 if err != nil { 306 t.Fatalf("Prepare: %v", err) 307 } 308 err = stmt.Close() 309 if err != nil { 310 t.Fatalf("Close: %v", err) 311 } 312 var name string 313 err = stmt.QueryRow("foo").Scan(&name) 314 if err == nil { 315 t.Errorf("expected error from QueryRow.Scan after Stmt.Close") 316 } 317 } 318 319 func TestStatementQueryRow(t *testing.T) { 320 db := newTestDB(t, "people") 321 defer closeDB(t, db) 322 stmt, err := db.Prepare("SELECT|people|age|name=?") 323 if err != nil { 324 t.Fatalf("Prepare: %v", err) 325 } 326 defer stmt.Close() 327 var age int 328 for n, tt := range []struct { 329 name string 330 want int 331 }{ 332 {"Alice", 1}, 333 {"Bob", 2}, 334 {"Chris", 3}, 335 } { 336 if err := stmt.QueryRow(tt.name).Scan(&age); err != nil { 337 t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err) 338 } else if age != tt.want { 339 t.Errorf("%d: age=%d, want %d", n, age, tt.want) 340 } 341 } 342 343 } 344 345 // golang.org/issue/3734 346 func TestStatementQueryRowConcurrent(t *testing.T) { 347 db := newTestDB(t, "people") 348 defer closeDB(t, db) 349 stmt, err := db.Prepare("SELECT|people|age|name=?") 350 if err != nil { 351 t.Fatalf("Prepare: %v", err) 352 } 353 defer stmt.Close() 354 355 const n = 10 356 ch := make(chan error, n) 357 for i := 0; i < n; i++ { 358 go func() { 359 var age int 360 err := stmt.QueryRow("Alice").Scan(&age) 361 if err == nil && age != 1 { 362 err = fmt.Errorf("unexpected age %d", age) 363 } 364 ch <- err 365 }() 366 } 367 for i := 0; i < n; i++ { 368 if err := <-ch; err != nil { 369 t.Error(err) 370 } 371 } 372 } 373 374 // just a test of fakedb itself 375 func TestBogusPreboundParameters(t *testing.T) { 376 db := newTestDB(t, "foo") 377 defer closeDB(t, db) 378 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 379 _, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion") 380 if err == nil { 381 t.Fatalf("expected error") 382 } 383 if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` { 384 t.Errorf("unexpected error: %v", err) 385 } 386 } 387 388 func TestExec(t *testing.T) { 389 db := newTestDB(t, "foo") 390 defer closeDB(t, db) 391 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 392 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 393 if err != nil { 394 t.Errorf("Stmt, err = %v, %v", stmt, err) 395 } 396 defer stmt.Close() 397 398 type execTest struct { 399 args []interface{} 400 wantErr string 401 } 402 execTests := []execTest{ 403 // Okay: 404 {[]interface{}{"Brad", 31}, ""}, 405 {[]interface{}{"Brad", int64(31)}, ""}, 406 {[]interface{}{"Bob", "32"}, ""}, 407 {[]interface{}{7, 9}, ""}, 408 409 // Invalid conversions: 410 {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"}, 411 {[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"}, 412 413 // Wrong number of args: 414 {[]interface{}{}, "sql: expected 2 arguments, got 0"}, 415 {[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"}, 416 } 417 for n, et := range execTests { 418 _, err := stmt.Exec(et.args...) 419 errStr := "" 420 if err != nil { 421 errStr = err.Error() 422 } 423 if errStr != et.wantErr { 424 t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q", 425 n, et.args, errStr, et.wantErr) 426 } 427 } 428 } 429 430 func TestTxStmt(t *testing.T) { 431 db := newTestDB(t, "") 432 defer closeDB(t, db) 433 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 434 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 435 if err != nil { 436 t.Fatalf("Stmt, err = %v, %v", stmt, err) 437 } 438 defer stmt.Close() 439 tx, err := db.Begin() 440 if err != nil { 441 t.Fatalf("Begin = %v", err) 442 } 443 txs := tx.Stmt(stmt) 444 defer txs.Close() 445 _, err = txs.Exec("Bobby", 7) 446 if err != nil { 447 t.Fatalf("Exec = %v", err) 448 } 449 err = tx.Commit() 450 if err != nil { 451 t.Fatalf("Commit = %v", err) 452 } 453 } 454 455 // Issue: http://golang.org/issue/2784 456 // This test didn't fail before because we got luckly with the fakedb driver. 457 // It was failing, and now not, in github.com/bradfitz/go-sql-test 458 func TestTxQuery(t *testing.T) { 459 db := newTestDB(t, "") 460 defer closeDB(t, db) 461 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 462 exec(t, db, "INSERT|t1|name=Alice") 463 464 tx, err := db.Begin() 465 if err != nil { 466 t.Fatal(err) 467 } 468 defer tx.Rollback() 469 470 r, err := tx.Query("SELECT|t1|name|") 471 if err != nil { 472 t.Fatal(err) 473 } 474 defer r.Close() 475 476 if !r.Next() { 477 if r.Err() != nil { 478 t.Fatal(r.Err()) 479 } 480 t.Fatal("expected one row") 481 } 482 483 var x string 484 err = r.Scan(&x) 485 if err != nil { 486 t.Fatal(err) 487 } 488 } 489 490 func TestTxQueryInvalid(t *testing.T) { 491 db := newTestDB(t, "") 492 defer closeDB(t, db) 493 494 tx, err := db.Begin() 495 if err != nil { 496 t.Fatal(err) 497 } 498 defer tx.Rollback() 499 500 _, err = tx.Query("SELECT|t1|name|") 501 if err == nil { 502 t.Fatal("Error expected") 503 } 504 } 505 506 // Tests fix for issue 4433, that retries in Begin happen when 507 // conn.Begin() returns ErrBadConn 508 func TestTxErrBadConn(t *testing.T) { 509 db, err := Open("test", fakeDBName+";badConn") 510 if err != nil { 511 t.Fatalf("Open: %v", err) 512 } 513 if _, err := db.Exec("WIPE"); err != nil { 514 t.Fatalf("exec wipe: %v", err) 515 } 516 defer closeDB(t, db) 517 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 518 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 519 if err != nil { 520 t.Fatalf("Stmt, err = %v, %v", stmt, err) 521 } 522 defer stmt.Close() 523 tx, err := db.Begin() 524 if err != nil { 525 t.Fatalf("Begin = %v", err) 526 } 527 txs := tx.Stmt(stmt) 528 defer txs.Close() 529 _, err = txs.Exec("Bobby", 7) 530 if err != nil { 531 t.Fatalf("Exec = %v", err) 532 } 533 err = tx.Commit() 534 if err != nil { 535 t.Fatalf("Commit = %v", err) 536 } 537 } 538 539 // Tests fix for issue 2542, that we release a lock when querying on 540 // a closed connection. 541 func TestIssue2542Deadlock(t *testing.T) { 542 db := newTestDB(t, "people") 543 closeDB(t, db) 544 for i := 0; i < 2; i++ { 545 _, err := db.Query("SELECT|people|age,name|") 546 if err == nil { 547 t.Fatalf("expected error") 548 } 549 } 550 } 551 552 // From golang.org/issue/3865 553 func TestCloseStmtBeforeRows(t *testing.T) { 554 db := newTestDB(t, "people") 555 defer closeDB(t, db) 556 557 s, err := db.Prepare("SELECT|people|name|") 558 if err != nil { 559 t.Fatal(err) 560 } 561 562 r, err := s.Query() 563 if err != nil { 564 s.Close() 565 t.Fatal(err) 566 } 567 568 err = s.Close() 569 if err != nil { 570 t.Fatal(err) 571 } 572 573 r.Close() 574 } 575 576 // Tests fix for issue 2788, that we bind nil to a []byte if the 577 // value in the column is sql null 578 func TestNullByteSlice(t *testing.T) { 579 db := newTestDB(t, "") 580 defer closeDB(t, db) 581 exec(t, db, "CREATE|t|id=int32,name=nullstring") 582 exec(t, db, "INSERT|t|id=10,name=?", nil) 583 584 var name []byte 585 586 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 587 if err != nil { 588 t.Fatal(err) 589 } 590 if name != nil { 591 t.Fatalf("name []byte should be nil for null column value, got: %#v", name) 592 } 593 594 exec(t, db, "INSERT|t|id=11,name=?", "bob") 595 err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name) 596 if err != nil { 597 t.Fatal(err) 598 } 599 if string(name) != "bob" { 600 t.Fatalf("name []byte should be bob, got: %q", string(name)) 601 } 602 } 603 604 func TestPointerParamsAndScans(t *testing.T) { 605 db := newTestDB(t, "") 606 defer closeDB(t, db) 607 exec(t, db, "CREATE|t|id=int32,name=nullstring") 608 609 bob := "bob" 610 var name *string 611 612 name = &bob 613 exec(t, db, "INSERT|t|id=10,name=?", name) 614 name = nil 615 exec(t, db, "INSERT|t|id=20,name=?", name) 616 617 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 618 if err != nil { 619 t.Fatalf("querying id 10: %v", err) 620 } 621 if name == nil { 622 t.Errorf("id 10's name = nil; want bob") 623 } else if *name != "bob" { 624 t.Errorf("id 10's name = %q; want bob", *name) 625 } 626 627 err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name) 628 if err != nil { 629 t.Fatalf("querying id 20: %v", err) 630 } 631 if name != nil { 632 t.Errorf("id 20 = %q; want nil", *name) 633 } 634 } 635 636 func TestQueryRowClosingStmt(t *testing.T) { 637 db := newTestDB(t, "people") 638 defer closeDB(t, db) 639 var name string 640 var age int 641 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name) 642 if err != nil { 643 t.Fatal(err) 644 } 645 if db.freeConn.Len() != 1 { 646 t.Fatalf("expected 1 free conn") 647 } 648 fakeConn := (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn) 649 if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed { 650 t.Errorf("statement close mismatch: made %d, closed %d", made, closed) 651 } 652 } 653 654 type nullTestRow struct { 655 nullParam interface{} 656 notNullParam interface{} 657 scanNullVal interface{} 658 } 659 660 type nullTestSpec struct { 661 nullType string 662 notNullType string 663 rows [6]nullTestRow 664 } 665 666 func TestNullStringParam(t *testing.T) { 667 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{ 668 {NullString{"aqua", true}, "", NullString{"aqua", true}}, 669 {NullString{"brown", false}, "", NullString{"", false}}, 670 {"chartreuse", "", NullString{"chartreuse", true}}, 671 {NullString{"darkred", true}, "", NullString{"darkred", true}}, 672 {NullString{"eel", false}, "", NullString{"", false}}, 673 {"foo", NullString{"black", false}, nil}, 674 }} 675 nullTestRun(t, spec) 676 } 677 678 func TestNullInt64Param(t *testing.T) { 679 spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{ 680 {NullInt64{31, true}, 1, NullInt64{31, true}}, 681 {NullInt64{-22, false}, 1, NullInt64{0, false}}, 682 {22, 1, NullInt64{22, true}}, 683 {NullInt64{33, true}, 1, NullInt64{33, true}}, 684 {NullInt64{222, false}, 1, NullInt64{0, false}}, 685 {0, NullInt64{31, false}, nil}, 686 }} 687 nullTestRun(t, spec) 688 } 689 690 func TestNullFloat64Param(t *testing.T) { 691 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{ 692 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}}, 693 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}}, 694 {-22.9, 1, NullFloat64{-22.9, true}}, 695 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}}, 696 {NullFloat64{222, false}, 1, NullFloat64{0, false}}, 697 {10, NullFloat64{31.2, false}, nil}, 698 }} 699 nullTestRun(t, spec) 700 } 701 702 func TestNullBoolParam(t *testing.T) { 703 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{ 704 {NullBool{false, true}, true, NullBool{false, true}}, 705 {NullBool{true, false}, false, NullBool{false, false}}, 706 {true, true, NullBool{true, true}}, 707 {NullBool{true, true}, false, NullBool{true, true}}, 708 {NullBool{true, false}, true, NullBool{false, false}}, 709 {true, NullBool{true, false}, nil}, 710 }} 711 nullTestRun(t, spec) 712 } 713 714 func nullTestRun(t *testing.T, spec nullTestSpec) { 715 db := newTestDB(t, "") 716 defer closeDB(t, db) 717 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType)) 718 719 // Inserts with db.Exec: 720 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam) 721 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam) 722 723 // Inserts with a prepared statement: 724 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?") 725 if err != nil { 726 t.Fatalf("prepare: %v", err) 727 } 728 defer stmt.Close() 729 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil { 730 t.Errorf("exec insert chris: %v", err) 731 } 732 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil { 733 t.Errorf("exec insert dave: %v", err) 734 } 735 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil { 736 t.Errorf("exec insert eleanor: %v", err) 737 } 738 739 // Can't put null val into non-null col 740 if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil { 741 t.Errorf("expected error inserting nil val with prepared statement Exec") 742 } 743 744 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil) 745 if err == nil { 746 // TODO: this test fails, but it's just because 747 // fakeConn implements the optional Execer interface, 748 // so arguably this is the correct behavior. But 749 // maybe I should flesh out the fakeConn.Exec 750 // implementation so this properly fails. 751 // t.Errorf("expected error inserting nil name with Exec") 752 } 753 754 paramtype := reflect.TypeOf(spec.rows[0].nullParam) 755 bindVal := reflect.New(paramtype).Interface() 756 757 for i := 0; i < 5; i++ { 758 id := i + 1 759 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil { 760 t.Errorf("id=%d Scan: %v", id, err) 761 } 762 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface() 763 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) { 764 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal) 765 } 766 } 767 } 768 769 // golang.org/issue/4859 770 func TestQueryRowNilScanDest(t *testing.T) { 771 db := newTestDB(t, "people") 772 defer closeDB(t, db) 773 var name *string // nil pointer 774 err := db.QueryRow("SELECT|people|name|").Scan(name) 775 want := "sql: Scan error on column index 0: destination pointer is nil" 776 if err == nil || err.Error() != want { 777 t.Errorf("error = %q; want %q", err.Error(), want) 778 } 779 } 780 781 func TestIssue4902(t *testing.T) { 782 db := newTestDB(t, "people") 783 defer closeDB(t, db) 784 785 driver := db.driver.(*fakeDriver) 786 opens0 := driver.openCount 787 788 var stmt *Stmt 789 var err error 790 for i := 0; i < 10; i++ { 791 stmt, err = db.Prepare("SELECT|people|name|") 792 if err != nil { 793 t.Fatal(err) 794 } 795 err = stmt.Close() 796 if err != nil { 797 t.Fatal(err) 798 } 799 } 800 801 opens := driver.openCount - opens0 802 if opens > 1 { 803 t.Errorf("opens = %d; want <= 1", opens) 804 t.Logf("db = %#v", db) 805 t.Logf("driver = %#v", driver) 806 t.Logf("stmt = %#v", stmt) 807 } 808 } 809 810 // Issue 3857 811 // This used to deadlock. 812 func TestSimultaneousQueries(t *testing.T) { 813 db := newTestDB(t, "people") 814 defer closeDB(t, db) 815 816 tx, err := db.Begin() 817 if err != nil { 818 t.Fatal(err) 819 } 820 defer tx.Rollback() 821 822 r1, err := tx.Query("SELECT|people|name|") 823 if err != nil { 824 t.Fatal(err) 825 } 826 defer r1.Close() 827 828 r2, err := tx.Query("SELECT|people|name|") 829 if err != nil { 830 t.Fatal(err) 831 } 832 defer r2.Close() 833 } 834 835 func TestMaxIdleConns(t *testing.T) { 836 db := newTestDB(t, "people") 837 defer closeDB(t, db) 838 839 tx, err := db.Begin() 840 if err != nil { 841 t.Fatal(err) 842 } 843 tx.Commit() 844 if got := db.freeConn.Len(); got != 1 { 845 t.Errorf("freeConns = %d; want 1", got) 846 } 847 848 db.SetMaxIdleConns(0) 849 850 if got := db.freeConn.Len(); got != 0 { 851 t.Errorf("freeConns after set to zero = %d; want 0", got) 852 } 853 854 tx, err = db.Begin() 855 if err != nil { 856 t.Fatal(err) 857 } 858 tx.Commit() 859 if got := db.freeConn.Len(); got != 0 { 860 t.Errorf("freeConns = %d; want 0", got) 861 } 862 } 863 864 func TestMaxOpenConns(t *testing.T) { 865 if testing.Short() { 866 t.Skip("skipping in short mode") 867 } 868 defer setHookpostCloseConn(nil) 869 setHookpostCloseConn(func(_ *fakeConn, err error) { 870 if err != nil { 871 t.Errorf("Error closing fakeConn: %v", err) 872 } 873 }) 874 875 db := newTestDB(t, "magicquery") 876 defer closeDB(t, db) 877 878 driver := db.driver.(*fakeDriver) 879 880 // Force the number of open connections to 0 so we can get an accurate 881 // count for the test 882 db.SetMaxIdleConns(0) 883 884 if g, w := db.numFreeConns(), 0; g != w { 885 t.Errorf("free conns = %d; want %d", g, w) 886 } 887 888 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 889 t.Errorf("number of dependencies = %d; expected 0", n) 890 db.dumpDeps(t) 891 } 892 893 driver.mu.Lock() 894 opens0 := driver.openCount 895 closes0 := driver.closeCount 896 driver.mu.Unlock() 897 898 db.SetMaxIdleConns(10) 899 db.SetMaxOpenConns(10) 900 901 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 902 if err != nil { 903 t.Fatal(err) 904 } 905 906 // Start 50 parallel slow queries. 907 const ( 908 nquery = 50 909 sleepMillis = 25 910 nbatch = 2 911 ) 912 var wg sync.WaitGroup 913 for batch := 0; batch < nbatch; batch++ { 914 for i := 0; i < nquery; i++ { 915 wg.Add(1) 916 go func() { 917 defer wg.Done() 918 var op string 919 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 920 t.Error(err) 921 } 922 }() 923 } 924 // Sleep for twice the expected length of time for the 925 // batch of 50 queries above to finish before starting 926 // the next round. 927 time.Sleep(2 * sleepMillis * time.Millisecond) 928 } 929 wg.Wait() 930 931 if g, w := db.numFreeConns(), 10; g != w { 932 t.Errorf("free conns = %d; want %d", g, w) 933 } 934 935 if n := db.numDepsPollUntil(20, time.Second); n > 20 { 936 t.Errorf("number of dependencies = %d; expected <= 20", n) 937 db.dumpDeps(t) 938 } 939 940 driver.mu.Lock() 941 opens := driver.openCount - opens0 942 closes := driver.closeCount - closes0 943 driver.mu.Unlock() 944 945 if opens > 10 { 946 t.Logf("open calls = %d", opens) 947 t.Logf("close calls = %d", closes) 948 t.Errorf("db connections opened = %d; want <= 10", opens) 949 db.dumpDeps(t) 950 } 951 952 if err := stmt.Close(); err != nil { 953 t.Fatal(err) 954 } 955 956 if g, w := db.numFreeConns(), 10; g != w { 957 t.Errorf("free conns = %d; want %d", g, w) 958 } 959 960 if n := db.numDepsPollUntil(10, time.Second); n > 10 { 961 t.Errorf("number of dependencies = %d; expected <= 10", n) 962 db.dumpDeps(t) 963 } 964 965 db.SetMaxOpenConns(5) 966 967 if g, w := db.numFreeConns(), 5; g != w { 968 t.Errorf("free conns = %d; want %d", g, w) 969 } 970 971 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 972 t.Errorf("number of dependencies = %d; expected 0", n) 973 db.dumpDeps(t) 974 } 975 976 db.SetMaxOpenConns(0) 977 978 if g, w := db.numFreeConns(), 5; g != w { 979 t.Errorf("free conns = %d; want %d", g, w) 980 } 981 982 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 983 t.Errorf("number of dependencies = %d; expected 0", n) 984 db.dumpDeps(t) 985 } 986 987 db.SetMaxIdleConns(0) 988 989 if g, w := db.numFreeConns(), 0; g != w { 990 t.Errorf("free conns = %d; want %d", g, w) 991 } 992 993 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 994 t.Errorf("number of dependencies = %d; expected 0", n) 995 db.dumpDeps(t) 996 } 997 } 998 999 // golang.org/issue/5323 1000 func TestStmtCloseDeps(t *testing.T) { 1001 if testing.Short() { 1002 t.Skip("skipping in short mode") 1003 } 1004 defer setHookpostCloseConn(nil) 1005 setHookpostCloseConn(func(_ *fakeConn, err error) { 1006 if err != nil { 1007 t.Errorf("Error closing fakeConn: %v", err) 1008 } 1009 }) 1010 1011 db := newTestDB(t, "magicquery") 1012 defer closeDB(t, db) 1013 1014 driver := db.driver.(*fakeDriver) 1015 1016 driver.mu.Lock() 1017 opens0 := driver.openCount 1018 closes0 := driver.closeCount 1019 driver.mu.Unlock() 1020 openDelta0 := opens0 - closes0 1021 1022 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 1023 if err != nil { 1024 t.Fatal(err) 1025 } 1026 1027 // Start 50 parallel slow queries. 1028 const ( 1029 nquery = 50 1030 sleepMillis = 25 1031 nbatch = 2 1032 ) 1033 var wg sync.WaitGroup 1034 for batch := 0; batch < nbatch; batch++ { 1035 for i := 0; i < nquery; i++ { 1036 wg.Add(1) 1037 go func() { 1038 defer wg.Done() 1039 var op string 1040 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 1041 t.Error(err) 1042 } 1043 }() 1044 } 1045 // Sleep for twice the expected length of time for the 1046 // batch of 50 queries above to finish before starting 1047 // the next round. 1048 time.Sleep(2 * sleepMillis * time.Millisecond) 1049 } 1050 wg.Wait() 1051 1052 if g, w := db.numFreeConns(), 2; g != w { 1053 t.Errorf("free conns = %d; want %d", g, w) 1054 } 1055 1056 if n := db.numDepsPollUntil(4, time.Second); n > 4 { 1057 t.Errorf("number of dependencies = %d; expected <= 4", n) 1058 db.dumpDeps(t) 1059 } 1060 1061 driver.mu.Lock() 1062 opens := driver.openCount - opens0 1063 closes := driver.closeCount - closes0 1064 openDelta := (driver.openCount - driver.closeCount) - openDelta0 1065 driver.mu.Unlock() 1066 1067 if openDelta > 2 { 1068 t.Logf("open calls = %d", opens) 1069 t.Logf("close calls = %d", closes) 1070 t.Logf("open delta = %d", openDelta) 1071 t.Errorf("db connections opened = %d; want <= 2", openDelta) 1072 db.dumpDeps(t) 1073 } 1074 1075 if len(stmt.css) > nquery { 1076 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery) 1077 } 1078 1079 if err := stmt.Close(); err != nil { 1080 t.Fatal(err) 1081 } 1082 1083 if g, w := db.numFreeConns(), 2; g != w { 1084 t.Errorf("free conns = %d; want %d", g, w) 1085 } 1086 1087 if n := db.numDepsPollUntil(2, time.Second); n > 2 { 1088 t.Errorf("number of dependencies = %d; expected <= 2", n) 1089 db.dumpDeps(t) 1090 } 1091 1092 db.SetMaxIdleConns(0) 1093 1094 if g, w := db.numFreeConns(), 0; g != w { 1095 t.Errorf("free conns = %d; want %d", g, w) 1096 } 1097 1098 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 1099 t.Errorf("number of dependencies = %d; expected 0", n) 1100 db.dumpDeps(t) 1101 } 1102 } 1103 1104 // golang.org/issue/5046 1105 func TestCloseConnBeforeStmts(t *testing.T) { 1106 db := newTestDB(t, "people") 1107 defer closeDB(t, db) 1108 1109 defer setHookpostCloseConn(nil) 1110 setHookpostCloseConn(func(_ *fakeConn, err error) { 1111 if err != nil { 1112 t.Errorf("Error closing fakeConn: %v; from %s", err, stack()) 1113 db.dumpDeps(t) 1114 t.Errorf("DB = %#v", db) 1115 } 1116 }) 1117 1118 stmt, err := db.Prepare("SELECT|people|name|") 1119 if err != nil { 1120 t.Fatal(err) 1121 } 1122 1123 if db.freeConn.Len() != 1 { 1124 t.Fatalf("expected 1 freeConn; got %d", db.freeConn.Len()) 1125 } 1126 dc := db.freeConn.Front().Value.(*driverConn) 1127 if dc.closed { 1128 t.Errorf("conn shouldn't be closed") 1129 } 1130 1131 if n := len(dc.openStmt); n != 1 { 1132 t.Errorf("driverConn num openStmt = %d; want 1", n) 1133 } 1134 err = db.Close() 1135 if err != nil { 1136 t.Errorf("db Close = %v", err) 1137 } 1138 if !dc.closed { 1139 t.Errorf("after db.Close, driverConn should be closed") 1140 } 1141 if n := len(dc.openStmt); n != 0 { 1142 t.Errorf("driverConn num openStmt = %d; want 0", n) 1143 } 1144 1145 err = stmt.Close() 1146 if err != nil { 1147 t.Errorf("Stmt close = %v", err) 1148 } 1149 1150 if !dc.closed { 1151 t.Errorf("conn should be closed") 1152 } 1153 if dc.ci != nil { 1154 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil") 1155 } 1156 } 1157 1158 // golang.org/issue/5283: don't release the Rows' connection in Close 1159 // before calling Stmt.Close. 1160 func TestRowsCloseOrder(t *testing.T) { 1161 db := newTestDB(t, "people") 1162 defer closeDB(t, db) 1163 1164 db.SetMaxIdleConns(0) 1165 setStrictFakeConnClose(t) 1166 defer setStrictFakeConnClose(nil) 1167 1168 rows, err := db.Query("SELECT|people|age,name|") 1169 if err != nil { 1170 t.Fatal(err) 1171 } 1172 err = rows.Close() 1173 if err != nil { 1174 t.Fatal(err) 1175 } 1176 } 1177 1178 func TestRowsImplicitClose(t *testing.T) { 1179 db := newTestDB(t, "people") 1180 defer closeDB(t, db) 1181 1182 rows, err := db.Query("SELECT|people|age,name|") 1183 if err != nil { 1184 t.Fatal(err) 1185 } 1186 1187 want, fail := 2, errors.New("fail") 1188 r := rows.rowsi.(*rowsCursor) 1189 r.errPos, r.err = want, fail 1190 1191 got := 0 1192 for rows.Next() { 1193 got++ 1194 } 1195 if got != want { 1196 t.Errorf("got %d rows, want %d", got, want) 1197 } 1198 if err := rows.Err(); err != fail { 1199 t.Errorf("got error %v, want %v", err, fail) 1200 } 1201 if !r.closed { 1202 t.Errorf("r.closed is false, want true") 1203 } 1204 } 1205 1206 func TestStmtCloseOrder(t *testing.T) { 1207 db := newTestDB(t, "people") 1208 defer closeDB(t, db) 1209 1210 db.SetMaxIdleConns(0) 1211 setStrictFakeConnClose(t) 1212 defer setStrictFakeConnClose(nil) 1213 1214 _, err := db.Query("SELECT|non_existent|name|") 1215 if err == nil { 1216 t.Fatal("Quering non-existent table should fail") 1217 } 1218 } 1219 1220 type concurrentTest interface { 1221 init(t testing.TB, db *DB) 1222 finish(t testing.TB) 1223 test(t testing.TB) error 1224 } 1225 1226 type concurrentDBQueryTest struct { 1227 db *DB 1228 } 1229 1230 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) { 1231 c.db = db 1232 } 1233 1234 func (c *concurrentDBQueryTest) finish(t testing.TB) { 1235 c.db = nil 1236 } 1237 1238 func (c *concurrentDBQueryTest) test(t testing.TB) error { 1239 rows, err := c.db.Query("SELECT|people|name|") 1240 if err != nil { 1241 t.Error(err) 1242 return err 1243 } 1244 var name string 1245 for rows.Next() { 1246 rows.Scan(&name) 1247 } 1248 rows.Close() 1249 return nil 1250 } 1251 1252 type concurrentDBExecTest struct { 1253 db *DB 1254 } 1255 1256 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) { 1257 c.db = db 1258 } 1259 1260 func (c *concurrentDBExecTest) finish(t testing.TB) { 1261 c.db = nil 1262 } 1263 1264 func (c *concurrentDBExecTest) test(t testing.TB) error { 1265 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 1266 if err != nil { 1267 t.Error(err) 1268 return err 1269 } 1270 return nil 1271 } 1272 1273 type concurrentStmtQueryTest struct { 1274 db *DB 1275 stmt *Stmt 1276 } 1277 1278 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) { 1279 c.db = db 1280 var err error 1281 c.stmt, err = db.Prepare("SELECT|people|name|") 1282 if err != nil { 1283 t.Fatal(err) 1284 } 1285 } 1286 1287 func (c *concurrentStmtQueryTest) finish(t testing.TB) { 1288 if c.stmt != nil { 1289 c.stmt.Close() 1290 c.stmt = nil 1291 } 1292 c.db = nil 1293 } 1294 1295 func (c *concurrentStmtQueryTest) test(t testing.TB) error { 1296 rows, err := c.stmt.Query() 1297 if err != nil { 1298 t.Errorf("error on query: %v", err) 1299 return err 1300 } 1301 1302 var name string 1303 for rows.Next() { 1304 rows.Scan(&name) 1305 } 1306 rows.Close() 1307 return nil 1308 } 1309 1310 type concurrentStmtExecTest struct { 1311 db *DB 1312 stmt *Stmt 1313 } 1314 1315 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) { 1316 c.db = db 1317 var err error 1318 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 1319 if err != nil { 1320 t.Fatal(err) 1321 } 1322 } 1323 1324 func (c *concurrentStmtExecTest) finish(t testing.TB) { 1325 if c.stmt != nil { 1326 c.stmt.Close() 1327 c.stmt = nil 1328 } 1329 c.db = nil 1330 } 1331 1332 func (c *concurrentStmtExecTest) test(t testing.TB) error { 1333 _, err := c.stmt.Exec(3, chrisBirthday) 1334 if err != nil { 1335 t.Errorf("error on exec: %v", err) 1336 return err 1337 } 1338 return nil 1339 } 1340 1341 type concurrentTxQueryTest struct { 1342 db *DB 1343 tx *Tx 1344 } 1345 1346 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) { 1347 c.db = db 1348 var err error 1349 c.tx, err = c.db.Begin() 1350 if err != nil { 1351 t.Fatal(err) 1352 } 1353 } 1354 1355 func (c *concurrentTxQueryTest) finish(t testing.TB) { 1356 if c.tx != nil { 1357 c.tx.Rollback() 1358 c.tx = nil 1359 } 1360 c.db = nil 1361 } 1362 1363 func (c *concurrentTxQueryTest) test(t testing.TB) error { 1364 rows, err := c.db.Query("SELECT|people|name|") 1365 if err != nil { 1366 t.Error(err) 1367 return err 1368 } 1369 var name string 1370 for rows.Next() { 1371 rows.Scan(&name) 1372 } 1373 rows.Close() 1374 return nil 1375 } 1376 1377 type concurrentTxExecTest struct { 1378 db *DB 1379 tx *Tx 1380 } 1381 1382 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) { 1383 c.db = db 1384 var err error 1385 c.tx, err = c.db.Begin() 1386 if err != nil { 1387 t.Fatal(err) 1388 } 1389 } 1390 1391 func (c *concurrentTxExecTest) finish(t testing.TB) { 1392 if c.tx != nil { 1393 c.tx.Rollback() 1394 c.tx = nil 1395 } 1396 c.db = nil 1397 } 1398 1399 func (c *concurrentTxExecTest) test(t testing.TB) error { 1400 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 1401 if err != nil { 1402 t.Error(err) 1403 return err 1404 } 1405 return nil 1406 } 1407 1408 type concurrentTxStmtQueryTest struct { 1409 db *DB 1410 tx *Tx 1411 stmt *Stmt 1412 } 1413 1414 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) { 1415 c.db = db 1416 var err error 1417 c.tx, err = c.db.Begin() 1418 if err != nil { 1419 t.Fatal(err) 1420 } 1421 c.stmt, err = c.tx.Prepare("SELECT|people|name|") 1422 if err != nil { 1423 t.Fatal(err) 1424 } 1425 } 1426 1427 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) { 1428 if c.stmt != nil { 1429 c.stmt.Close() 1430 c.stmt = nil 1431 } 1432 if c.tx != nil { 1433 c.tx.Rollback() 1434 c.tx = nil 1435 } 1436 c.db = nil 1437 } 1438 1439 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error { 1440 rows, err := c.stmt.Query() 1441 if err != nil { 1442 t.Errorf("error on query: %v", err) 1443 return err 1444 } 1445 1446 var name string 1447 for rows.Next() { 1448 rows.Scan(&name) 1449 } 1450 rows.Close() 1451 return nil 1452 } 1453 1454 type concurrentTxStmtExecTest struct { 1455 db *DB 1456 tx *Tx 1457 stmt *Stmt 1458 } 1459 1460 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) { 1461 c.db = db 1462 var err error 1463 c.tx, err = c.db.Begin() 1464 if err != nil { 1465 t.Fatal(err) 1466 } 1467 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 1468 if err != nil { 1469 t.Fatal(err) 1470 } 1471 } 1472 1473 func (c *concurrentTxStmtExecTest) finish(t testing.TB) { 1474 if c.stmt != nil { 1475 c.stmt.Close() 1476 c.stmt = nil 1477 } 1478 if c.tx != nil { 1479 c.tx.Rollback() 1480 c.tx = nil 1481 } 1482 c.db = nil 1483 } 1484 1485 func (c *concurrentTxStmtExecTest) test(t testing.TB) error { 1486 _, err := c.stmt.Exec(3, chrisBirthday) 1487 if err != nil { 1488 t.Errorf("error on exec: %v", err) 1489 return err 1490 } 1491 return nil 1492 } 1493 1494 type concurrentRandomTest struct { 1495 tests []concurrentTest 1496 } 1497 1498 func (c *concurrentRandomTest) init(t testing.TB, db *DB) { 1499 c.tests = []concurrentTest{ 1500 new(concurrentDBQueryTest), 1501 new(concurrentDBExecTest), 1502 new(concurrentStmtQueryTest), 1503 new(concurrentStmtExecTest), 1504 new(concurrentTxQueryTest), 1505 new(concurrentTxExecTest), 1506 new(concurrentTxStmtQueryTest), 1507 new(concurrentTxStmtExecTest), 1508 } 1509 for _, ct := range c.tests { 1510 ct.init(t, db) 1511 } 1512 } 1513 1514 func (c *concurrentRandomTest) finish(t testing.TB) { 1515 for _, ct := range c.tests { 1516 ct.finish(t) 1517 } 1518 } 1519 1520 func (c *concurrentRandomTest) test(t testing.TB) error { 1521 ct := c.tests[rand.Intn(len(c.tests))] 1522 return ct.test(t) 1523 } 1524 1525 func doConcurrentTest(t testing.TB, ct concurrentTest) { 1526 maxProcs, numReqs := 1, 500 1527 if testing.Short() { 1528 maxProcs, numReqs = 4, 50 1529 } 1530 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1531 1532 db := newTestDB(t, "people") 1533 defer closeDB(t, db) 1534 1535 ct.init(t, db) 1536 defer ct.finish(t) 1537 1538 var wg sync.WaitGroup 1539 wg.Add(numReqs) 1540 1541 reqs := make(chan bool) 1542 defer close(reqs) 1543 1544 for i := 0; i < maxProcs*2; i++ { 1545 go func() { 1546 for _ = range reqs { 1547 err := ct.test(t) 1548 if err != nil { 1549 wg.Done() 1550 continue 1551 } 1552 wg.Done() 1553 } 1554 }() 1555 } 1556 1557 for i := 0; i < numReqs; i++ { 1558 reqs <- true 1559 } 1560 1561 wg.Wait() 1562 } 1563 1564 func manyConcurrentQueries(t testing.TB) { 1565 maxProcs, numReqs := 16, 500 1566 if testing.Short() { 1567 maxProcs, numReqs = 4, 50 1568 } 1569 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1570 1571 db := newTestDB(t, "people") 1572 defer closeDB(t, db) 1573 1574 stmt, err := db.Prepare("SELECT|people|name|") 1575 if err != nil { 1576 t.Fatal(err) 1577 } 1578 defer stmt.Close() 1579 1580 var wg sync.WaitGroup 1581 wg.Add(numReqs) 1582 1583 reqs := make(chan bool) 1584 defer close(reqs) 1585 1586 for i := 0; i < maxProcs*2; i++ { 1587 go func() { 1588 for _ = range reqs { 1589 rows, err := stmt.Query() 1590 if err != nil { 1591 t.Errorf("error on query: %v", err) 1592 wg.Done() 1593 continue 1594 } 1595 1596 var name string 1597 for rows.Next() { 1598 rows.Scan(&name) 1599 } 1600 rows.Close() 1601 1602 wg.Done() 1603 } 1604 }() 1605 } 1606 1607 for i := 0; i < numReqs; i++ { 1608 reqs <- true 1609 } 1610 1611 wg.Wait() 1612 } 1613 1614 func TestIssue6081(t *testing.T) { 1615 db := newTestDB(t, "people") 1616 defer closeDB(t, db) 1617 1618 drv := db.driver.(*fakeDriver) 1619 drv.mu.Lock() 1620 opens0 := drv.openCount 1621 closes0 := drv.closeCount 1622 drv.mu.Unlock() 1623 1624 stmt, err := db.Prepare("SELECT|people|name|") 1625 if err != nil { 1626 t.Fatal(err) 1627 } 1628 rowsCloseHook = func(rows *Rows, err *error) { 1629 *err = driver.ErrBadConn 1630 } 1631 defer func() { rowsCloseHook = nil }() 1632 for i := 0; i < 10; i++ { 1633 rows, err := stmt.Query() 1634 if err != nil { 1635 t.Fatal(err) 1636 } 1637 rows.Close() 1638 } 1639 if n := len(stmt.css); n > 1 { 1640 t.Errorf("len(css slice) = %d; want <= 1", n) 1641 } 1642 stmt.Close() 1643 if n := len(stmt.css); n != 0 { 1644 t.Errorf("len(css slice) after Close = %d; want 0", n) 1645 } 1646 1647 drv.mu.Lock() 1648 opens := drv.openCount - opens0 1649 closes := drv.closeCount - closes0 1650 drv.mu.Unlock() 1651 if opens < 9 { 1652 t.Errorf("opens = %d; want >= 9", opens) 1653 } 1654 if closes < 9 { 1655 t.Errorf("closes = %d; want >= 9", closes) 1656 } 1657 } 1658 1659 func TestConcurrency(t *testing.T) { 1660 doConcurrentTest(t, new(concurrentDBQueryTest)) 1661 doConcurrentTest(t, new(concurrentDBExecTest)) 1662 doConcurrentTest(t, new(concurrentStmtQueryTest)) 1663 doConcurrentTest(t, new(concurrentStmtExecTest)) 1664 doConcurrentTest(t, new(concurrentTxQueryTest)) 1665 doConcurrentTest(t, new(concurrentTxExecTest)) 1666 doConcurrentTest(t, new(concurrentTxStmtQueryTest)) 1667 doConcurrentTest(t, new(concurrentTxStmtExecTest)) 1668 doConcurrentTest(t, new(concurrentRandomTest)) 1669 } 1670 1671 func BenchmarkConcurrentDBExec(b *testing.B) { 1672 b.ReportAllocs() 1673 ct := new(concurrentDBExecTest) 1674 for i := 0; i < b.N; i++ { 1675 doConcurrentTest(b, ct) 1676 } 1677 } 1678 1679 func BenchmarkConcurrentStmtQuery(b *testing.B) { 1680 b.ReportAllocs() 1681 ct := new(concurrentStmtQueryTest) 1682 for i := 0; i < b.N; i++ { 1683 doConcurrentTest(b, ct) 1684 } 1685 } 1686 1687 func BenchmarkConcurrentStmtExec(b *testing.B) { 1688 b.ReportAllocs() 1689 ct := new(concurrentStmtExecTest) 1690 for i := 0; i < b.N; i++ { 1691 doConcurrentTest(b, ct) 1692 } 1693 } 1694 1695 func BenchmarkConcurrentTxQuery(b *testing.B) { 1696 b.ReportAllocs() 1697 ct := new(concurrentTxQueryTest) 1698 for i := 0; i < b.N; i++ { 1699 doConcurrentTest(b, ct) 1700 } 1701 } 1702 1703 func BenchmarkConcurrentTxExec(b *testing.B) { 1704 b.ReportAllocs() 1705 ct := new(concurrentTxExecTest) 1706 for i := 0; i < b.N; i++ { 1707 doConcurrentTest(b, ct) 1708 } 1709 } 1710 1711 func BenchmarkConcurrentTxStmtQuery(b *testing.B) { 1712 b.ReportAllocs() 1713 ct := new(concurrentTxStmtQueryTest) 1714 for i := 0; i < b.N; i++ { 1715 doConcurrentTest(b, ct) 1716 } 1717 } 1718 1719 func BenchmarkConcurrentTxStmtExec(b *testing.B) { 1720 b.ReportAllocs() 1721 ct := new(concurrentTxStmtExecTest) 1722 for i := 0; i < b.N; i++ { 1723 doConcurrentTest(b, ct) 1724 } 1725 } 1726 1727 func BenchmarkConcurrentRandom(b *testing.B) { 1728 b.ReportAllocs() 1729 ct := new(concurrentRandomTest) 1730 for i := 0; i < b.N; i++ { 1731 doConcurrentTest(b, ct) 1732 } 1733 }