Skip to content

Commit

Permalink
Fix ExploreRecursive stopAt condition, add tests, add error return to…
Browse files Browse the repository at this point in the history
… Explore (#229)

* stopAt simple testcase

* fixed stopAt in ExploreRecursive. Added tests

* return error in Explore() of selector interface
  • Loading branch information
adlrocha authored Aug 19, 2021
1 parent 5c39e68 commit d7e93a8
Show file tree
Hide file tree
Showing 15 changed files with 330 additions and 75 deletions.
4 changes: 2 additions & 2 deletions traversal/selector/exploreAll.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ func (s ExploreAll) Interests() []ipld.PathSegment {
}

// Explore returns the node's selector for all fields
func (s ExploreAll) Explore(n ipld.Node, p ipld.PathSegment) Selector {
return s.next
func (s ExploreAll) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
return s.next, nil
}

// Decide always returns false because this is not a matcher
Expand Down
4 changes: 2 additions & 2 deletions traversal/selector/exploreFields.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func (s ExploreFields) Interests() []ipld.PathSegment {

// Explore returns the selector for the given path if it is a field in
// the selector node or nil if not
func (s ExploreFields) Explore(n ipld.Node, p ipld.PathSegment) Selector {
return s.selections[p.String()]
func (s ExploreFields) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
return s.selections[p.String()], nil
}

// Decide always returns false because this is not a matcher
Expand Down
8 changes: 4 additions & 4 deletions traversal/selector/exploreIndex.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ func (s ExploreIndex) Interests() []ipld.PathSegment {

// Explore returns the node's selector if
// the path matches the index for this selector or nil if not
func (s ExploreIndex) Explore(n ipld.Node, p ipld.PathSegment) Selector {
func (s ExploreIndex) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
if n.Kind() != ipld.Kind_List {
return nil
return nil, nil
}
expectedIndex, expectedErr := p.Index()
actualIndex, actualErr := s.interest[0].Index()
if expectedErr != nil || actualErr != nil || expectedIndex != actualIndex {
return nil
return nil, nil
}
return s.next
return s.next, nil
}

// Decide always returns false because this is not a matcher
Expand Down
8 changes: 4 additions & 4 deletions traversal/selector/exploreIndex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func TestExploreIndexExplore(t *testing.T) {
s := ExploreIndex{Matcher{}, [1]ipld.PathSegment{ipld.PathSegmentOfInt(3)}}
t.Run("exploring should return nil unless node is a list", func(t *testing.T) {
n := fluent.MustBuildMap(basicnode.Prototype__Map{}, 0, func(na fluent.MapAssembler) {})
returnedSelector := s.Explore(n, ipld.PathSegmentOfInt(3))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfInt(3))
Wish(t, returnedSelector, ShouldEqual, nil)
})
n := fluent.MustBuildList(basicnode.Prototype__List{}, 4, func(na fluent.ListAssembler) {
Expand All @@ -78,15 +78,15 @@ func TestExploreIndexExplore(t *testing.T) {
na.AssembleValue().AssignInt(3)
})
t.Run("exploring should return nil when given a path segment with a different index", func(t *testing.T) {
returnedSelector := s.Explore(n, ipld.PathSegmentOfInt(2))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfInt(2))
Wish(t, returnedSelector, ShouldEqual, nil)
})
t.Run("exploring should return nil when given a path segment that isn't an index", func(t *testing.T) {
returnedSelector := s.Explore(n, ipld.PathSegmentOfString("cheese"))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfString("cheese"))
Wish(t, returnedSelector, ShouldEqual, nil)
})
t.Run("exploring should return the next selector when given a path segment with the right index", func(t *testing.T) {
returnedSelector := s.Explore(n, ipld.PathSegmentOfInt(3))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfInt(3))
Wish(t, returnedSelector, ShouldEqual, Matcher{})
})
}
10 changes: 5 additions & 5 deletions traversal/selector/exploreRange.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ func (s ExploreRange) Interests() []ipld.PathSegment {

// Explore returns the node's selector if
// the path matches an index in the range of this selector
func (s ExploreRange) Explore(n ipld.Node, p ipld.PathSegment) Selector {
func (s ExploreRange) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
if n.Kind() != ipld.Kind_List {
return nil
return nil, nil
}
index, err := p.Index()
if err != nil {
return nil
return nil, nil
}
if index < s.start || index >= s.end {
return nil
return nil, nil
}
return s.next
return s.next, nil
}

// Decide always returns false because this is not a matcher
Expand Down
8 changes: 4 additions & 4 deletions traversal/selector/exploreRange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TestExploreRangeExplore(t *testing.T) {
s := ExploreRange{Matcher{}, 3, 4, []ipld.PathSegment{ipld.PathSegmentOfInt(3)}}
t.Run("exploring should return nil unless node is a list", func(t *testing.T) {
n := fluent.MustBuildMap(basicnode.Prototype__Map{}, 0, func(na fluent.MapAssembler) {})
returnedSelector := s.Explore(n, ipld.PathSegmentOfInt(3))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfInt(3))
Wish(t, returnedSelector, ShouldEqual, nil)
})
n := fluent.MustBuildList(basicnode.Prototype__List{}, 4, func(na fluent.ListAssembler) {
Expand All @@ -116,15 +116,15 @@ func TestExploreRangeExplore(t *testing.T) {
na.AssembleValue().AssignInt(3)
})
t.Run("exploring should return nil when given a path segment out of range", func(t *testing.T) {
returnedSelector := s.Explore(n, ipld.PathSegmentOfInt(2))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfInt(2))
Wish(t, returnedSelector, ShouldEqual, nil)
})
t.Run("exploring should return nil when given a path segment that isn't an index", func(t *testing.T) {
returnedSelector := s.Explore(n, ipld.PathSegmentOfString("cheese"))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfString("cheese"))
Wish(t, returnedSelector, ShouldEqual, nil)
})
t.Run("exploring should return the next selector when given a path segment with index in range", func(t *testing.T) {
returnedSelector := s.Explore(n, ipld.PathSegmentOfInt(3))
returnedSelector, _ := s.Explore(n, ipld.PathSegmentOfInt(3))
Wish(t, returnedSelector, ShouldEqual, Matcher{})
})
}
24 changes: 15 additions & 9 deletions traversal/selector/exploreRecursive.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,34 @@ func (s ExploreRecursive) Interests() []ipld.PathSegment {
}

// Explore returns the node's selector for all fields
func (s ExploreRecursive) Explore(n ipld.Node, p ipld.PathSegment) Selector {
if s.stopAt != nil && s.stopAt.Match(n) {
return nil
func (s ExploreRecursive) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
if s.stopAt != nil {
target, err := n.LookupBySegment(p)
if err != nil {
return nil, err
}
if s.stopAt.Match(target) {
return nil, nil
}
}

nextSelector := s.current.Explore(n, p)
nextSelector, _ := s.current.Explore(n, p)
limit := s.limit

if nextSelector == nil {
return nil
return nil, nil
}
if !s.hasRecursiveEdge(nextSelector) {
return ExploreRecursive{s.sequence, nextSelector, limit, s.stopAt}
return ExploreRecursive{s.sequence, nextSelector, limit, s.stopAt}, nil
}
switch limit.mode {
case RecursionLimit_Depth:
if limit.depth < 2 {
return s.replaceRecursiveEdge(nextSelector, nil)
return s.replaceRecursiveEdge(nextSelector, nil), nil
}
return ExploreRecursive{s.sequence, s.replaceRecursiveEdge(nextSelector, s.sequence), RecursionLimit{RecursionLimit_Depth, limit.depth - 1}, s.stopAt}
return ExploreRecursive{s.sequence, s.replaceRecursiveEdge(nextSelector, s.sequence), RecursionLimit{RecursionLimit_Depth, limit.depth - 1}, s.stopAt}, nil
case RecursionLimit_None:
return ExploreRecursive{s.sequence, s.replaceRecursiveEdge(nextSelector, s.sequence), limit, s.stopAt}
return ExploreRecursive{s.sequence, s.replaceRecursiveEdge(nextSelector, s.sequence), limit, s.stopAt}, nil
default:
panic("Unsupported recursion limit type")
}
Expand Down
2 changes: 1 addition & 1 deletion traversal/selector/exploreRecursiveEdge.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (s ExploreRecursiveEdge) Interests() []ipld.PathSegment {
}

// Explore should ultimately never get called for an ExploreRecursiveEdge selector
func (s ExploreRecursiveEdge) Explore(n ipld.Node, p ipld.PathSegment) Selector {
func (s ExploreRecursiveEdge) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
panic("Traversed Explore Recursive Edge Node With No Parent")
}

Expand Down
62 changes: 31 additions & 31 deletions traversal/selector/exploreRecursive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,28 +202,28 @@ func TestExploreRecursiveExplore(t *testing.T) {
err := dagjson.Decode(nb, strings.NewReader(nodeString))
Wish(t, err, ShouldEqual, nil)
rn := nb.Build()
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))

rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_Depth, maxDepth - 2}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 2}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, nil)
Wish(t, err, ShouldEqual, nil)
Expand Down Expand Up @@ -253,31 +253,31 @@ func TestExploreRecursiveExplore(t *testing.T) {
err := dagjson.Decode(nb, strings.NewReader(nodeString))
Wish(t, err, ShouldEqual, nil)
rn := nb.Build()
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_None, 0}, nil})
Wish(t, err, ShouldEqual, nil)
Expand All @@ -296,11 +296,11 @@ func TestExploreRecursiveExplore(t *testing.T) {
err := dagjson.Decode(nb, strings.NewReader(nodeString))
Wish(t, err, ShouldEqual, nil)
rn := nb.Build()
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
Wish(t, rs, ShouldEqual, nil)
})
t.Run("exploring should work when there is nested recursion", func(t *testing.T) {
Expand Down Expand Up @@ -345,59 +345,59 @@ func TestExploreRecursiveExplore(t *testing.T) {
// traverse down Parent nodes
rn := n
rs = s
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)

// traverse down top level Side tree (nested recursion)
rn = n
rs = s
rs = rs.Explore(rn, ipld.PathSegmentOfString("Side"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Side"))
rn, err = rn.LookupByString("Side")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreRecursive{sideSelector, sideSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil}, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("real"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("real"))
rn, err = rn.LookupByString("real")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreRecursive{sideSelector, sideSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil}, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("apple"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("apple"))
rn, err = rn.LookupByString("apple")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreRecursive{sideSelector, sideSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 2}, nil}, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("sauce"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("sauce"))
rn, err = rn.LookupByString("sauce")
Wish(t, rs, ShouldEqual, nil)
Wish(t, err, ShouldEqual, nil)

// traverse once down Parent (top level recursion) then down Side tree (nested recursion)
rn = n
rs = s
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, subTree, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Side"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Side"))
rn, err = rn.LookupByString("Side")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreRecursive{sideSelector, sideSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil}, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("cheese"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("cheese"))
rn, err = rn.LookupByString("cheese")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreRecursive{sideSelector, sideSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil}, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("whiz"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("whiz"))
rn, err = rn.LookupByString("whiz")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreRecursive{sideSelector, sideSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 2}, nil}, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
Expand Down Expand Up @@ -426,20 +426,20 @@ func TestExploreRecursiveExplore(t *testing.T) {
err := dagjson.Decode(nb, strings.NewReader(nodeString))
Wish(t, err, ShouldEqual, nil)
rn := nb.Build()
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreUnion{[]Selector{Matcher{}, subTree}}, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfString("Parents"))

rn, err = rn.LookupByString("Parents")
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, parentsSelector, RecursionLimit{RecursionLimit_Depth, maxDepth - 1}, nil})
Wish(t, err, ShouldEqual, nil)
rs = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rs, _ = rs.Explore(rn, ipld.PathSegmentOfInt(0))
rn, err = rn.LookupByIndex(0)
Wish(t, rs, ShouldEqual, ExploreRecursive{subTree, ExploreUnion{[]Selector{Matcher{}, subTree}}, RecursionLimit{RecursionLimit_Depth, maxDepth - 2}, nil})
Wish(t, err, ShouldEqual, nil)
Expand Down
13 changes: 8 additions & 5 deletions traversal/selector/exploreUnion.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,25 @@ func (s ExploreUnion) Interests() []ipld.PathSegment {
// - a new union selector if more than one member returns a selector
// - if exactly one member returns a selector, that selector
// - nil if no members return a selector
func (s ExploreUnion) Explore(n ipld.Node, p ipld.PathSegment) Selector {
func (s ExploreUnion) Explore(n ipld.Node, p ipld.PathSegment) (Selector, error) {
// TODO: memory efficient?
nonNilResults := make([]Selector, 0, len(s.Members))
for _, member := range s.Members {
resultSelector := member.Explore(n, p)
resultSelector, err := member.Explore(n, p)
if err != nil {
return nil, err
}
if resultSelector != nil {
nonNilResults = append(nonNilResults, resultSelector)
}
}
if len(nonNilResults) == 0 {
return nil
return nil, nil
}
if len(nonNilResults) == 1 {
return nonNilResults[0]
return nonNilResults[0], nil
}
return ExploreUnion{nonNilResults}
return ExploreUnion{nonNilResults}, nil
}

// Decide returns true for a Union selector if any of the member selectors
Expand Down
Loading

0 comments on commit d7e93a8

Please sign in to comment.