package chain import ( "fmt" "testing" "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/google/uuid" "github.com/stretchr/testify/require" ) func TestChainMarshalling(t *testing.T) { t.Parallel() for _, id := range generateTestIDs() { for _, rules := range generateTestRules() { for _, matchType := range generateTestMatchTypes() { performMarshalTest(t, id, rules, matchType) } } } } func TestInvalidChainData(t *testing.T) { var ch Chain require.Error(t, ch.UnmarshalBinary(nil)) require.Error(t, ch.UnmarshalBinary([]byte{})) require.Error(t, ch.UnmarshalBinary([]byte{1, 2, 3})) require.Error(t, ch.UnmarshalBinary([]byte("\x00\x00:aws:iam::namespace:group/so\x82\x82\x82\x82\x82\x82u\x82"))) } func FuzzUnmarshal(f *testing.F) { for _, id := range generateTestIDs() { for _, rules := range generateTestRules() { for _, matchType := range generateTestMatchTypes() { chain := Chain{ ID: id, Rules: rules, MatchType: matchType, } data, err := chain.MarshalBinary() require.NoError(f, err) f.Add(data) } } } f.Fuzz(func(t *testing.T, data []byte) { var ch Chain require.NotPanics(t, func() { _ = ch.UnmarshalBinary(data) }) }) } func performMarshalTest(t *testing.T, id ID, r []Rule, mt MatchType) { chain := Chain{ ID: id, Rules: r, MatchType: mt, } data, err := chain.MarshalBinary() require.NoError(t, err) var unmarshalledChain Chain require.NoError(t, unmarshalledChain.UnmarshalBinary(data)) require.Equal(t, chain, unmarshalledChain) } func generateTestIDs() []ID { return []ID{ ID(""), ID(uuid.New().String()), ID("*::/"), ID("avada kedavra"), ID("arn:aws:iam::namespace:group/some_group"), ID("$Object:homomorphicHash"), ID("native:container/ns/9LPLUFZpEmfidG4n44vi2cjXKXSqWT492tCvLJiJ8W1J"), } } func generateTestRules() [][]Rule { result := [][]Rule{ nil, {}, {}, } for _, st := range generateTestStatuses() { for _, act := range generateTestActions() { for _, res := range generateTestResources() { for _, cond := range generateTestConditions() { result[2] = append(result[2], Rule{ Status: st, Actions: act, Resources: res, Condition: cond, Any: true, }) result[2] = append(result[2], Rule{ Status: st, Actions: act, Resources: res, Condition: cond, }) } } } } return result } func generateTestStatuses() []Status { return []Status{ Allow, NoRuleFound, AccessDenied, QuotaLimitReached, } } func generateTestActions() []Actions { return []Actions{ { Inverted: true, Names: nil, }, { Names: nil, }, { Inverted: true, Names: []string{}, }, { Names: []string{}, }, { Inverted: true, Names: []string{native.MethodPutObject}, }, { Names: []string{native.MethodPutObject}, }, { Inverted: true, Names: []string{native.MethodPutObject, native.MethodDeleteContainer, native.MethodDeleteObject}, }, { Names: []string{native.MethodPutObject, native.MethodDeleteContainer, native.MethodDeleteObject}, }, } } func generateTestResources() []Resources { return []Resources{ { Inverted: true, Names: nil, }, { Names: nil, }, { Inverted: true, Names: []string{}, }, { Names: []string{}, }, { Inverted: true, Names: []string{native.ResourceFormatAllObjects}, }, { Names: []string{native.ResourceFormatAllObjects}, }, { Inverted: true, Names: []string{ native.ResourceFormatAllObjects, fmt.Sprintf(native.ResourceFormatRootContainer, "9LPLUFZpEmfidG4n44vi2cjXKXSqWT492tCvLJiJ8W1J"), }, }, { Names: []string{ native.ResourceFormatAllObjects, fmt.Sprintf(native.ResourceFormatRootContainer, "9LPLUFZpEmfidG4n44vi2cjXKXSqWT492tCvLJiJ8W1J"), }, }, } } func generateTestConditions() [][]Condition { result := [][]Condition{ nil, {}, {}, } for _, ct := range generateTestConditionTypes() { for _, ot := range generateObjectTypes() { result[2] = append(result[2], Condition{ Op: ct, Object: ot, Key: "", Value: "", }) result[2] = append(result[2], Condition{ Op: ct, Object: ot, Key: "key", Value: "", }) result[2] = append(result[2], Condition{ Op: ct, Object: ot, Key: "", Value: "value", }) result[2] = append(result[2], Condition{ Op: ct, Object: ot, Key: "key", Value: "value", }) } } return result } func generateTestConditionTypes() []ConditionType { return []ConditionType{ CondStringEquals, CondStringNotEquals, CondStringEqualsIgnoreCase, CondStringNotEqualsIgnoreCase, CondStringLike, CondStringNotLike, CondStringLessThan, CondStringLessThanEquals, CondStringGreaterThan, CondStringGreaterThanEquals, CondNumericEquals, CondNumericNotEquals, CondNumericLessThan, CondNumericLessThanEquals, CondNumericGreaterThan, CondNumericGreaterThanEquals, CondSliceContains, } } func generateObjectTypes() []ObjectType { return []ObjectType{ ObjectResource, ObjectRequest, } } func generateTestMatchTypes() []MatchType { return []MatchType{ MatchTypeDenyPriority, MatchTypeFirstMatch, } }