forked from kyma-project/infrastructure-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package shoot | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"strings" | ||
|
||
"github.com/gardener/gardener/pkg/apis/core/v1beta1" | ||
"github.com/onsi/gomega" | ||
"github.com/onsi/gomega/types" | ||
"sigs.k8s.io/yaml" | ||
) | ||
|
||
var ( | ||
errInvalidType = fmt.Errorf("invalid type") | ||
) | ||
|
||
type ShootMatcher struct { | ||
toMatch interface{} | ||
fails []string | ||
} | ||
|
||
func Matcher(i interface{}) types.GomegaMatcher { | ||
return &ShootMatcher{ | ||
toMatch: i, | ||
} | ||
} | ||
|
||
func getShoot(i interface{}) (shoot v1beta1.Shoot, err error) { | ||
if i == nil { | ||
return v1beta1.Shoot{}, fmt.Errorf("invalid value nil") | ||
} | ||
|
||
switch v := i.(type) { | ||
|
||
case string: | ||
err = yaml.Unmarshal([]byte(v), &shoot) | ||
return shoot, err | ||
|
||
case v1beta1.Shoot: | ||
return v, nil | ||
|
||
case *v1beta1.Shoot: | ||
return *v, nil | ||
|
||
default: | ||
return v1beta1.Shoot{}, fmt.Errorf(`%w: %s`, errInvalidType, reflect.TypeOf(v)) | ||
} | ||
} | ||
|
||
type matcher struct { | ||
types.GomegaMatcher | ||
path string | ||
actual interface{} | ||
} | ||
|
||
func (m *ShootMatcher) Match(actual interface{}) (success bool, err error) { | ||
aShoot, err := getShoot(actual) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
eShoot, err := getShoot(m.toMatch) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
for _, matcher := range []matcher{ | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.TypeMeta), | ||
actual: aShoot.TypeMeta, | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.Name), | ||
actual: aShoot.Name, | ||
path: "metadata/name", | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.Namespace), | ||
actual: aShoot.Namespace, | ||
path: "metadata/namespace", | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.Labels), | ||
actual: aShoot.Labels, | ||
path: "metadata/labels", | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.Annotations), | ||
actual: aShoot.Annotations, | ||
path: "metadata/annotations", | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.OwnerReferences), | ||
actual: aShoot.OwnerReferences, | ||
path: "metadata/ownerReferences", | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.Finalizers), | ||
actual: aShoot.Finalizers, | ||
path: "metadata/finalizers", | ||
}, | ||
{ | ||
GomegaMatcher: gomega.Equal(eShoot.Spec), | ||
actual: aShoot.Spec, | ||
path: "spec", | ||
}, | ||
} { | ||
ok, err := matcher.Match(matcher.actual) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
if !ok { | ||
msg := matcher.FailureMessage(matcher.actual) | ||
if matcher.path != "" { | ||
msg = fmt.Sprintf("%s: %s", matcher.path, msg) | ||
} | ||
m.fails = append(m.fails, msg) | ||
} | ||
} | ||
|
||
return len(m.fails) == 0, nil | ||
} | ||
|
||
func (m *ShootMatcher) NegatedFailureMessage(actual interface{}) string { | ||
return "expected should not equal actual" | ||
} | ||
|
||
func (m *ShootMatcher) FailureMessage(actualuu interface{}) string { | ||
return strings.Join(m.fails, "\n") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package shoot_test | ||
|
||
import ( | ||
"github.com/gardener/gardener/pkg/apis/core/v1beta1" | ||
"github.com/kyma-project/infrastructure-manager/internal/testing/shoot" | ||
corev1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
. "github.com/onsi/ginkgo/v2" //nolint:revive | ||
. "github.com/onsi/gomega" //nolint:reviv | ||
) | ||
|
||
type deepCpOpts = func(*v1beta1.Shoot) | ||
|
||
func withName(name string) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.Name = name | ||
} | ||
} | ||
|
||
func withNamespace(namespace string) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.Namespace = namespace | ||
} | ||
} | ||
|
||
func withLabels(labels map[string]string) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.Labels = labels | ||
} | ||
} | ||
|
||
func withFinalizers(finalizers []string) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.Finalizers = finalizers | ||
} | ||
} | ||
|
||
func withOwnerReferences(ownerReferences []corev1.OwnerReference) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.OwnerReferences = ownerReferences | ||
} | ||
} | ||
|
||
func withAnnotations(annotations map[string]string) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.Annotations = annotations | ||
} | ||
} | ||
|
||
func withShootSpec(spec v1beta1.ShootSpec) deepCpOpts { | ||
return func(s *v1beta1.Shoot) { | ||
s.Spec = spec | ||
} | ||
} | ||
|
||
func deepCp(s v1beta1.Shoot, opts ...deepCpOpts) v1beta1.Shoot { | ||
cp := s.DeepCopy() | ||
|
||
for _, opt := range opts { | ||
opt(cp) | ||
} | ||
|
||
return *cp | ||
} | ||
|
||
func testInvalidArgs(actual, expected interface{}) { | ||
matcher := shoot.Matcher(expected) | ||
_, err := matcher.Match(actual) | ||
Expect(err).To(HaveOccurred()) | ||
} | ||
|
||
func testResults(actual, expected interface{}, expectedMatch bool) { | ||
matcher := shoot.Matcher(expected) | ||
actualMatch, err := matcher.Match(actual) | ||
Expect(err).ShouldNot(HaveOccurred()) | ||
Expect(actualMatch).Should(Equal(expectedMatch), matcher.FailureMessage(actual)) | ||
} | ||
|
||
var _ = Describe(":: shoot matcher :: ", func() { | ||
var empty v1beta1.Shoot | ||
|
||
DescribeTable( | ||
"checking invalid args :: ", | ||
testInvalidArgs, | ||
Entry("when actual is nil", nil, empty), | ||
Entry("when expected is nil", "", nil), | ||
) | ||
|
||
DescribeTable( | ||
"checking results :: ", | ||
testResults, | ||
Entry( | ||
"should match empty and zero values", | ||
"", | ||
empty, | ||
true, | ||
), | ||
Entry( | ||
"should match copies of the same instance", | ||
deepCp(empty), | ||
deepCp(empty), | ||
true, | ||
), | ||
Entry( | ||
"should detect name difference", | ||
deepCp(empty, withName("test1")), | ||
deepCp(empty, withName("test2")), | ||
false, | ||
), | ||
Entry( | ||
"should detect namespace difference", | ||
deepCp(empty, withNamespace("test1")), | ||
deepCp(empty, withNamespace("test2")), | ||
false, | ||
), | ||
Entry( | ||
"should detect difference in labels", | ||
deepCp(empty, withLabels(map[string]string{"test": "me"})), | ||
deepCp(empty, withLabels(map[string]string{})), | ||
false, | ||
), | ||
Entry( | ||
"should detect difference in annotations", | ||
deepCp(empty, withAnnotations(map[string]string{"test": "me"})), | ||
deepCp(empty, withAnnotations(map[string]string{"test": "it"})), | ||
false, | ||
), | ||
Entry( | ||
"should detect differences in finalizers", | ||
deepCp(empty, withFinalizers([]string{"test", "me"})), | ||
deepCp(empty, withFinalizers([]string{"test", "me 2"})), | ||
false, | ||
), | ||
Entry( | ||
"should detect differences in owner references", | ||
deepCp(empty, withOwnerReferences([]corev1.OwnerReference{ | ||
{Name: "test1", UID: "1"}, | ||
{Name: "test2", UID: "2"}, | ||
})), | ||
deepCp(empty, withOwnerReferences([]corev1.OwnerReference{ | ||
{Name: "test1", UID: "1"}, | ||
{Name: "test3", UID: "3"}, | ||
})), | ||
false, | ||
), | ||
Entry( | ||
"should detect differences in spec", | ||
deepCp(empty, withShootSpec(v1beta1.ShootSpec{ | ||
Region: "test1", | ||
})), | ||
deepCp(empty, withShootSpec(v1beta1.ShootSpec{ | ||
Region: "test2", | ||
})), | ||
false, | ||
), | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package shoot_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/onsi/ginkgo/v2" //nolint:revive | ||
"github.com/onsi/gomega" //nolint:revive | ||
) | ||
|
||
func TestMatcher(t *testing.T) { | ||
gomega.RegisterFailHandler(ginkgo.Fail) | ||
ginkgo.RunSpecs(t, "shoot matcher") | ||
} |