libgo: update to final Go 1.8 release
Along with the update this fixes a problem that was always present but only showed up with the new reflect test. When a program used a **unsafe.Pointer and stored the value in an interface type, the generated type descriptor pointed to the GC data for *unsafe.Pointer. It did that by name, but we were not generating a variable with the right name. Reviewed-on: https://go-review.googlesource.com/37144 From-SVN: r245535
This commit is contained in:
parent
4bcd6597a3
commit
00b2a30fd4
20 changed files with 895 additions and 266 deletions
|
@ -153,8 +153,13 @@ func closeDB(t testing.TB, db *DB) {
|
|||
if err != nil {
|
||||
t.Fatalf("error closing DB: %v", err)
|
||||
}
|
||||
if count := db.numOpenConns(); count != 0 {
|
||||
t.Fatalf("%d connections still open after closing DB", count)
|
||||
|
||||
var numOpen int
|
||||
if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
|
||||
numOpen = db.numOpenConns()
|
||||
return numOpen == 0
|
||||
}) {
|
||||
t.Fatalf("%d connections still open after closing DB", numOpen)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,6 +281,7 @@ func TestQuery(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestQueryContext tests canceling the context while scanning the rows.
|
||||
func TestQueryContext(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
@ -297,7 +303,7 @@ func TestQueryContext(t *testing.T) {
|
|||
for rows.Next() {
|
||||
if index == 2 {
|
||||
cancel()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
waitForRowsClose(t, rows, 5*time.Second)
|
||||
}
|
||||
var r row
|
||||
err = rows.Scan(&r.age, &r.name)
|
||||
|
@ -313,9 +319,13 @@ func TestQueryContext(t *testing.T) {
|
|||
got = append(got, r)
|
||||
index++
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
t.Fatalf("Err: %v", err)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if err := ctx.Err(); err != context.Canceled {
|
||||
t.Fatalf("context err = %v; want context.Canceled")
|
||||
}
|
||||
default:
|
||||
t.Fatalf("context err = nil; want context.Canceled")
|
||||
}
|
||||
want := []row{
|
||||
{age: 1, name: "Alice"},
|
||||
|
@ -327,6 +337,7 @@ func TestQueryContext(t *testing.T) {
|
|||
|
||||
// And verify that the final rows.Next() call, which hit EOF,
|
||||
// also closed the rows connection.
|
||||
waitForRowsClose(t, rows, 5*time.Second)
|
||||
waitForFree(t, db, 5*time.Second, 1)
|
||||
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
|
||||
t.Errorf("executed %d Prepare statements; want 1", prepares)
|
||||
|
@ -356,12 +367,27 @@ func waitForFree(t *testing.T, db *DB, maxWait time.Duration, want int) {
|
|||
}
|
||||
}
|
||||
|
||||
func waitForRowsClose(t *testing.T, rows *Rows, maxWait time.Duration) {
|
||||
if !waitCondition(maxWait, 5*time.Millisecond, func() bool {
|
||||
rows.closemu.RLock()
|
||||
defer rows.closemu.RUnlock()
|
||||
return rows.closed
|
||||
}) {
|
||||
t.Fatal("failed to close rows")
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueryContextWait ensures that rows and all internal statements are closed when
|
||||
// a query context is closed during execution.
|
||||
func TestQueryContextWait(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
prepares0 := numPrepares(t, db)
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*15)
|
||||
// TODO(kardianos): convert this from using a timeout to using an explicit
|
||||
// cancel when the query signals that is is "executing" the query.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
// This will trigger the *fakeConn.Prepare method which will take time
|
||||
// performing the query. The ctxDriverPrepare func will check the context
|
||||
|
@ -374,10 +400,15 @@ func TestQueryContextWait(t *testing.T) {
|
|||
// Verify closed rows connection after error condition.
|
||||
waitForFree(t, db, 5*time.Second, 1)
|
||||
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
|
||||
t.Errorf("executed %d Prepare statements; want 1", prepares)
|
||||
// TODO(kardianos): if the context timeouts before the db.QueryContext
|
||||
// executes this check may fail. After adjusting how the context
|
||||
// is canceled above revert this back to a Fatal error.
|
||||
t.Logf("executed %d Prepare statements; want 1", prepares)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTxContextWait tests the transaction behavior when the tx context is canceled
|
||||
// during execution of the query.
|
||||
func TestTxContextWait(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
@ -386,6 +417,10 @@ func TestTxContextWait(t *testing.T) {
|
|||
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
// Guard against the context being canceled before BeginTx completes.
|
||||
if err == context.DeadlineExceeded {
|
||||
t.Skip("tx context canceled prior to first use")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -398,12 +433,6 @@ func TestTxContextWait(t *testing.T) {
|
|||
}
|
||||
|
||||
waitForFree(t, db, 5*time.Second, 0)
|
||||
|
||||
// Ensure the dropped connection allows more connections to be made.
|
||||
// Checked on DB Close.
|
||||
waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
|
||||
return db.numOpenConns() == 0
|
||||
})
|
||||
}
|
||||
|
||||
func TestMultiResultSetQuery(t *testing.T) {
|
||||
|
@ -527,6 +556,63 @@ func TestQueryNamedArg(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPoolExhaustOnCancel(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("long test")
|
||||
}
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
max := 3
|
||||
|
||||
db.SetMaxOpenConns(max)
|
||||
|
||||
// First saturate the connection pool.
|
||||
// Then start new requests for a connection that is cancelled after it is requested.
|
||||
|
||||
var saturate, saturateDone sync.WaitGroup
|
||||
saturate.Add(max)
|
||||
saturateDone.Add(max)
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
go func() {
|
||||
saturate.Done()
|
||||
rows, err := db.Query("WAIT|500ms|SELECT|people|name,photo|")
|
||||
if err != nil {
|
||||
t.Fatalf("Query: %v", err)
|
||||
}
|
||||
rows.Close()
|
||||
saturateDone.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
saturate.Wait()
|
||||
|
||||
// Now cancel the request while it is waiting.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
defer cancel()
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
ctxReq, cancelReq := context.WithCancel(ctx)
|
||||
go func() {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
cancelReq()
|
||||
}()
|
||||
err := db.PingContext(ctxReq)
|
||||
if err != context.Canceled {
|
||||
t.Fatalf("PingContext (Exhaust): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
saturateDone.Wait()
|
||||
|
||||
// Now try to open a normal connection.
|
||||
err := db.PingContext(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("PingContext (Normal): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestByteOwnership(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
@ -2677,7 +2763,6 @@ func TestIssue18429(t *testing.T) {
|
|||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
time.Sleep(milliWait * 3 * time.Millisecond)
|
||||
}
|
||||
|
||||
// TestIssue18719 closes the context right before use. The sql.driverConn
|
||||
|
@ -2720,14 +2805,8 @@ func TestIssue18719(t *testing.T) {
|
|||
// Do not explicitly rollback. The rollback will happen from the
|
||||
// canceled context.
|
||||
|
||||
// Wait for connections to return to pool.
|
||||
var numOpen int
|
||||
if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
|
||||
numOpen = db.numOpenConns()
|
||||
return numOpen == 0
|
||||
}) {
|
||||
t.Fatalf("open conns after hitting EOF = %d; want 0", numOpen)
|
||||
}
|
||||
cancel()
|
||||
waitForRowsClose(t, rows, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestConcurrency(t *testing.T) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue