<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/main_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'subex/main_test.go')
-rw-r--r--subex/main_test.go783
1 files changed, 390 insertions, 393 deletions
diff --git a/subex/main_test.go b/subex/main_test.go
index f0350d2..fb6f152 100644
--- a/subex/main_test.go
+++ b/subex/main_test.go
@@ -1,10 +1,10 @@
package subex
import (
- "testing"
"main/walk"
- "fmt"
+ "reflect"
"strings"
+ "testing"
)
func buildTransducer(subex string) Transducer {
@@ -14,429 +14,426 @@ func buildTransducer(subex string) Transducer {
return transducer
}
-func fatalMismatch(t *testing.T, path walk.ValueList, message string) {
- var sep string
+func fmtValueList(values []walk.Value) string {
var builder strings.Builder
- for _, segment := range path {
- builder.WriteString(sep)
- builder.WriteString(segment.Debug())
- sep = "."
- }
- builder.WriteString(": ")
- builder.WriteString(message)
- t.Fatal(builder.String())
-}
-
-func expectEqual(t *testing.T, path walk.ValueList, output walk.Value, expected walk.Value) {
- switch expected := expected.(type) {
- case walk.NullScalar:
- _, isNull := output.(walk.NullScalar)
- if !isNull {
- fatalMismatch(t, path, fmt.Sprintf("expected null, found %s", output.Debug()))
- }
- case walk.BoolScalar:
- b, isBool := output.(walk.BoolScalar)
- if !isBool {
- fatalMismatch(t, path, fmt.Sprintf("expected boolean, found %s", output.Debug()))
- }
- if expected != b {
- fatalMismatch(t, path, fmt.Sprintf("expected %s, found %s", expected.Debug(), b.Debug()))
- }
- case walk.NumberScalar:
- n, isNumber := output.(walk.NumberScalar)
- if !isNumber {
- fatalMismatch(t, path, fmt.Sprintf("expected number, found %s", output.Debug()))
- }
- if expected != n {
- fatalMismatch(t, path, fmt.Sprintf("expected %s, found %s", expected.Debug(), n.Debug()))
- }
- case walk.StringStructure:
- s, isString := output.(walk.StringStructure)
- if !isString {
- fatalMismatch(t, path, fmt.Sprintf("expected string, found %s", output.Debug()))
- }
- if s != expected {
- fatalMismatch(t, path, fmt.Sprintf("expected %s, found %s", expected.Debug(), s.Debug()))
- }
- case walk.ArrayStructure:
- array, isArray := output.(walk.ArrayStructure)
- if !isArray {
- fatalMismatch(t, path, fmt.Sprintf("expected array, found %s", output.Debug()))
- }
- if len(array) != len(expected) {
- fatalMismatch(t, path, fmt.Sprintf("Expected array length %d, found %d", len(expected), len(array)))
- }
- for i, value := range expected {
- expectEqual(t, append(path, walk.NumberScalar(i)), array[i], value)
- }
- case walk.MapStructure:
- m, isMap := output.(walk.MapStructure)
- if !isMap {
- fatalMismatch(t, path, fmt.Sprintf("expected map, found %s", output.Debug()))
- }
- for key, expected := range expected {
- value, hasValue := m[key]
- if !hasValue {
- fatalMismatch(t, path, fmt.Sprintf("expected map to have key %s, but it doesn't", key))
- }
- expectEqual(t, append(path, walk.StringStructure(key)), value, expected)
+ builder.WriteRune('[')
+ for i, value := range values {
+ if i != 0 {
+ builder.WriteString(", ")
}
- for key := range m {
- _, hasValue := expected[key]
- if !hasValue {
- fatalMismatch(t, path, fmt.Sprintf("Didn't expect map to have key %s, but it does", key))
- }
- }
- default:
- panic("Expected contains an invalid value")
+ builder.WriteString(value.Debug())
}
+ builder.WriteRune(']')
+ return builder.String()
}
-func expectOutput(t *testing.T, transducer Transducer, input walk.ValueList, expected walk.ValueList) {
- output, err := RunTransducer(transducer, input)
-
- if err {
- t.Fatalf("Error")
- }
-
- if len(output) != len(expected) {
- t.Fatalf("Output has incorrect length. Expected %d, got %d", len(expected), len(output))
+func TestSubexMain(t *testing.T) {
+ type test struct {
+ subex string
+ input []walk.Value
+ expected []walk.Value
}
- for i, value := range output {
- expectEqual(t, walk.ValueList{walk.NumberScalar(i)}, value, expected[i])
- }
-}
-
-func expectReject(t *testing.T, transducer Transducer, input walk.ValueList) {
- _, err := RunTransducer(transducer, input)
-
- if !err {
- t.Fatalf("Expected transducer to error, but it accepted input: %v", input)
- }
-}
-
-func TestSimpleProcessInput(t *testing.T) {
- states := []SubexBranch{{
- state: SubexCopyState {
- next: SubexNoneState{},
- filter: anyValueFilter{},
- },
- aux: auxiliaryState {
- outputStack: OutputStack {
- head: walk.ValueList{},
- tail: nil,
+ tests := []test {
+ {
+ subex: `..+`,
+ input: []walk.Value {
+ walk.NumberValue(12),
+ walk.NumberValue(34),
},
- store: nil,
- nesting: 0,
- },
- }}
-
- input := walk.ValueList{
- walk.NumberScalar(2),
- }
-
- states = processInput(states, walk.NewValueIter(input), 0)
-
- if len(states) != 1 {
- t.Fatalf("States has wrong length")
- }
-
- accepting := states[0].accepting()
-
- if len(accepting) != 1 {
- t.Fatalf("Wrong number of accepting branches")
- }
-
- values, isValues := accepting[0].head.(walk.ValueList)
-
- if !isValues {
- t.Fatalf("Output is not a value list")
- }
-
- if len(values) != 1 {
- t.Fatalf("Output has wrong length")
- }
-
- if values[0] != walk.NumberScalar(2) {
- t.Fatalf("Outputted the wrong value")
- }
-}
-
-func TestTopAppendFromEmpty(t *testing.T) {
- output := OutputStack {
- head: walk.ValueList{},
- tail: nil,
- }
-
- output = topAppend(output, []walk.Value{walk.NumberScalar(1), walk.NumberScalar(2)})
-
- values, isValues := output.head.(walk.ValueList)
-
- if !isValues {
- t.Fatalf("head is not values")
- }
-
- if len(values) != 2 {
- t.Fatalf("values has the wrong length")
- }
-
- if values[0] != walk.NumberScalar(1) || values[1] != walk.NumberScalar(2) {
- t.Fatalf("output has the wrong values")
- }
-}
-
-func TestArrayPriority1(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(":[.$_]|."),
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(5),
+ expected: []walk.Value {
+ walk.NumberValue(46),
},
},
- walk.ValueList{
- walk.ArrayStructure{},
- },
- )
-}
-
-func TestArrayPriority2(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(".|:[.$_]"),
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(5),
+ {
+ subex: `.`,
+ input: []walk.Value {
+ walk.MapValue {{
+ Key: "a",
+ Value: walk.StringValue("b"),
+ }},
},
- },
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(5),
+ expected: []walk.Value {
+ walk.MapValue {{
+ Key: "a",
+ Value: walk.StringValue("b"),
+ }},
},
},
- )
-}
-
-func TestDropSecondArrayElement(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(":[.(.$_)(.{-0})]"),
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
- walk.NumberScalar(3),
- walk.NumberScalar(4),
+ {
+ subex: `~(.)~`,
+ input: []walk.Value {
+ walk.StringValue("a"),
},
- },
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(1),
- walk.NumberScalar(3),
- walk.NumberScalar(4),
+ expected: []walk.Value {
+ walk.StringValue("a"),
},
},
- )
-}
-
-func TestDropSecondElement(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(".(.$_)(.{-0})"),
- walk.ValueList{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
- walk.NumberScalar(3),
- walk.NumberScalar(4),
- },
- walk.ValueList{
- walk.NumberScalar(1),
- walk.NumberScalar(3),
- walk.NumberScalar(4),
- },
- )
-}
-
-func TestCopyManyValues(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(".{-0}"),
- walk.ValueList{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
- walk.NumberScalar(3),
- walk.NumberScalar(4),
- },
- walk.ValueList{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
- walk.NumberScalar(3),
- walk.NumberScalar(4),
- },
- )
-}
-
-func TestCopyTwoValues(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(".."),
- walk.ValueList{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
- },
- walk.ValueList{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
- },
- )
-}
-
-func TestCopyValue(t *testing.T) {
- expectOutput(
- t,
- buildTransducer("."),
- walk.ValueList{
- walk.NumberScalar(1),
- },
- walk.ValueList{
- walk.NumberScalar(1),
- },
- )
-}
-
-func TestSimpleArrayEntry(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(":[..]"),
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
+ {
+ subex: `~(.$_(.{-0}))~`,
+ input: []walk.Value {
+ walk.StringValue("hello"),
+ },
+ expected: []walk.Value {
+ walk.StringValue("ello"),
},
},
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(1),
- walk.NumberScalar(2),
+ {
+ subex: `#(".".{-0})-`,
+ input: []walk.Value {
+ walk.MapValue {
+ {
+ Key: "a",
+ Value: walk.NullValue{},
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.StringValue("a"),
+ walk.NullValue{},
},
},
- )
-}
-
-func TestArrayEntrySum(t *testing.T) {
- expectOutput(
- t,
- buildTransducer(":[%{-0}+]"),
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(1),
- walk.NumberScalar(7),
- walk.NumberScalar(8),
- walk.NumberScalar(3),
+ {
+ subex: "@(..$a`$a$a`{-0})@",
+ input: []walk.Value {
+ walk.ArrayValue {
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.BoolValue(true),
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NumberValue(5.4),
+ },
+ walk.ArrayElement {
+ Index: 5,
+ Value: walk.StringValue("hello"),
+ },
+ walk.ArrayElement {
+ Index: 3,
+ Value: walk.ArrayValue {
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ },
+ },
+ walk.ArrayElement {
+ Index: 1,
+ Value: walk.MapValue {
+ walk.MapElement {
+ Key: "key",
+ Value: walk.StringValue("value"),
+ },
+ },
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.ArrayValue {
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.BoolValue(true),
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.BoolValue(true),
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NumberValue(5.4),
+ },
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NumberValue(5.4),
+ },
+ walk.ArrayElement {
+ Index: 5,
+ Value: walk.StringValue("hello"),
+ },
+ walk.ArrayElement {
+ Index: 5,
+ Value: walk.StringValue("hello"),
+ },
+ walk.ArrayElement {
+ Index: 3,
+ Value: walk.ArrayValue {
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ },
+ },
+ walk.ArrayElement {
+ Index: 3,
+ Value: walk.ArrayValue {
+ walk.ArrayElement {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ },
+ },
+ walk.ArrayElement {
+ Index: 1,
+ Value: walk.MapValue {
+ walk.MapElement {
+ Key: "key",
+ Value: walk.StringValue("value"),
+ },
+ },
+ },
+ walk.ArrayElement {
+ Index: 1,
+ Value: walk.MapValue {
+ walk.MapElement {
+ Key: "key",
+ Value: walk.StringValue("value"),
+ },
+ },
+ },
+ },
},
},
- walk.ValueList{
- walk.ArrayStructure{
- walk.NumberScalar(19),
+ {
+ subex: "-(`0`.)@",
+ input: []walk.Value {
+ walk.NumberValue(4),
+ },
+ expected: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.NumberValue(4),
+ },
+ },
},
},
- )
-}
-
-func TestStringEmptyMatch(t *testing.T) {
- expectOutput(
- t,
- buildTransducer("~\"\""),
- walk.ValueList{
- walk.StringStructure(""),
+ {
+ subex: `@(.$_~(.{-0})-{-0})~`,
+ input: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.StringValue("ab"),
+ },
+ {
+ Index: 1,
+ Value: walk.StringValue("cd"),
+ },
+ {
+ Index: 2,
+ Value: walk.StringValue("efg"),
+ },
+ {
+ Index: 3,
+ Value: walk.StringValue(""),
+ },
+ {
+ Index: 4,
+ Value: walk.StringValue("hijklm"),
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.StringValue("abcdefghijklm"),
+ },
},
- walk.ValueList{
- walk.StringStructure(""),
+ {
+ subex: ":(.)-",
+ input: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.NullValue{},
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.NullValue{},
+ },
},
- )
-}
-
-func TestStringSimpleMatch(t *testing.T) {
- expectOutput(
- t,
- buildTransducer("~\"hello\""),
- walk.ValueList{
- walk.StringStructure("hello"),
+ {
+ subex: ":(.{-0}+)-",
+ input: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.NumberValue(4),
+ },
+ {
+ Index: 1,
+ Value: walk.NumberValue(-123),
+ },
+ {
+ Index: 2,
+ Value: walk.NumberValue(124),
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.NumberValue(5),
+ },
},
- walk.ValueList{
- walk.StringStructure("hello"),
+ {
+ subex: "~(-(.)~{-0}):",
+ input: []walk.Value {
+ walk.StringValue("abc"),
+ },
+ expected: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.StringValue("a"),
+ },
+ {
+ Index: 0,
+ Value: walk.StringValue("b"),
+ },
+ {
+ Index: 0,
+ Value: walk.StringValue("c"),
+ },
+ },
+ },
},
- )
-}
-
-func TestDiscardString(t *testing.T) {
- expectOutput(
- t,
- buildTransducer("~\"test\"$_."),
- walk.ValueList{
- walk.StringStructure("test"),
- walk.NumberScalar(2),
+ {
+ subex: "#(.(.$_){-0}):",
+ input: []walk.Value {
+ walk.MapValue {
+ {
+ Key: "a",
+ Value: walk.NullValue{},
+ },
+ {
+ Key: "b",
+ Value: walk.NumberValue(4),
+ },
+ {
+ Key: "c",
+ Value: walk.StringValue("hello"),
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.StringValue("a"),
+ },
+ {
+ Index: 0,
+ Value: walk.StringValue("b"),
+ },
+ {
+ Index: 0,
+ Value: walk.StringValue("c"),
+ },
+ },
+ },
},
- walk.ValueList{
- walk.NumberScalar(2),
+ {
+ subex: ":(.`null`{-0})#",
+ input: []walk.Value {
+ walk.ArrayValue {
+ {
+ Index: 0,
+ Value: walk.StringValue("a"),
+ },
+ {
+ Index: 1,
+ Value: walk.StringValue("b"),
+ },
+ {
+ Index: 2,
+ Value: walk.StringValue("c"),
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.MapValue {
+ {
+ Key: "a",
+ Value: walk.NullValue{},
+ },
+ {
+ Key: "b",
+ Value: walk.NullValue{},
+ },
+ {
+ Key: "c",
+ Value: walk.NullValue{},
+ },
+ },
+ },
},
- )
-}
-
-func TestStringThenValue(t *testing.T) {
- expectOutput(
- t,
- buildTransducer("~\"test\"."),
- walk.ValueList{
- walk.StringStructure("test"),
- walk.NumberScalar(2),
+ {
+ subex: `#(".$_(.{-0})".{-0})#`,
+ input: []walk.Value {
+ walk.MapValue {
+ {
+ Key: "hello",
+ Value: walk.NullValue{},
+ },
+ {
+ Key: "world",
+ Value: walk.NullValue{},
+ },
+ },
+ },
+ expected: []walk.Value {
+ walk.MapValue {
+ {
+ Key: "ello",
+ Value: walk.NullValue{},
+ },
+ {
+ Key: "orld",
+ Value: walk.NullValue{},
+ },
+ },
+ },
},
- walk.ValueList{
- walk.StringStructure("test"),
- walk.NumberScalar(2),
+ {
+ subex: ".{-0}`\"hello\"`",
+ input: []walk.Value {
+ walk.NumberValue(1),
+ walk.NumberValue(2),
+ },
+ expected: []walk.Value {
+ walk.NumberValue(1),
+ walk.NumberValue(2),
+ walk.StringValue("hello"),
+ },
},
- )
-}
+ }
-func TestCutStringFromStart(t *testing.T) {
- //transducer := buildTransducer("~\"test\"$_(.{-0})")
- lexer := NewStringRuneReader("~\"test\"$_(.{-0})")
- ast := Parse(lexer)
- t.Log(ast)
- transducer := CompileTransducer(ast)
+ for i, test := range tests {
+ t.Logf("Running test: %d", i)
+ lexer := NewStringRuneReader(test.subex)
+ ast := Parse(lexer)
+ transducer := CompileTransducer(ast)
+ output, err := RunTransducer(transducer, test.input)
+
+ if err {
+ t.Errorf("Subex %q rejected input %v", test.subex, fmtValueList(test.input))
+ t.Logf("AST: %v", ast)
+ continue
+ }
- expectOutput(
- t,
- transducer,
- walk.ValueList{
- walk.StringStructure("test"),
- walk.NumberScalar(2),
- walk.StringStructure("test"),
- },
- walk.ValueList{
- walk.NumberScalar(2),
- walk.StringStructure("test"),
- },
- )
- expectOutput(
- t,
- transducer,
- walk.ValueList{
- walk.StringStructure("test"),
- },
- walk.ValueList{},
- )
- expectReject(
- t,
- transducer,
- walk.ValueList{
- walk.StringStructure("yeet"),
- },
- )
- expectReject(
- t,
- transducer,
- walk.ValueList{},
- )
+ if !reflect.DeepEqual(output, test.expected) {
+ t.Errorf("Subex %q transformed input %s to output %s", test.subex, fmtValueList(test.input), fmtValueList(output))
+ }
+ }
}