...

Source file src/github.com/lib/pq/issues_test.go

Documentation: github.com/lib/pq

     1  package pq
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  func TestIssue494(t *testing.T) {
    12  	db := openTestConn(t)
    13  	defer db.Close()
    14  
    15  	query := `CREATE TEMP TABLE t (i INT PRIMARY KEY)`
    16  	if _, err := db.Exec(query); err != nil {
    17  		t.Fatal(err)
    18  	}
    19  
    20  	txn, err := db.Begin()
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  
    25  	if _, err := txn.Prepare(CopyIn("t", "i")); err != nil {
    26  		t.Fatal(err)
    27  	}
    28  
    29  	if _, err := txn.Query("SELECT 1"); err == nil {
    30  		t.Fatal("expected error")
    31  	}
    32  }
    33  
    34  func TestIssue1046(t *testing.T) {
    35  	ctxTimeout := time.Second * 2
    36  
    37  	db := openTestConn(t)
    38  	defer db.Close()
    39  
    40  	ctx, cancel := context.WithTimeout(context.Background(), ctxTimeout)
    41  	defer cancel()
    42  
    43  	stmt, err := db.PrepareContext(ctx, `SELECT pg_sleep(10) AS id`)
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  
    48  	var d []uint8
    49  	err = stmt.QueryRowContext(ctx).Scan(&d)
    50  	dl, _ := ctx.Deadline()
    51  	since := time.Since(dl)
    52  	if since > ctxTimeout {
    53  		t.Logf("FAIL %s: query returned after context deadline: %v\n", t.Name(), since)
    54  		t.Fail()
    55  	}
    56  	if pgErr := (*Error)(nil); !(errors.As(err, &pgErr) && pgErr.Code == cancelErrorCode) {
    57  		t.Logf("ctx.Err(): [%T]%+v\n", ctx.Err(), ctx.Err())
    58  		t.Logf("got err: [%T] %+v expected errCode: %v", err, err, cancelErrorCode)
    59  		t.Fail()
    60  	}
    61  }
    62  
    63  func TestIssue1062(t *testing.T) {
    64  	db := openTestConn(t)
    65  	defer db.Close()
    66  
    67  	// Ensure that cancelling a QueryRowContext does not result in an ErrBadConn.
    68  
    69  	for i := 0; i < 100; i++ {
    70  		ctx, cancel := context.WithCancel(context.Background())
    71  		go cancel()
    72  		row := db.QueryRowContext(ctx, "select 1")
    73  
    74  		var v int
    75  		err := row.Scan(&v)
    76  		if pgErr := (*Error)(nil); err != nil &&
    77  			err != context.Canceled &&
    78  			!(errors.As(err, &pgErr) && pgErr.Code == cancelErrorCode) {
    79  			t.Fatalf("Scan resulted in unexpected error %v for canceled QueryRowContext at attempt %d", err, i+1)
    80  		}
    81  	}
    82  }
    83  
    84  func connIsValid(t *testing.T, db *sql.DB) {
    85  	t.Helper()
    86  
    87  	ctx := context.Background()
    88  	conn, err := db.Conn(ctx)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	defer conn.Close()
    93  
    94  	// the connection must be valid
    95  	err = conn.PingContext(ctx)
    96  	if err != nil {
    97  		t.Errorf("PingContext err=%#v", err)
    98  	}
    99  	// close must not return an error
   100  	err = conn.Close()
   101  	if err != nil {
   102  		t.Errorf("Close err=%#v", err)
   103  	}
   104  }
   105  
   106  func TestQueryCancelRace(t *testing.T) {
   107  	db := openTestConn(t)
   108  	defer db.Close()
   109  
   110  	// cancel a query while executing on Postgres: must return the cancelled error code
   111  	ctx, cancel := context.WithCancel(context.Background())
   112  	go func() {
   113  		time.Sleep(10 * time.Millisecond)
   114  		cancel()
   115  	}()
   116  	row := db.QueryRowContext(ctx, "select pg_sleep(0.5)")
   117  	var pgSleepVoid string
   118  	err := row.Scan(&pgSleepVoid)
   119  	if pgErr := (*Error)(nil); !(errors.As(err, &pgErr) && pgErr.Code == cancelErrorCode) {
   120  		t.Fatalf("expected cancelled error; err=%#v", err)
   121  	}
   122  
   123  	// get a connection: it must be a valid
   124  	connIsValid(t, db)
   125  }
   126  
   127  // Test cancelling a scan after it is started. This broke with 1.10.4.
   128  func TestQueryCancelledReused(t *testing.T) {
   129  	db := openTestConn(t)
   130  	defer db.Close()
   131  
   132  	ctx, cancel := context.WithCancel(context.Background())
   133  	// run a query that returns a lot of data
   134  	rows, err := db.QueryContext(ctx, "select generate_series(1, 10000)")
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	// scan the first value
   140  	if !rows.Next() {
   141  		t.Error("expected rows.Next() to return true")
   142  	}
   143  	var i int
   144  	err = rows.Scan(&i)
   145  	if err != nil {
   146  		t.Fatal(err)
   147  	}
   148  	if i != 1 {
   149  		t.Error(i)
   150  	}
   151  
   152  	// cancel the context and close rows, ignoring errors
   153  	cancel()
   154  	rows.Close()
   155  
   156  	// get a connection: it must be valid
   157  	connIsValid(t, db)
   158  }
   159  

View as plain text