Add support for new policy conditions (#7024)
This PR implements following condition types - StringEqualsIgnoreCase and StringNotEqualsIgnoreCase - BinaryEqualsmaster
parent
2db22deb93
commit
4e4f855b30
@ -0,0 +1,138 @@ |
||||
/* |
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package condition |
||||
|
||||
import ( |
||||
"encoding/base64" |
||||
"fmt" |
||||
"net/http" |
||||
"sort" |
||||
|
||||
"github.com/minio/minio-go/pkg/s3utils" |
||||
"github.com/minio/minio-go/pkg/set" |
||||
) |
||||
|
||||
func toBinaryEqualsFuncString(n name, key Key, values set.StringSet) string { |
||||
valueStrings := values.ToSlice() |
||||
sort.Strings(valueStrings) |
||||
|
||||
return fmt.Sprintf("%v:%v:%v", n, key, valueStrings) |
||||
} |
||||
|
||||
// binaryEqualsFunc - String equals function. It checks whether value by Key in given
|
||||
// values map is in condition values.
|
||||
// For example,
|
||||
// - if values = ["mybucket/foo"], at evaluate() it returns whether string
|
||||
// in value map for Key is in values.
|
||||
type binaryEqualsFunc struct { |
||||
k Key |
||||
values set.StringSet |
||||
} |
||||
|
||||
// evaluate() - evaluates to check whether value by Key in given values is in
|
||||
// condition values.
|
||||
func (f binaryEqualsFunc) evaluate(values map[string][]string) bool { |
||||
requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())] |
||||
if !ok { |
||||
requestValue = values[f.k.Name()] |
||||
} |
||||
|
||||
return !f.values.Intersection(set.CreateStringSet(requestValue...)).IsEmpty() |
||||
} |
||||
|
||||
// key() - returns condition key which is used by this condition function.
|
||||
func (f binaryEqualsFunc) key() Key { |
||||
return f.k |
||||
} |
||||
|
||||
// name() - returns "BinaryEquals" condition name.
|
||||
func (f binaryEqualsFunc) name() name { |
||||
return binaryEquals |
||||
} |
||||
|
||||
func (f binaryEqualsFunc) String() string { |
||||
return toBinaryEqualsFuncString(binaryEquals, f.k, f.values) |
||||
} |
||||
|
||||
// toMap - returns map representation of this function.
|
||||
func (f binaryEqualsFunc) toMap() map[Key]ValueSet { |
||||
if !f.k.IsValid() { |
||||
return nil |
||||
} |
||||
|
||||
values := NewValueSet() |
||||
for _, value := range f.values.ToSlice() { |
||||
values.Add(NewStringValue(base64.StdEncoding.EncodeToString([]byte(value)))) |
||||
} |
||||
|
||||
return map[Key]ValueSet{ |
||||
f.k: values, |
||||
} |
||||
} |
||||
|
||||
func validateBinaryEqualsValues(n name, key Key, values set.StringSet) error { |
||||
vslice := values.ToSlice() |
||||
for _, s := range vslice { |
||||
sbytes, err := base64.StdEncoding.DecodeString(s) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
values.Remove(s) |
||||
s = string(sbytes) |
||||
switch key { |
||||
case S3XAmzCopySource: |
||||
bucket, object := path2BucketAndObject(s) |
||||
if object == "" { |
||||
return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzCopySource, n) |
||||
} |
||||
if err = s3utils.CheckValidBucketName(bucket); err != nil { |
||||
return err |
||||
} |
||||
case S3XAmzServerSideEncryption: |
||||
if s != "aws:kms" && s != "AES256" { |
||||
return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzServerSideEncryption, n) |
||||
} |
||||
case S3XAmzMetadataDirective: |
||||
if s != "COPY" && s != "REPLACE" { |
||||
return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzMetadataDirective, n) |
||||
} |
||||
} |
||||
values.Add(s) |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
// newBinaryEqualsFunc - returns new BinaryEquals function.
|
||||
func newBinaryEqualsFunc(key Key, values ValueSet) (Function, error) { |
||||
valueStrings, err := valuesToStringSlice(binaryEquals, values) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return NewBinaryEqualsFunc(key, valueStrings...) |
||||
} |
||||
|
||||
// NewBinaryEqualsFunc - returns new BinaryEquals function.
|
||||
func NewBinaryEqualsFunc(key Key, values ...string) (Function, error) { |
||||
sset := set.CreateStringSet(values...) |
||||
if err := validateBinaryEqualsValues(binaryEquals, key, sset); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &binaryEqualsFunc{key, sset}, nil |
||||
} |
@ -0,0 +1,387 @@ |
||||
/* |
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package condition |
||||
|
||||
import ( |
||||
"encoding/base64" |
||||
"reflect" |
||||
"testing" |
||||
) |
||||
|
||||
func TestBinaryEqualsFuncEvaluate(t *testing.T) { |
||||
case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newBinaryEqualsFunc(S3LocationConstraint, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
function Function |
||||
values map[string][]string |
||||
expectedResult bool |
||||
}{ |
||||
{case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true}, |
||||
{case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false}, |
||||
{case1Function, map[string][]string{}, false}, |
||||
{case1Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
|
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true}, |
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"aws:kms"}}, false}, |
||||
{case2Function, map[string][]string{}, false}, |
||||
{case2Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
|
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true}, |
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false}, |
||||
{case3Function, map[string][]string{}, false}, |
||||
{case3Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
|
||||
{case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true}, |
||||
{case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false}, |
||||
{case4Function, map[string][]string{}, false}, |
||||
{case4Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.function.evaluate(testCase.values) |
||||
|
||||
if result != testCase.expectedResult { |
||||
t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestBinaryEqualsFuncKey(t *testing.T) { |
||||
case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newBinaryEqualsFunc(S3LocationConstraint, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
function Function |
||||
expectedResult Key |
||||
}{ |
||||
{case1Function, S3XAmzCopySource}, |
||||
{case2Function, S3XAmzServerSideEncryption}, |
||||
{case3Function, S3XAmzMetadataDirective}, |
||||
{case4Function, S3LocationConstraint}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.function.key() |
||||
|
||||
if result != testCase.expectedResult { |
||||
t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestBinaryEqualsFuncToMap(t *testing.T) { |
||||
case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case1Result := map[Key]ValueSet{ |
||||
S3XAmzCopySource: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))), |
||||
} |
||||
|
||||
case2Function, err := newBinaryEqualsFunc(S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Result := map[Key]ValueSet{ |
||||
S3XAmzCopySource: NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))), |
||||
), |
||||
} |
||||
|
||||
case3Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Result := map[Key]ValueSet{ |
||||
S3XAmzServerSideEncryption: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))), |
||||
} |
||||
|
||||
case4Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("aws:kms"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Result := map[Key]ValueSet{ |
||||
S3XAmzServerSideEncryption: NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("aws:kms"))), |
||||
), |
||||
} |
||||
|
||||
case5Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case5Result := map[Key]ValueSet{ |
||||
S3XAmzMetadataDirective: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))), |
||||
} |
||||
|
||||
case6Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case6Result := map[Key]ValueSet{ |
||||
S3XAmzMetadataDirective: NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))), |
||||
), |
||||
} |
||||
|
||||
case7Function, err := newBinaryEqualsFunc(S3LocationConstraint, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case7Result := map[Key]ValueSet{ |
||||
S3LocationConstraint: NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))), |
||||
} |
||||
|
||||
case8Function, err := newBinaryEqualsFunc(S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case8Result := map[Key]ValueSet{ |
||||
S3LocationConstraint: NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))), |
||||
), |
||||
} |
||||
|
||||
testCases := []struct { |
||||
f Function |
||||
expectedResult map[Key]ValueSet |
||||
}{ |
||||
{case1Function, case1Result}, |
||||
{case2Function, case2Result}, |
||||
{case3Function, case3Result}, |
||||
{case4Function, case4Result}, |
||||
{case5Function, case5Result}, |
||||
{case6Function, case6Result}, |
||||
{case7Function, case7Result}, |
||||
{case8Function, case8Result}, |
||||
{&binaryEqualsFunc{}, nil}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.f.toMap() |
||||
|
||||
if !reflect.DeepEqual(result, testCase.expectedResult) { |
||||
t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestNewBinaryEqualsFunc(t *testing.T) { |
||||
case1Function, err := newBinaryEqualsFunc(S3XAmzCopySource, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newBinaryEqualsFunc(S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newBinaryEqualsFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("aws:kms"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case5Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case6Function, err := newBinaryEqualsFunc(S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case7Function, err := newBinaryEqualsFunc(S3LocationConstraint, |
||||
NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case8Function, err := newBinaryEqualsFunc(S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
key Key |
||||
values ValueSet |
||||
expectedResult Function |
||||
expectErr bool |
||||
}{ |
||||
{S3XAmzCopySource, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject")))), case1Function, false}, |
||||
{S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("yourbucket/myobject"))), |
||||
), case2Function, false}, |
||||
|
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256")))), case3Function, false}, |
||||
{S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("aws:kms"))), |
||||
), case4Function, false}, |
||||
|
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE")))), case5Function, false}, |
||||
{S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("COPY"))), |
||||
), case6Function, false}, |
||||
|
||||
{S3LocationConstraint, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1")))), case7Function, false}, |
||||
{S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))), |
||||
NewStringValue(base64.StdEncoding.EncodeToString([]byte("us-west-1"))), |
||||
), case8Function, false}, |
||||
|
||||
// Unsupported value error.
|
||||
{S3XAmzCopySource, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket/myobject"))), NewIntValue(7)), nil, true}, |
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("AES256"))), NewIntValue(7)), nil, true}, |
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("REPLACE"))), NewIntValue(7)), nil, true}, |
||||
{S3LocationConstraint, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("eu-west-1"))), NewIntValue(7)), nil, true}, |
||||
|
||||
// Invalid value error.
|
||||
{S3XAmzCopySource, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("mybucket")))), nil, true}, |
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("SSE-C")))), nil, true}, |
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue(base64.StdEncoding.EncodeToString([]byte("DUPLICATE")))), nil, true}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result, err := newBinaryEqualsFunc(testCase.key, testCase.values) |
||||
expectErr := (err != nil) |
||||
|
||||
if expectErr != testCase.expectErr { |
||||
t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr) |
||||
} |
||||
|
||||
if !testCase.expectErr { |
||||
if !reflect.DeepEqual(result, testCase.expectedResult) { |
||||
t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,157 @@ |
||||
/* |
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package condition |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/http" |
||||
"sort" |
||||
"strings" |
||||
|
||||
"github.com/minio/minio-go/pkg/set" |
||||
) |
||||
|
||||
func toStringEqualsIgnoreCaseFuncString(n name, key Key, values set.StringSet) string { |
||||
valueStrings := values.ToSlice() |
||||
sort.Strings(valueStrings) |
||||
|
||||
return fmt.Sprintf("%v:%v:%v", n, key, valueStrings) |
||||
} |
||||
|
||||
// stringEqualsIgnoreCaseFunc - String equals function. It checks whether value by Key in given
|
||||
// values map is in condition values.
|
||||
// For example,
|
||||
// - if values = ["mybucket/foo"], at evaluate() it returns whether string
|
||||
// in value map for Key is in values.
|
||||
type stringEqualsIgnoreCaseFunc struct { |
||||
k Key |
||||
values set.StringSet |
||||
} |
||||
|
||||
// evaluate() - evaluates to check whether value by Key in given values is in
|
||||
// condition values, ignores case.
|
||||
func (f stringEqualsIgnoreCaseFunc) evaluate(values map[string][]string) bool { |
||||
requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())] |
||||
if !ok { |
||||
requestValue = values[f.k.Name()] |
||||
} |
||||
|
||||
for _, v := range requestValue { |
||||
if !f.values.FuncMatch(strings.EqualFold, v).IsEmpty() { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// key() - returns condition key which is used by this condition function.
|
||||
func (f stringEqualsIgnoreCaseFunc) key() Key { |
||||
return f.k |
||||
} |
||||
|
||||
// name() - returns "StringEqualsIgnoreCase" condition name.
|
||||
func (f stringEqualsIgnoreCaseFunc) name() name { |
||||
return stringEqualsIgnoreCase |
||||
} |
||||
|
||||
func (f stringEqualsIgnoreCaseFunc) String() string { |
||||
return toStringEqualsIgnoreCaseFuncString(stringEqualsIgnoreCase, f.k, f.values) |
||||
} |
||||
|
||||
// toMap - returns map representation of this function.
|
||||
func (f stringEqualsIgnoreCaseFunc) toMap() map[Key]ValueSet { |
||||
if !f.k.IsValid() { |
||||
return nil |
||||
} |
||||
|
||||
values := NewValueSet() |
||||
for _, value := range f.values.ToSlice() { |
||||
values.Add(NewStringValue(value)) |
||||
} |
||||
|
||||
return map[Key]ValueSet{ |
||||
f.k: values, |
||||
} |
||||
} |
||||
|
||||
// stringNotEqualsIgnoreCaseFunc - String not equals function. It checks whether value by Key in
|
||||
// given values is NOT in condition values.
|
||||
// For example,
|
||||
// - if values = ["mybucket/foo"], at evaluate() it returns whether string
|
||||
// in value map for Key is NOT in values.
|
||||
type stringNotEqualsIgnoreCaseFunc struct { |
||||
stringEqualsIgnoreCaseFunc |
||||
} |
||||
|
||||
// evaluate() - evaluates to check whether value by Key in given values is NOT in
|
||||
// condition values.
|
||||
func (f stringNotEqualsIgnoreCaseFunc) evaluate(values map[string][]string) bool { |
||||
return !f.stringEqualsIgnoreCaseFunc.evaluate(values) |
||||
} |
||||
|
||||
// name() - returns "StringNotEqualsIgnoreCase" condition name.
|
||||
func (f stringNotEqualsIgnoreCaseFunc) name() name { |
||||
return stringNotEqualsIgnoreCase |
||||
} |
||||
|
||||
func (f stringNotEqualsIgnoreCaseFunc) String() string { |
||||
return toStringEqualsIgnoreCaseFuncString(stringNotEqualsIgnoreCase, f.stringEqualsIgnoreCaseFunc.k, f.stringEqualsIgnoreCaseFunc.values) |
||||
} |
||||
|
||||
func validateStringEqualsIgnoreCaseValues(n name, key Key, values set.StringSet) error { |
||||
return validateStringEqualsValues(n, key, values) |
||||
} |
||||
|
||||
// newStringEqualsIgnoreCaseFunc - returns new StringEqualsIgnoreCase function.
|
||||
func newStringEqualsIgnoreCaseFunc(key Key, values ValueSet) (Function, error) { |
||||
valueStrings, err := valuesToStringSlice(stringEqualsIgnoreCase, values) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return NewStringEqualsIgnoreCaseFunc(key, valueStrings...) |
||||
} |
||||
|
||||
// NewStringEqualsIgnoreCaseFunc - returns new StringEqualsIgnoreCase function.
|
||||
func NewStringEqualsIgnoreCaseFunc(key Key, values ...string) (Function, error) { |
||||
sset := set.CreateStringSet(values...) |
||||
if err := validateStringEqualsIgnoreCaseValues(stringEqualsIgnoreCase, key, sset); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &stringEqualsIgnoreCaseFunc{key, sset}, nil |
||||
} |
||||
|
||||
// newStringNotEqualsIgnoreCaseFunc - returns new StringNotEqualsIgnoreCase function.
|
||||
func newStringNotEqualsIgnoreCaseFunc(key Key, values ValueSet) (Function, error) { |
||||
valueStrings, err := valuesToStringSlice(stringNotEqualsIgnoreCase, values) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return NewStringNotEqualsIgnoreCaseFunc(key, valueStrings...) |
||||
} |
||||
|
||||
// NewStringNotEqualsIgnoreCaseFunc - returns new StringNotEqualsIgnoreCase function.
|
||||
func NewStringNotEqualsIgnoreCaseFunc(key Key, values ...string) (Function, error) { |
||||
sset := set.CreateStringSet(values...) |
||||
if err := validateStringEqualsIgnoreCaseValues(stringNotEqualsIgnoreCase, key, sset); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &stringNotEqualsIgnoreCaseFunc{stringEqualsIgnoreCaseFunc{key, sset}}, nil |
||||
} |
@ -0,0 +1,720 @@ |
||||
/* |
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package condition |
||||
|
||||
import ( |
||||
"reflect" |
||||
"testing" |
||||
) |
||||
|
||||
func TestStringEqualsIgnoreCaseFuncEvaluate(t *testing.T) { |
||||
case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
function Function |
||||
values map[string][]string |
||||
expectedResult bool |
||||
}{ |
||||
{case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, true}, |
||||
{case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, false}, |
||||
{case1Function, map[string][]string{}, false}, |
||||
{case1Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
|
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, true}, |
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"aes256"}}, true}, |
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"aws:kms"}}, false}, |
||||
{case2Function, map[string][]string{}, false}, |
||||
{case2Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
|
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, true}, |
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"replace"}}, true}, |
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, false}, |
||||
{case3Function, map[string][]string{}, false}, |
||||
{case3Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
|
||||
{case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, true}, |
||||
{case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, false}, |
||||
{case4Function, map[string][]string{}, false}, |
||||
{case4Function, map[string][]string{"delimiter": {"/"}}, false}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.function.evaluate(testCase.values) |
||||
|
||||
if result != testCase.expectedResult { |
||||
t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestStringEqualsIgnoreCaseFuncKey(t *testing.T) { |
||||
case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
function Function |
||||
expectedResult Key |
||||
}{ |
||||
{case1Function, S3XAmzCopySource}, |
||||
{case2Function, S3XAmzServerSideEncryption}, |
||||
{case3Function, S3XAmzMetadataDirective}, |
||||
{case4Function, S3LocationConstraint}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.function.key() |
||||
|
||||
if result != testCase.expectedResult { |
||||
t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestStringEqualsIgnoreCaseFuncToMap(t *testing.T) { |
||||
case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case1Result := map[Key]ValueSet{ |
||||
S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/myobject")), |
||||
} |
||||
|
||||
case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Result := map[Key]ValueSet{ |
||||
S3XAmzCopySource: NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), |
||||
} |
||||
|
||||
case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Result := map[Key]ValueSet{ |
||||
S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES256")), |
||||
} |
||||
|
||||
case4Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Result := map[Key]ValueSet{ |
||||
S3XAmzServerSideEncryption: NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), |
||||
} |
||||
|
||||
case5Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case5Result := map[Key]ValueSet{ |
||||
S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPLACE")), |
||||
} |
||||
|
||||
case6Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case6Result := map[Key]ValueSet{ |
||||
S3XAmzMetadataDirective: NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), |
||||
} |
||||
|
||||
case7Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case7Result := map[Key]ValueSet{ |
||||
S3LocationConstraint: NewValueSet(NewStringValue("eu-west-1")), |
||||
} |
||||
|
||||
case8Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case8Result := map[Key]ValueSet{ |
||||
S3LocationConstraint: NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), |
||||
} |
||||
|
||||
testCases := []struct { |
||||
f Function |
||||
expectedResult map[Key]ValueSet |
||||
}{ |
||||
{case1Function, case1Result}, |
||||
{case2Function, case2Result}, |
||||
{case3Function, case3Result}, |
||||
{case4Function, case4Result}, |
||||
{case5Function, case5Result}, |
||||
{case6Function, case6Result}, |
||||
{case7Function, case7Result}, |
||||
{case8Function, case8Result}, |
||||
{&stringEqualsFunc{}, nil}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.f.toMap() |
||||
|
||||
if !reflect.DeepEqual(result, testCase.expectedResult) { |
||||
t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestStringNotEqualsIgnoreCaseFuncEvaluate(t *testing.T) { |
||||
case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
function Function |
||||
values map[string][]string |
||||
expectedResult bool |
||||
}{ |
||||
{case1Function, map[string][]string{"x-amz-copy-source": {"mybucket/myobject"}}, false}, |
||||
{case1Function, map[string][]string{"x-amz-copy-source": {"yourbucket/myobject"}}, true}, |
||||
{case1Function, map[string][]string{}, true}, |
||||
{case1Function, map[string][]string{"delimiter": {"/"}}, true}, |
||||
|
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"AES256"}}, false}, |
||||
{case2Function, map[string][]string{"x-amz-server-side-encryption": {"aws:kms"}}, true}, |
||||
{case2Function, map[string][]string{}, true}, |
||||
{case2Function, map[string][]string{"delimiter": {"/"}}, true}, |
||||
|
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"REPLACE"}}, false}, |
||||
{case3Function, map[string][]string{"x-amz-metadata-directive": {"COPY"}}, true}, |
||||
{case3Function, map[string][]string{}, true}, |
||||
{case3Function, map[string][]string{"delimiter": {"/"}}, true}, |
||||
|
||||
{case4Function, map[string][]string{"LocationConstraint": {"eu-west-1"}}, false}, |
||||
{case4Function, map[string][]string{"LocationConstraint": {"us-east-1"}}, true}, |
||||
{case4Function, map[string][]string{}, true}, |
||||
{case4Function, map[string][]string{"delimiter": {"/"}}, true}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.function.evaluate(testCase.values) |
||||
|
||||
if result != testCase.expectedResult { |
||||
t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestStringNotEqualsIgnoreCaseFuncKey(t *testing.T) { |
||||
case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
function Function |
||||
expectedResult Key |
||||
}{ |
||||
{case1Function, S3XAmzCopySource}, |
||||
{case2Function, S3XAmzServerSideEncryption}, |
||||
{case3Function, S3XAmzMetadataDirective}, |
||||
{case4Function, S3LocationConstraint}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.function.key() |
||||
|
||||
if result != testCase.expectedResult { |
||||
t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestStringNotEqualsIgnoreCaseFuncToMap(t *testing.T) { |
||||
case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case1Result := map[Key]ValueSet{ |
||||
S3XAmzCopySource: NewValueSet(NewStringValue("mybucket/myobject")), |
||||
} |
||||
|
||||
case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Result := map[Key]ValueSet{ |
||||
S3XAmzCopySource: NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), |
||||
} |
||||
|
||||
case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Result := map[Key]ValueSet{ |
||||
S3XAmzServerSideEncryption: NewValueSet(NewStringValue("AES256")), |
||||
} |
||||
|
||||
case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Result := map[Key]ValueSet{ |
||||
S3XAmzServerSideEncryption: NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), |
||||
} |
||||
|
||||
case5Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case5Result := map[Key]ValueSet{ |
||||
S3XAmzMetadataDirective: NewValueSet(NewStringValue("REPLACE")), |
||||
} |
||||
|
||||
case6Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case6Result := map[Key]ValueSet{ |
||||
S3XAmzMetadataDirective: NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), |
||||
} |
||||
|
||||
case7Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case7Result := map[Key]ValueSet{ |
||||
S3LocationConstraint: NewValueSet(NewStringValue("eu-west-1")), |
||||
} |
||||
|
||||
case8Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case8Result := map[Key]ValueSet{ |
||||
S3LocationConstraint: NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), |
||||
} |
||||
|
||||
testCases := []struct { |
||||
f Function |
||||
expectedResult map[Key]ValueSet |
||||
}{ |
||||
{case1Function, case1Result}, |
||||
{case2Function, case2Result}, |
||||
{case3Function, case3Result}, |
||||
{case4Function, case4Result}, |
||||
{case5Function, case5Result}, |
||||
{case6Function, case6Result}, |
||||
{case7Function, case7Result}, |
||||
{case8Function, case8Result}, |
||||
{&stringNotEqualsFunc{}, nil}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result := testCase.f.toMap() |
||||
|
||||
if !reflect.DeepEqual(result, testCase.expectedResult) { |
||||
t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestNewStringEqualsIgnoreCaseFunc(t *testing.T) { |
||||
case1Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case5Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case6Function, err := newStringEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case7Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case8Function, err := newStringEqualsIgnoreCaseFunc(S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
key Key |
||||
values ValueSet |
||||
expectedResult Function |
||||
expectErr bool |
||||
}{ |
||||
{S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")), case1Function, false}, |
||||
{S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), case2Function, false}, |
||||
|
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")), case3Function, false}, |
||||
{S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), case4Function, false}, |
||||
|
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")), case5Function, false}, |
||||
{S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), case6Function, false}, |
||||
|
||||
{S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")), case7Function, false}, |
||||
{S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), case8Function, false}, |
||||
|
||||
// Unsupported value error.
|
||||
{S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true}, |
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true}, |
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true}, |
||||
{S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true}, |
||||
|
||||
// Invalid value error.
|
||||
{S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true}, |
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue("SSE-C")), nil, true}, |
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue("DUPLICATE")), nil, true}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result, err := newStringEqualsIgnoreCaseFunc(testCase.key, testCase.values) |
||||
expectErr := (err != nil) |
||||
|
||||
if expectErr != testCase.expectErr { |
||||
t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr) |
||||
} |
||||
|
||||
if !testCase.expectErr { |
||||
if !reflect.DeepEqual(result, testCase.expectedResult) { |
||||
t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestNewStringNotEqualsIgnoreCaseFunc(t *testing.T) { |
||||
case1Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case2Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case3Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case4Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case5Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case6Function, err := newStringNotEqualsIgnoreCaseFunc(S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case7Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"))) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
case8Function, err := newStringNotEqualsIgnoreCaseFunc(S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), |
||||
) |
||||
if err != nil { |
||||
t.Fatalf("unexpected error. %v\n", err) |
||||
} |
||||
|
||||
testCases := []struct { |
||||
key Key |
||||
values ValueSet |
||||
expectedResult Function |
||||
expectErr bool |
||||
}{ |
||||
{S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject")), case1Function, false}, |
||||
{S3XAmzCopySource, |
||||
NewValueSet( |
||||
NewStringValue("mybucket/myobject"), |
||||
NewStringValue("yourbucket/myobject"), |
||||
), case2Function, false}, |
||||
|
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256")), case3Function, false}, |
||||
{S3XAmzServerSideEncryption, |
||||
NewValueSet( |
||||
NewStringValue("AES256"), |
||||
NewStringValue("aws:kms"), |
||||
), case4Function, false}, |
||||
|
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE")), case5Function, false}, |
||||
{S3XAmzMetadataDirective, |
||||
NewValueSet( |
||||
NewStringValue("REPLACE"), |
||||
NewStringValue("COPY"), |
||||
), case6Function, false}, |
||||
|
||||
{S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1")), case7Function, false}, |
||||
{S3LocationConstraint, |
||||
NewValueSet( |
||||
NewStringValue("eu-west-1"), |
||||
NewStringValue("us-west-1"), |
||||
), case8Function, false}, |
||||
|
||||
// Unsupported value error.
|
||||
{S3XAmzCopySource, NewValueSet(NewStringValue("mybucket/myobject"), NewIntValue(7)), nil, true}, |
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue("AES256"), NewIntValue(7)), nil, true}, |
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue("REPLACE"), NewIntValue(7)), nil, true}, |
||||
{S3LocationConstraint, NewValueSet(NewStringValue("eu-west-1"), NewIntValue(7)), nil, true}, |
||||
|
||||
// Invalid value error.
|
||||
{S3XAmzCopySource, NewValueSet(NewStringValue("mybucket")), nil, true}, |
||||
{S3XAmzServerSideEncryption, NewValueSet(NewStringValue("SSE-C")), nil, true}, |
||||
{S3XAmzMetadataDirective, NewValueSet(NewStringValue("DUPLICATE")), nil, true}, |
||||
} |
||||
|
||||
for i, testCase := range testCases { |
||||
result, err := newStringNotEqualsIgnoreCaseFunc(testCase.key, testCase.values) |
||||
expectErr := (err != nil) |
||||
|
||||
if expectErr != testCase.expectErr { |
||||
t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr) |
||||
} |
||||
|
||||
if !testCase.expectErr { |
||||
if !reflect.DeepEqual(result, testCase.expectedResult) { |
||||
t.Fatalf("case %v: result: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue