lru_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package cache
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/require"
  7. )
  8. func TestLRU(t *testing.T) {
  9. testCache(t, &LRU{
  10. ItemTTL: time.Minute,
  11. })
  12. }
  13. func TestLRUEvict(t *testing.T) {
  14. ctx := context.TODO()
  15. isHelloEvicted := false
  16. c := LRU{
  17. MaxSize: 12,
  18. ItemTTL: time.Minute,
  19. OnEvict: func(key string, i Item) {
  20. isHelloEvicted = key == "/hello"
  21. require.Equal(t, String("hello"), i)
  22. },
  23. }
  24. c.Set(ctx, "/hello", String("hello"))
  25. require.Len(t, c.priority, 1)
  26. require.Equal(t, 1, c.Len())
  27. require.Equal(t, 5, c.Size())
  28. c.Set(ctx, "/world", String("world"))
  29. require.Len(t, c.priority, 2)
  30. require.Equal(t, 2, c.Len())
  31. require.Equal(t, 10, c.Size())
  32. c.Get(ctx, "/world")
  33. c.Set(ctx, "/goodbye", String("goodbye"))
  34. require.Len(t, c.priority, 2)
  35. require.Equal(t, 2, c.Len())
  36. require.Equal(t, 12, c.Size())
  37. require.True(t, isHelloEvicted)
  38. hello, isCached := c.Get(ctx, "/hello")
  39. require.False(t, isCached)
  40. require.Nil(t, hello)
  41. world, isCached := c.Get(ctx, "/world")
  42. require.True(t, isCached)
  43. require.Equal(t, String("world"), world)
  44. goodbye, isCached := c.Get(ctx, "/goodbye")
  45. require.True(t, isCached)
  46. require.Equal(t, String("goodbye"), goodbye)
  47. }
  48. func TestLRUSetSameKey(t *testing.T) {
  49. ctx := context.TODO()
  50. c := LRU{
  51. ItemTTL: time.Minute,
  52. }
  53. c.Set(ctx, "/test", String("test"))
  54. require.Len(t, c.priority, 1)
  55. require.Equal(t, 1, c.Len())
  56. require.Equal(t, 4, c.Size())
  57. c.Set(ctx, "/test", String("unit-test"))
  58. require.Len(t, c.priority, 2)
  59. require.Equal(t, 1, c.Len())
  60. require.Equal(t, 13, c.Size())
  61. }
  62. func TestSortLRUItems(t *testing.T) {
  63. now := time.Now()
  64. utests := []struct {
  65. scenario string
  66. now time.Time
  67. in []*lruItem
  68. out []*lruItem
  69. }{
  70. {
  71. scenario: "nil",
  72. now: now,
  73. },
  74. {
  75. scenario: "empty",
  76. now: now,
  77. in: []*lruItem{},
  78. out: []*lruItem{},
  79. },
  80. {
  81. scenario: "1 item",
  82. now: now,
  83. in: []*lruItem{
  84. {
  85. count: 1,
  86. expiresAt: now.Add(time.Second),
  87. },
  88. },
  89. out: []*lruItem{
  90. {
  91. count: 1,
  92. expiresAt: now.Add(time.Second),
  93. },
  94. },
  95. },
  96. {
  97. scenario: "2 items",
  98. now: now,
  99. in: []*lruItem{
  100. {
  101. count: 1,
  102. expiresAt: now.Add(time.Second),
  103. },
  104. {
  105. count: 42,
  106. expiresAt: now.Add(time.Second),
  107. },
  108. },
  109. out: []*lruItem{
  110. {
  111. count: 42,
  112. expiresAt: now.Add(time.Second),
  113. },
  114. {
  115. count: 1,
  116. expiresAt: now.Add(time.Second),
  117. },
  118. },
  119. },
  120. {
  121. scenario: "multiple items",
  122. now: now,
  123. in: []*lruItem{
  124. {
  125. count: 1,
  126. expiresAt: now.Add(time.Second),
  127. },
  128. {
  129. count: 42,
  130. expiresAt: now.Add(time.Second),
  131. },
  132. {
  133. count: 1,
  134. expiresAt: now.Add(time.Second),
  135. },
  136. {
  137. count: 7,
  138. expiresAt: now.Add(time.Second),
  139. },
  140. {
  141. count: -21,
  142. expiresAt: now.Add(time.Second),
  143. },
  144. },
  145. out: []*lruItem{
  146. {
  147. count: 42,
  148. expiresAt: now.Add(time.Second),
  149. },
  150. {
  151. count: 7,
  152. expiresAt: now.Add(time.Second),
  153. },
  154. {
  155. count: 1,
  156. expiresAt: now.Add(time.Second),
  157. },
  158. {
  159. count: 1,
  160. expiresAt: now.Add(time.Second),
  161. },
  162. {
  163. count: -21,
  164. expiresAt: now.Add(time.Second),
  165. },
  166. },
  167. },
  168. {
  169. scenario: "multiple items with expired ones",
  170. now: now,
  171. in: []*lruItem{
  172. {
  173. count: 1,
  174. expiresAt: now.Add(time.Second),
  175. },
  176. {
  177. count: 42,
  178. expiresAt: now.Add(-time.Second),
  179. },
  180. {
  181. count: 1,
  182. expiresAt: now.Add(time.Second),
  183. },
  184. {
  185. count: 7,
  186. expiresAt: now.Add(time.Second),
  187. },
  188. {
  189. count: -21,
  190. expiresAt: now.Add(time.Second),
  191. },
  192. },
  193. out: []*lruItem{
  194. {
  195. count: 7,
  196. expiresAt: now.Add(time.Second),
  197. },
  198. {
  199. count: 1,
  200. expiresAt: now.Add(time.Second),
  201. },
  202. {
  203. count: 1,
  204. expiresAt: now.Add(time.Second),
  205. },
  206. {
  207. count: 42,
  208. expiresAt: now.Add(-time.Second),
  209. },
  210. {
  211. count: -21,
  212. expiresAt: now.Add(time.Second),
  213. },
  214. },
  215. },
  216. }
  217. for _, u := range utests {
  218. t.Run(u.scenario, func(t *testing.T) {
  219. sortLRUItems(u.now, u.in)
  220. require.Equal(t, u.out, u.in)
  221. })
  222. }
  223. }