func TestComparisons(t *testing.T) { examples := []struct { A, B Version Lt, Lte bool Gt, Gte bool }{ // TODO: Constraint based testing (ie. https://golang.org/pkg/testing/quick) {Version{0, 0, 0}, Version{0, 0, 0}, false, true, false, true}, {Version{0, 0, 1}, Version{0, 0, 0}, false, false, true, true}, {Version{0, 1, 0}, Version{0, 0, 0}, false, false, true, true}, {Version{1, 0, 0}, Version{0, 0, 0}, false, false, true, true}, {Version{0, 0, 0}, Version{1, 0, 0}, true, true, false, false}, {Version{0, 0, 1}, Version{1, 0, 0}, true, true, false, false}, {Version{0, 1, 0}, Version{1, 0, 0}, true, true, false, false}, {Version{1, 0, 0}, Version{1, 0, 0}, false, true, false, true}, {Version{1, 2, 3}, Version{3, 2, 1}, true, true, false, false}, {Version{0, 3, 1}, Version{0, 1, 3}, false, false, true, true}, {Version{1, 1, 4}, Version{1, 1, 6}, true, true, false, false}, } for _, ex := range examples { expect.Equal(t, ex.A.LessThan(ex.B), ex.Lt, ex.A.String()+" < "+ex.B.String()) expect.Equal(t, ex.A.GreaterThan(ex.B), ex.Gt, ex.A.String()+" > "+ex.B.String()) expect.Equal(t, ex.A.AtMost(ex.B), ex.Lte, ex.A.String()+" <= "+ex.B.String()) expect.Equal(t, ex.A.AtLeast(ex.B), ex.Gte, ex.A.String()+" >= "+ex.B.String()) } }
func TestUnmarshalJSON(t *testing.T) { examples := []struct { Json string Version Version }{ {`"5.0.0"`, Version{5, 0, 0}}, {`"v2.4.12"`, Version{2, 4, 12}}, {`"3.5.0ab"`, Version{3, 5, 0}}, {`"8.22"`, Version{8, 22, 0}}, } var v Version for _, ex := range examples { err := json.Unmarshal([]byte(ex.Json), &v) expect.Nil(t, err, ex.Json) expect.Equal(t, v, ex.Version, ex.Json) } badExamples := []struct { Json string Error string }{ {`null`, "semver: cannot parse version from non-string JSON value"}, {`""`, "semver: json string is not a valid version"}, {`"bogus"`, "semver: json string is not a valid version"}, } for _, ex := range badExamples { err := json.Unmarshal([]byte(ex.Json), &v) if expect.NotNil(t, err, ex.Json) { expect.Equal(t, err.Error(), ex.Error, ex.Json) } } }
func TestLookup(t *testing.T) { // an arbitrary string expect.Equal(t, Lookup("something"), IDENT) // all keyword tokens and no non-keyword tokens for i, name := range tokens { if len(name) > 0 { tok := Token(i) if tok.IsKeyword() { expect.Equal(t, Lookup(name), tok) } else { expect.Equal(t, Lookup(name), IDENT) } } } // case-insensitive expect.Equal(t, Lookup("SELECT"), SELECT) expect.Equal(t, Lookup("Select"), SELECT) expect.Equal(t, Lookup("select"), SELECT) expect.Equal(t, Lookup("sElECt"), SELECT) expect.Equal(t, Lookup("selecT"), SELECT) expect.Equal(t, Lookup("WHERE"), WHERE) expect.Equal(t, Lookup("where"), WHERE) }
func TestScanNullTime(t *testing.T) { var rawTime = time.Now() var mysqlTime = "2010-07-03 13:24:33" var byteTime = []byte(mysqlTime) var notTime = 3 var n Time var err error err = n.Scan(rawTime) expect.Nil(t, err) expect.True(t, n.Valid) expect.NotEmpty(t, n.Time.Format("2006-01-02 15:04:05")) err = n.Scan(mysqlTime) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Time.Format("2006-01-02 15:04:05"), mysqlTime) err = n.Scan(byteTime) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Time.Format("2006-01-02 15:04:05"), mysqlTime) err = n.Scan(notTime) expect.NotNil(t, err) expect.False(t, n.Valid) }
func TestUnmarshalNullDate(t *testing.T) { var jsonNull string = `null` var jsonEmpty string = `""` var stringDate string = `"2010-07-03"` var stringTime string = `"2010-07-03T13:24:33"` var stringBogus string = `"bogus"` var n Date var err error err = json.Unmarshal([]byte(jsonNull), &n) expect.Nil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(jsonEmpty), &n) expect.Nil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(stringDate), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Date.Year, 2010) expect.Equal(t, n.Date.Month, time.July) expect.Equal(t, n.Date.Day, 3) err = json.Unmarshal([]byte(stringTime), &n) expect.NotNil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(stringBogus), &n) expect.NotNil(t, err) expect.False(t, n.Valid) }
func TestUnmarshalNullString(t *testing.T) { var jsonNull string = `null` var jsonNumber string = `3` var jsonEmpty string = `""` var validString string = `"foo"` var n String var err error err = json.Unmarshal([]byte(jsonNull), &n) expect.Nil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(jsonNumber), &n) expect.NotNil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(jsonEmpty), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.String, "") err = json.Unmarshal([]byte(validString), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.String, "foo") }
func TestSelect(t *testing.T) { query := `SELECT * FROM users WHERE id = 3` failOnError := func(pos token.Position, msg string) { t.Errorf("At Line %d, Col %d: %s", pos.Line, pos.Column, msg) } s := Scanner{} s.Init([]byte(query), failOnError, Ruleset{}) var tokens []token.Token MAX_ITER := 200 // Don't loop forever for i := 0; i < MAX_ITER; i++ { _, tok, _ := s.Scan() tokens = append(tokens, tok) if tok == token.INVALID || tok == token.EOS { break } } expect.Equal(t, s.ErrorCount, 0) expect.Equal(t, tokens, []token.Token{ // SELECT * FROM users token.SELECT, token.ASTERISK, token.FROM, token.IDENT, // WHERE id = 3 token.WHERE, token.IDENT, token.EQUALS, token.NUMBER, token.EOS, }) }
func TestMarshalJSON(t *testing.T) { b1, err1 := json.Marshal(Version{1, 0, 0}) expect.Nil(t, err1) expect.Equal(t, string(b1), `"1.0.0"`) b2, err2 := json.Marshal(Version{2, 0, 30}) expect.Nil(t, err2) expect.Equal(t, string(b2), `"2.0.30"`) }
func TestErrorsRespectWhitespace(t *testing.T) { scan, err := scanOnce("\n\n ~\n") expect.Equal(t, token.INVALID, scan.tok) if expect.NotNil(t, err) { expect.Equal(t, err.pos.Offset, 6) expect.Equal(t, err.pos.Line, 3) expect.Equal(t, err.pos.Column, 5) expect.Equal(t, err.msg, `unexpected character U+007E '~'`) } }
func TestPositionString(t *testing.T) { var pos Position pos = Position{"", 0, 0, 0} expect.Equal(t, pos.String(), "-") pos = Position{"Src", 0, 1, 1} expect.Equal(t, pos.String(), "Src:1:1") pos = Position{"Name", 15, 7, 16} expect.Equal(t, pos.String(), "Name:7:16") }
func TestScannerNextCharacter(t *testing.T) { var err *scanError err = scanAll("SELECT * FROM candies\r\n WHERE sweetness = 11\n\r\r") expect.Nil(t, err) err = scanAll(string([]byte{0x00, 0xFF})) if expect.NotNil(t, err) { expect.Equal(t, err.pos.Offset, 0) expect.Equal(t, err.pos.Line, 1) expect.Equal(t, err.pos.Column, 1) expect.Equal(t, err.msg, `unexpected character U+0000`) } }
func TestParseErrors(t *testing.T) { examples := []struct { Input string Error string }{ {Input: `mytable`, Error: `sql:1:8: expected 'SELECT, INSERT, or UPDATE' but received 'Identifier'`}, {Input: `SELECT * WHERE`, Error: `sql:1:15: expected 'FROM' but received 'WHERE'`}, {Input: `SELECT * FROM *`, Error: `sql:1:16: expected 'a table name' but received '*'`}, {Input: "SELECT `mycolumn` FROM mytable", // backticks (w/ ansi ruleset) Error: "sql:1:8: unexpected character U+0060 '`'"}, {Input: `SELECT DISTINCTROW * FROM mytable`, // distinctrow (w/ ansi ruleset) Error: `sql:1:19: statement includes SELECT "DISTINCTROW", but CanSelectDistinctRow is false`}, {Input: `~`, Error: `sql:1:1: unexpected character U+007E '~'`}, {Input: `SELECT * FROM foos; SELECT * FROM bars;`, Error: `sql:1:27: statement does not end at semicolon`}, {Input: `SELECT * FROM mytable PROCEDURE compute(foo)`, // with HasLiteral Error: `sql:1:32: cannot parse statement; reached unimplemented clause at 'PROCEDURE'`}, {Input: `SELECT * FROM mytable +`, // without HasLiteral Error: `sql:1:24: cannot parse statement; reached unimplemented clause at '+'`}, } for _, example := range examples { parser := New([]byte(example.Input), Ruleset{}) stmt, err := parser.ParseStatement() expect.Nil(t, stmt) if expect.NotNil(t, err, "expected a parsing error") { expect.Equal(t, err.Error(), example.Error) } } }
func TestTraceParser(t *testing.T) { output := bytes.Buffer{} parser := New([]byte(`SELECT * FROM table_with_long_name WHERE ♫`), Ruleset{}) parser.Trace = &output stmt, err := parser.ParseStatement() expect.NotNil(t, err, "expected a parsing error") expect.Nil(t, stmt) expected := []string{ regexp.QuoteMeta(` SELECT : SELECT @ Parser.parseSelect:`) + "[0-9]+", regexp.QuoteMeta(` : * @ Parser.parseSelect:`) + "[0-9]+", regexp.QuoteMeta(` FROM : FROM @ Parser.parseSelect:`) + "[0-9]+", regexp.QuoteMeta(` table_~ : Identifier @ Parser.parseSelect:`) + "[0-9]+", regexp.QuoteMeta(` WHERE : WHERE @ Parser.parseSelect:`) + "[0-9]+", regexp.QuoteMeta(` (error) sql:1:42: unexpected character U+266B '♫'`), "$", // string ends with newline } // compare trace output, ignoring the source line numbers lines := strings.Split(output.String(), "\n") if expect.Equal(t, len(lines), len(expected)) { maxSafe := utils.MinInt(len(expected), len(lines)) for i := 0; i < maxSafe; i++ { expect.Regexp(t, lines[i], "^"+expected[i]) } } else { t.Log("Error:", err) t.Log("Full trace output:\n", output.String()) } }
func TestUnmarshalNullTime(t *testing.T) { var jsonNull string = `null` var jsonEmpty string = `""` var stringTime string = `"2010-07-03T13:24:33Z"` var stringBogus string = `"bogus"` var n Time var err error err = json.Unmarshal([]byte(jsonNull), &n) expect.Nil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(jsonEmpty), &n) expect.Nil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(stringTime), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Time.Format("2006-01-02 15:04:05"), "2010-07-03 13:24:33") err = json.Unmarshal([]byte(stringBogus), &n) expect.NotNil(t, err) expect.False(t, n.Valid) }
func TestParseInsert(t *testing.T) { parser := New([]byte(`INSERT INTO mytable`), Ruleset{}) stmt, err := parser.ParseStatement() expect.Nil(t, stmt) if expect.NotNil(t, err) { expect.Equal(t, err.Error(), `sql:1:20: cannot parse statement; reached unimplemented clause at 'mytable'`) } }
func TestParseUpdate(t *testing.T) { parser := New([]byte(`UPDATE mytable SET a = 1`), Ruleset{}) stmt, err := parser.ParseStatement() expect.Nil(t, stmt) if expect.NotNil(t, err) { expect.Equal(t, err.Error(), `sql:1:15: cannot parse statement; reached unimplemented clause at 'mytable'`) } }
func TestSqlParseError(t *testing.T) { db, err := sql.Open("sqltest", "") expect.Nil(t, err) _, err = db.Query("SELECT * FROM") expect.NotNil(t, err) expect.Equal(t, err.Error(), "sql:1:14: expected 'a table name' but received 'End of statement'") }
func TestCreateTable(t *testing.T) { tbl := Table{ Name: "testers", Columns: []Column{ {"name", "text", []string{"NOT NULL"}}, {"experience", "integer", []string{"DEFAULT 0"}}, {"pet_name", "text", nil}, }, } var expected string expected = `CREATE TABLE "testers" ("name" text NOT NULL, "experience" integer DEFAULT 0, "pet_name" text)` expect.Equal(t, tbl.Create().Sql(), expected) expected = `CREATE TABLE IF NOT EXISTS "testers" ("name" text NOT NULL, "experience" integer DEFAULT 0, "pet_name" text)` expect.Equal(t, tbl.Create().IfNotExists().Sql(), expected) expect.Equal(t, len(tbl.Create().Args()), 0) }
func TestSkipsWhitesace(t *testing.T) { scan, err := scanOnce("\n SELECT\n") expect.Nil(t, err) expect.Equal(t, scan.tok, token.SELECT) expect.Equal(t, scan.pos, 5) expect.Equal(t, scan.lit, "SELECT") // scan, err = scanOnce("\n --comment\n SELECT--comment\n") // expect.Nil(t, err) // expect.Equal(t, scan.tok, token.SELECT) // expect.Equal(t, scan.pos, 18) // expect.Equal(t, scan.lit, "SELECT") // // scan, err = scanOnce("\n --comment\r\n SELECT--comment\n") // expect.Nil(t, err) // expect.Equal(t, scan.tok, token.SELECT) // expect.Equal(t, scan.pos, 19) // expect.Equal(t, scan.lit, "SELECT") }
func TestReportsUsefulunknownCharacter(t *testing.T) { scan, err := scanOnce("\u203B") expect.Equal(t, scan.tok, token.INVALID) if expect.NotNil(t, err) { expect.Equal(t, err.pos.Offset, 0) expect.Equal(t, err.pos.Line, 1) expect.Equal(t, err.pos.Column, 1) expect.Equal(t, err.msg, "unexpected character U+203B '\u203B'") } scan, err = scanOnce("\u200b") expect.Equal(t, scan.tok, token.INVALID) if expect.NotNil(t, err) { expect.Equal(t, err.pos.Offset, 0) expect.Equal(t, err.pos.Line, 1) expect.Equal(t, err.pos.Column, 1) expect.Equal(t, err.msg, `unexpected character U+200B`) } }
func TestScansIdentifier(t *testing.T) { scan, err := scanOnce(`simple`) expect.Nil(t, err) expect.Equal(t, scan.tok, token.IDENT) expect.Equal(t, scan.pos, 0) expect.Equal(t, scan.lit, `simple`) scan, err = scanOnce("sim$ple") expect.Equal(t, scan.tok, token.IDENT) expect.Equal(t, scan.pos, 0) expect.Equal(t, scan.lit, `sim`) scan, err = scanOnceWith("sim$ple", Ruleset{DollarIsLetter: true}) expect.Equal(t, scan.tok, token.IDENT) expect.Equal(t, scan.pos, 0) expect.Equal(t, scan.lit, `sim$ple`) }
func TestScanPos(t *testing.T) { var err *scanError handleError := func(pos token.Position, msg string) { err = &scanError{pos, msg} } var scan scanToken s := Scanner{} s.Init([]byte("CREATE TABLE\n candies\n()"), handleError, Ruleset{}) expect.Equal(t, s.Pos(), token.Position{"sql", 0, 1, 1}) expect.Nil(t, err) scan.pos, scan.tok, scan.lit = s.Scan() expect.Equal(t, s.Pos(), token.Position{"sql", 6, 1, 7}) expect.Nil(t, err) scan.pos, scan.tok, scan.lit = s.Scan() expect.Equal(t, s.Pos(), token.Position{"sql", 12, 1, 13}) expect.Nil(t, err) scan.pos, scan.tok, scan.lit = s.Scan() expect.Equal(t, s.Pos(), token.Position{"sql", 22, 2, 10}) expect.Nil(t, err) scan.pos, scan.tok, scan.lit = s.Scan() expect.Equal(t, s.Pos(), token.Position{"sql", 24, 3, 2}) expect.Nil(t, err) scan.pos, scan.tok, scan.lit = s.Scan() expect.Equal(t, s.Pos(), token.Position{"sql", 25, 3, 3}) expect.Nil(t, err) }
func TestScanNullUUID(t *testing.T) { // start with a null UUID and scan a typical UUID { expectedUUID := uuid.UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} stringUUID := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" n := UUID{} err := n.Scan(stringUUID) expect.Nil(t, err, "error unmarshaling null.UUID") expect.True(t, n.Valid, "null.UUID should be valid") expect.Equal(t, n.UUID, expectedUUID, "UUIDs should be equal") } // start with some UUID, and scan nil { n := SomeUUID(uuid.UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}) err := n.Scan(nil) expect.Nil(t, err, "error unmarshaling null.UUID") expect.False(t, n.Valid, "null.UUID should not be valid") expect.Equal(t, n.UUID, uuid.Nil, "null.UUID value should be equal to uuid.Nil") } }
func TestScanNullDate(t *testing.T) { var rawTime = time.Date(2010, time.July, 3, 13, 24, 33, 999, time.UTC) var mysqlTime = "2010-07-03 13:24:33" var mysqlDate = "2010-07-03" var byteTime = []byte(mysqlTime) var byteDate = []byte(mysqlDate) var notTime = 3 var n Date var err error err = n.Scan(rawTime) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Date.Year, 2010) expect.Equal(t, n.Date.Month, time.July) expect.Equal(t, n.Date.Day, 3) err = n.Scan(mysqlTime) expect.NotNil(t, err) expect.False(t, n.Valid) err = n.Scan(mysqlDate) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Date.Year, 2010) expect.Equal(t, n.Date.Month, time.July) expect.Equal(t, n.Date.Day, 3) err = n.Scan(byteTime) expect.NotNil(t, err) expect.False(t, n.Valid) err = n.Scan(byteDate) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Date.Year, 2010) expect.Equal(t, n.Date.Month, time.July) expect.Equal(t, n.Date.Day, 3) err = n.Scan(notTime) expect.NotNil(t, err) expect.False(t, n.Valid) }
func TestUnmarshalNullInt(t *testing.T) { var jsonNull string = `null` var rationalFloat string = `12.22` var roundedFloat string = `16.0` var validZero string = `0` var validNegative string = `-300` var validPositive string = `1602525` var n Int var err error err = json.Unmarshal([]byte(jsonNull), &n) expect.Nil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(rationalFloat), &n) expect.NotNil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(roundedFloat), &n) expect.NotNil(t, err) expect.False(t, n.Valid) err = json.Unmarshal([]byte(validZero), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Int, 0) err = json.Unmarshal([]byte(validNegative), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Int, -300) err = json.Unmarshal([]byte(validPositive), &n) expect.Nil(t, err) expect.True(t, n.Valid) expect.Equal(t, n.Int, 1602525) }
func TestParse(t *testing.T) { examples := []struct { String string Version Version NotOk bool }{ {String: "0.0.0", Version: Version{0, 0, 0}}, {String: "1.0.0", Version: Version{1, 0, 0}}, {String: "14.54.23", Version: Version{14, 54, 23}}, {String: "0.2.4", Version: Version{0, 2, 4}}, {String: "v15.0.3", Version: Version{15, 0, 3}}, {String: "v9a", Version: Version{9, 0, 0}}, {String: "v9.1a", Version: Version{9, 1, 0}}, {String: "hello world", NotOk: true}, {String: "good 1", NotOk: true}, } for _, example := range examples { parsed, ok := Parse(example.String) expect.Equal(t, parsed, example.Version, example.String) expect.Equal(t, !ok, example.NotOk, example.String) } }
func TestDriverUsage(t *testing.T) { db, err := sql.Open("sqltest", "") expect.Nil(t, err) rows, err := db.Query("SELECT * FROM examples") expect.Nil(t, err) total := 0 for rows.Next() { err := rows.Scan() expect.Nil(t, err) total += 1 } err = rows.Close() expect.Nil(t, err) expect.Equal(t, total, 0) }
func TestSnakecase(t *testing.T) { examples := []struct { Input string Output string }{ {Input: "snake_case", Output: "snake_case"}, // NOTE: expected input is camelCase or pascalCase {Input: "camelCase", Output: "camel_case"}, {Input: "PascalCase", Output: "pascal_case"}, {Input: "exampleID", Output: "example_id"}, {Input: "HTTPPost", Output: "http_post"}, {Input: "HostURL", Output: "host_url"}, {Input: "XMLHttpRequest", Output: "xml_http_request"}, } for _, ex := range examples { expect.Equal(t, snakecase(ex.Input), ex.Output) } }
func TestString(t *testing.T) { examples := []struct { Version Version String string }{ {Version: Version{0, 0, 0}, String: "0.0.0"}, {Version: Version{1, 0, 0}, String: "1.0.0"}, {Version: Version{14, 54, 23}, String: "14.54.23"}, {Version: Version{0, 2, 4}, String: "0.2.4"}, {Version: Version{15, 0, 3}, String: "15.0.3"}, {Version: Version{9, 0, 0}, String: "9.0.0"}, {Version: Version{9, 1, 0}, String: "9.1.0"}, } for _, ex := range examples { expect.Equal(t, ex.Version.String(), ex.String) } }
func TestScansQuotedIdentifier(t *testing.T) { scan, err := scanOnce(`"simple"`) expect.Nil(t, err) expect.Equal(t, scan.tok, token.QUOTED_IDENT) expect.Equal(t, scan.pos, 0) expect.Equal(t, scan.lit, `simple`) scan, err = scanOnceWith("`simple`", Ruleset{BacktickIsQuotemark: true}) expect.Nil(t, err) expect.Equal(t, scan.tok, token.QUOTED_IDENT) expect.Equal(t, scan.pos, 0) expect.Equal(t, scan.lit, `simple`) }