From aa27069a22edb79a0ae643cb1fc22954f75c2075 Mon Sep 17 00:00:00 2001 From: Luca Burgazzoli Date: Wed, 26 Feb 2025 09:26:24 +0100 Subject: [PATCH] fix(test): ensure jq matchers can handle null values --- pkg/utils/test/matchers/jq/jq_support.go | 8 +++ pkg/utils/test/matchers/jq/jq_support_test.go | 52 +++++++++++++------ pkg/utils/test/testf/testf_witht_test.go | 19 +++++++ 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/pkg/utils/test/matchers/jq/jq_support.go b/pkg/utils/test/matchers/jq/jq_support.go index 0779bda3098..6ca2a86148b 100644 --- a/pkg/utils/test/matchers/jq/jq_support.go +++ b/pkg/utils/test/matchers/jq/jq_support.go @@ -46,6 +46,14 @@ func formattedFailurePath(failurePath []interface{}) string { //nolint:cyclop func toType(in any) (any, error) { + valof := reflect.ValueOf(in) + if !valof.IsValid() { + return nil, nil + } + if valof.Kind() == reflect.Ptr && valof.IsNil() { + return nil, nil + } + switch v := in.(type) { case string: d, err := byteToType([]byte(v)) diff --git a/pkg/utils/test/matchers/jq/jq_support_test.go b/pkg/utils/test/matchers/jq/jq_support_test.go index aa3c54af582..b59c0c9609a 100644 --- a/pkg/utils/test/matchers/jq/jq_support_test.go +++ b/pkg/utils/test/matchers/jq/jq_support_test.go @@ -8,6 +8,8 @@ import ( "testing" "github.com/onsi/gomega/gbytes" + "github.com/onsi/gomega/types" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/cluster/gvk" "github.com/opendatahub-io/opendatahub-operator/v2/pkg/resources" @@ -68,6 +70,12 @@ func TestBytesToType(t *testing.T) { } } +func haveType(kind reflect.Kind) func(in any) bool { + return func(in any) bool { + return reflect.TypeOf(in).Kind() == kind + } +} + func TestToType(t *testing.T) { t.Parallel() @@ -76,9 +84,9 @@ func TestToType(t *testing.T) { g := NewWithT(t) tests := []struct { - name string - fn func() any - expectedType reflect.Kind + name string + fn func() any + expectation types.GomegaMatcher }{ { name: "gbytes", @@ -90,70 +98,84 @@ func TestToType(t *testing.T) { return b }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "bytes", fn: func() any { return typeTestData }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "string_map", fn: func() any { return string(typeTestData) }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "string_slice", fn: func() any { return `[ "foo", "bar" ]` }, - expectedType: reflect.Slice, + expectation: Satisfy(haveType(reflect.Slice)), }, { name: "json.RawMessage", fn: func() any { return json.RawMessage(typeTestData) }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "io.Reader", fn: func() any { return strings.NewReader(string(typeTestData)) }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "unstructured.Unstructured", fn: func() any { return *resources.GvkToUnstructured(gvk.ConfigMap) }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "*unstructured.Unstructured", fn: func() any { return resources.GvkToUnstructured(gvk.ConfigMap) }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "map", fn: func() any { return map[string]string{"foo": "bar"} }, - expectedType: reflect.Map, + expectation: Satisfy(haveType(reflect.Map)), }, { name: "slice", fn: func() any { return []string{"foo", "bar"} }, - expectedType: reflect.Slice, + expectation: Satisfy(haveType(reflect.Slice)), + }, + { + name: "*unstructured.Unstructured(nil)", + fn: func() any { + return (*unstructured.Unstructured)(nil) + }, + expectation: BeNil(), + }, + { + name: "nil", + fn: func() any { + return nil + }, + expectation: BeNil(), }, } @@ -164,9 +186,7 @@ func TestToType(t *testing.T) { convertedType, err := toType(tt.fn()) g.Expect(err).ShouldNot(HaveOccurred()) - g.Expect(convertedType).Should(Satisfy(func(in any) bool { - return reflect.TypeOf(in).Kind() == tt.expectedType - })) + g.Expect(convertedType).Should(tt.expectation) }) } } diff --git a/pkg/utils/test/testf/testf_witht_test.go b/pkg/utils/test/testf/testf_witht_test.go index 13e097cfeb1..cf60280f8f7 100644 --- a/pkg/utils/test/testf/testf_witht_test.go +++ b/pkg/utils/test/testf/testf_witht_test.go @@ -81,6 +81,25 @@ func TestGet(t *testing.T) { v := wt.Get(gvk.ConfigMap, key).Consistently().WithTimeout(1 * time.Second).Should(Succeed()) g.Expect(v).ShouldNot(BeNil()) }) + + t.Run("Get Not Found", func(t *testing.T) { + wt := tc.NewWithT(t) + + key := client.ObjectKey{Namespace: "ns", Name: "name"} + + v, err := wt.Get(gvk.ConfigMap, key).Get() + g.Expect(err).ShouldNot(HaveOccurred()) + g.Expect(v).Should(BeNil()) + }) + + t.Run("Eventually Not Found", func(t *testing.T) { + wt := tc.NewWithT(t) + + key := client.ObjectKey{Namespace: "ns", Name: "name"} + + v := wt.Get(gvk.ConfigMap, key).Eventually().WithTimeout(1 * time.Second).ShouldNot(matchMetadata) + g.Expect(v).Should(BeNil()) + }) } func TestList(t *testing.T) {