github.com/ipld/go-ipld-prime@v0.21.0/traversal/selector/exploreUnion_test.go (about) 1 package selector 2 3 import ( 4 "testing" 5 6 qt "github.com/frankban/quicktest" 7 8 "github.com/ipld/go-ipld-prime/datamodel" 9 "github.com/ipld/go-ipld-prime/fluent" 10 "github.com/ipld/go-ipld-prime/node/basicnode" 11 ) 12 13 func TestParseExploreUnion(t *testing.T) { 14 t.Run("parsing non list node should error", func(t *testing.T) { 15 sn := fluent.MustBuildMap(basicnode.Prototype__Map{}, 0, func(na fluent.MapAssembler) {}) 16 _, err := ParseContext{}.ParseExploreUnion(sn) 17 qt.Check(t, err, qt.ErrorMatches, "selector spec parse rejected: explore union selector must be a list") 18 }) 19 t.Run("parsing list node where one node is invalid should return child's error", func(t *testing.T) { 20 sn := fluent.MustBuildList(basicnode.Prototype__List{}, 2, func(na fluent.ListAssembler) { 21 na.AssembleValue().CreateMap(1, func(na fluent.MapAssembler) { 22 na.AssembleEntry(SelectorKey_Matcher).CreateMap(0, func(na fluent.MapAssembler) {}) 23 }) 24 na.AssembleValue().AssignInt(2) 25 }) 26 _, err := ParseContext{}.ParseExploreUnion(sn) 27 qt.Check(t, err, qt.ErrorMatches, "selector spec parse rejected: selector is a keyed union and thus must be a map") 28 }) 29 30 t.Run("parsing map node with next field with valid selector node should parse", func(t *testing.T) { 31 sn := fluent.MustBuildList(basicnode.Prototype__List{}, 2, func(na fluent.ListAssembler) { 32 na.AssembleValue().CreateMap(1, func(na fluent.MapAssembler) { 33 na.AssembleEntry(SelectorKey_Matcher).CreateMap(0, func(na fluent.MapAssembler) {}) 34 }) 35 na.AssembleValue().CreateMap(1, func(na fluent.MapAssembler) { 36 na.AssembleEntry(SelectorKey_ExploreIndex).CreateMap(2, func(na fluent.MapAssembler) { 37 na.AssembleEntry(SelectorKey_Index).AssignInt(2) 38 na.AssembleEntry(SelectorKey_Next).CreateMap(1, func(na fluent.MapAssembler) { 39 na.AssembleEntry(SelectorKey_Matcher).CreateMap(0, func(na fluent.MapAssembler) {}) 40 }) 41 }) 42 }) 43 }) 44 s, err := ParseContext{}.ParseExploreUnion(sn) 45 qt.Check(t, err, qt.IsNil) 46 qt.Check(t, s, deepEqualsAllowAllUnexported, ExploreUnion{[]Selector{Matcher{}, ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}}}) 47 }) 48 } 49 50 func TestExploreUnionExplore(t *testing.T) { 51 n := fluent.MustBuildList(basicnode.Prototype__List{}, 4, func(na fluent.ListAssembler) { 52 na.AssembleValue().AssignInt(0) 53 na.AssembleValue().AssignInt(1) 54 na.AssembleValue().AssignInt(2) 55 na.AssembleValue().AssignInt(3) 56 }) 57 t.Run("exploring should return nil if all member selectors return nil when explored", func(t *testing.T) { 58 s := ExploreUnion{[]Selector{Matcher{}, ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}}} 59 returnedSelector, _ := s.Explore(n, datamodel.PathSegmentOfInt(3)) 60 qt.Check(t, returnedSelector, qt.IsNil) 61 }) 62 63 t.Run("if exactly one member selector returns a non-nil selector when explored, exploring should return that value", func(t *testing.T) { 64 s := ExploreUnion{[]Selector{Matcher{}, ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}}} 65 66 returnedSelector, _ := s.Explore(n, datamodel.PathSegmentOfInt(2)) 67 qt.Check(t, returnedSelector, qt.Equals, Matcher{}) 68 }) 69 t.Run("exploring should return a new union selector if more than one member selector returns a non nil selector when explored", func(t *testing.T) { 70 s := ExploreUnion{[]Selector{ 71 Matcher{}, 72 ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}, 73 ExploreRange{Matcher{}, 2, 3, []datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}, 74 ExploreFields{map[string]Selector{"applesauce": Matcher{}}, []datamodel.PathSegment{datamodel.PathSegmentOfString("applesauce")}}, 75 }} 76 77 returnedSelector, _ := s.Explore(n, datamodel.PathSegmentOfInt(2)) 78 qt.Check(t, returnedSelector, deepEqualsAllowAllUnexported, ExploreUnion{[]Selector{Matcher{}, Matcher{}}}) 79 }) 80 } 81 82 func TestExploreUnionInterests(t *testing.T) { 83 t.Run("if any member selector is high-cardinality, interests should be high-cardinality", func(t *testing.T) { 84 s := ExploreUnion{[]Selector{ 85 ExploreAll{Matcher{}}, 86 Matcher{}, 87 ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}, 88 }} 89 qt.Check(t, s.Interests(), deepEqualsAllowAllUnexported, []datamodel.PathSegment(nil)) 90 }) 91 t.Run("if no member selector is high-cardinality, interests should be combination of member selectors interests", func(t *testing.T) { 92 s := ExploreUnion{[]Selector{ 93 ExploreFields{map[string]Selector{"applesauce": Matcher{}}, []datamodel.PathSegment{datamodel.PathSegmentOfString("applesauce")}}, 94 Matcher{}, 95 ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}, 96 }} 97 qt.Check(t, s.Interests(), deepEqualsAllowAllUnexported, []datamodel.PathSegment{datamodel.PathSegmentOfString("applesauce"), datamodel.PathSegmentOfInt(2)}) 98 }) 99 } 100 101 func TestExploreUnionDecide(t *testing.T) { 102 n := basicnode.NewInt(2) 103 t.Run("if any member selector returns true, decide should be true", func(t *testing.T) { 104 s := ExploreUnion{[]Selector{ 105 ExploreAll{Matcher{}}, 106 Matcher{}, 107 ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}, 108 }} 109 qt.Check(t, s.Decide(n), qt.IsTrue) 110 }) 111 t.Run("if no member selector returns true, decide should be false", func(t *testing.T) { 112 s := ExploreUnion{[]Selector{ 113 ExploreFields{map[string]Selector{"applesauce": Matcher{}}, []datamodel.PathSegment{datamodel.PathSegmentOfString("applesauce")}}, 114 ExploreAll{Matcher{}}, 115 ExploreIndex{Matcher{}, [1]datamodel.PathSegment{datamodel.PathSegmentOfInt(2)}}, 116 }} 117 qt.Check(t, s.Decide(n), qt.IsFalse) 118 }) 119 }