1 package object
2
3 import (
4 "fmt"
5 "strings"
6 "testing"
7 "time"
8
9 "github.com/google/go-cmp/cmp"
10 "k8s.io/apimachinery/pkg/api/errors"
11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12 "sigs.k8s.io/controller-runtime/pkg/client"
13
14 "edge-infra.dev/pkg/k8s/object/fobject"
15 )
16
17 func TestCmpMaskData(t *testing.T) {
18 testCases := []struct {
19 name string
20 current map[string]interface{}
21 future map[string]interface{}
22 expected string
23 }{
24 {
25 name: "empty",
26 current: map[string]interface{}{},
27 future: map[string]interface{}{},
28 expected: "",
29 },
30 {
31 name: "no change",
32 current: map[string]interface{}{
33 "foo": "bar",
34 },
35 future: map[string]interface{}{
36 "foo": "bar",
37 },
38 expected: "",
39 },
40 {
41 name: "simple value changed",
42 current: map[string]interface{}{
43 "foo": "bar",
44 },
45 future: map[string]interface{}{
46 "foo": "baz",
47 },
48 expected: fmt.Sprintf("foo\": string(\"%s\")", DefaultMask),
49 },
50 {
51 name: "simple value changed with different casing",
52 current: map[string]interface{}{
53 "foo": "bar",
54 },
55 future: map[string]interface{}{
56 "FOO": "baz",
57 },
58 expected: fmt.Sprintf("foo\": string(\"%s\")", DefaultMask),
59 },
60 {
61 name: "value changed with different casing and different values",
62 current: map[string]interface{}{
63 "foo": "bar",
64 "baz": "qux",
65 },
66 future: map[string]interface{}{
67 "foo": "baz",
68 "baz": "qux",
69 },
70 expected: fmt.Sprintf("baz\": string(\"%s\")", DefaultMask),
71 },
72 }
73
74 t.Parallel()
75 for _, tc := range testCases {
76 tc := tc
77 t.Run(tc.name, func(t *testing.T) {
78 t.Parallel()
79 c, ft := CmpMaskData(tc.current, tc.future)
80 if diff := cmp.Diff(c, ft); !strings.Contains(diff, tc.expected) {
81 t.Errorf("Unexpected value in Diff")
82 }
83 })
84 }
85 }
86
87 func TestReadObjects_DropsInvalid(t *testing.T) {
88 testCases := []struct {
89 name string
90 resources string
91 expected int
92 }{
93 {
94 name: "valid resources",
95 resources: `
96 ---
97 apiVersion: v1
98 kind: Secret
99 metadata:
100 name: test
101 namespace: default
102 immutable: true
103 stringData:
104 key: "private-key"
105 ---
106 apiVersion: pkg.crossplane.io/v1
107 kind: Provider
108 metadata:
109 name: crossplane-provider-aws2
110 spec:
111 package: crossplane/provider-aws:v0.23.0
112 controllerConfigRef:
113 name: provider-aws
114 `,
115 expected: 2,
116 },
117 {
118 name: "some invalid resources",
119 resources: `
120 ---
121 piVersion: pkg.crossplane.io/v1
122 kind: Provider
123 metadata:
124 name: crossplane-provider-aws1
125 spec:
126 package: crossplane/provider-aws:v0.23.0
127 controllerConfigRef:
128 name: provider-aws
129 ---
130 apiVersion: v1
131 kind: Secret
132 metadata:
133 name: test
134 namespace: default
135 immutable: true
136 stringData:
137 key: "private-key"
138 `,
139 expected: 1,
140 },
141 }
142
143 t.Parallel()
144 for _, tc := range testCases {
145 tc := tc
146 t.Run(tc.name, func(t *testing.T) {
147 t.Parallel()
148 objects, err := ReadObjects(strings.NewReader(tc.resources))
149 if err != nil {
150 t.Errorf("unexpected error: %v", err)
151 }
152
153 if len(objects) != tc.expected {
154 t.Errorf("unexpected number of objects in %v", objects)
155 }
156 })
157 }
158 }
159
160 func TestIsDeleted(t *testing.T) {
161 tcs := map[string]struct {
162 obj client.Object
163 err error
164 expected bool
165 }{
166 "Marked for deletion no error": {
167 &fobject.Fake{ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: &metav1.Time{Time: time.Now()}}},
168 nil,
169 true,
170 },
171 "Marked for deletion error IsGone": {
172 &fobject.Fake{ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: &metav1.Time{Time: time.Now()}}},
173 errors.NewGone(""),
174 true,
175 },
176 "Marked for deletion error IsNotFound": {
177 &fobject.Fake{ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: &metav1.Time{Time: time.Now()}}},
178 errors.NewNotFound(fobject.FakeGroupResource, ""),
179 true,
180 },
181 "Error IsGone": {
182 &fobject.Fake{},
183 errors.NewGone(""),
184 true,
185 },
186 "Error IsNotFound": {
187 &fobject.Fake{},
188 errors.NewNotFound(fobject.FakeGroupResource, ""),
189 true,
190 },
191 "Not deleted": {
192 &fobject.Fake{},
193 nil,
194 false,
195 },
196 }
197
198 t.Parallel()
199 for name, tc := range tcs {
200 tc := tc
201 t.Run(name, func(t *testing.T) {
202 t.Parallel()
203 actual := IsDeleted(tc.obj, tc.err)
204 if tc.expected != actual {
205 t.Error("expected", tc.expected, "got", actual,
206 "error", tc.err, "object", tc.obj)
207 }
208 })
209 }
210 }
211
212 func TestFmtObject(t *testing.T) {
213 tcs := map[string]struct {
214 obj client.Object
215 expected string
216 }{
217 "Namespaced": {
218 &fobject.Fake{
219 TypeMeta: metav1.TypeMeta{Kind: "Fake"},
220 ObjectMeta: metav1.ObjectMeta{Name: "special-boy", Namespace: "special-home"},
221 },
222 "Fake/special-home/special-boy",
223 },
224 "Cluster": {
225 &fobject.Fake{
226 TypeMeta: metav1.TypeMeta{Kind: "Fake"},
227 ObjectMeta: metav1.ObjectMeta{Name: "special-girl"},
228 },
229 "Fake/special-girl",
230 },
231 }
232
233 t.Parallel()
234 for name, tc := range tcs {
235 tc := tc
236 t.Run(name, func(t *testing.T) {
237 t.Parallel()
238 actual := FmtObject(tc.obj)
239 if tc.expected != actual {
240 t.Error("expected", tc.expected, "got", actual)
241 }
242 })
243 }
244 }
245
View as plain text