Upgrading server dependancies (#8154)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8d66523ba7
Коммит
961c04cae9
310
vendor/github.com/go-sql-driver/mysql/driver_test.go
сгенерированный
поставляемый
310
vendor/github.com/go-sql-driver/mysql/driver_test.go
сгенерированный
поставляемый
@@ -27,6 +27,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Ensure that all the driver interfaces are implemented
|
||||
var (
|
||||
_ driver.Rows = &binaryRows{}
|
||||
_ driver.Rows = &textRows{}
|
||||
)
|
||||
|
||||
var (
|
||||
user string
|
||||
pass string
|
||||
@@ -63,7 +69,7 @@ func init() {
|
||||
addr = env("MYSQL_TEST_ADDR", "localhost:3306")
|
||||
dbname = env("MYSQL_TEST_DBNAME", "gotest")
|
||||
netAddr = fmt.Sprintf("%s(%s)", prot, addr)
|
||||
dsn = fmt.Sprintf("%s:%s@%s/%s?timeout=30s&strict=true", user, pass, netAddr, dbname)
|
||||
dsn = fmt.Sprintf("%s:%s@%s/%s?timeout=30s", user, pass, netAddr, dbname)
|
||||
c, err := net.Dial(prot, addr)
|
||||
if err == nil {
|
||||
available = true
|
||||
@@ -171,6 +177,17 @@ func (dbt *DBTest) mustQuery(query string, args ...interface{}) (rows *sql.Rows)
|
||||
return rows
|
||||
}
|
||||
|
||||
func maybeSkip(t *testing.T, err error, skipErrno uint16) {
|
||||
mySQLErr, ok := err.(*MySQLError)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if mySQLErr.Number == skipErrno {
|
||||
t.Skipf("skipping test for error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyQuery(t *testing.T) {
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
// just a comment, no query
|
||||
@@ -482,6 +499,85 @@ func TestString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
type testValuer struct {
|
||||
value string
|
||||
}
|
||||
|
||||
func (tv testValuer) Value() (driver.Value, error) {
|
||||
return tv.value, nil
|
||||
}
|
||||
|
||||
func TestValuer(t *testing.T) {
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
in := testValuer{"a_value"}
|
||||
var out string
|
||||
var rows *sql.Rows
|
||||
|
||||
dbt.mustExec("CREATE TABLE test (value VARCHAR(255)) CHARACTER SET utf8")
|
||||
dbt.mustExec("INSERT INTO test VALUES (?)", in)
|
||||
rows = dbt.mustQuery("SELECT value FROM test")
|
||||
if rows.Next() {
|
||||
rows.Scan(&out)
|
||||
if in.value != out {
|
||||
dbt.Errorf("Valuer: %v != %s", in, out)
|
||||
}
|
||||
} else {
|
||||
dbt.Errorf("Valuer: no data")
|
||||
}
|
||||
|
||||
dbt.mustExec("DROP TABLE IF EXISTS test")
|
||||
})
|
||||
}
|
||||
|
||||
type testValuerWithValidation struct {
|
||||
value string
|
||||
}
|
||||
|
||||
func (tv testValuerWithValidation) Value() (driver.Value, error) {
|
||||
if len(tv.value) == 0 {
|
||||
return nil, fmt.Errorf("Invalid string valuer. Value must not be empty")
|
||||
}
|
||||
|
||||
return tv.value, nil
|
||||
}
|
||||
|
||||
func TestValuerWithValidation(t *testing.T) {
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
in := testValuerWithValidation{"a_value"}
|
||||
var out string
|
||||
var rows *sql.Rows
|
||||
|
||||
dbt.mustExec("CREATE TABLE testValuer (value VARCHAR(255)) CHARACTER SET utf8")
|
||||
dbt.mustExec("INSERT INTO testValuer VALUES (?)", in)
|
||||
|
||||
rows = dbt.mustQuery("SELECT value FROM testValuer")
|
||||
defer rows.Close()
|
||||
|
||||
if rows.Next() {
|
||||
rows.Scan(&out)
|
||||
if in.value != out {
|
||||
dbt.Errorf("Valuer: %v != %s", in, out)
|
||||
}
|
||||
} else {
|
||||
dbt.Errorf("Valuer: no data")
|
||||
}
|
||||
|
||||
if _, err := dbt.db.Exec("INSERT INTO testValuer VALUES (?)", testValuerWithValidation{""}); err == nil {
|
||||
dbt.Errorf("Failed to check valuer error")
|
||||
}
|
||||
|
||||
if _, err := dbt.db.Exec("INSERT INTO testValuer VALUES (?)", nil); err != nil {
|
||||
dbt.Errorf("Failed to check nil")
|
||||
}
|
||||
|
||||
if _, err := dbt.db.Exec("INSERT INTO testValuer VALUES (?)", map[string]bool{}); err == nil {
|
||||
dbt.Errorf("Failed to check not valuer")
|
||||
}
|
||||
|
||||
dbt.mustExec("DROP TABLE IF EXISTS testValuer")
|
||||
})
|
||||
}
|
||||
|
||||
type timeTests struct {
|
||||
dbtype string
|
||||
tlayout string
|
||||
@@ -684,7 +780,7 @@ func TestDateTime(t *testing.T) {
|
||||
for _, setup := range setups.tests {
|
||||
allowBinTime := true
|
||||
if setup.s == "" {
|
||||
// fill time string whereever Go can reliable produce it
|
||||
// fill time string wherever Go can reliable produce it
|
||||
setup.s = setup.t.Format(setups.tlayout)
|
||||
} else if setup.s[0] == '!' {
|
||||
// skip tests using setup.t as source in queries
|
||||
@@ -856,14 +952,14 @@ func TestNULL(t *testing.T) {
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
if b != nil {
|
||||
dbt.Error("non-nil []byte wich should be nil")
|
||||
dbt.Error("non-nil []byte which should be nil")
|
||||
}
|
||||
// Read non-nil
|
||||
if err = nonNullStmt.QueryRow().Scan(&b); err != nil {
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
if b == nil {
|
||||
dbt.Error("nil []byte wich should be non-nil")
|
||||
dbt.Error("nil []byte which should be non-nil")
|
||||
}
|
||||
// Insert nil
|
||||
b = nil
|
||||
@@ -953,7 +1049,7 @@ func TestUint64(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLongData(t *testing.T) {
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
runTests(t, dsn+"&maxAllowedPacket=0", func(dbt *DBTest) {
|
||||
var maxAllowedPacketSize int
|
||||
err := dbt.db.QueryRow("select @@max_allowed_packet").Scan(&maxAllowedPacketSize)
|
||||
if err != nil {
|
||||
@@ -1054,22 +1150,36 @@ func TestLoadData(t *testing.T) {
|
||||
dbt.Fatalf("rows count mismatch. Got %d, want 4", i)
|
||||
}
|
||||
}
|
||||
file, err := ioutil.TempFile("", "gotest")
|
||||
defer os.Remove(file.Name())
|
||||
if err != nil {
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
file.WriteString("1\ta string\n2\ta string containing a \\t\n3\ta string containing a \\n\n4\ta string containing both \\t\\n\n")
|
||||
file.Close()
|
||||
|
||||
dbt.db.Exec("DROP TABLE IF EXISTS test")
|
||||
dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8")
|
||||
|
||||
// Local File
|
||||
file, err := ioutil.TempFile("", "gotest")
|
||||
defer os.Remove(file.Name())
|
||||
if err != nil {
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
RegisterLocalFile(file.Name())
|
||||
|
||||
// Try first with empty file
|
||||
dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name()))
|
||||
var count int
|
||||
err = dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&count)
|
||||
if err != nil {
|
||||
dbt.Fatal(err.Error())
|
||||
}
|
||||
if count != 0 {
|
||||
dbt.Fatalf("unexpected row count: got %d, want 0", count)
|
||||
}
|
||||
|
||||
// Then fille File with data and try to load it
|
||||
file.WriteString("1\ta string\n2\ta string containing a \\t\n3\ta string containing a \\n\n4\ta string containing both \\t\\n\n")
|
||||
file.Close()
|
||||
dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name()))
|
||||
verifyLoadDataResult()
|
||||
// negative test
|
||||
|
||||
// Try with non-existing file
|
||||
_, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'doesnotexist' INTO TABLE test")
|
||||
if err == nil {
|
||||
dbt.Fatal("load non-existent file didn't fail")
|
||||
@@ -1145,84 +1255,6 @@ func TestFoundRows(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrict(t *testing.T) {
|
||||
// ALLOW_INVALID_DATES to get rid of stricter modes - we want to test for warnings, not errors
|
||||
relaxedDsn := dsn + "&sql_mode='ALLOW_INVALID_DATES,NO_AUTO_CREATE_USER'"
|
||||
// make sure the MySQL version is recent enough with a separate connection
|
||||
// before running the test
|
||||
conn, err := MySQLDriver{}.Open(relaxedDsn)
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
if me, ok := err.(*MySQLError); ok && me.Number == 1231 {
|
||||
// Error 1231: Variable 'sql_mode' can't be set to the value of 'ALLOW_INVALID_DATES'
|
||||
// => skip test, MySQL server version is too old
|
||||
return
|
||||
}
|
||||
runTests(t, relaxedDsn, func(dbt *DBTest) {
|
||||
dbt.mustExec("CREATE TABLE test (a TINYINT NOT NULL, b CHAR(4))")
|
||||
|
||||
var queries = [...]struct {
|
||||
in string
|
||||
codes []string
|
||||
}{
|
||||
{"DROP TABLE IF EXISTS no_such_table", []string{"1051"}},
|
||||
{"INSERT INTO test VALUES(10,'mysql'),(NULL,'test'),(300,'Open Source')", []string{"1265", "1048", "1264", "1265"}},
|
||||
}
|
||||
var err error
|
||||
|
||||
var checkWarnings = func(err error, mode string, idx int) {
|
||||
if err == nil {
|
||||
dbt.Errorf("expected STRICT error on query [%s] %s", mode, queries[idx].in)
|
||||
}
|
||||
|
||||
if warnings, ok := err.(MySQLWarnings); ok {
|
||||
var codes = make([]string, len(warnings))
|
||||
for i := range warnings {
|
||||
codes[i] = warnings[i].Code
|
||||
}
|
||||
if len(codes) != len(queries[idx].codes) {
|
||||
dbt.Errorf("unexpected STRICT error count on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
|
||||
}
|
||||
|
||||
for i := range warnings {
|
||||
if codes[i] != queries[idx].codes[i] {
|
||||
dbt.Errorf("unexpected STRICT error codes on query [%s] %s: Wanted %v, Got %v", mode, queries[idx].in, queries[idx].codes, codes)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
dbt.Errorf("unexpected error on query [%s] %s: %s", mode, queries[idx].in, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// text protocol
|
||||
for i := range queries {
|
||||
_, err = dbt.db.Exec(queries[i].in)
|
||||
checkWarnings(err, "text", i)
|
||||
}
|
||||
|
||||
var stmt *sql.Stmt
|
||||
|
||||
// binary protocol
|
||||
for i := range queries {
|
||||
stmt, err = dbt.db.Prepare(queries[i].in)
|
||||
if err != nil {
|
||||
dbt.Errorf("error on preparing query %s: %s", queries[i].in, err.Error())
|
||||
}
|
||||
|
||||
_, err = stmt.Exec()
|
||||
checkWarnings(err, "binary", i)
|
||||
|
||||
err = stmt.Close()
|
||||
if err != nil {
|
||||
dbt.Errorf("error on closing stmt for query %s: %s", queries[i].in, err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestTLS(t *testing.T) {
|
||||
tlsTest := func(dbt *DBTest) {
|
||||
if err := dbt.db.Ping(); err != nil {
|
||||
@@ -1422,7 +1454,6 @@ func TestTimezoneConversion(t *testing.T) {
|
||||
|
||||
// Regression test for timezone handling
|
||||
tzTest := func(dbt *DBTest) {
|
||||
|
||||
// Create table
|
||||
dbt.mustExec("CREATE TABLE test (ts TIMESTAMP)")
|
||||
|
||||
@@ -1638,8 +1669,9 @@ func TestStmtMultiRows(t *testing.T) {
|
||||
// Regression test for
|
||||
// * more than 32 NULL parameters (issue 209)
|
||||
// * more parameters than fit into the buffer (issue 201)
|
||||
// * parameters * 64 > max_allowed_packet (issue 734)
|
||||
func TestPreparedManyCols(t *testing.T) {
|
||||
const numParams = defaultBufSize
|
||||
numParams := 65535
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
query := "SELECT ?" + strings.Repeat(",?", numParams-1)
|
||||
stmt, err := dbt.db.Prepare(query)
|
||||
@@ -1647,15 +1679,25 @@ func TestPreparedManyCols(t *testing.T) {
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
// create more parameters than fit into the buffer
|
||||
// which will take nil-values
|
||||
params := make([]interface{}, numParams)
|
||||
rows, err := stmt.Query(params...)
|
||||
if err != nil {
|
||||
stmt.Close()
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Close()
|
||||
|
||||
// Create 0byte string which we can't send via STMT_LONG_DATA.
|
||||
for i := 0; i < numParams; i++ {
|
||||
params[i] = ""
|
||||
}
|
||||
rows, err = stmt.Query(params...)
|
||||
if err != nil {
|
||||
dbt.Fatal(err)
|
||||
}
|
||||
rows.Close()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1739,7 +1781,7 @@ func TestCustomDial(t *testing.T) {
|
||||
return net.Dial(prot, addr)
|
||||
})
|
||||
|
||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@mydial(%s)/%s?timeout=30s&strict=true", user, pass, addr, dbname))
|
||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@mydial(%s)/%s?timeout=30s", user, pass, addr, dbname))
|
||||
if err != nil {
|
||||
t.Fatalf("error connecting: %s", err.Error())
|
||||
}
|
||||
@@ -1836,7 +1878,7 @@ func TestUnixSocketAuthFail(t *testing.T) {
|
||||
}
|
||||
}
|
||||
t.Logf("socket: %s", socket)
|
||||
badDSN := fmt.Sprintf("%s:%s@unix(%s)/%s?timeout=30s&strict=true", user, badPass, socket, dbname)
|
||||
badDSN := fmt.Sprintf("%s:%s@unix(%s)/%s?timeout=30s", user, badPass, socket, dbname)
|
||||
db, err := sql.Open("mysql", badDSN)
|
||||
if err != nil {
|
||||
t.Fatalf("error connecting: %s", err.Error())
|
||||
@@ -1902,3 +1944,77 @@ func TestInterruptBySignal(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestColumnsReusesSlice(t *testing.T) {
|
||||
rows := mysqlRows{
|
||||
rs: resultSet{
|
||||
columns: []mysqlField{
|
||||
{
|
||||
tableName: "test",
|
||||
name: "A",
|
||||
},
|
||||
{
|
||||
tableName: "test",
|
||||
name: "B",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
allocs := testing.AllocsPerRun(1, func() {
|
||||
cols := rows.Columns()
|
||||
|
||||
if len(cols) != 2 {
|
||||
t.Fatalf("expected 2 columns, got %d", len(cols))
|
||||
}
|
||||
})
|
||||
|
||||
if allocs != 0 {
|
||||
t.Fatalf("expected 0 allocations, got %d", int(allocs))
|
||||
}
|
||||
|
||||
if rows.rs.columnNames == nil {
|
||||
t.Fatalf("expected columnNames to be set, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRejectReadOnly(t *testing.T) {
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
// Create Table
|
||||
dbt.mustExec("CREATE TABLE test (value BOOL)")
|
||||
// Set the session to read-only. We didn't set the `rejectReadOnly`
|
||||
// option, so any writes after this should fail.
|
||||
_, err := dbt.db.Exec("SET SESSION TRANSACTION READ ONLY")
|
||||
// Error 1193: Unknown system variable 'TRANSACTION' => skip test,
|
||||
// MySQL server version is too old
|
||||
maybeSkip(t, err, 1193)
|
||||
if _, err := dbt.db.Exec("DROP TABLE test"); err == nil {
|
||||
t.Fatalf("writing to DB in read-only session without " +
|
||||
"rejectReadOnly did not error")
|
||||
}
|
||||
// Set the session back to read-write so runTests() can properly clean
|
||||
// up the table `test`.
|
||||
dbt.mustExec("SET SESSION TRANSACTION READ WRITE")
|
||||
})
|
||||
|
||||
// Enable the `rejectReadOnly` option.
|
||||
runTests(t, dsn+"&rejectReadOnly=true", func(dbt *DBTest) {
|
||||
// Create Table
|
||||
dbt.mustExec("CREATE TABLE test (value BOOL)")
|
||||
// Set the session to read only. Any writes after this should error on
|
||||
// a driver.ErrBadConn, and cause `database/sql` to initiate a new
|
||||
// connection.
|
||||
dbt.mustExec("SET SESSION TRANSACTION READ ONLY")
|
||||
// This would error, but `database/sql` should automatically retry on a
|
||||
// new connection which is not read-only, and eventually succeed.
|
||||
dbt.mustExec("DROP TABLE test")
|
||||
})
|
||||
}
|
||||
|
||||
func TestPing(t *testing.T) {
|
||||
runTests(t, dsn, func(dbt *DBTest) {
|
||||
if err := dbt.db.Ping(); err != nil {
|
||||
dbt.fail("Ping", "Ping", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user