cache_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package collection
  2. import (
  3. "errors"
  4. "strconv"
  5. "sync"
  6. "sync/atomic"
  7. "testing"
  8. "time"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. var errDummy = errors.New("dummy")
  12. func TestCacheSet(t *testing.T) {
  13. cache, err := NewCache(time.Second*2, WithName("any"))
  14. assert.Nil(t, err)
  15. cache.Set("first", "first element")
  16. cache.Set("second", "second element")
  17. value, ok := cache.Get("first")
  18. assert.True(t, ok)
  19. assert.Equal(t, "first element", value)
  20. value, ok = cache.Get("second")
  21. assert.True(t, ok)
  22. assert.Equal(t, "second element", value)
  23. }
  24. func TestCacheDel(t *testing.T) {
  25. cache, err := NewCache(time.Second * 2)
  26. assert.Nil(t, err)
  27. cache.Set("first", "first element")
  28. cache.Set("second", "second element")
  29. cache.Del("first")
  30. _, ok := cache.Get("first")
  31. assert.False(t, ok)
  32. value, ok := cache.Get("second")
  33. assert.True(t, ok)
  34. assert.Equal(t, "second element", value)
  35. }
  36. func TestCacheTake(t *testing.T) {
  37. cache, err := NewCache(time.Second * 2)
  38. assert.Nil(t, err)
  39. var count int32
  40. var wg sync.WaitGroup
  41. for i := 0; i < 100; i++ {
  42. wg.Add(1)
  43. go func() {
  44. cache.Take("first", func() (interface{}, error) {
  45. atomic.AddInt32(&count, 1)
  46. time.Sleep(time.Millisecond * 100)
  47. return "first element", nil
  48. })
  49. wg.Done()
  50. }()
  51. }
  52. wg.Wait()
  53. assert.Equal(t, 1, cache.size())
  54. assert.Equal(t, int32(1), atomic.LoadInt32(&count))
  55. }
  56. func TestCacheTakeExists(t *testing.T) {
  57. cache, err := NewCache(time.Second * 2)
  58. assert.Nil(t, err)
  59. var count int32
  60. var wg sync.WaitGroup
  61. for i := 0; i < 100; i++ {
  62. wg.Add(1)
  63. go func() {
  64. cache.Set("first", "first element")
  65. cache.Take("first", func() (interface{}, error) {
  66. atomic.AddInt32(&count, 1)
  67. time.Sleep(time.Millisecond * 100)
  68. return "first element", nil
  69. })
  70. wg.Done()
  71. }()
  72. }
  73. wg.Wait()
  74. assert.Equal(t, 1, cache.size())
  75. assert.Equal(t, int32(0), atomic.LoadInt32(&count))
  76. }
  77. func TestCacheTakeError(t *testing.T) {
  78. cache, err := NewCache(time.Second * 2)
  79. assert.Nil(t, err)
  80. var count int32
  81. var wg sync.WaitGroup
  82. for i := 0; i < 100; i++ {
  83. wg.Add(1)
  84. go func() {
  85. _, err := cache.Take("first", func() (interface{}, error) {
  86. atomic.AddInt32(&count, 1)
  87. time.Sleep(time.Millisecond * 100)
  88. return "", errDummy
  89. })
  90. assert.Equal(t, errDummy, err)
  91. wg.Done()
  92. }()
  93. }
  94. wg.Wait()
  95. assert.Equal(t, 0, cache.size())
  96. assert.Equal(t, int32(1), atomic.LoadInt32(&count))
  97. }
  98. func TestCacheWithLruEvicts(t *testing.T) {
  99. cache, err := NewCache(time.Minute, WithLimit(3))
  100. assert.Nil(t, err)
  101. cache.Set("first", "first element")
  102. cache.Set("second", "second element")
  103. cache.Set("third", "third element")
  104. cache.Set("fourth", "fourth element")
  105. _, ok := cache.Get("first")
  106. assert.False(t, ok)
  107. value, ok := cache.Get("second")
  108. assert.True(t, ok)
  109. assert.Equal(t, "second element", value)
  110. value, ok = cache.Get("third")
  111. assert.True(t, ok)
  112. assert.Equal(t, "third element", value)
  113. value, ok = cache.Get("fourth")
  114. assert.True(t, ok)
  115. assert.Equal(t, "fourth element", value)
  116. }
  117. func TestCacheWithLruEvicted(t *testing.T) {
  118. cache, err := NewCache(time.Minute, WithLimit(3))
  119. assert.Nil(t, err)
  120. cache.Set("first", "first element")
  121. cache.Set("second", "second element")
  122. cache.Set("third", "third element")
  123. cache.Set("fourth", "fourth element")
  124. _, ok := cache.Get("first")
  125. assert.False(t, ok)
  126. value, ok := cache.Get("second")
  127. assert.True(t, ok)
  128. assert.Equal(t, "second element", value)
  129. cache.Set("fifth", "fifth element")
  130. cache.Set("sixth", "sixth element")
  131. _, ok = cache.Get("third")
  132. assert.False(t, ok)
  133. _, ok = cache.Get("fourth")
  134. assert.False(t, ok)
  135. value, ok = cache.Get("second")
  136. assert.True(t, ok)
  137. assert.Equal(t, "second element", value)
  138. }
  139. func BenchmarkCache(b *testing.B) {
  140. cache, err := NewCache(time.Second*5, WithLimit(100000))
  141. if err != nil {
  142. b.Fatal(err)
  143. }
  144. for i := 0; i < 10000; i++ {
  145. for j := 0; j < 10; j++ {
  146. index := strconv.Itoa(i*10000 + j)
  147. cache.Set("key:"+index, "value:"+index)
  148. }
  149. }
  150. time.Sleep(time.Second * 5)
  151. b.RunParallel(func(pb *testing.PB) {
  152. for pb.Next() {
  153. for i := 0; i < b.N; i++ {
  154. index := strconv.Itoa(i % 10000)
  155. cache.Get("key:" + index)
  156. if i%100 == 0 {
  157. cache.Set("key1:"+index, "value1:"+index)
  158. }
  159. }
  160. }
  161. })
  162. }