glob/compiler/compiler_test.go

574 lines
14 KiB
Go
Raw Normal View History

2016-05-30 19:35:53 +03:00
package compiler
import (
"github.com/gobwas/glob/match"
"github.com/gobwas/glob/match/debug"
"github.com/gobwas/glob/syntax/ast"
"reflect"
"testing"
)
var separators = []rune{'.'}
func TestCommonChildren(t *testing.T) {
for i, test := range []struct {
nodes []*ast.Node
left []*ast.Node
right []*ast.Node
}{
// {
// nodes: []*ast.Node{
// ast.NewNode(ast.KindNothing, nil,
// ast.NewNode(ast.KindText, ast.Text{"a"}),
// ast.NewNode(ast.KindText, ast.Text{"z"}),
// ast.NewNode(ast.KindText, ast.Text{"c"}),
// ),
// ast.NewNode(ast.KindNothing, nil,
// ast.NewNode(ast.KindText, ast.Text{"a"}),
// ast.NewNode(ast.KindText, ast.Text{"b"}),
// ast.NewNode(ast.KindText, ast.Text{"c"}),
// ),
// },
// left: []*ast.Node{
// ast.NewNode(ast.KindText, ast.Text{"a"}),
// },
// right: []*ast.Node{
// ast.NewNode(ast.KindText, ast.Text{"c"}),
// },
// },
{
nodes: []*ast.Node{
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
ast.NewNode(ast.KindText, ast.Text{"d"}),
),
ast.NewNode(ast.KindNothing, nil,
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
ast.NewNode(ast.KindText, ast.Text{"d"}),
),
},
left: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"a"}),
ast.NewNode(ast.KindText, ast.Text{"b"}),
ast.NewNode(ast.KindText, ast.Text{"c"}),
},
right: []*ast.Node{
ast.NewNode(ast.KindText, ast.Text{"d"}),
},
},
} {
left, right := commonChildren(test.nodes)
if !nodesEqual(left, test.left) {
t.Errorf("[%d] left, right := commonChildren(); left = %v; want %v", i, left, test.left)
}
if !nodesEqual(right, test.right) {
t.Errorf("[%d] left, right := commonChildren(); right = %v; want %v", i, right, test.right)
}
}
}
func nodesEqual(a, b []*ast.Node) bool {
if len(a) != len(b) {
return false
}
for i, av := range a {
if !av.Equal(b[i]) {
return false
}
}
return true
}
func TestGlueMatchers(t *testing.T) {
for id, test := range []struct {
in []match.Matcher
exp match.Matcher
}{
{
[]match.Matcher{
match.NewSuper(),
match.NewSingle(nil),
},
match.NewMin(1),
},
{
[]match.Matcher{
match.NewAny(separators),
match.NewSingle(separators),
},
match.EveryOf{match.Matchers{
match.NewMin(1),
match.NewContains(string(separators), true),
}},
},
{
[]match.Matcher{
match.NewSingle(nil),
match.NewSingle(nil),
match.NewSingle(nil),
},
match.EveryOf{match.Matchers{
match.NewMin(3),
match.NewMax(3),
}},
},
{
[]match.Matcher{
match.NewList([]rune{'a'}, true),
match.NewAny([]rune{'a'}),
},
match.EveryOf{match.Matchers{
match.NewMin(1),
match.NewContains("a", true),
}},
},
} {
act, err := compileMatchers(test.in)
if err != nil {
t.Errorf("#%d convert matchers error: %s", id, err)
continue
}
if !reflect.DeepEqual(act, test.exp) {
t.Errorf("#%d unexpected convert matchers result:\nact: %#v;\nexp: %#v", id, act, test.exp)
continue
}
}
}
func TestCompileMatchers(t *testing.T) {
for id, test := range []struct {
in []match.Matcher
exp match.Matcher
}{
{
[]match.Matcher{
match.NewSuper(),
match.NewSingle(separators),
match.NewText("c"),
},
match.NewBTree(
match.NewText("c"),
match.NewBTree(
match.NewSingle(separators),
match.NewSuper(),
nil,
),
nil,
),
},
{
[]match.Matcher{
match.NewAny(nil),
match.NewText("c"),
match.NewAny(nil),
},
match.NewBTree(
match.NewText("c"),
match.NewAny(nil),
match.NewAny(nil),
),
},
{
[]match.Matcher{
match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"),
match.NewSingle(nil),
},
match.NewRow(
4,
match.Matchers{
match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"),
match.NewSingle(nil),
}...,
),
},
} {
act, err := compileMatchers(test.in)
if err != nil {
t.Errorf("#%d convert matchers error: %s", id, err)
continue
}
if !reflect.DeepEqual(act, test.exp) {
t.Errorf("#%d unexpected convert matchers result:\nact: %#v\nexp: %#v", id, act, test.exp)
continue
}
}
}
func TestConvertMatchers(t *testing.T) {
for id, test := range []struct {
in, exp []match.Matcher
}{
{
[]match.Matcher{
match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"),
match.NewSingle(nil),
match.NewAny(nil),
},
[]match.Matcher{
match.NewRow(
4,
[]match.Matcher{
match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"),
match.NewSingle(nil),
}...,
),
match.NewAny(nil),
},
},
{
[]match.Matcher{
match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"),
match.NewSingle(nil),
match.NewAny(nil),
match.NewSingle(nil),
match.NewSingle(nil),
match.NewAny(nil),
},
[]match.Matcher{
match.NewRow(
3,
match.Matchers{
match.NewRange('a', 'c', true),
match.NewList([]rune{'z', 't', 'e'}, false),
match.NewText("c"),
}...,
),
match.NewMin(3),
},
},
} {
act := minimizeMatchers(test.in)
if !reflect.DeepEqual(act, test.exp) {
t.Errorf("#%d unexpected convert matchers 2 result:\nact: %#v\nexp: %#v", id, act, test.exp)
continue
}
}
}
func TestCompiler(t *testing.T) {
for id, test := range []struct {
ast *ast.Node
result match.Matcher
sep []rune
}{
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ),
// result: match.NewText("abc"),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ),
// sep: separators,
// result: match.NewAny(separators),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ),
// result: match.NewSuper(),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSuper, nil),
// ),
// result: match.NewSuper(),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSingle, nil),
// ),
// sep: separators,
// result: match.NewSingle(separators),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindRange, &ast.Range{
// Lo: 'a',
// Hi: 'z',
// Not: true,
// }),
// ),
// result: match.NewRange('a', 'z', true),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindList, &ast.List{
// Chars: "abc",
// Not: true,
// }),
// ),
// result: match.NewList([]rune{'a', 'b', 'c'}, true),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil),
// ),
// sep: separators,
// result: match.EveryOf{Matchers: match.Matchers{
// match.NewMin(3),
// match.NewContains(string(separators), true),
// }},
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindSingle, nil),
// ),
// result: match.NewMin(3),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindSingle, nil),
// ),
// sep: separators,
// result: match.NewBTree(
// match.NewRow(
// 4,
// match.Matchers{
// match.NewText("abc"),
// match.NewSingle(separators),
// }...,
// ),
// match.NewAny(separators),
// nil,
// ),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"/"}),
// ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindText, &ast.Text{"z"}),
// ast.NewNode(ast.KindText, &ast.Text{"ab"}),
// ),
// ast.NewNode(ast.KindSuper, nil),
// ),
// sep: separators,
// result: match.NewBTree(
// match.NewText("/"),
// nil,
// match.NewBTree(
// match.NewAnyOf(match.NewText("z"), match.NewText("ab")),
// nil,
// match.NewSuper(),
// ),
// ),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSuper, nil),
// ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindSingle, nil),
// ),
// sep: separators,
// result: match.NewBTree(
// match.NewRow(
// 5,
// match.Matchers{
// match.NewSingle(separators),
// match.NewText("abc"),
// match.NewSingle(separators),
// }...,
// ),
// match.NewSuper(),
// nil,
// ),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ),
// result: match.NewSuffix("abc"),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil),
// ),
// result: match.NewPrefix("abc"),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"def"}),
// ),
// result: match.NewPrefixSuffix("abc", "def"),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil),
// ),
// result: match.NewContains("abc", false),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindAny, nil),
// ast.NewNode(ast.KindAny, nil),
// ),
// sep: separators,
// result: match.NewBTree(
// match.NewText("abc"),
// match.NewAny(separators),
// match.NewAny(separators),
// ),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindSuper, nil),
// ast.NewNode(ast.KindSingle, nil),
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindSuper, nil),
// ast.NewNode(ast.KindSingle, nil),
// ),
// result: match.NewBTree(
// match.NewText("abc"),
// match.NewMin(1),
// match.NewMin(1),
// ),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ),
// result: match.NewText("abc"),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ),
// ),
// ),
// ),
// ),
// result: match.NewText("abc"),
// },
{
ast: ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindAnyOf, nil,
ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}),
ast.NewNode(ast.KindSingle, nil),
),
ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}),
ast.NewNode(ast.KindList, &ast.List{Chars: "def"}),
),
ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}),
),
ast.NewNode(ast.KindPattern, nil,
ast.NewNode(ast.KindText, &ast.Text{"abc"}),
),
),
),
result: match.NewBTree(
match.NewText("abc"),
nil,
match.AnyOf{Matchers: match.Matchers{
match.NewSingle(nil),
match.NewList([]rune{'d', 'e', 'f'}, false),
match.NewNothing(),
}},
),
},
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindRange, &ast.Range{Lo: 'a', Hi: 'z'}),
// ast.NewNode(ast.KindRange, &ast.Range{Lo: 'a', Hi: 'x', Not: true}),
// ast.NewNode(ast.KindAny, nil),
// ),
// result: match.NewBTree(
// match.NewRow(
// 2,
// match.Matchers{
// match.NewRange('a', 'z', false),
// match.NewRange('a', 'x', true),
// }...,
// ),
// nil,
// match.NewSuper(),
// ),
// },
// {
// ast: ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindAnyOf, nil,
// ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindList, &ast.List{Chars: "abc"}),
// ast.NewNode(ast.KindText, &ast.Text{"ghi"}),
// ),
// ast.NewNode(ast.KindPattern, nil,
// ast.NewNode(ast.KindText, &ast.Text{"abc"}),
// ast.NewNode(ast.KindList, &ast.List{Chars: "def"}),
// ast.NewNode(ast.KindText, &ast.Text{"ghi"}),
// ),
// ),
// ),
// result: match.NewRow(
// 7,
// match.Matchers{
// match.NewText("abc"),
// match.AnyOf{Matchers: match.Matchers{
// match.NewList([]rune{'a', 'b', 'c'}, false),
// match.NewList([]rune{'d', 'e', 'f'}, false),
// }},
// match.NewText("ghi"),
// }...,
// ),
// },
} {
m, err := Compile(test.ast, test.sep)
if err != nil {
t.Errorf("compilation error: %s", err)
continue
}
if !reflect.DeepEqual(m, test.result) {
t.Errorf("[%d] Compile():\nexp: %#v\nact: %#v\n\ngraphviz:\nexp:\n%s\nact:\n%s\n", id, test.result, m, debug.Graphviz("", test.result.(match.Matcher)), debug.Graphviz("", m.(match.Matcher)))
continue
}
}
}