1
16
17 package container
18
19 import (
20 "fmt"
21 "strconv"
22 "testing"
23 "time"
24
25 "github.com/stretchr/testify/assert"
26 "k8s.io/apimachinery/pkg/types"
27 )
28
29 func newTestCache() *cache {
30 c := NewCache()
31 return c.(*cache)
32 }
33
34 func TestCacheNotInitialized(t *testing.T) {
35 cache := newTestCache()
36
37 d := cache.getIfNewerThan(types.UID("1234"), time.Time{})
38 assert.True(t, d == nil, "should return nil since cache is not initialized")
39 }
40
41 func getTestPodIDAndStatus(numContainers int) (types.UID, *PodStatus) {
42 id := types.UID(strconv.FormatInt(time.Now().UnixNano(), 10))
43 name := fmt.Sprintf("cache-foo-%s", string(id))
44 namespace := "ns"
45 var status *PodStatus
46 if numContainers > 0 {
47 status = &PodStatus{ID: id, Name: name, Namespace: namespace}
48 } else {
49 status = &PodStatus{ID: id}
50 }
51 for i := 0; i < numContainers; i++ {
52 status.ContainerStatuses = append(status.ContainerStatuses, &Status{Name: strconv.Itoa(i)})
53 }
54 return id, status
55 }
56
57 func TestGetIfNewerThanWhenPodExists(t *testing.T) {
58 cache := newTestCache()
59 timestamp := time.Now()
60
61 cases := []struct {
62 cacheTime time.Time
63 modified time.Time
64 expected bool
65 }{
66 {
67
68
69 cacheTime: timestamp.Add(time.Second),
70 modified: timestamp,
71 expected: true,
72 },
73 {
74
75
76
77 cacheTime: timestamp.Add(time.Second),
78 modified: timestamp.Add(-time.Second * 10),
79 expected: true,
80 },
81 {
82
83
84
85
86 cacheTime: timestamp.Add(-time.Second),
87 modified: timestamp.Add(time.Second * 3),
88 expected: true,
89 },
90 {
91
92
93 cacheTime: timestamp.Add(-time.Second),
94 modified: timestamp.Add(-time.Second),
95 expected: false,
96 },
97 }
98 for i, c := range cases {
99 podID, status := getTestPodIDAndStatus(2)
100 cache.UpdateTime(c.cacheTime)
101 cache.Set(podID, status, nil, c.modified)
102 d := cache.getIfNewerThan(podID, timestamp)
103 assert.Equal(t, c.expected, d != nil, "test[%d]", i)
104 }
105 }
106
107 func TestGetPodNewerThanWhenPodDoesNotExist(t *testing.T) {
108 cache := newTestCache()
109 cacheTime := time.Now()
110 cache.UpdateTime(cacheTime)
111 podID := types.UID("1234")
112
113 cases := []struct {
114 timestamp time.Time
115 expected bool
116 }{
117 {
118 timestamp: cacheTime.Add(-time.Second),
119 expected: true,
120 },
121 {
122 timestamp: cacheTime.Add(time.Second),
123 expected: false,
124 },
125 }
126 for i, c := range cases {
127 d := cache.getIfNewerThan(podID, c.timestamp)
128 assert.Equal(t, c.expected, d != nil, "test[%d]", i)
129 }
130 }
131
132 func TestCacheSetAndGet(t *testing.T) {
133 cache := NewCache()
134 cases := []struct {
135 numContainers int
136 error error
137 }{
138 {numContainers: 3, error: nil},
139 {numContainers: 2, error: fmt.Errorf("unable to get status")},
140 {numContainers: 0, error: nil},
141 }
142 for i, c := range cases {
143 podID, status := getTestPodIDAndStatus(c.numContainers)
144 cache.Set(podID, status, c.error, time.Time{})
145
146
147 actualStatus, actualErr := cache.Get(podID)
148 assert.Equal(t, status, actualStatus, "test[%d]", i)
149 assert.Equal(t, c.error, actualErr, "test[%d]", i)
150 }
151 }
152
153 func TestCacheGetPodDoesNotExist(t *testing.T) {
154 cache := NewCache()
155 podID, status := getTestPodIDAndStatus(0)
156
157
158 actualStatus, actualErr := cache.Get(podID)
159 assert.Equal(t, status, actualStatus)
160 assert.Equal(t, nil, actualErr)
161 }
162
163 func TestDelete(t *testing.T) {
164 cache := &cache{pods: map[types.UID]*data{}}
165
166 podID, status := getTestPodIDAndStatus(3)
167 cache.Set(podID, status, nil, time.Time{})
168 actualStatus, actualErr := cache.Get(podID)
169 assert.Equal(t, status, actualStatus)
170 assert.Equal(t, nil, actualErr)
171
172 cache.Delete(podID)
173 expectedStatus := &PodStatus{ID: podID}
174 actualStatus, actualErr = cache.Get(podID)
175 assert.Equal(t, expectedStatus, actualStatus)
176 assert.Equal(t, nil, actualErr)
177 }
178
179 func verifyNotification(t *testing.T, ch chan *data, expectNotification bool) {
180 if expectNotification {
181 assert.True(t, len(ch) > 0, "Did not receive notification")
182 } else {
183 assert.True(t, len(ch) < 1, "Should not have triggered the notification")
184 }
185
186 for i := 0; i < len(ch); i++ {
187 <-ch
188 }
189 }
190
191 func TestRegisterNotification(t *testing.T) {
192 cache := newTestCache()
193 cacheTime := time.Now()
194 cache.UpdateTime(cacheTime)
195
196 podID, status := getTestPodIDAndStatus(1)
197 ch := cache.subscribe(podID, cacheTime.Add(time.Second))
198 verifyNotification(t, ch, false)
199 cache.Set(podID, status, nil, cacheTime.Add(time.Second))
200
201 verifyNotification(t, ch, true)
202
203 podID, _ = getTestPodIDAndStatus(1)
204
205 ch = cache.subscribe(podID, cacheTime.Add(time.Second))
206 verifyNotification(t, ch, false)
207 cache.UpdateTime(cacheTime.Add(time.Second * 2))
208
209 verifyNotification(t, ch, true)
210 }
211
View as plain text