Skip to content

Commit

Permalink
Merge pull request kubevirt#7250 from fossedihelm/enrich_matcher
Browse files Browse the repository at this point in the history
e2e: enrich phase matcher
  • Loading branch information
kubevirt-bot authored Mar 2, 2022
2 parents 195a7ea + 74a42a0 commit 404feeb
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 21 deletions.
3 changes: 3 additions & 0 deletions tests/framework/matcher/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//staging/src/kubevirt.io/api/core/v1:go_default_library",
"//staging/src/kubevirt.io/client-go/testutils:go_default_library",
"//tests/framework/matcher/helper:go_default_library",
"//vendor/github.com/onsi/ginkgo:go_default_library",
"//vendor/github.com/onsi/ginkgo/extensions/table:go_default_library",
"//vendor/github.com/onsi/gomega:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1:go_default_library",
],
)
8 changes: 8 additions & 0 deletions tests/framework/matcher/getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ func ThisPodWith(namespace string, name string) func() (*v1.Pod, error) {
if errors.IsNotFound(err) {
return nil, nil
}
//Since https://github.com/kubernetes/client-go/issues/861 we manually add the Kind
p.Kind = "Pod"
return
}
}
Expand Down Expand Up @@ -101,6 +103,8 @@ func ThisDVWith(namespace string, name string) func() (*v1beta1.DataVolume, erro
if errors.IsNotFound(err) {
return nil, nil
}
//Since https://github.com/kubernetes/client-go/issues/861 we manually add the Kind
p.Kind = "DataVolume"
return
}
}
Expand All @@ -121,6 +125,8 @@ func ThisPVCWith(namespace string, name string) func() (*v1.PersistentVolumeClai
if errors.IsNotFound(err) {
return nil, nil
}
//Since https://github.com/kubernetes/client-go/issues/861 we manually add the Kind
p.Kind = "PersistentVolumeClaim"
return
}
}
Expand Down Expand Up @@ -156,6 +162,8 @@ func ThisDeploymentWith(namespace string, name string) func() (*k8sv1.Deployment
if errors.IsNotFound(err) {
return nil, nil
}
//Since https://github.com/kubernetes/client-go/issues/861 we manually add the Kind
p.Kind = "Deployment"
return
}
}
4 changes: 4 additions & 0 deletions tests/framework/matcher/helper/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ go_library(
srcs = ["reflect.go"],
importpath = "kubevirt.io/kubevirt/tests/framework/matcher/helper",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
20 changes: 19 additions & 1 deletion tests/framework/matcher/helper/reflect.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package helper

import "reflect"
import (
"fmt"
"reflect"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)

func IsNil(actual interface{}) bool {
return actual == nil || (reflect.ValueOf(actual).Kind() == reflect.Ptr && reflect.ValueOf(actual).IsNil())
Expand Down Expand Up @@ -45,3 +51,15 @@ func MatchElementsInSlice(actual interface{}, matcher func(actual interface{}) (
})
return success, err
}

func ToUnstructured(actual interface{}) (*unstructured.Unstructured, error) {
if IsNil(actual) {
return nil, fmt.Errorf("object does not exist")
}
actual = ToPointer(actual)
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(actual)
if err != nil {
return nil, err
}
return &unstructured.Unstructured{Object: obj}, nil
}
23 changes: 5 additions & 18 deletions tests/framework/matcher/owner.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package matcher
import (
"fmt"

"github.com/onsi/gomega/types"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"

"kubevirt.io/kubevirt/tests/framework/matcher/helper"

"github.com/onsi/gomega/types"
)

func BeOwned() types.GomegaMatcher {
Expand All @@ -22,7 +20,7 @@ type ownedMatcher struct {
}

func (o ownedMatcher) Match(actual interface{}) (success bool, err error) {
u, err := toUnstructured(actual)
u, err := helper.ToUnstructured(actual)
if err != nil {
return false, nil
}
Expand All @@ -33,28 +31,17 @@ func (o ownedMatcher) Match(actual interface{}) (success bool, err error) {
}

func (o ownedMatcher) FailureMessage(actual interface{}) (message string) {
u, err := toUnstructured(actual)
u, err := helper.ToUnstructured(actual)
if err != nil {
return err.Error()
}
return fmt.Sprintf("Expected owner references to not be empty, but got '%v'", u)
}

func (o ownedMatcher) NegatedFailureMessage(actual interface{}) (message string) {
u, err := toUnstructured(actual)
u, err := helper.ToUnstructured(actual)
if err != nil {
return err.Error()
}
return fmt.Sprintf("Expected owner references to be empty, but got '%v'", u)
}

func toUnstructured(actual interface{}) (*unstructured.Unstructured, error) {
if helper.IsNil(actual) {
return nil, fmt.Errorf("object does not exist")
}
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(actual)
if err != nil {
return nil, err
}
return &unstructured.Unstructured{Object: obj}, nil
}
37 changes: 35 additions & 2 deletions tests/framework/matcher/phase.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,15 @@ func (p phaseMatcher) FailureMessage(actual interface{}) (message string) {
return fmt.Sprintf("expected phases to be in %v but got %v", expectedPhase, collectPhasesForPrinting(actual))
}

objectInfo, err := getObjectKindAndName(actual)
if err != nil {
return err.Error()
}
phase, err := getCurrentPhase(actual)
if err != nil {
return err.Error()
}
return fmt.Sprintf("expected phase is '%v' but got '%v'", expectedPhase, phase)
return fmt.Sprintf("%s expected phase is '%v' but got '%v'", objectInfo, expectedPhase, phase)
}

func (p phaseMatcher) NegatedFailureMessage(actual interface{}) (message string) {
Expand All @@ -88,11 +92,32 @@ func (p phaseMatcher) NegatedFailureMessage(actual interface{}) (message string)
if helper.IsSlice(actual) {
return fmt.Sprintf("expected phases to not be in %v but got %v", expectedPhase, collectPhasesForPrinting(actual))
}
objectInfo, err := getObjectKindAndName(actual)
if err != nil {
return err.Error()
}
phase, err := getCurrentPhase(actual)
if err != nil {
return err.Error()
}
return fmt.Sprintf("expected phase '%v' to not match '%v'", expectedPhase, phase)
return fmt.Sprintf("%s expected phase '%v' to not match '%v'", objectInfo, expectedPhase, phase)
}

func getObjectKindAndName(actual interface{}) (string, error) {
u, err := helper.ToUnstructured(actual)
if err != nil {
return "", err
}
objectInfo := ""
if u != nil {
if u.GetKind() != "" {
objectInfo = fmt.Sprintf("%s/", u.GetKind())
}
if u.GetName() != "" {
objectInfo = fmt.Sprintf("%s%s", objectInfo, u.GetName())
}
}
return objectInfo, nil
}

func getCurrentPhase(actual interface{}) (string, error) {
Expand All @@ -115,6 +140,14 @@ func collectPhasesForPrinting(actual interface{}) (phases []string) {
if err != nil {
phase = err.Error()
}
objectInfo, err := getObjectKindAndName(value)
if err != nil {
phase = err.Error()
}
if objectInfo != "" {
phase = fmt.Sprintf("%s:%s", objectInfo, phase)
}

phases = append(phases, phase)
return true
})
Expand Down
106 changes: 106 additions & 0 deletions tests/framework/matcher/phase_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package matcher

import (
"fmt"

. "github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
v1 "k8s.io/api/core/v1"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"

v13 "kubevirt.io/api/core/v1"
"kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
"kubevirt.io/kubevirt/tests/framework/matcher/helper"
)

var _ = Describe("Matcher", func() {
Expand All @@ -24,6 +31,69 @@ var _ = Describe("Matcher", func() {
},
}

var nameAndKindPod = &v1.Pod{
ObjectMeta: v12.ObjectMeta{
Name: "testpod",
},
TypeMeta: v12.TypeMeta{
Kind: "Pod",
},
}

var nameAndKindDV = &v1beta1.DataVolume{
ObjectMeta: v12.ObjectMeta{
Name: "testdv",
},
TypeMeta: v12.TypeMeta{
Kind: "DataVolume",
},
}

var nameAndKindVMI = &v13.VirtualMachineInstance{
ObjectMeta: v12.ObjectMeta{
Name: "testvmi",
},
TypeMeta: v12.TypeMeta{
Kind: "VirtualMachineInstance",
},
}

var onlyKindPod = &v1.Pod{
TypeMeta: v12.TypeMeta{
Kind: "Pod",
},
}

var onlyKindDV = &v1beta1.DataVolume{
TypeMeta: v12.TypeMeta{
Kind: "DataVolume",
},
}

var onlyKindVMI = &v13.VirtualMachineInstance{
TypeMeta: v12.TypeMeta{
Kind: "VirtualMachineInstance",
},
}

var onlyNamePod = &v1.Pod{
ObjectMeta: v12.ObjectMeta{
Name: "testpod",
},
}

var onlyNameDV = &v1beta1.DataVolume{
ObjectMeta: v12.ObjectMeta{
Name: "testdv",
},
}

var onlyNameVMI = &v13.VirtualMachineInstance{
ObjectMeta: v12.ObjectMeta{
Name: "testvmi",
},
}

table.DescribeTable("should work on a pod", func(exptectedPhase interface{}, pod interface{}, match bool) {
success, err := BeInPhase(exptectedPhase).Match(pod)
Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -59,4 +129,40 @@ var _ = Describe("Matcher", func() {
table.Entry("cope with a non-stringable object as expected phase", nil, []*v1.Pod{runningPod}, false),
table.Entry("with expected phase not match the pod phase", "Succeeded", []*v1.Pod{runningPod}, false),
)

table.DescribeTable("should print kind and name of the object depending on fields", func(object interface{}, kind string, name string) {
unstructured, err := helper.ToUnstructured(object)
Expect(err).ToNot(HaveOccurred())
Expect(unstructured.GetKind()).To(Equal(kind))
Expect(unstructured.GetName()).To(Equal(name))
if kind != "" && name != "" {
Expect(BeInPhase("testPhase").FailureMessage(object)).Should(HavePrefix(fmt.Sprintf("%s/%s", unstructured.GetKind(), unstructured.GetName())))
Expect(BeInPhase("testPhase").NegatedFailureMessage(object)).Should(HavePrefix(fmt.Sprintf("%s/%s", unstructured.GetKind(), unstructured.GetName())))
} else if kind != "" {
Expect(BeInPhase("testPhase").FailureMessage(object)).Should(HavePrefix(fmt.Sprintf("%s/", unstructured.GetKind())))
Expect(BeInPhase("testPhase").NegatedFailureMessage(object)).Should(HavePrefix(fmt.Sprintf("%s/", unstructured.GetKind())))
} else if name != "" {
Expect(BeInPhase("testPhase").FailureMessage(object)).Should(HavePrefix(fmt.Sprintf("%s", unstructured.GetName())))
Expect(BeInPhase("testPhase").NegatedFailureMessage(object)).Should(HavePrefix(fmt.Sprintf("%s", unstructured.GetName())))
} else {
Expect(BeInPhase("testPhase").FailureMessage(object)).ShouldNot(HavePrefix(fmt.Sprintf("%s/", unstructured.GetKind())))
Expect(BeInPhase("testPhase").NegatedFailureMessage(object)).ShouldNot(HavePrefix(fmt.Sprintf("%s/", unstructured.GetKind())))
Expect(BeInPhase("testPhase").FailureMessage(object)).Should(HavePrefix(" expected"))
Expect(BeInPhase("testPhase").NegatedFailureMessage(object)).Should(HavePrefix(" expected"))
}

},
table.Entry("with a Pod having name and kind", nameAndKindPod, nameAndKindPod.Kind, nameAndKindPod.Name),
table.Entry("with a DataVolume having name and kind", nameAndKindDV, nameAndKindDV.Kind, nameAndKindDV.Name),
table.Entry("with a VirtualMachineInstance having name and kind", nameAndKindVMI, nameAndKindVMI.Kind, nameAndKindVMI.Name),
table.Entry("with a Pod having only kind", onlyKindPod, onlyKindPod.Kind, onlyKindPod.Name),
table.Entry("with a DataVolume having only kind", onlyKindDV, onlyKindDV.Kind, onlyKindDV.Name),
table.Entry("with a VirtualMachineInstance having only kind", onlyKindVMI, onlyKindVMI.Kind, onlyKindVMI.Name),
table.Entry("with a Pod having only name", onlyNamePod, onlyNamePod.Kind, onlyNamePod.Name),
table.Entry("with a DataVolume having only name", onlyNameDV, onlyNameDV.Kind, onlyNameDV.Name),
table.Entry("with a VirtualMachineInstance having only name", onlyNameVMI, onlyNameVMI.Kind, onlyNameVMI.Name),
table.Entry("with a Pod having no kind and name", &v1.Pod{}, "", ""),
table.Entry("with a DataVolume having no kind and name", &v1beta1.DataVolume{}, "", ""),
table.Entry("with a VirtualMachineInstance having no kind and name", &v13.VirtualMachineInstance{}, "", ""),
)
})

0 comments on commit 404feeb

Please sign in to comment.