github.com/lingyao2333/mo-zero@v1.4.1/core/collection/cache_test.go (about)

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