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  }