...
1 package agent_test
2
3 import (
4 "context"
5 "testing"
6
7 "github.com/stretchr/testify/assert"
8 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
9 "k8s.io/apimachinery/pkg/runtime/schema"
10 "k8s.io/client-go/dynamic"
11 "k8s.io/client-go/tools/cache"
12
13 "github.com/datawire/ambassador/v2/pkg/agent"
14 "github.com/datawire/dlib/dlog"
15 )
16
17 type informerMock struct {
18 eventHandler cache.ResourceEventHandler
19 run func(handler cache.ResourceEventHandler)
20 }
21
22 func (i *informerMock) AddEventHandler(handler cache.ResourceEventHandler) {
23 i.eventHandler = handler
24
25 }
26 func (i *informerMock) Run(stopCh <-chan struct{}) {
27 i.run(i.eventHandler)
28 }
29
30 func (i *informerMock) ListCache() []interface{} {
31 return nil
32 }
33
34 func newInformerMock(run func(handler cache.ResourceEventHandler)) *informerMock {
35 return &informerMock{
36 run: run,
37 }
38 }
39
40 func (i *informerMock) fakeInformer(di dynamic.Interface, ns string, gvr *schema.GroupVersionResource) agent.Informer {
41 return i
42 }
43
44 func TestWatchGeneric(t *testing.T) {
45 type runFunc func(handler cache.ResourceEventHandler)
46 type fixture struct {
47 dc *agent.DynamicClient
48 rolloutGvr *schema.GroupVersionResource
49 }
50 defaultRunFunc := func(handler cache.ResourceEventHandler) {
51 obj := &unstructured.Unstructured{}
52 obj.SetName("obj1-added")
53 handler.OnAdd(obj)
54
55 objNew := &unstructured.Unstructured{}
56 objNew.SetName("obj1-new")
57 handler.OnUpdate(obj, objNew)
58
59 objDel := &unstructured.Unstructured{}
60 objDel.SetName("obj1-del")
61 handler.OnDelete(objDel)
62 }
63 setup := func(runFunc runFunc) *fixture {
64 rf := defaultRunFunc
65 if runFunc != nil {
66 rf = runFunc
67 }
68 mock := newInformerMock(rf)
69 dc := agent.NewDynamicClient(nil, mock.fakeInformer)
70 rolloutGvr, _ := schema.ParseResourceArg("rollouts.v1alpha1.argoproj.io")
71 return &fixture{
72 dc: dc,
73 rolloutGvr: rolloutGvr,
74 }
75
76 }
77 t.Run("will watch generic resource successfully", func(t *testing.T) {
78
79 t.Parallel()
80 ctx := dlog.NewTestContext(t, false)
81 f := setup(nil)
82
83
84 rolloutCallback := f.dc.WatchGeneric(ctx, "default", f.rolloutGvr)
85
86
87 assert.NotNil(t, rolloutCallback)
88 for i := 0; i < 3; i++ {
89 select {
90 case callback := <-rolloutCallback:
91 switch callback.EventType {
92 case agent.CallbackEventAdded:
93 assert.Equal(t, "obj1-added", callback.Obj.GetName())
94 case agent.CallbackEventUpdated:
95 assert.Equal(t, "obj1-new", callback.Obj.GetName())
96 case agent.CallbackEventDeleted:
97 assert.Equal(t, "obj1-del", callback.Obj.GetName())
98 }
99 }
100 }
101 })
102 t.Run("will handle context cancelation gracefully", func(t *testing.T) {
103
104 t.Parallel()
105 informerRunFunc := func(handler cache.ResourceEventHandler) {
106 obj := &unstructured.Unstructured{}
107 obj.SetName("obj1-added")
108 handler.OnAdd(obj)
109 }
110 ctx, cancel := context.WithCancel(dlog.NewTestContext(t, false))
111 cancel()
112 f := setup(informerRunFunc)
113
114
115 rolloutCallback := f.dc.WatchGeneric(ctx, "default", f.rolloutGvr)
116
117
118 assert.NotNil(t, rolloutCallback)
119 callback, ok := <-rolloutCallback
120 if ok {
121 assert.NotNil(t, callback)
122 assert.Equal(t, "obj1-added", callback.Obj.GetName())
123 } else {
124 assert.Nil(t, callback)
125 }
126 })
127 }
128
View as plain text