Skip to content
This repository was archived by the owner on Mar 14, 2023. It is now read-only.

Commit a4cfd35

Browse files
authored
Merge pull request #38 from nspcc-dev/fix/invalid_filter
Assume filter failed if bucket is non-existent
2 parents 51e333a + 48d994c commit a4cfd35

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

policy.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,34 @@ func (b Bucket) IsValid() bool {
227227
return len(nodes) == len(ns)
228228
}
229229

230-
func (b Bucket) findForbidden(fs []Filter) (forbidden Nodes) {
231-
// if root does not satisfy any filter it must be forbidden
232-
for _, f := range fs {
233-
if b.Key == f.Key && !f.Check(b) {
234-
return b.nodes
230+
func (b Bucket) findAllowed(fs []Filter) (nodes Nodes) {
231+
nodes = b.nodes
232+
233+
for i := range fs {
234+
var allowed Nodes
235+
for _, c := range b.findKey(fs[i].Key) {
236+
if fs[i].F.Check(c.Value) {
237+
allowed = append(allowed, c.nodes...)
238+
}
235239
}
240+
241+
sort.Sort(allowed)
242+
nodes = intersect(nodes, allowed)
236243
}
237244

238-
for _, c := range b.children {
239-
forbidden = union(forbidden, c.findForbidden(fs))
245+
return
246+
}
247+
248+
func (b *Bucket) findKey(key string) (bs []*Bucket) {
249+
if b.Key == key {
250+
bs = append(bs, b)
251+
return
240252
}
253+
254+
for i := range b.children {
255+
bs = append(bs, b.children[i].findKey(key)...)
256+
}
257+
241258
return
242259
}
243260

@@ -329,15 +346,15 @@ func (b Bucket) getMaxSelectionC(ss []Select, filter FilterFunc, cut bool) (*Buc
329346
// any other subgraph satisfying specified selects and filters.
330347
func (b Bucket) GetMaxSelection(s SFGroup) (r *Bucket) {
331348
var (
332-
forbidden = b.findForbidden(s.Filters)
333-
excludes = make(map[uint32]struct{}, len(forbidden)+len(s.Exclude))
349+
allowed = b.findAllowed(s.Filters)
350+
excludes = make(map[uint32]bool, len(s.Exclude))
334351
)
335352

336-
for _, c := range forbidden {
337-
excludes[c.N] = struct{}{}
353+
for _, c := range allowed {
354+
excludes[c.N] = false
338355
}
339356
for _, c := range s.Exclude {
340-
excludes[c] = struct{}{}
357+
excludes[c] = true
341358
}
342359

343360
r, _ = b.getMaxSelection(s.Selectors, func(nodes Nodes) Nodes {

policy_test.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ func TestBucket_RuntimeError(t *testing.T) {
8888
require.NotEqual(t, r2.nodes, r3.nodes)
8989
})
9090

91+
t.Run("non-existing bucket", func(t *testing.T) {
92+
buckets := []bucket{
93+
{"/Location:Europe/Country:Spain/City:Madrid", []uint32{17, 18}},
94+
{"/Location:Europe/Country:Spain/City:Barcelona", []uint32{16, 19}},
95+
}
96+
root, err := newRoot(buckets...)
97+
require.NoError(t, err)
98+
99+
ss := []Select{
100+
{Key: "InvalidSelect", Count: 1},
101+
{Key: NodesBucket, Count: 1},
102+
}
103+
104+
r := root.GetSelection(ss, defaultPivot)
105+
require.Nil(t, r)
106+
})
107+
91108
t.Run("regression test", func(t *testing.T) {
92109
buckets := []bucket{
93110
{"/Location:Europe/Country:Spain/City:Madrid", []uint32{17, 18}},
@@ -367,6 +384,24 @@ func TestBucket_GetMaxSelection(t *testing.T) {
367384
root, err = newRoot(buckets...)
368385
require.NoError(t, err)
369386

387+
t.Run("invalid filter", func(t *testing.T) {
388+
ss = []Select{{Key: "Country", Count: 1}}
389+
fs = []Filter{{Key: "InvalidFilter", F: FilterIn("Germany", "Spain")}}
390+
r = root.GetMaxSelection(SFGroup{Selectors: ss, Filters: fs})
391+
require.Nil(t, r)
392+
})
393+
394+
t.Run("match uniq attribute", func(t *testing.T) {
395+
ss = []Select{{Key: NodesBucket, Count: 2}}
396+
fs = []Filter{{Key: "City", F: FilterEQ("Madrid")}}
397+
r = root.GetMaxSelection(SFGroup{Selectors: ss, Filters: fs})
398+
require.NotNil(t, r)
399+
400+
ss = []Select{{Key: NodesBucket, Count: 3}}
401+
r = root.GetMaxSelection(SFGroup{Selectors: ss, Filters: fs})
402+
require.Nil(t, r)
403+
})
404+
370405
buckets = []bucket{
371406
{"/Location:Europe/Country:Germany/City:Berlin", []uint32{9, 10}},
372407
{"/Location:Europe/Country:Germany/City:Hamburg", []uint32{25}},
@@ -466,7 +501,6 @@ func TestBucket_GetMaxSelection(t *testing.T) {
466501
fs = []Filter{{Key: "Country", F: FilterEQ("Germany")}}
467502
r = root.GetMaxSelection(SFGroup{Selectors: ss, Filters: fs})
468503
require.Equal(t, &exp, r)
469-
470504
}
471505

472506
func TestNetMap_GetNodesByOption(t *testing.T) {

utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ func intersect(a, b Nodes) Nodes {
4848
return c
4949
}
5050

51-
func diff(a Nodes, b map[uint32]struct{}) (c Nodes) {
51+
func diff(a Nodes, exclude map[uint32]bool) (c Nodes) {
5252
c = make(Nodes, 0, len(a))
5353
for _, e := range a {
54-
if _, ok := b[e.N]; !ok {
54+
if excl, ok := exclude[e.N]; ok && !excl {
5555
c = append(c, e)
5656
}
5757
}

0 commit comments

Comments
 (0)