cachenode_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package cache
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/rand"
  6. "strconv"
  7. "sync"
  8. "testing"
  9. "time"
  10. "github.com/alicebob/miniredis/v2"
  11. "github.com/stretchr/testify/assert"
  12. "github.com/zeromicro/go-zero/core/logx"
  13. "github.com/zeromicro/go-zero/core/mathx"
  14. "github.com/zeromicro/go-zero/core/stat"
  15. "github.com/zeromicro/go-zero/core/stores/redis"
  16. "github.com/zeromicro/go-zero/core/stores/redis/redistest"
  17. "github.com/zeromicro/go-zero/core/syncx"
  18. )
  19. var errTestNotFound = errors.New("not found")
  20. func init() {
  21. logx.Disable()
  22. stat.SetReporter(nil)
  23. }
  24. func TestCacheNode_DelCache(t *testing.T) {
  25. store, clean, err := redistest.CreateRedis()
  26. assert.Nil(t, err)
  27. store.Type = redis.ClusterType
  28. defer clean()
  29. cn := cacheNode{
  30. rds: store,
  31. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  32. lock: new(sync.Mutex),
  33. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  34. stat: NewStat("any"),
  35. errNotFound: errTestNotFound,
  36. }
  37. assert.Nil(t, cn.Del())
  38. assert.Nil(t, cn.Del([]string{}...))
  39. assert.Nil(t, cn.Del(make([]string, 0)...))
  40. cn.Set("first", "one")
  41. assert.Nil(t, cn.Del("first"))
  42. cn.Set("first", "one")
  43. cn.Set("second", "two")
  44. assert.Nil(t, cn.Del("first", "second"))
  45. }
  46. func TestCacheNode_DelCacheWithErrors(t *testing.T) {
  47. store, clean, err := redistest.CreateRedis()
  48. assert.Nil(t, err)
  49. defer clean()
  50. store.Type = redis.ClusterType
  51. cn := cacheNode{
  52. rds: store,
  53. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  54. lock: new(sync.Mutex),
  55. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  56. stat: NewStat("any"),
  57. errNotFound: errTestNotFound,
  58. }
  59. assert.Nil(t, cn.Del("third", "fourth"))
  60. }
  61. func TestCacheNode_InvalidCache(t *testing.T) {
  62. s, err := miniredis.Run()
  63. assert.Nil(t, err)
  64. defer s.Close()
  65. cn := cacheNode{
  66. rds: redis.New(s.Addr()),
  67. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  68. lock: new(sync.Mutex),
  69. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  70. stat: NewStat("any"),
  71. errNotFound: errTestNotFound,
  72. }
  73. s.Set("any", "value")
  74. var str string
  75. assert.NotNil(t, cn.Get("any", &str))
  76. assert.Equal(t, "", str)
  77. _, err = s.Get("any")
  78. assert.Equal(t, miniredis.ErrKeyNotFound, err)
  79. }
  80. func TestCacheNode_SetWithExpire(t *testing.T) {
  81. store, clean, err := redistest.CreateRedis()
  82. assert.Nil(t, err)
  83. defer clean()
  84. cn := cacheNode{
  85. rds: store,
  86. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  87. barrier: syncx.NewSingleFlight(),
  88. lock: new(sync.Mutex),
  89. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  90. stat: NewStat("any"),
  91. errNotFound: errors.New("any"),
  92. }
  93. assert.NotNil(t, cn.SetWithExpire("key", make(chan int), time.Second))
  94. }
  95. func TestCacheNode_Take(t *testing.T) {
  96. store, clean, err := redistest.CreateRedis()
  97. assert.Nil(t, err)
  98. defer clean()
  99. cn := NewNode(store, syncx.NewSingleFlight(), NewStat("any"), errTestNotFound,
  100. WithExpiry(time.Second), WithNotFoundExpiry(time.Second))
  101. var str string
  102. err = cn.Take(&str, "any", func(v interface{}) error {
  103. *v.(*string) = "value"
  104. return nil
  105. })
  106. assert.Nil(t, err)
  107. assert.Equal(t, "value", str)
  108. assert.Nil(t, cn.Get("any", &str))
  109. val, err := store.Get("any")
  110. assert.Nil(t, err)
  111. assert.Equal(t, `"value"`, val)
  112. }
  113. func TestCacheNode_TakeNotFound(t *testing.T) {
  114. store, clean, err := redistest.CreateRedis()
  115. assert.Nil(t, err)
  116. defer clean()
  117. cn := cacheNode{
  118. rds: store,
  119. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  120. barrier: syncx.NewSingleFlight(),
  121. lock: new(sync.Mutex),
  122. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  123. stat: NewStat("any"),
  124. errNotFound: errTestNotFound,
  125. }
  126. var str string
  127. err = cn.Take(&str, "any", func(v interface{}) error {
  128. return errTestNotFound
  129. })
  130. assert.True(t, cn.IsNotFound(err))
  131. assert.True(t, cn.IsNotFound(cn.Get("any", &str)))
  132. val, err := store.Get("any")
  133. assert.Nil(t, err)
  134. assert.Equal(t, `*`, val)
  135. store.Set("any", "*")
  136. err = cn.Take(&str, "any", func(v interface{}) error {
  137. return nil
  138. })
  139. assert.True(t, cn.IsNotFound(err))
  140. assert.True(t, cn.IsNotFound(cn.Get("any", &str)))
  141. store.Del("any")
  142. errDummy := errors.New("dummy")
  143. err = cn.Take(&str, "any", func(v interface{}) error {
  144. return errDummy
  145. })
  146. assert.Equal(t, errDummy, err)
  147. }
  148. func TestCacheNode_TakeWithExpire(t *testing.T) {
  149. store, clean, err := redistest.CreateRedis()
  150. assert.Nil(t, err)
  151. defer clean()
  152. cn := cacheNode{
  153. rds: store,
  154. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  155. barrier: syncx.NewSingleFlight(),
  156. lock: new(sync.Mutex),
  157. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  158. stat: NewStat("any"),
  159. errNotFound: errors.New("any"),
  160. }
  161. var str string
  162. err = cn.TakeWithExpire(&str, "any", func(v interface{}, expire time.Duration) error {
  163. *v.(*string) = "value"
  164. return nil
  165. })
  166. assert.Nil(t, err)
  167. assert.Equal(t, "value", str)
  168. assert.Nil(t, cn.Get("any", &str))
  169. val, err := store.Get("any")
  170. assert.Nil(t, err)
  171. assert.Equal(t, `"value"`, val)
  172. }
  173. func TestCacheNode_String(t *testing.T) {
  174. store, clean, err := redistest.CreateRedis()
  175. assert.Nil(t, err)
  176. defer clean()
  177. cn := cacheNode{
  178. rds: store,
  179. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  180. barrier: syncx.NewSingleFlight(),
  181. lock: new(sync.Mutex),
  182. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  183. stat: NewStat("any"),
  184. errNotFound: errors.New("any"),
  185. }
  186. assert.Equal(t, store.Addr, cn.String())
  187. }
  188. func TestCacheValueWithBigInt(t *testing.T) {
  189. store, clean, err := redistest.CreateRedis()
  190. assert.Nil(t, err)
  191. defer clean()
  192. cn := cacheNode{
  193. rds: store,
  194. r: rand.New(rand.NewSource(time.Now().UnixNano())),
  195. barrier: syncx.NewSingleFlight(),
  196. lock: new(sync.Mutex),
  197. unstableExpiry: mathx.NewUnstable(expiryDeviation),
  198. stat: NewStat("any"),
  199. errNotFound: errors.New("any"),
  200. }
  201. const (
  202. key = "key"
  203. value int64 = 323427211229009810
  204. )
  205. assert.Nil(t, cn.Set(key, value))
  206. var val interface{}
  207. assert.Nil(t, cn.Get(key, &val))
  208. assert.Equal(t, strconv.FormatInt(value, 10), fmt.Sprintf("%v", val))
  209. }