frostfs-sdk-go/netmap/filter_test.go

231 lines
4.6 KiB
Go

package netmap
import (
"errors"
"testing"
"github.com/nspcc-dev/neofs-api-go/v2/netmap"
"github.com/stretchr/testify/require"
)
func TestContext_ProcessFilters(t *testing.T) {
fs := []*Filter{
newFilter("StorageSSD", "Storage", "SSD", OpEQ),
newFilter("GoodRating", "Rating", "4", OpGE),
newFilter("Main", "", "", OpAND,
newFilter("StorageSSD", "", "", 0),
newFilter("", "IntField", "123", OpLT),
newFilter("GoodRating", "", "", 0)),
}
nm, err := NewNetmap(nil)
require.NoError(t, err)
c := NewContext(nm)
p := newPlacementPolicy(1, nil, nil, fs)
require.NoError(t, c.processFilters(p))
require.Equal(t, 3, len(c.Filters))
for _, f := range fs {
require.Equal(t, f, c.Filters[f.Name()])
}
require.Equal(t, uint64(4), c.numCache[fs[1]])
require.Equal(t, uint64(123), c.numCache[fs[2].InnerFilters()[1]])
}
func TestContext_ProcessFiltersInvalid(t *testing.T) {
errTestCases := []struct {
name string
filter *Filter
err error
}{
{
"UnnamedTop",
newFilter("", "Storage", "SSD", OpEQ),
ErrUnnamedTopFilter,
},
{
"InvalidReference",
newFilter("Main", "", "", OpAND,
newFilter("StorageSSD", "", "", 0)),
ErrFilterNotFound,
},
{
"NonEmptyKeyed",
newFilter("Main", "Storage", "SSD", OpEQ,
newFilter("StorageSSD", "", "", 0)),
ErrNonEmptyFilters,
},
{
"InvalidNumber",
newFilter("Main", "Rating", "three", OpGE),
ErrInvalidNumber,
},
{
"InvalidOp",
newFilter("Main", "Rating", "3", 0),
ErrInvalidFilterOp,
},
{
"InvalidName",
newFilter("*", "Rating", "3", OpGE),
ErrInvalidFilterName,
},
{
"MissingFilter",
nil,
ErrMissingField,
},
}
for _, tc := range errTestCases {
t.Run(tc.name, func(t *testing.T) {
c := NewContext(new(Netmap))
p := newPlacementPolicy(1, nil, nil, []*Filter{tc.filter})
err := c.processFilters(p)
require.True(t, errors.Is(err, tc.err), "got: %v", err)
})
}
}
func TestFilter_MatchSimple_InvalidOp(t *testing.T) {
b := &Node{AttrMap: map[string]string{
"Rating": "4",
"Country": "Germany",
}}
f := newFilter("Main", "Rating", "5", OpEQ)
c := NewContext(new(Netmap))
p := newPlacementPolicy(1, nil, nil, []*Filter{f})
require.NoError(t, c.processFilters(p))
// just for the coverage
f.SetOperation(0)
require.False(t, c.match(f, b))
}
func testFilter() *Filter {
f := NewFilter()
f.SetOperation(OpGE)
f.SetName("name")
f.SetKey("key")
f.SetValue("value")
return f
}
func TestFilterFromV2(t *testing.T) {
t.Run("nil from V2", func(t *testing.T) {
var x *netmap.Filter
require.Nil(t, NewFilterFromV2(x))
})
t.Run("nil to V2", func(t *testing.T) {
var x *Filter
require.Nil(t, x.ToV2())
})
fV2 := new(netmap.Filter)
fV2.SetOp(netmap.GE)
fV2.SetName("name")
fV2.SetKey("key")
fV2.SetValue("value")
f := NewFilterFromV2(fV2)
require.Equal(t, fV2, f.ToV2())
}
func TestFilter_Key(t *testing.T) {
f := NewFilter()
key := "some key"
f.SetKey(key)
require.Equal(t, key, f.Key())
}
func TestFilter_Value(t *testing.T) {
f := NewFilter()
val := "some value"
f.SetValue(val)
require.Equal(t, val, f.Value())
}
func TestFilter_Name(t *testing.T) {
f := NewFilter()
name := "some name"
f.SetName(name)
require.Equal(t, name, f.Name())
}
func TestFilter_Operation(t *testing.T) {
f := NewFilter()
op := OpGE
f.SetOperation(op)
require.Equal(t, op, f.Operation())
}
func TestFilter_InnerFilters(t *testing.T) {
f := NewFilter()
f1, f2 := testFilter(), testFilter()
f.SetInnerFilters(f1, f2)
require.Equal(t, []*Filter{f1, f2}, f.InnerFilters())
}
func TestFilterEncoding(t *testing.T) {
f := newFilter("name", "key", "value", OpEQ,
newFilter("name2", "key2", "value", OpOR),
)
t.Run("binary", func(t *testing.T) {
data, err := f.Marshal()
require.NoError(t, err)
f2 := NewFilter()
require.NoError(t, f2.Unmarshal(data))
require.Equal(t, f, f2)
})
t.Run("json", func(t *testing.T) {
data, err := f.MarshalJSON()
require.NoError(t, err)
f2 := NewFilter()
require.NoError(t, f2.UnmarshalJSON(data))
require.Equal(t, f, f2)
})
}
func TestNewFilter(t *testing.T) {
t.Run("default values", func(t *testing.T) {
filter := NewFilter()
// check initial values
require.Empty(t, filter.Name())
require.Empty(t, filter.Key())
require.Empty(t, filter.Value())
require.Zero(t, filter.Operation())
require.Nil(t, filter.InnerFilters())
// convert to v2 message
filterV2 := filter.ToV2()
require.Empty(t, filterV2.GetName())
require.Empty(t, filterV2.GetKey())
require.Empty(t, filterV2.GetValue())
require.Equal(t, netmap.UnspecifiedOperation, filterV2.GetOp())
require.Nil(t, filterV2.GetFilters())
})
}