]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: adds test for fix in issue 4433.
authorJames David Chalfant <james.chalfant@gmail.com>
Fri, 14 Dec 2012 17:00:33 +0000 (09:00 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 14 Dec 2012 17:00:33 +0000 (09:00 -0800)
Tests that here should be automatic retries if a database
driver's connection returns ErrBadConn on Begin. See
"TestTxErrBadConn" in sql_test.go

R=golang-dev
CC=golang-dev
https://golang.org/cl/6942050

src/pkg/database/sql/fakedb_test.go
src/pkg/database/sql/sql_test.go

index aec572760fe6a1f4f93404e8cad55cd572d66fa3..c38ba7c849264036cc454873b38af736b5d1ad92 100644 (file)
@@ -42,9 +42,10 @@ type fakeDriver struct {
 type fakeDB struct {
        name string
 
-       mu     sync.Mutex
-       free   []*fakeConn
-       tables map[string]*table
+       mu      sync.Mutex
+       free    []*fakeConn
+       tables  map[string]*table
+       badConn bool
 }
 
 type table struct {
@@ -83,6 +84,7 @@ type fakeConn struct {
        stmtsMade   int
        stmtsClosed int
        numPrepare  int
+       bad         bool
 }
 
 func (c *fakeConn) incrStat(v *int) {
@@ -122,7 +124,9 @@ func init() {
 
 // Supports dsn forms:
 //    <dbname>
-//    <dbname>;<opts>  (no currently supported options)
+//    <dbname>;<opts>  (only currently supported option is `badConn`,
+//                      which causes driver.ErrBadConn to be returned on
+//                      every other conn.Begin())
 func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
        parts := strings.Split(dsn, ";")
        if len(parts) < 1 {
@@ -135,7 +139,12 @@ func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
        d.mu.Lock()
        d.openCount++
        d.mu.Unlock()
-       return &fakeConn{db: db}, nil
+       conn := &fakeConn{db: db}
+
+       if len(parts) >= 2 && parts[1] == "badConn" {
+               conn.bad = true
+       }
+       return conn, nil
 }
 
 func (d *fakeDriver) getDB(name string) *fakeDB {
@@ -199,7 +208,20 @@ func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
        return "", false
 }
 
+func (c *fakeConn) isBad() bool {
+       // if not simulating bad conn, do nothing
+       if !c.bad {
+               return false
+       }
+       // alternate between bad conn and not bad conn
+       c.db.badConn = !c.db.badConn
+       return c.db.badConn
+}
+
 func (c *fakeConn) Begin() (driver.Tx, error) {
+       if c.isBad() {
+               return nil, driver.ErrBadConn
+       }
        if c.currTx != nil {
                return nil, errors.New("already in a transaction")
        }
index 1bfb59020b4380eda25deadda398deda4090f1c7..b702b850ec2ff486d4d0b686159ed619dfa7db7c 100644 (file)
@@ -402,6 +402,39 @@ func TestTxQueryInvalid(t *testing.T) {
        }
 }
 
+// Tests fix for issue 4433, that retries in Begin happen when
+// conn.Begin() returns ErrBadConn
+func TestTxErrBadConn(t *testing.T) {
+       db, err := Open("test", fakeDBName+";badConn")
+       if err != nil {
+               t.Fatalf("Open: %v", err)
+       }
+       if _, err := db.Exec("WIPE"); err != nil {
+               t.Fatalf("exec wipe: %v", err)
+       }
+       defer closeDB(t, db)
+       exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+       stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+       if err != nil {
+               t.Fatalf("Stmt, err = %v, %v", stmt, err)
+       }
+       defer stmt.Close()
+       tx, err := db.Begin()
+       if err != nil {
+               t.Fatalf("Begin = %v", err)
+       }
+       txs := tx.Stmt(stmt)
+       defer txs.Close()
+       _, err = txs.Exec("Bobby", 7)
+       if err != nil {
+               t.Fatalf("Exec = %v", err)
+       }
+       err = tx.Commit()
+       if err != nil {
+               t.Fatalf("Commit = %v", err)
+       }
+}
+
 // Tests fix for issue 2542, that we release a lock when querying on
 // a closed connection.
 func TestIssue2542Deadlock(t *testing.T) {