diff options
Diffstat (limited to 'subex/main_test.go')
-rw-r--r-- | subex/main_test.go | 464 |
1 files changed, 56 insertions, 408 deletions
diff --git a/subex/main_test.go b/subex/main_test.go index f0350d2..0b4ee1b 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,77 @@ 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())) + builder.WriteRune('[') + for i, value := range values { + if i != 0 { + builder.WriteString(", ") } - 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) - } - 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)) - } - - for i, value := range output { - expectEqual(t, walk.ValueList{walk.NumberScalar(i)}, value, expected[i]) +func TestSubexMain(t *testing.T) { + type test struct { + subex string + input []walk.Value + expected []walk.Value } -} - -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, - }, - 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), - }, - }, - walk.ValueList{ - walk.ArrayStructure{}, - }, - ) -} -func TestArrayPriority2(t *testing.T) { - expectOutput( - t, - buildTransducer(".|:[.$_]"), - walk.ValueList{ - walk.ArrayStructure{ - walk.NumberScalar(5), + tests := []test { + { + subex: `..+`, + input: []walk.Value { + walk.NumberValue(12), + walk.NumberValue(34), }, - }, - walk.ValueList{ - walk.ArrayStructure{ - walk.NumberScalar(5), + expected: []walk.Value { + walk.NumberValue(46), }, }, - ) -} - -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.MapValue {{ + Key: "a", + Value: walk.StringValue("b"), + }}, }, - }, - walk.ValueList{ - walk.ArrayStructure{ - walk.NumberScalar(1), - walk.NumberScalar(3), - walk.NumberScalar(4), + expected: []walk.Value { + walk.MapValue {{ + Key: "a", + Value: walk.StringValue("b"), + }}, }, }, - ) -} - -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"), }, - }, - walk.ValueList{ - walk.ArrayStructure{ - walk.NumberScalar(1), - walk.NumberScalar(2), + expected: []walk.Value { + walk.StringValue("ello"), }, }, - ) -} - -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), - }, - }, - walk.ValueList{ - walk.ArrayStructure{ - walk.NumberScalar(19), - }, - }, - ) -} - -func TestStringEmptyMatch(t *testing.T) { - expectOutput( - t, - buildTransducer("~\"\""), - walk.ValueList{ - walk.StringStructure(""), - }, - walk.ValueList{ - walk.StringStructure(""), - }, - ) -} - -func TestStringSimpleMatch(t *testing.T) { - expectOutput( - t, - buildTransducer("~\"hello\""), - walk.ValueList{ - walk.StringStructure("hello"), - }, - walk.ValueList{ - walk.StringStructure("hello"), - }, - ) -} - -func TestDiscardString(t *testing.T) { - expectOutput( - t, - buildTransducer("~\"test\"$_."), - walk.ValueList{ - walk.StringStructure("test"), - walk.NumberScalar(2), - }, - walk.ValueList{ - walk.NumberScalar(2), - }, - ) -} + } -func TestStringThenValue(t *testing.T) { - expectOutput( - t, - buildTransducer("~\"test\"."), - walk.ValueList{ - walk.StringStructure("test"), - walk.NumberScalar(2), - }, - walk.ValueList{ - walk.StringStructure("test"), - walk.NumberScalar(2), - }, - ) -} + for _, test := range tests { + lexer := NewStringRuneReader(test.subex) + ast := Parse(lexer) + transducer := CompileTransducer(ast) + output, err := RunTransducer(transducer, test.input) -func TestCutStringFromStart(t *testing.T) { - //transducer := buildTransducer("~\"test\"$_(.{-0})") - lexer := NewStringRuneReader("~\"test\"$_(.{-0})") - ast := Parse(lexer) - t.Log(ast) - transducer := CompileTransducer(ast) + 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)) + } + } } |