func TestTopsyTurvy(t *testing.T) { p := ast.NewTreeNode(ast.NewAnyName(), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny())) gkey, err := FieldNamesToNumbers("protonum", "TopsyTurvy", ProtonumDescription(), p.Grammar()) if err == nil { t.Fatalf("Expected: Any Field Not Supported: Name: _, but got %v", gkey) } }
func TestSimplifyTree(t *testing.T) { left := ast.NewTreeNode(ast.NewStringName("A"), ast.NewTreeNode(ast.NewStringName("B"), ast.NewContains( ast.NewTreeNode(ast.NewStringName("C"), ast.NewZAny()), )), ) right := ast.NewTreeNode(ast.NewStringName("A"), ast.NewTreeNode(ast.NewStringName("B"), ast.NewContains( ast.NewTreeNode(ast.NewStringName("D"), ast.NewZAny()), )), ) input := ast.NewAnd(left, right) expected := ast.NewTreeNode(ast.NewStringName("A"), ast.NewTreeNode(ast.NewStringName("B"), ast.NewAnd( ast.NewContains( ast.NewTreeNode(ast.NewStringName("C"), ast.NewZAny()), ), ast.NewContains( ast.NewTreeNode(ast.NewStringName("D"), ast.NewZAny()), ), )), ) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestRecursiveKnotElbow(t *testing.T) { p := ast.NewOr(ast.NewTreeNode(ast.NewAnyName(), ast.NewReference("main")), ast.NewTreeNode(ast.NewStringName("Elbow"), ast.NewZAny())) gkey, err := FieldNamesToNumbers("protonum", "Knot", ProtonumDescription(), p.Grammar()) if err == nil { t.Fatalf("Expected: Any Field Not Supported: Name: _, but got %v", gkey) } }
func simplifyChildren(children []*ast.Pattern, op func(left, right *ast.Pattern) *ast.Pattern, record bool) []*ast.Pattern { if len(children) == 0 || len(children) == 1 { return children } if record { c0 := children[0].GetContains().GetPattern().GetTreeNode() c1 := children[1].GetContains().GetPattern().GetTreeNode() if c0 != nil && c1 != nil { if c0.GetName().Equal(c1.GetName()) { newchild := ast.NewContains(ast.NewTreeNode(c0.GetName(), op(c0.GetPattern(), c1.GetPattern()))) children[1] = newchild return simplifyChildren(children[1:], op, record) } } } t0 := children[0].TreeNode t1 := children[1].TreeNode if t0 != nil && t1 != nil { if t0.GetName().Equal(t1.GetName()) { newchild := ast.NewTreeNode(t0.GetName(), op(t0.GetPattern(), t1.GetPattern())) children[1] = newchild return simplifyChildren(children[1:], op, record) } } return append([]*ast.Pattern{children[0]}, simplifyChildren(children[1:], op, record)...) }
func TestNotUnreachable(t *testing.T) { p := ast.NewTreeNode(ast.NewAnyNameExcept(ast.NewStringName("NotC")), ast.NewTreeNode(ast.NewStringName("C"), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()))) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err == nil { t.Fatalf("Expected: AnyNameExcept Not Supported Error: Name: !(NotC), but got %v", gkey) } }
func TestUnreachable(t *testing.T) { p := ast.NewTreeNode(ast.NewStringName("NotC"), ast.NewTreeNode(ast.NewStringName("C"), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()))) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err == nil { t.Fatalf("Expected: Unknown Field Error: Name: NotC, Msg: Debug, but got %v", gkey) } }
func TestKeyAnyName(t *testing.T) { p := ast.NewOr( ast.NewTreeNode(ast.NewNameChoice(ast.NewAnyName(), ast.NewStringName("C")), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("B"), ast.NewZAny()), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err == nil { t.Fatalf("Expected: Any Field Not Supported: Name: _, but got %v", gkey) } }
func TestAnyIndex(t *testing.T) { p := ast.NewTreeNode(ast.NewStringName("KeyValue"), ast.NewTreeNode(ast.NewAnyName(), ast.NewConcat( ast.NewTreeNode(ast.NewStringName("Key"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("Value"), ast.NewZAny()), ))) gkey, err := FieldNamesToNumbers("protonum", "ProtoNum", ProtonumDescription(), p.Grammar()) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func TestKeyRecursive(t *testing.T) { p := ast.NewOr( ast.NewTreeNode(ast.NewStringName("C"), ast.NewReference("main")), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func (this *nameToNumber) translateName(current *context, name *ast.NameExpr, child *ast.Pattern) (*ast.Pattern, error) { switch n := name.GetValue().(type) { case *ast.Name: if current.index { if n.IntValue == nil { return nil, &errExpectedArray{name.String(), current} } c := &context{current.msg, false} newp, err := this.translate(c, child) if err != nil { return nil, err } return ast.NewTreeNode(name, newp), nil } if n.StringValue == nil { return nil, &errExpectedField{name.String(), current} } f := getField(this.descMap.LookupFields(current.msg), n.GetStringValue()) if f == nil { return nil, &errUnknownField{name.String(), current} } msg := this.descMap.LookupMessage(f) c := &context{msg, f.IsRepeated()} newp, err := this.translate(c, child) if err != nil { return nil, err } newName := ast.NewUintName(uint64(f.GetNumber())) return ast.NewTreeNode(newName, newp), nil case *ast.AnyName: if current.index { c := &context{current.msg, false} newp, err := this.translate(c, child) if err != nil { return nil, err } return ast.NewTreeNode(name, newp), nil } else { return nil, &errAnyFieldNotSupported{name.String()} } case *ast.AnyNameExcept: return nil, &errAnyNameExceptNotSupported{name.String()} case *ast.NameChoice: l, err1 := this.translateName(current, n.GetLeft(), child) r, err2 := this.translateName(current, n.GetRight(), child) return ast.NewOr(l, r), anyErr(err1, err2) } panic(fmt.Sprintf("unknown name typ %T", name)) }
func TestKeyTree(t *testing.T) { p := ast.NewTreeNode(ast.NewStringName("C"), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny())) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) if gkey.GetTopPattern().GetTreeNode().GetName().GetName().GetUintValue() != 3 { t.Fatalf("expected field 3, but got %v", gkey) } if gkey.GetTopPattern().GetTreeNode().GetPattern().GetTreeNode().GetName().GetName().GetUintValue() != 1 { t.Fatalf("expected field 1, but got %v", gkey) } check(t, gkey) }
func TestKeyLeftRecursive(t *testing.T) { p := ast.NewOr( ast.NewReference("a"), ast.NewTreeNode(ast.NewStringName("C"), ast.NewReference("main")), ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ) g := p.Grammar().AddRef("a", ast.NewReference("main")) gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) if gkey.GetTopPattern().GetOr().GetRightPattern().GetOr().GetLeftPattern().GetTreeNode().GetName().GetName().GetUintValue() != 3 { t.Fatalf("expected field 3, but got %v", gkey) } check(t, gkey) }
func TestSimplifyRecordLeaf1(t *testing.T) { input := ast.NewAnd( ast.NewContains(ast.NewTreeNode(ast.NewStringName("A"), combinator.Value(funcs.Contains(funcs.StringVar(), funcs.StringConst("a"))))), ast.NewContains(ast.NewTreeNode(ast.NewStringName("A"), combinator.Value(funcs.Contains(funcs.StringVar(), funcs.StringConst("b"))))), ) t.Logf("input: %v", input) expected := ast.NewContains(ast.NewTreeNode(ast.NewStringName("A"), combinator.Value(funcs.And( funcs.Contains(funcs.StringVar(), funcs.StringConst("a")), funcs.Contains(funcs.StringVar(), funcs.StringConst("b")), )))) output := NewSimplifier(input.Grammar()).OptimizeForRecord().Simplify(input) expected.Format() output.Format() t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestSimplifyContainsFalseTreeNode(t *testing.T) { input := ast.NewContains(ast.NewTreeNode(ast.NewAnyNameExcept(ast.NewAnyName()), ast.NewZAny())) expected := ast.NewNot(ast.NewZAny()) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestSimplifyTreeNodeWithNotZanyChild(t *testing.T) { input := ast.NewTreeNode(ast.NewAnyName(), ast.NewNot(ast.NewZAny())) expected := ast.NewNot(ast.NewZAny()) output := NewSimplifier(input.Grammar()).Simplify(input) t.Logf("%v", output) if !expected.Equal(output) { t.Fatalf("expected %v, but got %v", expected, output) } }
func TestRepeatedMessageWithNoFieldsOfTypeMessage(t *testing.T) { p := ast.NewConcat( ast.NewZAny(), ast.NewTreeNode(ast.NewStringName("KeyValue"), ast.NewTreeNode(ast.NewAnyName(), ast.NewConcat( ast.NewTreeNode(ast.NewStringName("Key"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("Value"), ast.NewZAny()), ), ), ), ast.NewZAny(), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("protonum", "ProtoNum", ProtonumDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func TestKeyAnyArrayIndex(t *testing.T) { p := ast.NewConcat( ast.NewZAny(), ast.NewTreeNode(ast.NewStringName("E"), ast.NewTreeNode(ast.NewAnyName(), ast.NewConcat( ast.NewTreeNode(ast.NewStringName("A"), ast.NewZAny()), ast.NewTreeNode(ast.NewStringName("B"), ast.NewZAny()), ), ), ), ast.NewZAny(), ) g := p.Grammar() gkey, err := FieldNamesToNumbers("debug", "Debug", debug.DebugDescription(), g) if err != nil { t.Fatal(err) } t.Logf("%v", gkey) check(t, gkey) }
func (this *simplifier) simplify(p *ast.Pattern, top bool) *ast.Pattern { cRef := func(cp *ast.Pattern) *ast.Pattern { if top { return cp } return checkRef(this.refs, cp) } cachesimp := func(sp *ast.Pattern) *ast.Pattern { if _, ok := this.cache[sp]; ok { return sp } s := this.simplify(sp, false) this.cache[s] = struct{}{} return s } simp := func(sp *ast.Pattern) *ast.Pattern { return this.simplify(sp, false) } typ := p.GetValue() switch v := typ.(type) { case *ast.Empty: return p case *ast.TreeNode: child := cachesimp(v.GetPattern()) if isNotZany(child) { return emptyset } name := v.GetName() b := nameexpr.NameToFunc(v.GetName()) if funcs.IsFalse(b) { return emptyset } if funcs.IsTrue(b) { name = ast.NewAnyName() } return cRef(ast.NewTreeNode(name, child)) case *ast.LeafNode: b, err := compose.NewBool(v.GetExpr()) if err != nil { //Don't simplify if there is an error to keep this function signature simple. return p } if funcs.IsFalse(b) { return emptyset } return p case *ast.Concat: return cRef(simplifyConcat( simp(v.GetLeftPattern()), simp(v.GetRightPattern()), )) case *ast.Or: return cRef(simplifyOr(this.refs, simp(v.GetLeftPattern()), simp(v.GetRightPattern()), this.record, )) case *ast.And: return cRef(simplifyAnd(this.refs, simp(v.GetLeftPattern()), simp(v.GetRightPattern()), this.record, )) case *ast.ZeroOrMore: return cRef(simplifyZeroOrMore(simp(v.GetPattern()))) case *ast.Reference: return p case *ast.Not: return cRef(simplifyNot(simp(v.GetPattern()))) case *ast.ZAny: return p case *ast.Contains: return cRef(simplifyContains(simp(v.GetPattern()))) case *ast.Optional: return simplifyOptional(simp(v.GetPattern())) case *ast.Interleave: return cRef(simplifyInterleave(this.refs, cachesimp(v.GetLeftPattern()), cachesimp(v.GetRightPattern()), )) } panic(fmt.Sprintf("unknown pattern typ %T", typ)) }
func newT(s string) *ast.Pattern { return ast.NewTreeNode(ast.NewStringName(s), ast.NewEmpty()) }