libgo: update to go1.9

Reviewed-on: https://go-review.googlesource.com/63753

From-SVN: r252767
This commit is contained in:
Ian Lance Taylor 2017-09-14 17:11:35 +00:00 committed by Ian Lance Taylor
parent a41a6142df
commit bc998d034f
985 changed files with 56892 additions and 20449 deletions

View file

@ -139,6 +139,7 @@ func closeDB(t testing.TB, db *DB) {
t.Errorf("Error closing fakeConn: %v", err)
}
})
db.mu.Lock()
for i, dc := range db.freeConn {
if n := len(dc.openStmt); n > 0 {
// Just a sanity check. This is legal in
@ -149,6 +150,8 @@ func closeDB(t testing.TB, db *DB) {
t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n)
}
}
db.mu.Unlock()
err := db.Close()
if err != nil {
t.Fatalf("error closing DB: %v", err)
@ -322,7 +325,7 @@ func TestQueryContext(t *testing.T) {
select {
case <-ctx.Done():
if err := ctx.Err(); err != context.Canceled {
t.Fatalf("context err = %v; want context.Canceled", ctx.Err())
t.Fatalf("context err = %v; want context.Canceled", err)
}
default:
t.Fatalf("context err = nil; want context.Canceled")
@ -413,7 +416,7 @@ func TestTxContextWait(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*15)
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond)
defer cancel()
tx, err := db.BeginTx(ctx, nil)
@ -590,13 +593,13 @@ func TestPoolExhaustOnCancel(t *testing.T) {
saturate.Wait()
// Now cancel the request while it is waiting.
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
for i := 0; i < max; i++ {
ctxReq, cancelReq := context.WithCancel(ctx)
go func() {
time.Sleep(time.Millisecond * 100)
time.Sleep(100 * time.Millisecond)
cancelReq()
}()
err := db.PingContext(ctxReq)
@ -874,7 +877,7 @@ func TestStatementClose(t *testing.T) {
msg string
}{
{&Stmt{stickyErr: want}, "stickyErr not propagated"},
{&Stmt{tx: &Tx{}, txds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
{&Stmt{cg: &Tx{}, cgds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
}
for _, test := range tests {
if err := test.stmt.Close(); err != want {
@ -1024,6 +1027,196 @@ func TestTxStmt(t *testing.T) {
}
}
func TestTxStmtPreparedOnce(t *testing.T) {
db := newTestDB(t, "")
defer closeDB(t, db)
exec(t, db, "CREATE|t1|name=string,age=int32")
prepares0 := numPrepares(t, db)
// db.Prepare increments numPrepares.
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)
}
txs1 := tx.Stmt(stmt)
txs2 := tx.Stmt(stmt)
_, err = txs1.Exec("Go", 7)
if err != nil {
t.Fatalf("Exec = %v", err)
}
txs1.Close()
_, err = txs2.Exec("Gopher", 8)
if err != nil {
t.Fatalf("Exec = %v", err)
}
txs2.Close()
err = tx.Commit()
if err != nil {
t.Fatalf("Commit = %v", err)
}
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
t.Errorf("executed %d Prepare statements; want 1", prepares)
}
}
func TestTxStmtClosedRePrepares(t *testing.T) {
db := newTestDB(t, "")
defer closeDB(t, db)
exec(t, db, "CREATE|t1|name=string,age=int32")
prepares0 := numPrepares(t, db)
// db.Prepare increments numPrepares.
stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
if err != nil {
t.Fatalf("Stmt, err = %v, %v", stmt, err)
}
tx, err := db.Begin()
if err != nil {
t.Fatalf("Begin = %v", err)
}
err = stmt.Close()
if err != nil {
t.Fatalf("stmt.Close() = %v", err)
}
// tx.Stmt increments numPrepares because stmt is closed.
txs := tx.Stmt(stmt)
if txs.stickyErr != nil {
t.Fatal(txs.stickyErr)
}
if txs.parentStmt != nil {
t.Fatal("expected nil parentStmt")
}
_, err = txs.Exec(`Eric`, 82)
if err != nil {
t.Fatalf("txs.Exec = %v", err)
}
err = txs.Close()
if err != nil {
t.Fatalf("txs.Close = %v", err)
}
tx.Rollback()
if prepares := numPrepares(t, db) - prepares0; prepares != 2 {
t.Errorf("executed %d Prepare statements; want 2", prepares)
}
}
func TestParentStmtOutlivesTxStmt(t *testing.T) {
db := newTestDB(t, "")
defer closeDB(t, db)
exec(t, db, "CREATE|t1|name=string,age=int32")
// Make sure everything happens on the same connection.
db.SetMaxOpenConns(1)
prepares0 := numPrepares(t, db)
// db.Prepare increments numPrepares.
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)
if len(stmt.css) != 1 {
t.Fatalf("len(stmt.css) = %v; want 1", len(stmt.css))
}
err = txs.Close()
if err != nil {
t.Fatalf("txs.Close() = %v", err)
}
err = tx.Rollback()
if err != nil {
t.Fatalf("tx.Rollback() = %v", err)
}
// txs must not be valid.
_, err = txs.Exec("Suzan", 30)
if err == nil {
t.Fatalf("txs.Exec(), expected err")
}
// Stmt must still be valid.
_, err = stmt.Exec("Janina", 25)
if err != nil {
t.Fatalf("stmt.Exec() = %v", err)
}
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
t.Errorf("executed %d Prepare statements; want 1", prepares)
}
}
// Test that tx.Stmt called with a statement already
// associated with tx as argument re-prepares the same
// statement again.
func TestTxStmtFromTxStmtRePrepares(t *testing.T) {
db := newTestDB(t, "")
defer closeDB(t, db)
exec(t, db, "CREATE|t1|name=string,age=int32")
prepares0 := numPrepares(t, db)
// db.Prepare increments numPrepares.
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)
}
txs1 := tx.Stmt(stmt)
// tx.Stmt(txs1) increments numPrepares because txs1 already
// belongs to a transaction (albeit the same transaction).
txs2 := tx.Stmt(txs1)
if txs2.stickyErr != nil {
t.Fatal(txs2.stickyErr)
}
if txs2.parentStmt != nil {
t.Fatal("expected nil parentStmt")
}
_, err = txs2.Exec(`Eric`, 82)
if err != nil {
t.Fatal(err)
}
err = txs1.Close()
if err != nil {
t.Fatalf("txs1.Close = %v", err)
}
err = txs2.Close()
if err != nil {
t.Fatalf("txs1.Close = %v", err)
}
err = tx.Rollback()
if err != nil {
t.Fatalf("tx.Rollback = %v", err)
}
if prepares := numPrepares(t, db) - prepares0; prepares != 2 {
t.Errorf("executed %d Prepare statements; want 2", prepares)
}
}
// Issue: https://golang.org/issue/2784
// This test didn't fail before because we got lucky with the fakedb driver.
// It was failing, and now not, in github.com/bradfitz/go-sql-test
@ -1108,6 +1301,69 @@ func TestTxErrBadConn(t *testing.T) {
}
}
func TestConnQuery(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conn, err := db.Conn(ctx)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
var name string
err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", 3).Scan(&name)
if err != nil {
t.Fatal(err)
}
if name != "Chris" {
t.Fatalf("unexpected result, got %q want Chris", name)
}
err = conn.PingContext(ctx)
if err != nil {
t.Fatal(err)
}
}
func TestConnTx(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conn, err := db.Conn(ctx)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
tx, err := conn.BeginTx(ctx, nil)
if err != nil {
t.Fatal(err)
}
insertName, insertAge := "Nancy", 33
_, err = tx.ExecContext(ctx, "INSERT|people|name=?,age=?,photo=APHOTO", insertName, insertAge)
if err != nil {
t.Fatal(err)
}
err = tx.Commit()
if err != nil {
t.Fatal(err)
}
var selectName string
err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", insertAge).Scan(&selectName)
if err != nil {
t.Fatal(err)
}
if selectName != insertName {
t.Fatalf("got %q want %q", selectName, insertName)
}
}
// Tests fix for issue 2542, that we release a lock when querying on
// a closed connection.
func TestIssue2542Deadlock(t *testing.T) {
@ -1831,8 +2087,8 @@ func TestConnMaxLifetime(t *testing.T) {
}
// Expire first conn
offset = time.Second * 11
db.SetConnMaxLifetime(time.Second * 10)
offset = 11 * time.Second
db.SetConnMaxLifetime(10 * time.Second)
if err != nil {
t.Fatal(err)
}
@ -2078,9 +2334,13 @@ func TestStmtCloseOrder(t *testing.T) {
// Test cases where there's more than maxBadConnRetries bad connections in the
// pool (issue 8834)
func TestManyErrBadConn(t *testing.T) {
manyErrBadConnSetup := func() *DB {
manyErrBadConnSetup := func(first ...func(db *DB)) *DB {
db := newTestDB(t, "people")
for _, f := range first {
f(db)
}
nconn := maxBadConnRetries + 1
db.SetMaxIdleConns(nconn)
db.SetMaxOpenConns(nconn)
@ -2148,6 +2408,128 @@ func TestManyErrBadConn(t *testing.T) {
if err = stmt.Close(); err != nil {
t.Fatal(err)
}
// Stmt.Exec
db = manyErrBadConnSetup(func(db *DB) {
stmt, err = db.Prepare("INSERT|people|name=Julia,age=19")
if err != nil {
t.Fatal(err)
}
})
defer closeDB(t, db)
_, err = stmt.Exec()
if err != nil {
t.Fatal(err)
}
if err = stmt.Close(); err != nil {
t.Fatal(err)
}
// Stmt.Query
db = manyErrBadConnSetup(func(db *DB) {
stmt, err = db.Prepare("SELECT|people|age,name|")
if err != nil {
t.Fatal(err)
}
})
defer closeDB(t, db)
rows, err = stmt.Query()
if err != nil {
t.Fatal(err)
}
if err = rows.Close(); err != nil {
t.Fatal(err)
}
if err = stmt.Close(); err != nil {
t.Fatal(err)
}
// Conn
db = manyErrBadConnSetup()
defer closeDB(t, db)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conn, err := db.Conn(ctx)
if err != nil {
t.Fatal(err)
}
err = conn.Close()
if err != nil {
t.Fatal(err)
}
// Ping
db = manyErrBadConnSetup()
defer closeDB(t, db)
err = db.PingContext(ctx)
if err != nil {
t.Fatal(err)
}
}
// TestIssue20575 ensures the Rows from query does not block
// closing a transaction. Ensure Rows is closed while closing a trasaction.
func TestIssue20575(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
tx, err := db.Begin()
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_, err = tx.QueryContext(ctx, "SELECT|people|age,name|")
if err != nil {
t.Fatal(err)
}
// Do not close Rows from QueryContext.
err = tx.Rollback()
if err != nil {
t.Fatal(err)
}
select {
default:
case <-ctx.Done():
t.Fatal("timeout: failed to rollback query without closing rows:", ctx.Err())
}
}
// TestIssue20622 tests closing the transaction before rows is closed, requires
// the race detector to fail.
func TestIssue20622(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
t.Fatal(err)
}
rows, err := tx.Query("SELECT|people|age,name|")
if err != nil {
t.Fatal(err)
}
count := 0
for rows.Next() {
count++
var age int
var name string
if err := rows.Scan(&age, &name); err != nil {
t.Fatal("scan failed", err)
}
if count == 1 {
cancel()
}
time.Sleep(100 * time.Millisecond)
}
rows.Close()
tx.Commit()
}
// golang.org/issue/5718
@ -2751,7 +3133,7 @@ func TestIssue18429(t *testing.T) {
if err != nil {
return
}
// This is expected to give a cancel error many, but not all the time.
// This is expected to give a cancel error most, but not all the time.
// Test failure will happen with a panic or other race condition being
// reported.
rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
@ -2766,6 +3148,46 @@ func TestIssue18429(t *testing.T) {
wg.Wait()
}
// TestIssue20160 attempts to test a short context life on a stmt Query.
func TestIssue20160(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx := context.Background()
sem := make(chan bool, 20)
var wg sync.WaitGroup
const milliWait = 30
stmt, err := db.PrepareContext(ctx, "SELECT|people|name|")
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
for i := 0; i < 100; i++ {
sem <- true
wg.Add(1)
go func() {
defer func() {
<-sem
wg.Done()
}()
ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
defer cancel()
// This is expected to give a cancel error most, but not all the time.
// Test failure will happen with a panic or other race condition being
// reported.
rows, _ := stmt.QueryContext(ctx)
if rows != nil {
rows.Close()
}
}()
}
wg.Wait()
}
// TestIssue18719 closes the context right before use. The sql.driverConn
// will nil out the ci on close in a lock, but if another process uses it right after
// it will panic with on the nil ref.
@ -2788,7 +3210,7 @@ func TestIssue18719(t *testing.T) {
// Wait for the context to cancel and tx to rollback.
for tx.isDone() == false {
time.Sleep(time.Millisecond * 3)
time.Sleep(3 * time.Millisecond)
}
}
defer func() { hookTxGrabConn = nil }()
@ -2807,19 +3229,64 @@ func TestIssue18719(t *testing.T) {
// canceled context.
cancel()
waitForRowsClose(t, rows, 5*time.Second)
}
func TestIssue20647(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conn, err := db.Conn(ctx)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
stmt, err := conn.PrepareContext(ctx, "SELECT|people|name|")
if err != nil {
t.Fatal(err)
}
defer stmt.Close()
rows1, err := stmt.QueryContext(ctx)
if err != nil {
t.Fatal("rows1", err)
}
defer rows1.Close()
rows2, err := stmt.QueryContext(ctx)
if err != nil {
t.Fatal("rows2", err)
}
defer rows2.Close()
if rows1.dc != rows2.dc {
t.Fatal("stmt prepared on Conn does not use same connection")
}
}
func TestConcurrency(t *testing.T) {
doConcurrentTest(t, new(concurrentDBQueryTest))
doConcurrentTest(t, new(concurrentDBExecTest))
doConcurrentTest(t, new(concurrentStmtQueryTest))
doConcurrentTest(t, new(concurrentStmtExecTest))
doConcurrentTest(t, new(concurrentTxQueryTest))
doConcurrentTest(t, new(concurrentTxExecTest))
doConcurrentTest(t, new(concurrentTxStmtQueryTest))
doConcurrentTest(t, new(concurrentTxStmtExecTest))
doConcurrentTest(t, new(concurrentRandomTest))
list := []struct {
name string
ct concurrentTest
}{
{"Query", new(concurrentDBQueryTest)},
{"Exec", new(concurrentDBExecTest)},
{"StmtQuery", new(concurrentStmtQueryTest)},
{"StmtExec", new(concurrentStmtExecTest)},
{"TxQuery", new(concurrentTxQueryTest)},
{"TxExec", new(concurrentTxExecTest)},
{"TxStmtQuery", new(concurrentTxStmtQueryTest)},
{"TxStmtExec", new(concurrentTxStmtExecTest)},
{"Random", new(concurrentRandomTest)},
}
for _, item := range list {
t.Run(item.name, func(t *testing.T) {
doConcurrentTest(t, item.ct)
})
}
}
func TestConnectionLeak(t *testing.T) {
@ -2874,6 +3341,131 @@ func TestConnectionLeak(t *testing.T) {
wg.Wait()
}
type nvcDriver struct {
fakeDriver
skipNamedValueCheck bool
}
func (d *nvcDriver) Open(dsn string) (driver.Conn, error) {
c, err := d.fakeDriver.Open(dsn)
fc := c.(*fakeConn)
fc.db.allowAny = true
return &nvcConn{fc, d.skipNamedValueCheck}, err
}
type nvcConn struct {
*fakeConn
skipNamedValueCheck bool
}
type decimal struct {
value int
}
type doNotInclude struct{}
var _ driver.NamedValueChecker = &nvcConn{}
func (c *nvcConn) CheckNamedValue(nv *driver.NamedValue) error {
if c.skipNamedValueCheck {
return driver.ErrSkip
}
switch v := nv.Value.(type) {
default:
return driver.ErrSkip
case Out:
switch ov := v.Dest.(type) {
default:
return errors.New("unkown NameValueCheck OUTPUT type")
case *string:
*ov = "from-server"
nv.Value = "OUT:*string"
}
return nil
case decimal, []int64:
return nil
case doNotInclude:
return driver.ErrRemoveArgument
}
}
func TestNamedValueChecker(t *testing.T) {
Register("NamedValueCheck", &nvcDriver{})
db, err := Open("NamedValueCheck", "")
if err != nil {
t.Fatal(err)
}
defer db.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, err = db.ExecContext(ctx, "WIPE")
if err != nil {
t.Fatal("exec wipe", err)
}
_, err = db.ExecContext(ctx, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any")
if err != nil {
t.Fatal("exec create", err)
}
o1 := ""
_, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A,str1=?,out1=?O1,array1=?", Named("A", decimal{123}), "hello", Named("O1", Out{Dest: &o1}), []int64{42, 128, 707}, doNotInclude{})
if err != nil {
t.Fatal("exec insert", err)
}
var (
str1 string
dec1 decimal
arr1 []int64
)
err = db.QueryRowContext(ctx, "SELECT|keys|dec1,str1,array1|").Scan(&dec1, &str1, &arr1)
if err != nil {
t.Fatal("select", err)
}
list := []struct{ got, want interface{} }{
{o1, "from-server"},
{dec1, decimal{123}},
{str1, "hello"},
{arr1, []int64{42, 128, 707}},
}
for index, item := range list {
if !reflect.DeepEqual(item.got, item.want) {
t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index)
}
}
}
func TestNamedValueCheckerSkip(t *testing.T) {
Register("NamedValueCheckSkip", &nvcDriver{skipNamedValueCheck: true})
db, err := Open("NamedValueCheckSkip", "")
if err != nil {
t.Fatal(err)
}
defer db.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, err = db.ExecContext(ctx, "WIPE")
if err != nil {
t.Fatal("exec wipe", err)
}
_, err = db.ExecContext(ctx, "CREATE|keys|dec1=any")
if err != nil {
t.Fatal("exec create", err)
}
_, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A", Named("A", decimal{123}))
if err == nil {
t.Fatalf("expected error with bad argument, got %v", err)
}
}
// badConn implements a bad driver.Conn, for TestBadDriver.
// The Exec method panics.
type badConn struct{}
@ -2965,6 +3557,24 @@ func TestPing(t *testing.T) {
}
}
// Issue 18101.
func TestTypedString(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
type Str string
var scanned Str
err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned)
if err != nil {
t.Fatal(err)
}
expected := Str("Alice")
if scanned != expected {
t.Errorf("expected %+v, got %+v", expected, scanned)
}
}
func BenchmarkConcurrentDBExec(b *testing.B) {
b.ReportAllocs()
ct := new(concurrentDBExecTest)