github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/lib/pq/conn_test.go (about)

     1  package pq
     2  
     3  import (
     4  	"database/sql"
     5  	"database/sql/driver"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"reflect"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  type Fatalistic interface {
    16  	Fatal(args ...interface{})
    17  }
    18  
    19  func forceBinaryParameters() bool {
    20  	bp := os.Getenv("PQTEST_BINARY_PARAMETERS")
    21  	if bp == "yes" {
    22  		return true
    23  	} else if bp == "" || bp == "no" {
    24  		return false
    25  	} else {
    26  		panic("unexpected value for PQTEST_BINARY_PARAMETERS")
    27  	}
    28  }
    29  
    30  func openTestConnConninfo(conninfo string) (*sql.DB, error) {
    31  	defaultTo := func(envvar string, value string) {
    32  		if os.Getenv(envvar) == "" {
    33  			os.Setenv(envvar, value)
    34  		}
    35  	}
    36  	defaultTo("PGDATABASE", "pqgotest")
    37  	defaultTo("PGSSLMODE", "disable")
    38  	defaultTo("PGCONNECT_TIMEOUT", "20")
    39  
    40  	if forceBinaryParameters() &&
    41  		!strings.HasPrefix(conninfo, "postgres://") &&
    42  		!strings.HasPrefix(conninfo, "postgresql://") {
    43  		conninfo = conninfo + " binary_parameters=yes"
    44  	}
    45  
    46  	return sql.Open("postgres", conninfo)
    47  }
    48  
    49  func openTestConn(t Fatalistic) *sql.DB {
    50  	conn, err := openTestConnConninfo("")
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  
    55  	return conn
    56  }
    57  
    58  func getServerVersion(t *testing.T, db *sql.DB) int {
    59  	var version int
    60  	err := db.QueryRow("SHOW server_version_num").Scan(&version)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	return version
    65  }
    66  
    67  func TestReconnect(t *testing.T) {
    68  	db1 := openTestConn(t)
    69  	defer db1.Close()
    70  	tx, err := db1.Begin()
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	var pid1 int
    75  	err = tx.QueryRow("SELECT pg_backend_pid()").Scan(&pid1)
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	db2 := openTestConn(t)
    80  	defer db2.Close()
    81  	_, err = db2.Exec("SELECT pg_terminate_backend($1)", pid1)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	// The rollback will probably "fail" because we just killed
    86  	// its connection above
    87  	_ = tx.Rollback()
    88  
    89  	const expected int = 42
    90  	var result int
    91  	err = db1.QueryRow(fmt.Sprintf("SELECT %d", expected)).Scan(&result)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	if result != expected {
    96  		t.Errorf("got %v; expected %v", result, expected)
    97  	}
    98  }
    99  
   100  func TestCommitInFailedTransaction(t *testing.T) {
   101  	db := openTestConn(t)
   102  	defer db.Close()
   103  
   104  	txn, err := db.Begin()
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  	rows, err := txn.Query("SELECT error")
   109  	if err == nil {
   110  		rows.Close()
   111  		t.Fatal("expected failure")
   112  	}
   113  	err = txn.Commit()
   114  	if err != ErrInFailedTransaction {
   115  		t.Fatalf("expected ErrInFailedTransaction; got %#v", err)
   116  	}
   117  }
   118  
   119  func TestOpenURL(t *testing.T) {
   120  	testURL := func(url string) {
   121  		db, err := openTestConnConninfo(url)
   122  		if err != nil {
   123  			t.Fatal(err)
   124  		}
   125  		defer db.Close()
   126  		// database/sql might not call our Open at all unless we do something with
   127  		// the connection
   128  		txn, err := db.Begin()
   129  		if err != nil {
   130  			t.Fatal(err)
   131  		}
   132  		txn.Rollback()
   133  	}
   134  	testURL("postgres://")
   135  	testURL("postgresql://")
   136  }
   137  
   138  const pgpass_file = "/tmp/pqgotest_pgpass"
   139  func TestPgpass(t *testing.T) {
   140  	testAssert := func(conninfo string, expected string, reason string) {
   141  		conn, err := openTestConnConninfo(conninfo)
   142  		if err != nil {
   143  			t.Fatal(err)
   144  		}
   145  		defer conn.Close()
   146  
   147  		txn, err := conn.Begin()
   148  		if err != nil {
   149  			if expected != "fail" {
   150  				t.Fatalf(reason, err)
   151  			}
   152  			return
   153  		}
   154  		rows, err := txn.Query("SELECT USER")
   155  		if err != nil {
   156  			txn.Rollback()
   157  			rows.Close()
   158  			if expected != "fail" {
   159  				t.Fatalf(reason, err)
   160  			}
   161  		} else {
   162  			if expected != "ok" {
   163  				t.Fatalf(reason, err)
   164  			}
   165  		}
   166  		txn.Rollback()
   167  	}
   168  	testAssert("", "ok", "missing .pgpass, unexpected error %#v")
   169  	os.Setenv("PGPASSFILE", pgpass_file)
   170  	testAssert("host=/tmp", "fail", ", unexpected error %#v")
   171  	os.Remove(pgpass_file)
   172  	pgpass, err := os.OpenFile(pgpass_file, os.O_RDWR|os.O_CREATE, 0644)
   173  	if err != nil {
   174  		t.Fatalf("Unexpected error writing pgpass file %#v", err)
   175  	}
   176  	_, err = pgpass.WriteString(`# comment
   177  server:5432:some_db:some_user:pass_A
   178  *:5432:some_db:some_user:pass_B
   179  localhost:*:*:*:pass_C
   180  *:*:*:*:pass_fallback
   181  `)
   182  	if err != nil {
   183  		t.Fatalf("Unexpected error writing pgpass file %#v", err)
   184  	}
   185  	pgpass.Close()
   186  
   187  	assertPassword := func(extra values, expected string) {
   188  		o := &values{"host": "localhost", "sslmode": "disable", "connect_timeout": "20", "user": "majid", "port": "5432", "extra_float_digits": "2", "dbname": "pqgotest", "client_encoding": "UTF8", "datestyle": "ISO, MDY"}
   189  		for k, v := range extra {
   190  			(*o)[k] = v
   191  		}
   192  		(&conn{}).handlePgpass(*o)
   193  		if o.Get("password") != expected {
   194  			t.Fatalf("For %v expected %s got %s", extra, expected, o.Get("password"))
   195  		}
   196  	}
   197  	// wrong permissions for the pgpass file means it should be ignored
   198  	assertPassword(values{"host": "example.com", "user": "foo"}, "")
   199  	// fix the permissions and check if it has taken effect
   200  	os.Chmod(pgpass_file, 0600)
   201  	assertPassword(values{"host": "server", "dbname": "some_db", "user": "some_user"}, "pass_A")
   202  	assertPassword(values{"host": "example.com", "user": "foo"}, "pass_fallback")
   203  	assertPassword(values{"host": "example.com", "dbname": "some_db", "user": "some_user"}, "pass_B")
   204  	// localhost also matches the default "" and UNIX sockets
   205  	assertPassword(values{"host": "", "user": "some_user"}, "pass_C")
   206  	assertPassword(values{"host": "/tmp", "user": "some_user"}, "pass_C")
   207  	// cleanup
   208  	os.Remove(pgpass_file)
   209  	os.Setenv("PGPASSFILE", "")
   210  }
   211  
   212  func TestExec(t *testing.T) {
   213  	db := openTestConn(t)
   214  	defer db.Close()
   215  
   216  	_, err := db.Exec("CREATE TEMP TABLE temp (a int)")
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  
   221  	r, err := db.Exec("INSERT INTO temp VALUES (1)")
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  
   226  	if n, _ := r.RowsAffected(); n != 1 {
   227  		t.Fatalf("expected 1 row affected, not %d", n)
   228  	}
   229  
   230  	r, err = db.Exec("INSERT INTO temp VALUES ($1), ($2), ($3)", 1, 2, 3)
   231  	if err != nil {
   232  		t.Fatal(err)
   233  	}
   234  
   235  	if n, _ := r.RowsAffected(); n != 3 {
   236  		t.Fatalf("expected 3 rows affected, not %d", n)
   237  	}
   238  
   239  	// SELECT doesn't send the number of returned rows in the command tag
   240  	// before 9.0
   241  	if getServerVersion(t, db) >= 90000 {
   242  		r, err = db.Exec("SELECT g FROM generate_series(1, 2) g")
   243  		if err != nil {
   244  			t.Fatal(err)
   245  		}
   246  		if n, _ := r.RowsAffected(); n != 2 {
   247  			t.Fatalf("expected 2 rows affected, not %d", n)
   248  		}
   249  
   250  		r, err = db.Exec("SELECT g FROM generate_series(1, $1) g", 3)
   251  		if err != nil {
   252  			t.Fatal(err)
   253  		}
   254  		if n, _ := r.RowsAffected(); n != 3 {
   255  			t.Fatalf("expected 3 rows affected, not %d", n)
   256  		}
   257  	}
   258  }
   259  
   260  func TestStatment(t *testing.T) {
   261  	db := openTestConn(t)
   262  	defer db.Close()
   263  
   264  	st, err := db.Prepare("SELECT 1")
   265  	if err != nil {
   266  		t.Fatal(err)
   267  	}
   268  
   269  	st1, err := db.Prepare("SELECT 2")
   270  	if err != nil {
   271  		t.Fatal(err)
   272  	}
   273  
   274  	r, err := st.Query()
   275  	if err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	defer r.Close()
   279  
   280  	if !r.Next() {
   281  		t.Fatal("expected row")
   282  	}
   283  
   284  	var i int
   285  	err = r.Scan(&i)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  
   290  	if i != 1 {
   291  		t.Fatalf("expected 1, got %d", i)
   292  	}
   293  
   294  	// st1
   295  
   296  	r1, err := st1.Query()
   297  	if err != nil {
   298  		t.Fatal(err)
   299  	}
   300  	defer r1.Close()
   301  
   302  	if !r1.Next() {
   303  		if r.Err() != nil {
   304  			t.Fatal(r1.Err())
   305  		}
   306  		t.Fatal("expected row")
   307  	}
   308  
   309  	err = r1.Scan(&i)
   310  	if err != nil {
   311  		t.Fatal(err)
   312  	}
   313  
   314  	if i != 2 {
   315  		t.Fatalf("expected 2, got %d", i)
   316  	}
   317  }
   318  
   319  func TestRowsCloseBeforeDone(t *testing.T) {
   320  	db := openTestConn(t)
   321  	defer db.Close()
   322  
   323  	r, err := db.Query("SELECT 1")
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  
   328  	err = r.Close()
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  
   333  	if r.Next() {
   334  		t.Fatal("unexpected row")
   335  	}
   336  
   337  	if r.Err() != nil {
   338  		t.Fatal(r.Err())
   339  	}
   340  }
   341  
   342  func TestParameterCountMismatch(t *testing.T) {
   343  	db := openTestConn(t)
   344  	defer db.Close()
   345  
   346  	var notused int
   347  	err := db.QueryRow("SELECT false", 1).Scan(&notused)
   348  	if err == nil {
   349  		t.Fatal("expected err")
   350  	}
   351  	// make sure we clean up correctly
   352  	err = db.QueryRow("SELECT 1").Scan(&notused)
   353  	if err != nil {
   354  		t.Fatal(err)
   355  	}
   356  
   357  	err = db.QueryRow("SELECT $1").Scan(&notused)
   358  	if err == nil {
   359  		t.Fatal("expected err")
   360  	}
   361  	// make sure we clean up correctly
   362  	err = db.QueryRow("SELECT 1").Scan(&notused)
   363  	if err != nil {
   364  		t.Fatal(err)
   365  	}
   366  }
   367  
   368  // Test that EmptyQueryResponses are handled correctly.
   369  func TestEmptyQuery(t *testing.T) {
   370  	db := openTestConn(t)
   371  	defer db.Close()
   372  
   373  	_, err := db.Exec("")
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  	rows, err := db.Query("")
   378  	if err != nil {
   379  		t.Fatal(err)
   380  	}
   381  	cols, err := rows.Columns()
   382  	if err != nil {
   383  		t.Fatal(err)
   384  	}
   385  	if len(cols) != 0 {
   386  		t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols))
   387  	}
   388  	if rows.Next() {
   389  		t.Fatal("unexpected row")
   390  	}
   391  	if rows.Err() != nil {
   392  		t.Fatal(rows.Err())
   393  	}
   394  
   395  	stmt, err := db.Prepare("")
   396  	if err != nil {
   397  		t.Fatal(err)
   398  	}
   399  	_, err = stmt.Exec()
   400  	if err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	rows, err = stmt.Query()
   404  	if err != nil {
   405  		t.Fatal(err)
   406  	}
   407  	cols, err = rows.Columns()
   408  	if err != nil {
   409  		t.Fatal(err)
   410  	}
   411  	if len(cols) != 0 {
   412  		t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols))
   413  	}
   414  	if rows.Next() {
   415  		t.Fatal("unexpected row")
   416  	}
   417  	if rows.Err() != nil {
   418  		t.Fatal(rows.Err())
   419  	}
   420  }
   421  
   422  // Test that rows.Columns() is correct even if there are no result rows.
   423  func TestEmptyResultSetColumns(t *testing.T) {
   424  	db := openTestConn(t)
   425  	defer db.Close()
   426  
   427  	rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar WHERE FALSE")
   428  	if err != nil {
   429  		t.Fatal(err)
   430  	}
   431  	cols, err := rows.Columns()
   432  	if err != nil {
   433  		t.Fatal(err)
   434  	}
   435  	if len(cols) != 2 {
   436  		t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols))
   437  	}
   438  	if rows.Next() {
   439  		t.Fatal("unexpected row")
   440  	}
   441  	if rows.Err() != nil {
   442  		t.Fatal(rows.Err())
   443  	}
   444  	if cols[0] != "a" || cols[1] != "bar" {
   445  		t.Fatalf("unexpected Columns result %v", cols)
   446  	}
   447  
   448  	stmt, err := db.Prepare("SELECT $1::int AS a, text 'bar' AS bar WHERE FALSE")
   449  	if err != nil {
   450  		t.Fatal(err)
   451  	}
   452  	rows, err = stmt.Query(1)
   453  	if err != nil {
   454  		t.Fatal(err)
   455  	}
   456  	cols, err = rows.Columns()
   457  	if err != nil {
   458  		t.Fatal(err)
   459  	}
   460  	if len(cols) != 2 {
   461  		t.Fatalf("unexpected number of columns %d in response to an empty query", len(cols))
   462  	}
   463  	if rows.Next() {
   464  		t.Fatal("unexpected row")
   465  	}
   466  	if rows.Err() != nil {
   467  		t.Fatal(rows.Err())
   468  	}
   469  	if cols[0] != "a" || cols[1] != "bar" {
   470  		t.Fatalf("unexpected Columns result %v", cols)
   471  	}
   472  
   473  }
   474  
   475  func TestEncodeDecode(t *testing.T) {
   476  	db := openTestConn(t)
   477  	defer db.Close()
   478  
   479  	q := `
   480  		SELECT
   481  			E'\\000\\001\\002'::bytea,
   482  			'foobar'::text,
   483  			NULL::integer,
   484  			'2000-1-1 01:02:03.04-7'::timestamptz,
   485  			0::boolean,
   486  			123,
   487  			-321,
   488  			3.14::float8
   489  		WHERE
   490  			    E'\\000\\001\\002'::bytea = $1
   491  			AND 'foobar'::text = $2
   492  			AND $3::integer is NULL
   493  	`
   494  	// AND '2000-1-1 12:00:00.000000-7'::timestamp = $3
   495  
   496  	exp1 := []byte{0, 1, 2}
   497  	exp2 := "foobar"
   498  
   499  	r, err := db.Query(q, exp1, exp2, nil)
   500  	if err != nil {
   501  		t.Fatal(err)
   502  	}
   503  	defer r.Close()
   504  
   505  	if !r.Next() {
   506  		if r.Err() != nil {
   507  			t.Fatal(r.Err())
   508  		}
   509  		t.Fatal("expected row")
   510  	}
   511  
   512  	var got1 []byte
   513  	var got2 string
   514  	var got3 = sql.NullInt64{Valid: true}
   515  	var got4 time.Time
   516  	var got5, got6, got7, got8 interface{}
   517  
   518  	err = r.Scan(&got1, &got2, &got3, &got4, &got5, &got6, &got7, &got8)
   519  	if err != nil {
   520  		t.Fatal(err)
   521  	}
   522  
   523  	if !reflect.DeepEqual(exp1, got1) {
   524  		t.Errorf("expected %q byte: %q", exp1, got1)
   525  	}
   526  
   527  	if !reflect.DeepEqual(exp2, got2) {
   528  		t.Errorf("expected %q byte: %q", exp2, got2)
   529  	}
   530  
   531  	if got3.Valid {
   532  		t.Fatal("expected invalid")
   533  	}
   534  
   535  	if got4.Year() != 2000 {
   536  		t.Fatal("wrong year")
   537  	}
   538  
   539  	if got5 != false {
   540  		t.Fatalf("expected false, got %q", got5)
   541  	}
   542  
   543  	if got6 != int64(123) {
   544  		t.Fatalf("expected 123, got %d", got6)
   545  	}
   546  
   547  	if got7 != int64(-321) {
   548  		t.Fatalf("expected -321, got %d", got7)
   549  	}
   550  
   551  	if got8 != float64(3.14) {
   552  		t.Fatalf("expected 3.14, got %f", got8)
   553  	}
   554  }
   555  
   556  func TestNoData(t *testing.T) {
   557  	db := openTestConn(t)
   558  	defer db.Close()
   559  
   560  	st, err := db.Prepare("SELECT 1 WHERE true = false")
   561  	if err != nil {
   562  		t.Fatal(err)
   563  	}
   564  	defer st.Close()
   565  
   566  	r, err := st.Query()
   567  	if err != nil {
   568  		t.Fatal(err)
   569  	}
   570  	defer r.Close()
   571  
   572  	if r.Next() {
   573  		if r.Err() != nil {
   574  			t.Fatal(r.Err())
   575  		}
   576  		t.Fatal("unexpected row")
   577  	}
   578  
   579  	_, err = db.Query("SELECT * FROM nonexistenttable WHERE age=$1", 20)
   580  	if err == nil {
   581  		t.Fatal("Should have raised an error on non existent table")
   582  	}
   583  
   584  	_, err = db.Query("SELECT * FROM nonexistenttable")
   585  	if err == nil {
   586  		t.Fatal("Should have raised an error on non existent table")
   587  	}
   588  }
   589  
   590  func TestErrorDuringStartup(t *testing.T) {
   591  	// Don't use the normal connection setup, this is intended to
   592  	// blow up in the startup packet from a non-existent user.
   593  	db, err := openTestConnConninfo("user=thisuserreallydoesntexist")
   594  	if err != nil {
   595  		t.Fatal(err)
   596  	}
   597  	defer db.Close()
   598  
   599  	_, err = db.Begin()
   600  	if err == nil {
   601  		t.Fatal("expected error")
   602  	}
   603  
   604  	e, ok := err.(*Error)
   605  	if !ok {
   606  		t.Fatalf("expected Error, got %#v", err)
   607  	} else if e.Code.Name() != "invalid_authorization_specification" && e.Code.Name() != "invalid_password" {
   608  		t.Fatalf("expected invalid_authorization_specification or invalid_password, got %s (%+v)", e.Code.Name(), err)
   609  	}
   610  }
   611  
   612  func TestBadConn(t *testing.T) {
   613  	var err error
   614  
   615  	cn := conn{}
   616  	func() {
   617  		defer cn.errRecover(&err)
   618  		panic(io.EOF)
   619  	}()
   620  	if err != driver.ErrBadConn {
   621  		t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
   622  	}
   623  	if !cn.bad {
   624  		t.Fatalf("expected cn.bad")
   625  	}
   626  
   627  	cn = conn{}
   628  	func() {
   629  		defer cn.errRecover(&err)
   630  		e := &Error{Severity: Efatal}
   631  		panic(e)
   632  	}()
   633  	if err != driver.ErrBadConn {
   634  		t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
   635  	}
   636  	if !cn.bad {
   637  		t.Fatalf("expected cn.bad")
   638  	}
   639  }
   640  
   641  func TestErrorOnExec(t *testing.T) {
   642  	db := openTestConn(t)
   643  	defer db.Close()
   644  
   645  	txn, err := db.Begin()
   646  	if err != nil {
   647  		t.Fatal(err)
   648  	}
   649  	defer txn.Rollback()
   650  
   651  	_, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)")
   652  	if err != nil {
   653  		t.Fatal(err)
   654  	}
   655  
   656  	_, err = txn.Exec("INSERT INTO foo VALUES (0), (0)")
   657  	if err == nil {
   658  		t.Fatal("Should have raised error")
   659  	}
   660  
   661  	e, ok := err.(*Error)
   662  	if !ok {
   663  		t.Fatalf("expected Error, got %#v", err)
   664  	} else if e.Code.Name() != "unique_violation" {
   665  		t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err)
   666  	}
   667  }
   668  
   669  func TestErrorOnQuery(t *testing.T) {
   670  	db := openTestConn(t)
   671  	defer db.Close()
   672  
   673  	txn, err := db.Begin()
   674  	if err != nil {
   675  		t.Fatal(err)
   676  	}
   677  	defer txn.Rollback()
   678  
   679  	_, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)")
   680  	if err != nil {
   681  		t.Fatal(err)
   682  	}
   683  
   684  	_, err = txn.Query("INSERT INTO foo VALUES (0), (0)")
   685  	if err == nil {
   686  		t.Fatal("Should have raised error")
   687  	}
   688  
   689  	e, ok := err.(*Error)
   690  	if !ok {
   691  		t.Fatalf("expected Error, got %#v", err)
   692  	} else if e.Code.Name() != "unique_violation" {
   693  		t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err)
   694  	}
   695  }
   696  
   697  func TestErrorOnQueryRowSimpleQuery(t *testing.T) {
   698  	db := openTestConn(t)
   699  	defer db.Close()
   700  
   701  	txn, err := db.Begin()
   702  	if err != nil {
   703  		t.Fatal(err)
   704  	}
   705  	defer txn.Rollback()
   706  
   707  	_, err = txn.Exec("CREATE TEMPORARY TABLE foo(f1 int PRIMARY KEY)")
   708  	if err != nil {
   709  		t.Fatal(err)
   710  	}
   711  
   712  	var v int
   713  	err = txn.QueryRow("INSERT INTO foo VALUES (0), (0)").Scan(&v)
   714  	if err == nil {
   715  		t.Fatal("Should have raised error")
   716  	}
   717  
   718  	e, ok := err.(*Error)
   719  	if !ok {
   720  		t.Fatalf("expected Error, got %#v", err)
   721  	} else if e.Code.Name() != "unique_violation" {
   722  		t.Fatalf("expected unique_violation, got %s (%+v)", e.Code.Name(), err)
   723  	}
   724  }
   725  
   726  // Test the QueryRow bug workarounds in stmt.exec() and simpleQuery()
   727  func TestQueryRowBugWorkaround(t *testing.T) {
   728  	db := openTestConn(t)
   729  	defer db.Close()
   730  
   731  	// stmt.exec()
   732  	_, err := db.Exec("CREATE TEMP TABLE notnulltemp (a varchar(10) not null)")
   733  	if err != nil {
   734  		t.Fatal(err)
   735  	}
   736  
   737  	var a string
   738  	err = db.QueryRow("INSERT INTO notnulltemp(a) values($1) RETURNING a", nil).Scan(&a)
   739  	if err == sql.ErrNoRows {
   740  		t.Fatalf("expected constraint violation error; got: %v", err)
   741  	}
   742  	pge, ok := err.(*Error)
   743  	if !ok {
   744  		t.Fatalf("expected *Error; got: %#v", err)
   745  	}
   746  	if pge.Code.Name() != "not_null_violation" {
   747  		t.Fatalf("expected not_null_violation; got: %s (%+v)", pge.Code.Name(), err)
   748  	}
   749  
   750  	// Test workaround in simpleQuery()
   751  	tx, err := db.Begin()
   752  	if err != nil {
   753  		t.Fatalf("unexpected error %s in Begin", err)
   754  	}
   755  	defer tx.Rollback()
   756  
   757  	_, err = tx.Exec("SET LOCAL check_function_bodies TO FALSE")
   758  	if err != nil {
   759  		t.Fatalf("could not disable check_function_bodies: %s", err)
   760  	}
   761  	_, err = tx.Exec(`
   762  CREATE OR REPLACE FUNCTION bad_function()
   763  RETURNS integer
   764  -- hack to prevent the function from being inlined
   765  SET check_function_bodies TO TRUE
   766  AS $$
   767  	SELECT text 'bad'
   768  $$ LANGUAGE sql`)
   769  	if err != nil {
   770  		t.Fatalf("could not create function: %s", err)
   771  	}
   772  
   773  	err = tx.QueryRow("SELECT * FROM bad_function()").Scan(&a)
   774  	if err == nil {
   775  		t.Fatalf("expected error")
   776  	}
   777  	pge, ok = err.(*Error)
   778  	if !ok {
   779  		t.Fatalf("expected *Error; got: %#v", err)
   780  	}
   781  	if pge.Code.Name() != "invalid_function_definition" {
   782  		t.Fatalf("expected invalid_function_definition; got: %s (%+v)", pge.Code.Name(), err)
   783  	}
   784  
   785  	err = tx.Rollback()
   786  	if err != nil {
   787  		t.Fatalf("unexpected error %s in Rollback", err)
   788  	}
   789  
   790  	// Also test that simpleQuery()'s workaround works when the query fails
   791  	// after a row has been received.
   792  	rows, err := db.Query(`
   793  select
   794  	(select generate_series(1, ss.i))
   795  from (select gs.i
   796        from generate_series(1, 2) gs(i)
   797        order by gs.i limit 2) ss`)
   798  	if err != nil {
   799  		t.Fatalf("query failed: %s", err)
   800  	}
   801  	if !rows.Next() {
   802  		t.Fatalf("expected at least one result row; got %s", rows.Err())
   803  	}
   804  	var i int
   805  	err = rows.Scan(&i)
   806  	if err != nil {
   807  		t.Fatalf("rows.Scan() failed: %s", err)
   808  	}
   809  	if i != 1 {
   810  		t.Fatalf("unexpected value for i: %d", i)
   811  	}
   812  	if rows.Next() {
   813  		t.Fatalf("unexpected row")
   814  	}
   815  	pge, ok = rows.Err().(*Error)
   816  	if !ok {
   817  		t.Fatalf("expected *Error; got: %#v", err)
   818  	}
   819  	if pge.Code.Name() != "cardinality_violation" {
   820  		t.Fatalf("expected cardinality_violation; got: %s (%+v)", pge.Code.Name(), rows.Err())
   821  	}
   822  }
   823  
   824  func TestSimpleQuery(t *testing.T) {
   825  	db := openTestConn(t)
   826  	defer db.Close()
   827  
   828  	r, err := db.Query("select 1")
   829  	if err != nil {
   830  		t.Fatal(err)
   831  	}
   832  	defer r.Close()
   833  
   834  	if !r.Next() {
   835  		t.Fatal("expected row")
   836  	}
   837  }
   838  
   839  func TestBindError(t *testing.T) {
   840  	db := openTestConn(t)
   841  	defer db.Close()
   842  
   843  	_, err := db.Exec("create temp table test (i integer)")
   844  	if err != nil {
   845  		t.Fatal(err)
   846  	}
   847  
   848  	_, err = db.Query("select * from test where i=$1", "hhh")
   849  	if err == nil {
   850  		t.Fatal("expected an error")
   851  	}
   852  
   853  	// Should not get error here
   854  	r, err := db.Query("select * from test where i=$1", 1)
   855  	if err != nil {
   856  		t.Fatal(err)
   857  	}
   858  	defer r.Close()
   859  }
   860  
   861  func TestParseErrorInExtendedQuery(t *testing.T) {
   862  	db := openTestConn(t)
   863  	defer db.Close()
   864  
   865  	rows, err := db.Query("PARSE_ERROR $1", 1)
   866  	if err == nil {
   867  		t.Fatal("expected error")
   868  	}
   869  
   870  	rows, err = db.Query("SELECT 1")
   871  	if err != nil {
   872  		t.Fatal(err)
   873  	}
   874  	rows.Close()
   875  }
   876  
   877  // TestReturning tests that an INSERT query using the RETURNING clause returns a row.
   878  func TestReturning(t *testing.T) {
   879  	db := openTestConn(t)
   880  	defer db.Close()
   881  
   882  	_, err := db.Exec("CREATE TEMP TABLE distributors (did integer default 0, dname text)")
   883  	if err != nil {
   884  		t.Fatal(err)
   885  	}
   886  
   887  	rows, err := db.Query("INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') " +
   888  		"RETURNING did;")
   889  	if err != nil {
   890  		t.Fatal(err)
   891  	}
   892  	if !rows.Next() {
   893  		t.Fatal("no rows")
   894  	}
   895  	var did int
   896  	err = rows.Scan(&did)
   897  	if err != nil {
   898  		t.Fatal(err)
   899  	}
   900  	if did != 0 {
   901  		t.Fatalf("bad value for did: got %d, want %d", did, 0)
   902  	}
   903  
   904  	if rows.Next() {
   905  		t.Fatal("unexpected next row")
   906  	}
   907  	err = rows.Err()
   908  	if err != nil {
   909  		t.Fatal(err)
   910  	}
   911  }
   912  
   913  func TestIssue186(t *testing.T) {
   914  	db := openTestConn(t)
   915  	defer db.Close()
   916  
   917  	// Exec() a query which returns results
   918  	_, err := db.Exec("VALUES (1), (2), (3)")
   919  	if err != nil {
   920  		t.Fatal(err)
   921  	}
   922  
   923  	_, err = db.Exec("VALUES ($1), ($2), ($3)", 1, 2, 3)
   924  	if err != nil {
   925  		t.Fatal(err)
   926  	}
   927  
   928  	// Query() a query which doesn't return any results
   929  	txn, err := db.Begin()
   930  	if err != nil {
   931  		t.Fatal(err)
   932  	}
   933  	defer txn.Rollback()
   934  
   935  	rows, err := txn.Query("CREATE TEMP TABLE foo(f1 int)")
   936  	if err != nil {
   937  		t.Fatal(err)
   938  	}
   939  	if err = rows.Close(); err != nil {
   940  		t.Fatal(err)
   941  	}
   942  
   943  	// small trick to get NoData from a parameterized query
   944  	_, err = txn.Exec("CREATE RULE nodata AS ON INSERT TO foo DO INSTEAD NOTHING")
   945  	if err != nil {
   946  		t.Fatal(err)
   947  	}
   948  	rows, err = txn.Query("INSERT INTO foo VALUES ($1)", 1)
   949  	if err != nil {
   950  		t.Fatal(err)
   951  	}
   952  	if err = rows.Close(); err != nil {
   953  		t.Fatal(err)
   954  	}
   955  }
   956  
   957  func TestIssue196(t *testing.T) {
   958  	db := openTestConn(t)
   959  	defer db.Close()
   960  
   961  	row := db.QueryRow("SELECT float4 '0.10000122' = $1, float8 '35.03554004971999' = $2",
   962  		float32(0.10000122), float64(35.03554004971999))
   963  
   964  	var float4match, float8match bool
   965  	err := row.Scan(&float4match, &float8match)
   966  	if err != nil {
   967  		t.Fatal(err)
   968  	}
   969  	if !float4match {
   970  		t.Errorf("Expected float4 fidelity to be maintained; got no match")
   971  	}
   972  	if !float8match {
   973  		t.Errorf("Expected float8 fidelity to be maintained; got no match")
   974  	}
   975  }
   976  
   977  // Test that any CommandComplete messages sent before the query results are
   978  // ignored.
   979  func TestIssue282(t *testing.T) {
   980  	db := openTestConn(t)
   981  	defer db.Close()
   982  
   983  	var search_path string
   984  	err := db.QueryRow(`
   985  		SET LOCAL search_path TO pg_catalog;
   986  		SET LOCAL search_path TO pg_catalog;
   987  		SHOW search_path`).Scan(&search_path)
   988  	if err != nil {
   989  		t.Fatal(err)
   990  	}
   991  	if search_path != "pg_catalog" {
   992  		t.Fatalf("unexpected search_path %s", search_path)
   993  	}
   994  }
   995  
   996  func TestReadFloatPrecision(t *testing.T) {
   997  	db := openTestConn(t)
   998  	defer db.Close()
   999  
  1000  	row := db.QueryRow("SELECT float4 '0.10000122', float8 '35.03554004971999'")
  1001  	var float4val float32
  1002  	var float8val float64
  1003  	err := row.Scan(&float4val, &float8val)
  1004  	if err != nil {
  1005  		t.Fatal(err)
  1006  	}
  1007  	if float4val != float32(0.10000122) {
  1008  		t.Errorf("Expected float4 fidelity to be maintained; got no match")
  1009  	}
  1010  	if float8val != float64(35.03554004971999) {
  1011  		t.Errorf("Expected float8 fidelity to be maintained; got no match")
  1012  	}
  1013  }
  1014  
  1015  func TestXactMultiStmt(t *testing.T) {
  1016  	// minified test case based on bug reports from
  1017  	// pico303@gmail.com and rangelspam@gmail.com
  1018  	t.Skip("Skipping failing test")
  1019  	db := openTestConn(t)
  1020  	defer db.Close()
  1021  
  1022  	tx, err := db.Begin()
  1023  	if err != nil {
  1024  		t.Fatal(err)
  1025  	}
  1026  	defer tx.Commit()
  1027  
  1028  	rows, err := tx.Query("select 1")
  1029  	if err != nil {
  1030  		t.Fatal(err)
  1031  	}
  1032  
  1033  	if rows.Next() {
  1034  		var val int32
  1035  		if err = rows.Scan(&val); err != nil {
  1036  			t.Fatal(err)
  1037  		}
  1038  	} else {
  1039  		t.Fatal("Expected at least one row in first query in xact")
  1040  	}
  1041  
  1042  	rows2, err := tx.Query("select 2")
  1043  	if err != nil {
  1044  		t.Fatal(err)
  1045  	}
  1046  
  1047  	if rows2.Next() {
  1048  		var val2 int32
  1049  		if err := rows2.Scan(&val2); err != nil {
  1050  			t.Fatal(err)
  1051  		}
  1052  	} else {
  1053  		t.Fatal("Expected at least one row in second query in xact")
  1054  	}
  1055  
  1056  	if err = rows.Err(); err != nil {
  1057  		t.Fatal(err)
  1058  	}
  1059  
  1060  	if err = rows2.Err(); err != nil {
  1061  		t.Fatal(err)
  1062  	}
  1063  
  1064  	if err = tx.Commit(); err != nil {
  1065  		t.Fatal(err)
  1066  	}
  1067  }
  1068  
  1069  var envParseTests = []struct {
  1070  	Expected map[string]string
  1071  	Env      []string
  1072  }{
  1073  	{
  1074  		Env:      []string{"PGDATABASE=hello", "PGUSER=goodbye"},
  1075  		Expected: map[string]string{"dbname": "hello", "user": "goodbye"},
  1076  	},
  1077  	{
  1078  		Env:      []string{"PGDATESTYLE=ISO, MDY"},
  1079  		Expected: map[string]string{"datestyle": "ISO, MDY"},
  1080  	},
  1081  	{
  1082  		Env:      []string{"PGCONNECT_TIMEOUT=30"},
  1083  		Expected: map[string]string{"connect_timeout": "30"},
  1084  	},
  1085  }
  1086  
  1087  func TestParseEnviron(t *testing.T) {
  1088  	for i, tt := range envParseTests {
  1089  		results := parseEnviron(tt.Env)
  1090  		if !reflect.DeepEqual(tt.Expected, results) {
  1091  			t.Errorf("%d: Expected: %#v Got: %#v", i, tt.Expected, results)
  1092  		}
  1093  	}
  1094  }
  1095  
  1096  func TestParseComplete(t *testing.T) {
  1097  	tpc := func(commandTag string, command string, affectedRows int64, shouldFail bool) {
  1098  		defer func() {
  1099  			if p := recover(); p != nil {
  1100  				if !shouldFail {
  1101  					t.Error(p)
  1102  				}
  1103  			}
  1104  		}()
  1105  		cn := &conn{}
  1106  		res, c := cn.parseComplete(commandTag)
  1107  		if c != command {
  1108  			t.Errorf("Expected %v, got %v", command, c)
  1109  		}
  1110  		n, err := res.RowsAffected()
  1111  		if err != nil {
  1112  			t.Fatal(err)
  1113  		}
  1114  		if n != affectedRows {
  1115  			t.Errorf("Expected %d, got %d", affectedRows, n)
  1116  		}
  1117  	}
  1118  
  1119  	tpc("ALTER TABLE", "ALTER TABLE", 0, false)
  1120  	tpc("INSERT 0 1", "INSERT", 1, false)
  1121  	tpc("UPDATE 100", "UPDATE", 100, false)
  1122  	tpc("SELECT 100", "SELECT", 100, false)
  1123  	tpc("FETCH 100", "FETCH", 100, false)
  1124  	// allow COPY (and others) without row count
  1125  	tpc("COPY", "COPY", 0, false)
  1126  	// don't fail on command tags we don't recognize
  1127  	tpc("UNKNOWNCOMMANDTAG", "UNKNOWNCOMMANDTAG", 0, false)
  1128  
  1129  	// failure cases
  1130  	tpc("INSERT 1", "", 0, true)   // missing oid
  1131  	tpc("UPDATE 0 1", "", 0, true) // too many numbers
  1132  	tpc("SELECT foo", "", 0, true) // invalid row count
  1133  }
  1134  
  1135  func TestExecerInterface(t *testing.T) {
  1136  	// Gin up a straw man private struct just for the type check
  1137  	cn := &conn{c: nil}
  1138  	var cni interface{} = cn
  1139  
  1140  	_, ok := cni.(driver.Execer)
  1141  	if !ok {
  1142  		t.Fatal("Driver doesn't implement Execer")
  1143  	}
  1144  }
  1145  
  1146  func TestNullAfterNonNull(t *testing.T) {
  1147  	db := openTestConn(t)
  1148  	defer db.Close()
  1149  
  1150  	r, err := db.Query("SELECT 9::integer UNION SELECT NULL::integer")
  1151  	if err != nil {
  1152  		t.Fatal(err)
  1153  	}
  1154  
  1155  	var n sql.NullInt64
  1156  
  1157  	if !r.Next() {
  1158  		if r.Err() != nil {
  1159  			t.Fatal(err)
  1160  		}
  1161  		t.Fatal("expected row")
  1162  	}
  1163  
  1164  	if err := r.Scan(&n); err != nil {
  1165  		t.Fatal(err)
  1166  	}
  1167  
  1168  	if n.Int64 != 9 {
  1169  		t.Fatalf("expected 2, not %d", n.Int64)
  1170  	}
  1171  
  1172  	if !r.Next() {
  1173  		if r.Err() != nil {
  1174  			t.Fatal(err)
  1175  		}
  1176  		t.Fatal("expected row")
  1177  	}
  1178  
  1179  	if err := r.Scan(&n); err != nil {
  1180  		t.Fatal(err)
  1181  	}
  1182  
  1183  	if n.Valid {
  1184  		t.Fatal("expected n to be invalid")
  1185  	}
  1186  
  1187  	if n.Int64 != 0 {
  1188  		t.Fatalf("expected n to 2, not %d", n.Int64)
  1189  	}
  1190  }
  1191  
  1192  func Test64BitErrorChecking(t *testing.T) {
  1193  	defer func() {
  1194  		if err := recover(); err != nil {
  1195  			t.Fatal("panic due to 0xFFFFFFFF != -1 " +
  1196  				"when int is 64 bits")
  1197  		}
  1198  	}()
  1199  
  1200  	db := openTestConn(t)
  1201  	defer db.Close()
  1202  
  1203  	r, err := db.Query(`SELECT *
  1204  FROM (VALUES (0::integer, NULL::text), (1, 'test string')) AS t;`)
  1205  
  1206  	if err != nil {
  1207  		t.Fatal(err)
  1208  	}
  1209  
  1210  	defer r.Close()
  1211  
  1212  	for r.Next() {
  1213  	}
  1214  }
  1215  
  1216  func TestCommit(t *testing.T) {
  1217  	db := openTestConn(t)
  1218  	defer db.Close()
  1219  
  1220  	_, err := db.Exec("CREATE TEMP TABLE temp (a int)")
  1221  	if err != nil {
  1222  		t.Fatal(err)
  1223  	}
  1224  	sqlInsert := "INSERT INTO temp VALUES (1)"
  1225  	sqlSelect := "SELECT * FROM temp"
  1226  	tx, err := db.Begin()
  1227  	if err != nil {
  1228  		t.Fatal(err)
  1229  	}
  1230  	_, err = tx.Exec(sqlInsert)
  1231  	if err != nil {
  1232  		t.Fatal(err)
  1233  	}
  1234  	err = tx.Commit()
  1235  	if err != nil {
  1236  		t.Fatal(err)
  1237  	}
  1238  	var i int
  1239  	err = db.QueryRow(sqlSelect).Scan(&i)
  1240  	if err != nil {
  1241  		t.Fatal(err)
  1242  	}
  1243  	if i != 1 {
  1244  		t.Fatalf("expected 1, got %d", i)
  1245  	}
  1246  }
  1247  
  1248  func TestErrorClass(t *testing.T) {
  1249  	db := openTestConn(t)
  1250  	defer db.Close()
  1251  
  1252  	_, err := db.Query("SELECT int 'notint'")
  1253  	if err == nil {
  1254  		t.Fatal("expected error")
  1255  	}
  1256  	pge, ok := err.(*Error)
  1257  	if !ok {
  1258  		t.Fatalf("expected *pq.Error, got %#+v", err)
  1259  	}
  1260  	if pge.Code.Class() != "22" {
  1261  		t.Fatalf("expected class 28, got %v", pge.Code.Class())
  1262  	}
  1263  	if pge.Code.Class().Name() != "data_exception" {
  1264  		t.Fatalf("expected data_exception, got %v", pge.Code.Class().Name())
  1265  	}
  1266  }
  1267  
  1268  func TestParseOpts(t *testing.T) {
  1269  	tests := []struct {
  1270  		in       string
  1271  		expected values
  1272  		valid    bool
  1273  	}{
  1274  		{"dbname=hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true},
  1275  		{"dbname=hello user=goodbye  ", values{"dbname": "hello", "user": "goodbye"}, true},
  1276  		{"dbname = hello user=goodbye", values{"dbname": "hello", "user": "goodbye"}, true},
  1277  		{"dbname=hello user =goodbye", values{"dbname": "hello", "user": "goodbye"}, true},
  1278  		{"dbname=hello user= goodbye", values{"dbname": "hello", "user": "goodbye"}, true},
  1279  		{"host=localhost password='correct horse battery staple'", values{"host": "localhost", "password": "correct horse battery staple"}, true},
  1280  		{"dbname=データベース password=パスワード", values{"dbname": "データベース", "password": "パスワード"}, true},
  1281  		{"dbname=hello user=''", values{"dbname": "hello", "user": ""}, true},
  1282  		{"user='' dbname=hello", values{"dbname": "hello", "user": ""}, true},
  1283  		// The last option value is an empty string if there's no non-whitespace after its =
  1284  		{"dbname=hello user=   ", values{"dbname": "hello", "user": ""}, true},
  1285  
  1286  		// The parser ignores spaces after = and interprets the next set of non-whitespace characters as the value.
  1287  		{"user= password=foo", values{"user": "password=foo"}, true},
  1288  
  1289  		// Backslash escapes next char
  1290  		{`user=a\ \'\\b`, values{"user": `a '\b`}, true},
  1291  		{`user='a \'b'`, values{"user": `a 'b`}, true},
  1292  
  1293  		// Incomplete escape
  1294  		{`user=x\`, values{}, false},
  1295  
  1296  		// No '=' after the key
  1297  		{"postgre://marko@internet", values{}, false},
  1298  		{"dbname user=goodbye", values{}, false},
  1299  		{"user=foo blah", values{}, false},
  1300  		{"user=foo blah   ", values{}, false},
  1301  
  1302  		// Unterminated quoted value
  1303  		{"dbname=hello user='unterminated", values{}, false},
  1304  	}
  1305  
  1306  	for _, test := range tests {
  1307  		o := make(values)
  1308  		err := parseOpts(test.in, o)
  1309  
  1310  		switch {
  1311  		case err != nil && test.valid:
  1312  			t.Errorf("%q got unexpected error: %s", test.in, err)
  1313  		case err == nil && test.valid && !reflect.DeepEqual(test.expected, o):
  1314  			t.Errorf("%q got: %#v want: %#v", test.in, o, test.expected)
  1315  		case err == nil && !test.valid:
  1316  			t.Errorf("%q expected an error", test.in)
  1317  		}
  1318  	}
  1319  }
  1320  
  1321  func TestRuntimeParameters(t *testing.T) {
  1322  	type RuntimeTestResult int
  1323  	const (
  1324  		ResultUnknown RuntimeTestResult = iota
  1325  		ResultSuccess
  1326  		ResultError // other error
  1327  	)
  1328  
  1329  	tests := []struct {
  1330  		conninfo        string
  1331  		param           string
  1332  		expected        string
  1333  		expectedOutcome RuntimeTestResult
  1334  	}{
  1335  		// invalid parameter
  1336  		{"DOESNOTEXIST=foo", "", "", ResultError},
  1337  		// we can only work with a specific value for these two
  1338  		{"client_encoding=SQL_ASCII", "", "", ResultError},
  1339  		{"datestyle='ISO, YDM'", "", "", ResultError},
  1340  		// "options" should work exactly as it does in libpq
  1341  		{"options='-c search_path=pqgotest'", "search_path", "pqgotest", ResultSuccess},
  1342  		// pq should override client_encoding in this case
  1343  		{"options='-c client_encoding=SQL_ASCII'", "client_encoding", "UTF8", ResultSuccess},
  1344  		// allow client_encoding to be set explicitly
  1345  		{"client_encoding=UTF8", "client_encoding", "UTF8", ResultSuccess},
  1346  		// test a runtime parameter not supported by libpq
  1347  		{"work_mem='139kB'", "work_mem", "139kB", ResultSuccess},
  1348  		// test fallback_application_name
  1349  		{"application_name=foo fallback_application_name=bar", "application_name", "foo", ResultSuccess},
  1350  		{"application_name='' fallback_application_name=bar", "application_name", "", ResultSuccess},
  1351  		{"fallback_application_name=bar", "application_name", "bar", ResultSuccess},
  1352  	}
  1353  
  1354  	for _, test := range tests {
  1355  		db, err := openTestConnConninfo(test.conninfo)
  1356  		if err != nil {
  1357  			t.Fatal(err)
  1358  		}
  1359  
  1360  		// application_name didn't exist before 9.0
  1361  		if test.param == "application_name" && getServerVersion(t, db) < 90000 {
  1362  			db.Close()
  1363  			continue
  1364  		}
  1365  
  1366  		tryGetParameterValue := func() (value string, outcome RuntimeTestResult) {
  1367  			defer db.Close()
  1368  			row := db.QueryRow("SELECT current_setting($1)", test.param)
  1369  			err = row.Scan(&value)
  1370  			if err != nil {
  1371  				return "", ResultError
  1372  			}
  1373  			return value, ResultSuccess
  1374  		}
  1375  
  1376  		value, outcome := tryGetParameterValue()
  1377  		if outcome != test.expectedOutcome && outcome == ResultError {
  1378  			t.Fatalf("%v: unexpected error: %v", test.conninfo, err)
  1379  		}
  1380  		if outcome != test.expectedOutcome {
  1381  			t.Fatalf("unexpected outcome %v (was expecting %v) for conninfo \"%s\"",
  1382  				outcome, test.expectedOutcome, test.conninfo)
  1383  		}
  1384  		if value != test.expected {
  1385  			t.Fatalf("bad value for %s: got %s, want %s with conninfo \"%s\"",
  1386  				test.param, value, test.expected, test.conninfo)
  1387  		}
  1388  	}
  1389  }
  1390  
  1391  func TestIsUTF8(t *testing.T) {
  1392  	var cases = []struct {
  1393  		name string
  1394  		want bool
  1395  	}{
  1396  		{"unicode", true},
  1397  		{"utf-8", true},
  1398  		{"utf_8", true},
  1399  		{"UTF-8", true},
  1400  		{"UTF8", true},
  1401  		{"utf8", true},
  1402  		{"u n ic_ode", true},
  1403  		{"ut_f%8", true},
  1404  		{"ubf8", false},
  1405  		{"punycode", false},
  1406  	}
  1407  
  1408  	for _, test := range cases {
  1409  		if g := isUTF8(test.name); g != test.want {
  1410  			t.Errorf("isUTF8(%q) = %v want %v", test.name, g, test.want)
  1411  		}
  1412  	}
  1413  }
  1414  
  1415  func TestQuoteIdentifier(t *testing.T) {
  1416  	var cases = []struct {
  1417  		input string
  1418  		want  string
  1419  	}{
  1420  		{`foo`, `"foo"`},
  1421  		{`foo bar baz`, `"foo bar baz"`},
  1422  		{`foo"bar`, `"foo""bar"`},
  1423  		{"foo\x00bar", `"foo"`},
  1424  		{"\x00foo", `""`},
  1425  	}
  1426  
  1427  	for _, test := range cases {
  1428  		got := QuoteIdentifier(test.input)
  1429  		if got != test.want {
  1430  			t.Errorf("QuoteIdentifier(%q) = %v want %v", test.input, got, test.want)
  1431  		}
  1432  	}
  1433  }