203 lines
4.7 KiB
Go
203 lines
4.7 KiB
Go
package tokenizer
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestTokenizer_NextTokenType(t *testing.T) {
|
|
type Case struct {
|
|
input string
|
|
expected TokenType
|
|
}
|
|
|
|
cases := []Case{
|
|
{input: "SELECT", expected: Select},
|
|
{input: "FROM", expected: From},
|
|
{input: "WHERE", expected: Where},
|
|
{input: "AS", expected: As},
|
|
{input: "OR", expected: Or},
|
|
{input: "AND", expected: And},
|
|
{input: "NOT", expected: Not},
|
|
{input: "IN", expected: In},
|
|
{input: "IS", expected: Is},
|
|
{input: "LIKE", expected: Like},
|
|
{input: "RLIKE", expected: RLike},
|
|
{input: "foo", expected: Identifier},
|
|
{input: "(", expected: OpenParen},
|
|
{input: ")", expected: CloseParen},
|
|
{input: ",", expected: Comma},
|
|
{input: "-", expected: Hyphen},
|
|
{input: "=", expected: Equals},
|
|
{input: "<>", expected: NotEquals},
|
|
{input: "<", expected: LessThan},
|
|
{input: "<=", expected: LessThanEquals},
|
|
{input: ">", expected: GreaterThan},
|
|
{input: ">=", expected: GreaterThanEquals},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
actual := NewTokenizer(c.input).Next()
|
|
expected := &Token{Type: c.expected, Raw: c.input}
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", expected, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenizer_NextRaw(t *testing.T) {
|
|
type Case struct {
|
|
input string
|
|
expected string
|
|
}
|
|
|
|
// TODO: Fix the last 2 cases, they're currently hanging.
|
|
cases := []Case{
|
|
{input: "foo", expected: "foo"},
|
|
{input: " foo ", expected: "foo"},
|
|
{input: "\" foo \"", expected: " foo "},
|
|
{input: "' foo '", expected: " foo "},
|
|
{input: "` foo `", expected: " foo "},
|
|
// Case{input: "\"foo'bar\"", expected: "foo'bar"},
|
|
// Case{input: "\"()\"", expected: "()"},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
actual := NewTokenizer(c.input).Next()
|
|
expected := &Token{Type: Identifier, Raw: c.expected}
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", expected, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenizer_AllSimple(t *testing.T) {
|
|
input := `
|
|
SELECT
|
|
name, size
|
|
FROM
|
|
~/Desktop
|
|
WHERE
|
|
name LIKE %go
|
|
`
|
|
|
|
actual := NewTokenizer(input).All()
|
|
expected := []Token{
|
|
{Type: Select, Raw: "SELECT"},
|
|
{Type: Identifier, Raw: "name"},
|
|
{Type: Comma, Raw: ","},
|
|
{Type: Identifier, Raw: "size"},
|
|
{Type: From, Raw: "FROM"},
|
|
{Type: Identifier, Raw: "~/Desktop"},
|
|
{Type: Where, Raw: "WHERE"},
|
|
{Type: Identifier, Raw: "name"},
|
|
{Type: Like, Raw: "LIKE"},
|
|
{Type: Identifier, Raw: "%go"},
|
|
}
|
|
|
|
for i := range expected {
|
|
if !reflect.DeepEqual(actual[i], expected[i]) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", expected[i], actual[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenizer_AllSubquery(t *testing.T) {
|
|
input := `
|
|
SELECT
|
|
name, size
|
|
FROM
|
|
~/Desktop
|
|
WHERE
|
|
name LIKE %go OR
|
|
name IN (
|
|
SELECT
|
|
name
|
|
FROM
|
|
$GOPATH/src/github.com
|
|
WHERE
|
|
name RLIKE .*_test\.go)
|
|
`
|
|
|
|
actual := NewTokenizer(input).All()
|
|
expected := []Token{
|
|
{Type: Select, Raw: "SELECT"},
|
|
{Type: Identifier, Raw: "name"},
|
|
{Type: Comma, Raw: ","},
|
|
{Type: Identifier, Raw: "size"},
|
|
{Type: From, Raw: "FROM"},
|
|
{Type: Identifier, Raw: "~/Desktop"},
|
|
{Type: Where, Raw: "WHERE"},
|
|
{Type: Identifier, Raw: "name"},
|
|
{Type: Like, Raw: "LIKE"},
|
|
{Type: Identifier, Raw: "%go"},
|
|
{Type: Or, Raw: "OR"},
|
|
{Type: Identifier, Raw: "name"},
|
|
{Type: In, Raw: "IN"},
|
|
{Type: OpenParen, Raw: "("},
|
|
{Type: Subquery, Raw: "SELECT name FROM $GOPATH/src/github.com WHERE name RLIKE .*_test\\.go"},
|
|
{Type: CloseParen, Raw: ")"},
|
|
}
|
|
|
|
for i := range expected {
|
|
if !reflect.DeepEqual(actual[i], expected[i]) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", expected[i], actual[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenizer_ReadWord(t *testing.T) {
|
|
type Case struct {
|
|
input string
|
|
expected string
|
|
}
|
|
|
|
cases := []Case{
|
|
{input: "foo", expected: "foo"},
|
|
{input: "foo bar", expected: "foo"},
|
|
{input: "", expected: ""},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
actual := NewTokenizer(c.input).readWord()
|
|
if !reflect.DeepEqual(actual, c.expected) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", c.expected, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenizer_ReadQuery(t *testing.T) {
|
|
type Case struct {
|
|
input string
|
|
expected string
|
|
}
|
|
|
|
// TODO: Complete these cases.
|
|
cases := []Case{}
|
|
|
|
for _, c := range cases {
|
|
actual := NewTokenizer(c.input).readQuery()
|
|
if !reflect.DeepEqual(actual, c.expected) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", c.expected, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenizer_ReadUntil(t *testing.T) {
|
|
type Case struct {
|
|
input string
|
|
until []rune
|
|
expected string
|
|
}
|
|
|
|
// TODO: Complete these cases.
|
|
cases := []Case{}
|
|
|
|
for _, c := range cases {
|
|
actual := NewTokenizer(c.input).readUntil(c.until...)
|
|
if !reflect.DeepEqual(actual, c.expected) {
|
|
t.Fatalf("\nExpected: %v\n Got: %v", c.expected, actual)
|
|
}
|
|
}
|
|
}
|