github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/cache/cache_test.go (about) 1 // +build !windows 2 3 package cache 4 5 import ( 6 "testing" 7 "time" 8 9 "github.com/rs/xid" 10 . "github.com/smartystreets/goconvey/convey" 11 ) 12 13 func TestConstructorNewCache(t *testing.T) { 14 15 // t.Parallel() 16 17 Convey("Given I call the method NewCache, I should a new cache", t, func() { 18 19 c := &Cache{ 20 name: "cache", 21 } 22 23 So(NewCache("cache"), ShouldHaveSameTypeAs, c) 24 }) 25 } 26 27 func TestElements(t *testing.T) { 28 29 // t.Parallel() 30 31 c := NewCache("cache") 32 id := xid.New() 33 fakeid := xid.New() 34 newid := xid.New() 35 value := "element" 36 secondValue := "element2" 37 thirdValue := "element3" 38 39 Convey("Given that I want to test elemenets, I must initialize a cache", t, func() { 40 41 // Test Write 42 Convey("Given that I add a new element in the cache, it should not have errors", func() { 43 err := c.Add(id, value) 44 So(err, ShouldBeNil) 45 }) 46 47 Convey("Given that I add the same element for a second time, I should get an error", func() { 48 err := c.Add(id, value) 49 So(err, ShouldNotBeNil) 50 }) 51 52 // Test Read 53 Convey("Given that I have an element in the cache, I should be able to read it", func() { 54 newvalue, err := c.Get(id) 55 So(value, ShouldEqual, newvalue) 56 So(err, ShouldBeNil) 57 }) 58 59 Convey("Given that I try to read an element that is not there, I should get an error", func() { 60 _, err := c.Get(fakeid) 61 So(err, ShouldNotBeNil) 62 }) 63 64 // Test Update 65 Convey("Given that I want to update the element, I should be able to do it", func() { 66 67 err := c.Update(id, secondValue) 68 So(err, ShouldBeNil) 69 newvalue, err := c.Get(id) 70 So(newvalue, ShouldEqual, secondValue) 71 So(err, ShouldBeNil) 72 }) 73 74 Convey("Given that I try to update an element that doesn't exist, I should get an error ", func() { 75 nextid := xid.New() 76 err := c.Update(nextid, value) 77 So(err, ShouldNotBeNil) 78 }) 79 80 Convey("Given that I try to add or update an element in the cache, I should not get an error", func() { 81 82 ok := c.AddOrUpdate(newid, secondValue) 83 newvalue, err := c.Get(newid) 84 So(newvalue, ShouldEqual, secondValue) 85 So(err, ShouldBeNil) 86 So(ok, ShouldBeFalse) 87 }) 88 89 Convey("Given that I try to update an element in the cache, I should not get an error", func() { 90 91 ok := c.AddOrUpdate(newid, thirdValue) 92 newvalue, err := c.Get(newid) 93 So(newvalue, ShouldEqual, thirdValue) 94 So(err, ShouldBeNil) 95 So(ok, ShouldBeTrue) 96 }) 97 98 Convey("Given that I have an element in the cache, I should be able to delete it", func() { 99 err := c.Remove(id) 100 So(err, ShouldBeNil) 101 }) 102 103 Convey("Given that I try to delete the same element twice, I should not be able to do it", func() { 104 err := c.Remove(id) 105 So(err, ShouldNotBeNil) 106 }) 107 }) 108 } 109 110 func Test_CacheTimer(t *testing.T) { 111 112 //t.Parallel() 113 114 Convey("Given a new cache with an expiration timer ", t, func() { 115 c := NewCacheWithExpiration("cache", 3*time.Second) 116 117 Convey("When I create an item that has to exist for a second", func() { 118 err := c.Add("key", "value") 119 So(err, ShouldBeNil) 120 121 Convey("Then I should be able to get back the item", func() { 122 val, err := c.Get("key") 123 So(err, ShouldBeNil) 124 So(val.(string), ShouldResemble, "value") 125 126 Convey("When I wait for 1 second and update the time", func() { 127 <-time.After(1 * time.Second) 128 129 c.AddOrUpdate("key", "value2") 130 131 Convey("I should be able to read the second item", func() { 132 val, err := c.Get("key") 133 So(err, ShouldBeNil) 134 So(val.(string), ShouldResemble, "value2") 135 136 Convey("But when I wait for a another second, the items should still exist", func() { 137 <-time.After(1 * time.Second) 138 val, err := c.Get("key") 139 So(err, ShouldBeNil) 140 So(val.(string), ShouldResemble, "value2") 141 142 Convey("But if I wait for two seconds after the update, the item must not exixt", func() { 143 <-time.After(4 * time.Second) 144 _, err := c.Get("key") 145 So(err, ShouldNotBeNil) 146 }) 147 }) 148 }) 149 150 }) 151 152 }) 153 }) 154 }) 155 } 156 157 func add(a, b interface{}) interface{} { 158 return a.(int) + b.(int) 159 } 160 161 func TestLockedModify(t *testing.T) { 162 163 //t.Parallel() 164 165 Convey("Given a new cache", t, func() { 166 c := NewCache("cache") 167 168 Convey("Given an element that is an integer", func() { 169 err := c.Add("key", 1) 170 So(err, ShouldBeNil) 171 Convey("Given an an incremental add function", func() { 172 value, err := c.LockedModify("key", add, 1) 173 So(err, ShouldBeNil) 174 So(value, ShouldNotBeNil) 175 Convey("I should get the right value ", func() { 176 val, err := c.Get("key") 177 So(err, ShouldBeNil) 178 So(val.(int), ShouldEqual, 2) 179 }) 180 }) 181 }) 182 }) 183 } 184 185 func TestTimerExpirationWithUpdate(t *testing.T) { 186 187 //t.Parallel() 188 189 Convey("Given that I instantiate 1 objects with 2 second timers", t, func() { 190 i := 1 191 c := NewCacheWithExpiration("cache", 2*time.Second) 192 err := c.Add(i, i) 193 So(err, ShouldBeNil) 194 Convey("When I check the cache size After 1 seconds, the size should be 1", func() { 195 <-time.After(1 * time.Second) 196 // So(c.SizeOf(), ShouldEqual, 1) 197 Convey("When I update the object and check again after another 1 seconds, the size should be 1", func() { 198 err := c.Update(1, 1) 199 So(err, ShouldBeNil) 200 <-time.After(1 * time.Second) 201 // So(c.SizeOf(), ShouldEqual, 1) // @TODO: fix me it should be 1 202 Convey("When I check the cache size After another 2 seconds, the size should be 0", func() { 203 <-time.After(2 * time.Second) 204 So(c.SizeOf(), ShouldBeZeroValue) 205 }) 206 }) 207 }) 208 }) 209 } 210 211 func TestGetReset(t *testing.T) { 212 213 //t.Parallel() 214 215 Convey("Given that I instantiate 1 object with a 2 second timer", t, func() { 216 c := NewCacheWithExpiration("cache", 2*time.Second) 217 err := c.Add("test", "test") 218 So(err, ShouldBeNil) 219 Convey("When I check the cache after 1 second, the element should be there", func() { 220 <-time.After(1 * time.Second) 221 d, err := c.Get("test") 222 So(err, ShouldBeNil) 223 So(d.(string), ShouldResemble, "test") 224 225 Convey("When I retrieve the data with get reset", func() { 226 227 val, err := c.GetReset("test", 0) 228 So(err, ShouldBeNil) 229 So(val.(string), ShouldResemble, "test") 230 231 Convey("If I wait 1100, the data should still be there ", func() { 232 <-time.After(1100 * time.Millisecond) 233 d, err := c.Get("test") 234 So(err, ShouldBeNil) 235 So(d.(string), ShouldResemble, "test") 236 237 Convey("If I wait for another second, the data should be gone", func() { 238 <-time.After(1200 * time.Millisecond) 239 val, err := c.Get("test") 240 So(err, ShouldNotBeNil) 241 So(val, ShouldBeNil) 242 }) 243 }) 244 }) 245 }) 246 }) 247 } 248 249 func TestSetTimeOut(t *testing.T) { 250 251 //t.Parallel() 252 253 Convey("Given that I instantiate 1 object with a 2 second timer", t, func() { 254 c := NewCacheWithExpiration("cache", 2*time.Second) 255 err := c.Add("test", "test") 256 So(err, ShouldBeNil) 257 Convey("When I check the cache after 1 second, the element should be there", func() { 258 <-time.After(1 * time.Second) 259 d, err := c.Get("test") 260 So(err, ShouldBeNil) 261 err = c.SetTimeOut("test", 2*time.Second) 262 So(err, ShouldBeNil) 263 So(d.(string), ShouldResemble, "test") 264 265 Convey("When I reset the timer to two more seconds", func() { 266 267 err := c.SetTimeOut("test", 2*time.Second) 268 So(err, ShouldBeNil) 269 270 Convey("If I wait 1100, the data should still be there ", func() { 271 <-time.After(1500 * time.Millisecond) 272 d, err := c.Get("test") 273 So(err, ShouldBeNil) 274 So(d.(string), ShouldResemble, "test") 275 276 Convey("If I wait for another second, the data should be gone", func() { 277 <-time.After(1200 * time.Millisecond) 278 val, err := c.Get("test") 279 So(err, ShouldNotBeNil) 280 So(val, ShouldBeNil) 281 }) 282 }) 283 }) 284 }) 285 }) 286 } 287 288 func TestCacheWithExpirationNotifier(t *testing.T) { 289 290 //t.Parallel() 291 292 finished := make(chan bool) 293 294 Convey("Given a cache with an expiration notitifier ", t, func() { 295 c := NewCacheWithExpirationNotifier("cache", 2*time.Second, func(id interface{}, item interface{}) { 296 if id.(string) == "test" && item.(string) == "test" { 297 finished <- true 298 } else { 299 finished <- false 300 } 301 }) 302 303 Convey("When I add an element", func() { 304 oldtime := time.Now() 305 err := c.Add("test", "test") 306 So(err, ShouldBeNil) 307 Convey("I should receive a notification", func() { 308 r := <-finished 309 Duration := time.Since(oldtime) 310 So(r, ShouldBeTrue) 311 So(Duration.Seconds(), ShouldBeGreaterThanOrEqualTo, 2.0) 312 }) 313 }) 314 }) 315 } 316 317 // func TestThousandsOfTimers(t *testing.T) { 318 319 // //t.Parallel() 320 321 // Convey("Given that I instantiate 10K objects with 2 second timers", t, func() { 322 // c := NewCacheWithExpiration("cache", 2*time.Second) 323 // for i := 0; i < 1000; i++ { 324 // err := c.Add(i, i) 325 // So(err, ShouldBeNil) 326 // } 327 // Convey("After I wait for 1 second and add 10K more objects with 2 second timers", func() { 328 // <-time.After(1 * time.Second) 329 // for i := 20000; i < 30000; i++ { 330 // err := c.Add(i, i) 331 // So(err, ShouldBeNil) 332 // } 333 // //TODO: This test is failing if we wait 3 seconds 334 // Convey("After I wait for another 4 seconds", func() { 335 // <-time.After(5 * time.Second) 336 // Convey("I should have no objects in the cache", func() { 337 // So(c.SizeOf(), ShouldEqual, 0) 338 // }) 339 // }) 340 // }) 341 // }) 342 // } 343 344 func TestRemoveWithDelay(t *testing.T) { 345 Convey("Given an initial cache that is non empty", t, func() { 346 c := NewCache("cache") 347 c.Add("info1", "info1") // nolint 348 c.Add("info2", "info2") // nolint 349 c.Add("info3", "info3") // nolint 350 c.Add("info4", "info4") // nolint 351 352 Convey("When I remove an valid entry with a duration of -1", func() { 353 err := c.RemoveWithDelay("info1", -1) 354 Convey("It should remove the entry right away", func() { 355 So(err, ShouldBeNil) 356 So(c.SizeOf(), ShouldEqual, 3) 357 _, err := c.Get("info1") 358 So(err, ShouldNotBeNil) 359 }) 360 }) 361 362 Convey("When I remove an valid entry with a duration of 2 seconds", func() { 363 err := c.RemoveWithDelay("info2", 2*time.Second) 364 Convey("It should remove the entry right away", func() { 365 So(err, ShouldBeNil) 366 So(c.SizeOf(), ShouldEqual, 4) 367 <-time.After(3 * time.Second) 368 So(c.SizeOf(), ShouldEqual, 3) 369 _, err := c.Get("info2") 370 So(err, ShouldNotBeNil) 371 }) 372 }) 373 374 Convey("When I remove an unknown entry with a duration of 2 seconds", func() { 375 err := c.RemoveWithDelay("unknown", 2*time.Second) 376 Convey("It should return an error", func() { 377 So(err, ShouldNotBeNil) 378 }) 379 }) 380 381 }) 382 }