Skip to content

Commit 25cdefd

Browse files
add unit testing for events
Signed-off-by: François Rigaut <francois.rigaut@orange.com>
1 parent 1c76d24 commit 25cdefd

1 file changed

Lines changed: 162 additions & 0 deletions

File tree

pkg/event/event_test.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,32 @@ limitations under the License.
1717
package event
1818

1919
import (
20+
"fmt"
2021
"testing"
2122

2223
"github.com/google/go-cmp/cmp"
24+
corev1 "k8s.io/api/core/v1"
25+
"k8s.io/apimachinery/pkg/api/meta"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/apimachinery/pkg/runtime"
2328
)
2429

30+
type EventWrapperFunction func(reason, message string, annotations map[string]string)
31+
32+
type testEventRecorder struct {
33+
EventWrapperFunction
34+
}
35+
36+
func (r *testEventRecorder) Event(object runtime.Object, eventtype, reason, message string) {
37+
r.EventWrapperFunction(reason, message, nil)
38+
}
39+
func (r *testEventRecorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) {
40+
r.EventWrapperFunction(reason, fmt.Sprintf(messageFmt, args...), nil)
41+
}
42+
func (r *testEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) {
43+
r.EventWrapperFunction(reason, fmt.Sprintf(messageFmt, args...), annotations)
44+
}
45+
2546
func TestSliceMap(t *testing.T) {
2647
type args struct {
2748
from []string
@@ -86,3 +107,144 @@ func TestSliceMap(t *testing.T) {
86107
})
87108
}
88109
}
110+
111+
func TestEvent(t *testing.T) {
112+
var currentEvent Event
113+
114+
allowedNamespace := "allowed-namespace"
115+
forbiddenNamespace := "forbidden-namespace"
116+
117+
basicInputEvent := Event{
118+
Type: TypeNormal,
119+
Reason: "Basic reason",
120+
Message: "Basic message",
121+
Annotations: map[string]string{},
122+
}
123+
124+
emptyEvent := Event{
125+
Type: "",
126+
Reason: "",
127+
Message: "",
128+
Annotations: nil,
129+
}
130+
131+
inputCMInAllowedNamespace := corev1.ConfigMap{
132+
ObjectMeta: metav1.ObjectMeta{
133+
Name: "name",
134+
Namespace: allowedNamespace,
135+
},
136+
}
137+
138+
inputCMInForbiddenNamespace := corev1.ConfigMap{
139+
ObjectMeta: metav1.ObjectMeta{
140+
Name: "name",
141+
Namespace: forbiddenNamespace,
142+
},
143+
}
144+
145+
testRecorder := &testEventRecorder{
146+
EventWrapperFunction: func(reason, message string, annotations map[string]string) {
147+
currentEvent = Event{
148+
Type: TypeNormal,
149+
Reason: Reason(reason),
150+
Message: message,
151+
Annotations: annotations,
152+
}
153+
},
154+
}
155+
156+
cases := map[string]struct {
157+
reason string
158+
filterFunctions []FilterFn
159+
inputResource runtime.Object
160+
inputEvent Event
161+
want Event
162+
annotations []string
163+
}{
164+
"NoFilter": {
165+
reason: "Events should always be emitted when there is no filter function.",
166+
inputEvent: basicInputEvent,
167+
want: basicInputEvent,
168+
},
169+
"AllowAllFilter": {
170+
reason: "Events should always be emitted when the filter function allows all events.",
171+
filterFunctions: []FilterFn{
172+
func(_ runtime.Object, _ Event) bool {
173+
return false
174+
},
175+
},
176+
inputEvent: basicInputEvent,
177+
want: basicInputEvent,
178+
},
179+
"DenyAllFilter": {
180+
reason: "Events should never be emitted when the filter function denies all events.",
181+
filterFunctions: []FilterFn{
182+
func(_ runtime.Object, _ Event) bool {
183+
return true
184+
},
185+
},
186+
inputEvent: basicInputEvent,
187+
want: emptyEvent,
188+
},
189+
"NamespaceFilterDeny": {
190+
reason: "Events should be denied when the filter function denies events from a specific namespace.",
191+
filterFunctions: []FilterFn{
192+
func(o runtime.Object, _ Event) bool {
193+
meta, err := meta.Accessor(o)
194+
if err != nil {
195+
return false
196+
}
197+
return meta.GetNamespace() == forbiddenNamespace
198+
},
199+
},
200+
inputResource: &inputCMInForbiddenNamespace,
201+
inputEvent: basicInputEvent,
202+
want: emptyEvent,
203+
},
204+
"NamespaceFilterAllow": {
205+
reason: "Events should be emitted when the filter function allows events from all namespaces but a specific one, and the resource is not in that namespace.",
206+
filterFunctions: []FilterFn{
207+
func(o runtime.Object, _ Event) bool {
208+
meta, err := meta.Accessor(o)
209+
if err != nil {
210+
return false
211+
}
212+
return meta.GetNamespace() == forbiddenNamespace
213+
},
214+
},
215+
inputResource: &inputCMInAllowedNamespace,
216+
inputEvent: basicInputEvent,
217+
want: basicInputEvent,
218+
},
219+
"WithAnnotations": {
220+
reason: "Events should be emitted with annotations when WithAnnotations is used.",
221+
annotations: []string{
222+
"testKey", "testValue",
223+
},
224+
inputEvent: basicInputEvent,
225+
want: Event{
226+
Type: TypeNormal,
227+
Reason: basicInputEvent.Reason,
228+
Message: basicInputEvent.Message,
229+
Annotations: map[string]string{
230+
"testKey": "testValue",
231+
},
232+
},
233+
},
234+
}
235+
236+
for name, tc := range cases {
237+
t.Run(name, func(t *testing.T) {
238+
// Test with NewAPIRecorder
239+
// AND WithAnnotations to check if it correctly preserves the filter functions, and also to test annotations
240+
apiRecorder := NewAPIRecorder(testRecorder, tc.filterFunctions...).WithAnnotations(tc.annotations...)
241+
apiRecorder.Event(tc.inputResource, tc.inputEvent)
242+
243+
if diff := cmp.Diff(tc.want, currentEvent); diff != "" {
244+
t.Errorf("%s\nEvent(...): -want, +got:\n%s", tc.reason, diff)
245+
}
246+
})
247+
248+
currentEvent = Event{}
249+
}
250+
}

0 commit comments

Comments
 (0)