refactor test harness

This commit is contained in:
Arpad Ryszka 2017-10-27 17:25:20 +02:00
parent 0e236fb688
commit a09675fc27
12 changed files with 621 additions and 646 deletions

10
boot.go
View File

@ -187,21 +187,17 @@ func defineAllBoot(s *Syntax, defs [][]string) error {
return nil
}
func initBoot(definitions [][]string) (*Syntax, error) {
func createBoot() (*Syntax, error) {
s := NewSyntax()
if err := defineAllBoot(s, definitions); err != nil {
if err := defineAllBoot(s, bootSyntaxDefs); err != nil {
return nil, err
}
return s, s.Init()
}
func createBoot() (*Syntax, error) {
return initBoot(bootSyntaxDefs)
}
func bootSyntax() (*Syntax, error) {
b, err := initBoot(bootSyntaxDefs)
b, err := createBoot()
if err != nil {
return nil, err
}

View File

@ -40,7 +40,7 @@ func testParseFromTree(t *testing.T, n *Node, f io.ReadSeeker) *Node {
return nil
}
checkNode(t, nn, n)
checkNode(t, false, nn, n)
return nn
}

69
check_test.go Normal file
View File

@ -0,0 +1,69 @@
package treerack
import "testing"
func checkNodes(t *testing.T, ignorePosition bool, left, right []*Node) {
if len(left) != len(right) {
t.Error("length doesn't match", len(left), len(right))
return
}
for len(left) > 0 {
checkNode(t, ignorePosition, left[0], right[0])
if t.Failed() {
return
}
left, right = left[1:], right[1:]
}
}
func checkNode(t *testing.T, ignorePosition bool, left, right *Node) {
if (left == nil) != (right == nil) {
t.Error("nil reference doesn't match", left == nil, right == nil)
return
}
if left == nil {
return
}
if left.Name != right.Name {
t.Error("name doesn't match", left.Name, right.Name)
return
}
if !ignorePosition && left.From != right.From {
t.Error("from doesn't match", left.Name, left.From, right.From)
return
}
if !ignorePosition && left.To != right.To {
t.Error("to doesn't match", left.Name, left.To, right.To)
return
}
if len(left.Nodes) != len(right.Nodes) {
t.Error("length doesn't match", left.Name, len(left.Nodes), len(right.Nodes))
t.Log(left)
t.Log(right)
for {
if len(left.Nodes) > 0 {
t.Log("<", left.Nodes[0])
left.Nodes = left.Nodes[1:]
}
if len(right.Nodes) > 0 {
t.Log(">", right.Nodes[0])
right.Nodes = right.Nodes[1:]
}
if len(left.Nodes) == 0 && len(right.Nodes) == 0 {
break
}
}
return
}
checkNodes(t, ignorePosition, left.Nodes, right.Nodes)
}

View File

@ -724,10 +724,12 @@ func eskipTreeToEskip(n *Node) ([]*eskip.Route, error) {
}
func TestEskip(t *testing.T) {
r := generateEskip(1 << 9)
const count = 1 << 9
r := generateEskip(count)
e := eskip.Print(true, r...)
b := bytes.NewBufferString(e)
s, err := testSyntax("eskip.parser", -1)
s, err := openSyntaxFile("eskip.parser")
if err != nil {
t.Error(err)
return

View File

@ -285,9 +285,9 @@ func jsonTreeToJSON(n *Node) (interface{}, error) {
}
func TestJSON(t *testing.T) {
test(t, "json.parser", "value", []testItem{{
msg: "true",
text: "true",
runTestsFile(t, "json.parser", []testItem{{
title: "true",
text: "true",
node: &Node{
Name: "json",
Nodes: []*Node{{
@ -296,8 +296,8 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "false",
text: "false",
title: "false",
text: "false",
node: &Node{
Name: "json",
Nodes: []*Node{{
@ -306,8 +306,8 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "null",
text: "null",
title: "null",
text: "null",
node: &Node{
Name: "json",
Nodes: []*Node{{
@ -316,8 +316,8 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "string",
text: `"\"\\n\b\t\uabcd"`,
title: "string",
text: `"\"\\n\b\t\uabcd"`,
node: &Node{
Name: "json",
Nodes: []*Node{{
@ -326,8 +326,8 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "number",
text: "6.62e-34",
title: "number",
text: "6.62e-34",
node: &Node{
Name: "json",
Nodes: []*Node{{
@ -336,7 +336,7 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "object",
title: "object",
text: `{
"true": true,
"false": false,
@ -404,7 +404,7 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "array",
title: "array",
text: `[true, false, null, "string", 42, {
"true": true,
"false": false,
@ -487,8 +487,8 @@ func TestJSON(t *testing.T) {
},
ignorePosition: true,
}, {
msg: "bugfix, 100",
text: "100",
title: "bugfix, 100",
text: "100",
node: &Node{
Name: "json",
Nodes: []*Node{{
@ -509,7 +509,7 @@ func TestRandomJSON(t *testing.T) {
buf := bytes.NewBuffer(b)
s, err := testSyntax("json.parser", -1)
s, err := openSyntaxFile("json.parser")
if err != nil {
t.Error(err)
return

View File

@ -3,14 +3,14 @@ package treerack
import "testing"
func TestKeyVal(t *testing.T) {
test(t, "keyval.parser", "doc", []testItem{{
msg: "empty",
runTestsFile(t, "keyval.parser", []testItem{{
title: "empty",
}, {
msg: "a comment",
text: "# a comment",
title: "a comment",
text: "# a comment",
}, {
msg: "a key",
text: "a key",
title: "a key",
text: "a key",
nodes: []*Node{{
Name: "key-val",
To: 5,
@ -24,8 +24,8 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a key with a preceeding whitespace",
text: " a key",
title: "a key with a preceeding whitespace",
text: " a key",
nodes: []*Node{{
Name: "key-val",
From: 1,
@ -42,7 +42,7 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a key and a comment",
title: "a key and a comment",
text: `
# a comment
@ -64,8 +64,8 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a key value pair",
text: "a key = a value",
title: "a key value pair",
text: "a key = a value",
nodes: []*Node{{
Name: "key-val",
To: 15,
@ -83,7 +83,7 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "key value pairs with a comment at the end of line",
title: "key value pairs with a comment at the end of line",
text: `
a key = a value # a comment
another key = another value # another comment
@ -126,8 +126,8 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "value without a key",
text: "= a value",
title: "value without a key",
text: "= a value",
nodes: []*Node{{
Name: "key-val",
To: 9,
@ -138,7 +138,7 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a key value pair with comment",
title: "a key value pair with comment",
text: `
# a comment
a key = a value
@ -167,8 +167,8 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a key with multiple symbols",
text: "a key . with.multiple.symbols=a value",
title: "a key with multiple symbols",
text: "a key . with.multiple.symbols=a value",
nodes: []*Node{{
Name: "key-val",
To: 37,
@ -200,7 +200,7 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a group key",
title: "a group key",
text: `
# a comment
[a group key.empty]
@ -224,7 +224,7 @@ func TestKeyVal(t *testing.T) {
}},
}},
}, {
msg: "a group key with multiple values",
title: "a group key with multiple values",
text: `
[foo.bar.baz]
= one
@ -258,8 +258,8 @@ func TestKeyVal(t *testing.T) {
}},
ignorePosition: true,
}, {
msg: "a group key with multiple values, in a single line",
text: "[foo.bar.baz] = one = two = three",
title: "a group key with multiple values, in a single line",
text: "[foo.bar.baz] = one = two = three",
nodes: []*Node{{
Name: "group-key",
Nodes: []*Node{{
@ -287,7 +287,7 @@ func TestKeyVal(t *testing.T) {
}},
ignorePosition: true,
}, {
msg: "full example",
title: "full example",
text: `
# a keyval document

File diff suppressed because it is too large Load Diff

45
open_test.go Normal file
View File

@ -0,0 +1,45 @@
package treerack
import (
"bytes"
"io"
"os"
)
func openSyntaxReader(r io.Reader) (*Syntax, error) {
b, err := bootSyntax()
if err != nil {
return nil, err
}
doc, err := b.Parse(r)
if err != nil {
return nil, err
}
s := NewSyntax()
if err := define(s, doc); err != nil {
return nil, err
}
if err := s.Init(); err != nil {
return nil, err
}
return s, nil
}
func openSyntaxFile(file string) (*Syntax, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
return openSyntaxReader(f)
}
func openSyntaxString(syntax string) (*Syntax, error) {
b := bytes.NewBufferString(syntax)
return openSyntaxReader(b)
}

View File

@ -1,217 +1,16 @@
package treerack
import (
"bytes"
"io"
"os"
"testing"
"time"
)
type testItem struct {
msg string
text string
fail bool
node *Node
nodes []*Node
ignorePosition bool
}
func testSyntaxReader(r io.Reader, traceLevel int) (*Syntax, error) {
b, err := bootSyntax()
if err != nil {
return nil, err
}
doc, err := b.Parse(r)
if err != nil {
return nil, err
}
var trace Trace
if traceLevel >= 0 {
trace = NewTrace(traceLevel)
}
s := NewSyntaxTrace(trace)
if err := define(s, doc); err != nil {
return nil, err
}
if err := s.Init(); err != nil {
return nil, err
}
return s, nil
}
func testSyntax(file string, traceLevel int) (*Syntax, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
return testSyntaxReader(f, traceLevel)
}
func checkNodesPosition(t *testing.T, left, right []*Node, position bool) {
if len(left) != len(right) {
t.Error("length doesn't match", len(left), len(right))
return
}
for len(left) > 0 {
checkNodePosition(t, left[0], right[0], position)
if t.Failed() {
return
}
left, right = left[1:], right[1:]
}
}
func checkNodePosition(t *testing.T, left, right *Node, position bool) {
if (left == nil) != (right == nil) {
t.Error("nil reference doesn't match", left == nil, right == nil)
return
}
if left == nil {
return
}
if left.Name != right.Name {
t.Error("name doesn't match", left.Name, right.Name)
return
}
if position && left.From != right.From {
t.Error("from doesn't match", left.Name, left.From, right.From)
return
}
if position && left.To != right.To {
t.Error("to doesn't match", left.Name, left.To, right.To)
return
}
if len(left.Nodes) != len(right.Nodes) {
t.Error("length doesn't match", left.Name, len(left.Nodes), len(right.Nodes))
t.Log(left)
t.Log(right)
for {
if len(left.Nodes) > 0 {
t.Log("<", left.Nodes[0])
left.Nodes = left.Nodes[1:]
}
if len(right.Nodes) > 0 {
t.Log(">", right.Nodes[0])
right.Nodes = right.Nodes[1:]
}
if len(left.Nodes) == 0 && len(right.Nodes) == 0 {
break
}
}
return
}
checkNodesPosition(t, left.Nodes, right.Nodes, position)
}
func checkNodes(t *testing.T, left, right []*Node) {
checkNodesPosition(t, left, right, true)
}
func checkNode(t *testing.T, left, right *Node) {
checkNodePosition(t, left, right, true)
}
func checkNodesIgnorePosition(t *testing.T, left, right []*Node) {
checkNodesPosition(t, left, right, false)
}
func checkNodeIgnorePosition(t *testing.T, left, right *Node) {
checkNodePosition(t, left, right, false)
}
func testReaderTrace(t *testing.T, r io.Reader, rootName string, traceLevel int, tests []testItem) {
s, err := testSyntaxReader(r, traceLevel)
if err != nil {
t.Error(err)
return
}
for _, ti := range tests {
t.Run(ti.msg, func(t *testing.T) {
b := bytes.NewBufferString(ti.text)
start := time.Now()
n, err := s.Parse(b)
t.Log("parse duration:", time.Now().Sub(start))
if ti.fail && err == nil {
t.Error("failed to fail")
return
} else if !ti.fail && err != nil {
t.Error(err)
return
} else if ti.fail {
return
}
t.Log(n)
cn := checkNode
if ti.ignorePosition {
cn = checkNodeIgnorePosition
}
if ti.node != nil {
cn(t, n, ti.node)
} else {
cn(t, n, &Node{
Name: rootName,
To: len(ti.text),
Nodes: ti.nodes,
})
}
})
}
}
func testStringTrace(t *testing.T, s string, traceLevel int, tests []testItem) {
testReaderTrace(t, bytes.NewBufferString(s), "", traceLevel, tests)
}
func testString(t *testing.T, s string, tests []testItem) {
testStringTrace(t, s, -1, tests)
}
func testTrace(t *testing.T, file, rootName string, traceLevel int, tests []testItem) {
f, err := os.Open(file)
if err != nil {
t.Error(err)
return
}
defer f.Close()
testReaderTrace(t, f, rootName, traceLevel, tests)
}
func test(t *testing.T, file, rootName string, tests []testItem) {
testTrace(t, file, rootName, -1, tests)
}
func TestRecursion(t *testing.T) {
testString(
runTests(
t,
`A = "a" | A "a"`,
[]testItem{{
msg: "recursion in choice, right, left, commit",
text: "aaa",
title: "recursion in choice, right, left, commit",
text: "aaa",
node: &Node{
Name: "A",
Nodes: []*Node{{
@ -225,12 +24,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" | "a" A`,
[]testItem{{
msg: "recursion in choice, right, right, commit",
text: "aaa",
title: "recursion in choice, right, right, commit",
text: "aaa",
node: &Node{
Name: "A",
Nodes: []*Node{{
@ -244,12 +43,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" A | "a"`,
[]testItem{{
msg: "recursion in choice, left, right, commit",
text: "aaa",
title: "recursion in choice, left, right, commit",
text: "aaa",
node: &Node{
Name: "A",
Nodes: []*Node{{
@ -263,12 +62,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = A "a" | "a"`,
[]testItem{{
msg: "recursion in choice, left, left, commit",
text: "aaa",
title: "recursion in choice, left, left, commit",
text: "aaa",
node: &Node{
Name: "A",
Nodes: []*Node{{
@ -282,12 +81,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A':alias = "a" | A' "a"; A = A'`,
[]testItem{{
msg: "recursion in choice, right, left, alias",
text: "aaa",
title: "recursion in choice, right, left, alias",
text: "aaa",
node: &Node{
Name: "A",
To: 3,
@ -295,12 +94,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A':alias = "a" | "a" A'; A = A'`,
[]testItem{{
msg: "recursion in choice, right, right, alias",
text: "aaa",
title: "recursion in choice, right, right, alias",
text: "aaa",
node: &Node{
Name: "A",
To: 3,
@ -308,12 +107,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A':alias = "a" A' | "a"; A = A'`,
[]testItem{{
msg: "recursion in choice, left, right, alias",
text: "aaa",
title: "recursion in choice, left, right, alias",
text: "aaa",
node: &Node{
Name: "A",
To: 3,
@ -321,12 +120,12 @@ func TestRecursion(t *testing.T) {
}},
)
testString(
runTests(
t,
`A':alias = A' "a" | "a"; A = A'`,
[]testItem{{
msg: "recursion in choice, left, left, alias",
text: "aaa",
title: "recursion in choice, left, left, alias",
text: "aaa",
node: &Node{
Name: "A",
To: 3,
@ -336,19 +135,19 @@ func TestRecursion(t *testing.T) {
}
func TestSequence(t *testing.T) {
testString(
runTests(
t,
`AB = "a" | "a"? "a"? "b" "b"`,
[]testItem{{
msg: "sequence with optional items",
text: "abb",
title: "sequence with optional items",
text: "abb",
node: &Node{
Name: "AB",
To: 3,
},
}, {
msg: "sequence with optional items, none",
text: "bb",
title: "sequence with optional items, none",
text: "bb",
node: &Node{
Name: "AB",
To: 2,
@ -356,12 +155,12 @@ func TestSequence(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" | (A?)*`,
[]testItem{{
msg: "sequence in choice with redundant quantifier",
text: "aaa",
title: "sequence in choice with redundant quantifier",
text: "aaa",
node: &Node{
Name: "A",
Nodes: []*Node{{
@ -376,12 +175,12 @@ func TestSequence(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = ("a"*)*`,
[]testItem{{
msg: "sequence with redundant quantifier",
text: "aaa",
title: "sequence with redundant quantifier",
text: "aaa",
node: &Node{
Name: "A",
To: 3,
@ -391,268 +190,268 @@ func TestSequence(t *testing.T) {
}
func TestQuantifiers(t *testing.T) {
testString(
runTests(
t,
`A = "a" "b"{0} "a"`,
[]testItem{{
msg: "zero, considered as one",
text: "aba",
title: "zero, considered as one",
text: "aba",
node: &Node{
Name: "A",
To: 3,
},
}, {
msg: "zero, fail",
text: "aa",
fail: true,
title: "zero, fail",
text: "aa",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{1} "a"`,
[]testItem{{
msg: "one, missing",
text: "aa",
fail: true,
title: "one, missing",
text: "aa",
fail: true,
}, {
msg: "one",
text: "aba",
title: "one",
text: "aba",
node: &Node{
Name: "A",
To: 3,
},
}, {
msg: "one, too much",
text: "abba",
fail: true,
title: "one, too much",
text: "abba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{3} "a"`,
[]testItem{{
msg: "three, missing",
text: "abba",
fail: true,
title: "three, missing",
text: "abba",
fail: true,
}, {
msg: "three",
text: "abbba",
title: "three",
text: "abbba",
node: &Node{
Name: "A",
To: 5,
},
}, {
msg: "three, too much",
text: "abbbba",
fail: true,
title: "three, too much",
text: "abbbba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{0,1} "a"`,
[]testItem{{
msg: "zero or one explicit, missing",
text: "aa",
title: "zero or one explicit, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or one explicit",
text: "aba",
title: "zero or one explicit",
text: "aba",
node: &Node{
Name: "A",
To: 3,
},
}, {
msg: "zero or one explicit, too much",
text: "abba",
fail: true,
title: "zero or one explicit, too much",
text: "abba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{,1} "a"`,
[]testItem{{
msg: "zero or one explicit, omit zero, missing",
text: "aa",
title: "zero or one explicit, omit zero, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or one explicit, omit zero",
text: "aba",
title: "zero or one explicit, omit zero",
text: "aba",
node: &Node{
Name: "A",
To: 3,
},
}, {
msg: "zero or one explicit, omit zero, too much",
text: "abba",
fail: true,
title: "zero or one explicit, omit zero, too much",
text: "abba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"? "a"`,
[]testItem{{
msg: "zero or one explicit, shortcut, missing",
text: "aa",
title: "zero or one explicit, shortcut, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or one explicit, shortcut",
text: "aba",
title: "zero or one explicit, shortcut",
text: "aba",
node: &Node{
Name: "A",
To: 3,
},
}, {
msg: "zero or one explicit, shortcut, too much",
text: "abba",
fail: true,
title: "zero or one explicit, shortcut, too much",
text: "abba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{0,3} "a"`,
[]testItem{{
msg: "zero or three, missing",
text: "aa",
title: "zero or three, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or three",
text: "abba",
title: "zero or three",
text: "abba",
node: &Node{
Name: "A",
To: 4,
},
}, {
msg: "zero or three",
text: "abbba",
title: "zero or three",
text: "abbba",
node: &Node{
Name: "A",
To: 5,
},
}, {
msg: "zero or three, too much",
text: "abbbba",
fail: true,
title: "zero or three, too much",
text: "abbbba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{,3} "a"`,
[]testItem{{
msg: "zero or three, omit zero, missing",
text: "aa",
title: "zero or three, omit zero, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or three, omit zero",
text: "abba",
title: "zero or three, omit zero",
text: "abba",
node: &Node{
Name: "A",
To: 4,
},
}, {
msg: "zero or three, omit zero",
text: "abbba",
title: "zero or three, omit zero",
text: "abbba",
node: &Node{
Name: "A",
To: 5,
},
}, {
msg: "zero or three, omit zero, too much",
text: "abbbba",
fail: true,
title: "zero or three, omit zero, too much",
text: "abbbba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{1,3} "a"`,
[]testItem{{
msg: "one or three, missing",
text: "aa",
fail: true,
title: "one or three, missing",
text: "aa",
fail: true,
}, {
msg: "one or three",
text: "abba",
title: "one or three",
text: "abba",
node: &Node{
Name: "A",
To: 4,
},
}, {
msg: "one or three",
text: "abbba",
title: "one or three",
text: "abbba",
node: &Node{
Name: "A",
To: 5,
},
}, {
msg: "one or three, too much",
text: "abbbba",
fail: true,
title: "one or three, too much",
text: "abbbba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{3,5} "a"`,
[]testItem{{
msg: "three or five, missing",
text: "abba",
fail: true,
title: "three or five, missing",
text: "abba",
fail: true,
}, {
msg: "three or five",
text: "abbbba",
title: "three or five",
text: "abbbba",
node: &Node{
Name: "A",
To: 6,
},
}, {
msg: "three or five",
text: "abbbbba",
title: "three or five",
text: "abbbbba",
node: &Node{
Name: "A",
To: 7,
},
}, {
msg: "three or five, too much",
text: "abbbbbba",
fail: true,
title: "three or five, too much",
text: "abbbbbba",
fail: true,
}},
)
testString(
runTests(
t,
`A = "a" "b"{0,} "a"`,
[]testItem{{
msg: "zero or more, explicit, missing",
text: "aa",
title: "zero or more, explicit, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or more, explicit",
text: "abba",
title: "zero or more, explicit",
text: "abba",
node: &Node{
Name: "A",
To: 4,
@ -660,19 +459,19 @@ func TestQuantifiers(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" "b"* "a"`,
[]testItem{{
msg: "zero or more, shortcut, missing",
text: "aa",
title: "zero or more, shortcut, missing",
text: "aa",
node: &Node{
Name: "A",
To: 2,
},
}, {
msg: "zero or more, shortcut",
text: "abba",
title: "zero or more, shortcut",
text: "abba",
node: &Node{
Name: "A",
To: 4,
@ -680,16 +479,16 @@ func TestQuantifiers(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" "b"{1,} "a"`,
[]testItem{{
msg: "one or more, explicit, missing",
text: "aa",
fail: true,
title: "one or more, explicit, missing",
text: "aa",
fail: true,
}, {
msg: "one or more, explicit",
text: "abba",
title: "one or more, explicit",
text: "abba",
node: &Node{
Name: "A",
To: 4,
@ -697,16 +496,16 @@ func TestQuantifiers(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" "b"+ "a"`,
[]testItem{{
msg: "one or more, shortcut, missing",
text: "aa",
fail: true,
title: "one or more, shortcut, missing",
text: "aa",
fail: true,
}, {
msg: "one or more, shortcut",
text: "abba",
title: "one or more, shortcut",
text: "abba",
node: &Node{
Name: "A",
To: 4,
@ -714,16 +513,16 @@ func TestQuantifiers(t *testing.T) {
}},
)
testString(
runTests(
t,
`A = "a" "b"{3,} "a"`,
[]testItem{{
msg: "three or more, explicit, missing",
text: "abba",
fail: true,
title: "three or more, explicit, missing",
text: "abba",
fail: true,
}, {
msg: "three or more, explicit",
text: "abbbba",
title: "three or more, explicit",
text: "abbbba",
node: &Node{
Name: "A",
To: 6,

64
run_test.go Normal file
View File

@ -0,0 +1,64 @@
package treerack
import (
"bytes"
"testing"
"time"
)
type testItem struct {
title string
text string
fail bool
node *Node
nodes []*Node
ignorePosition bool
}
func runTestsSyntax(t *testing.T, s *Syntax, tests []testItem) {
for _, test := range tests {
t.Run(test.title, func(t *testing.T) {
b := bytes.NewBufferString(test.text)
start := time.Now()
n, err := s.Parse(b)
t.Log("parse duration:", time.Now().Sub(start))
if test.fail && err == nil {
t.Error("failed to fail")
return
} else if !test.fail && err != nil {
t.Error(err)
return
} else if test.fail {
return
}
if test.node != nil {
checkNode(t, test.ignorePosition, n, test.node)
} else {
checkNodes(t, test.ignorePosition, n.Nodes, test.nodes)
}
})
}
}
func runTests(t *testing.T, syntax string, tests []testItem) {
s, err := openSyntaxString(syntax)
if err != nil {
t.Error(err)
return
}
runTestsSyntax(t, s, tests)
}
func runTestsFile(t *testing.T, file string, tests []testItem) {
s, err := openSyntaxFile(file)
if err != nil {
t.Error(err)
return
}
runTestsSyntax(t, s, tests)
}

View File

@ -3,10 +3,10 @@ package treerack
import "testing"
func TestScheme(t *testing.T) {
test(t, "scheme.parser", "scheme", []testItem{{
msg: "empty",
runTestsFile(t, "scheme.parser", []testItem{{
title: "empty",
}, {
msg: "a function",
title: "a function",
text: `
(define (foo a b c)
(let ([bar (+ a b c)]

View File

@ -3,37 +3,37 @@ package treerack
import "testing"
func TestSExpr(t *testing.T) {
test(t, "sexpr.parser", "s-expression", []testItem{{
msg: "number",
text: "42",
runTestsFile(t, "sexpr.parser", []testItem{{
title: "number",
text: "42",
nodes: []*Node{{
Name: "number",
}},
ignorePosition: true,
}, {
msg: "string",
text: "\"foo\"",
title: "string",
text: "\"foo\"",
nodes: []*Node{{
Name: "string",
}},
ignorePosition: true,
}, {
msg: "symbol",
text: "foo",
title: "symbol",
text: "foo",
nodes: []*Node{{
Name: "symbol",
}},
ignorePosition: true,
}, {
msg: "nil",
text: "()",
title: "nil",
text: "()",
nodes: []*Node{{
Name: "list",
}},
ignorePosition: true,
}, {
msg: "list",
text: "(foo bar baz)",
title: "list",
text: "(foo bar baz)",
nodes: []*Node{{
Name: "list",
Nodes: []*Node{{
@ -46,8 +46,8 @@ func TestSExpr(t *testing.T) {
}},
ignorePosition: true,
}, {
msg: "embedded list",
text: "(foo (bar (baz)) qux)",
title: "embedded list",
text: "(foo (bar (baz)) qux)",
nodes: []*Node{{
Name: "list",
Nodes: []*Node{{