github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/cache/fastcache/fastcache_test.go (about)

     1  package fastcache
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"sync"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  func TestCacheSmall(t *testing.T) {
    12  	c := New(1)
    13  	defer c.Reset()
    14  
    15  	if v := c.Get(nil, []byte("aaa")); len(v) != 0 {
    16  		t.Fatalf("unexpected non-empty value obtained from small cache: %q", v)
    17  	}
    18  	if v, exist := c.HasGet(nil, []byte("aaa")); exist || len(v) != 0 {
    19  		t.Fatalf("unexpected non-empty value obtained from small cache: %q", v)
    20  	}
    21  
    22  	c.Set([]byte("key"), []byte("value"))
    23  	if v := c.Get(nil, []byte("key")); string(v) != "value" {
    24  		t.Fatalf("unexpected value obtained; got %q; want %q", v, "value")
    25  	}
    26  	if v := c.Get(nil, nil); len(v) != 0 {
    27  		t.Fatalf("unexpected non-empty value obtained from small cache: %q", v)
    28  	}
    29  	if v, exist := c.HasGet(nil, nil); exist {
    30  		t.Fatalf("unexpected nil-keyed value obtained in small cache: %q", v)
    31  	}
    32  	if v := c.Get(nil, []byte("aaa")); len(v) != 0 {
    33  		t.Fatalf("unexpected non-empty value obtained from small cache: %q", v)
    34  	}
    35  
    36  	c.Set([]byte("aaa"), []byte("bbb"))
    37  	if v := c.Get(nil, []byte("aaa")); string(v) != "bbb" {
    38  		t.Fatalf("unexpected value obtained; got %q; want %q", v, "bbb")
    39  	}
    40  	if v, exist := c.HasGet(nil, []byte("aaa")); !exist || string(v) != "bbb" {
    41  		t.Fatalf("unexpected value obtained; got %q; want %q", v, "bbb")
    42  	}
    43  
    44  	c.Reset()
    45  	if v := c.Get(nil, []byte("aaa")); len(v) != 0 {
    46  		t.Fatalf("unexpected non-empty value obtained from empty cache: %q", v)
    47  	}
    48  	if v, exist := c.HasGet(nil, []byte("aaa")); exist || len(v) != 0 {
    49  		t.Fatalf("unexpected non-empty value obtained from small cache: %q", v)
    50  	}
    51  
    52  	// Test empty value
    53  	k := []byte("empty")
    54  	c.Set(k, nil)
    55  	if v := c.Get(nil, k); len(v) != 0 {
    56  		t.Fatalf("unexpected non-empty value obtained from empty entry: %q", v)
    57  	}
    58  	if v, exist := c.HasGet(nil, k); !exist {
    59  		t.Fatalf("cannot find empty entry for key %q", k)
    60  	} else if len(v) != 0 {
    61  		t.Fatalf("unexpected non-empty value obtained from empty entry: %q", v)
    62  	}
    63  	if !c.Has(k) {
    64  		t.Fatalf("cannot find empty entry for key %q", k)
    65  	}
    66  	if c.Has([]byte("foobar")) {
    67  		t.Fatalf("non-existing entry found in the cache")
    68  	}
    69  }
    70  
    71  func TestCacheWrap(t *testing.T) {
    72  	c := New(bucketsCount * chunkSize * 1.5)
    73  	defer c.Reset()
    74  
    75  	calls := uint64(5e6)
    76  
    77  	for i := uint64(0); i < calls; i++ {
    78  		k := []byte(fmt.Sprintf("key %d", i))
    79  		v := []byte(fmt.Sprintf("value %d", i))
    80  		c.Set(k, v)
    81  		vv := c.Get(nil, k)
    82  		if string(vv) != string(v) {
    83  			t.Fatalf("unexpected value for key %q; got %q; want %q", k, vv, v)
    84  		}
    85  	}
    86  	for i := uint64(0); i < calls/10; i++ {
    87  		x := i * 10
    88  		k := []byte(fmt.Sprintf("key %d", x))
    89  		v := []byte(fmt.Sprintf("value %d", x))
    90  		vv := c.Get(nil, k)
    91  		if len(vv) > 0 && string(v) != string(vv) {
    92  			t.Fatalf("unexpected value for key %q; got %q; want %q", k, vv, v)
    93  		}
    94  	}
    95  
    96  	var s Stats
    97  	c.UpdateStats(&s)
    98  	getCalls := calls + calls/10
    99  	if s.GetCalls != getCalls {
   100  		t.Fatalf("unexpected number of getCalls; got %d; want %d", s.GetCalls, getCalls)
   101  	}
   102  	if s.SetCalls != calls {
   103  		t.Fatalf("unexpected number of setCalls; got %d; want %d", s.SetCalls, calls)
   104  	}
   105  	if s.Misses == 0 || s.Misses >= calls/10 {
   106  		t.Fatalf("unexpected number of misses; got %d; it should be between 0 and %d", s.Misses, calls/10)
   107  	}
   108  	if s.Collisions != 0 {
   109  		t.Fatalf("unexpected number of collisions; got %d; want 0", s.Collisions)
   110  	}
   111  	if s.EntriesCount < calls/5 {
   112  		t.Fatalf("unexpected number of items; got %d; cannot be smaller than %d", s.EntriesCount, calls/5)
   113  	}
   114  	if s.BytesSize < 1024 {
   115  		t.Fatalf("unexpected number of bytesSize; got %d; cannot be smaller than %d", s.BytesSize, 1024)
   116  	}
   117  }
   118  
   119  func TestCacheDel(t *testing.T) {
   120  	c := New(1024)
   121  	defer c.Reset()
   122  	for i := 0; i < 100; i++ {
   123  		k := []byte(fmt.Sprintf("key %d", i))
   124  		v := []byte(fmt.Sprintf("value %d", i))
   125  		c.Set(k, v)
   126  		vv := c.Get(nil, k)
   127  		if string(vv) != string(v) {
   128  			t.Fatalf("unexpected value for key %q; got %q; want %q", k, vv, v)
   129  		}
   130  		c.Del(k)
   131  		vv = c.Get(nil, k)
   132  		if len(vv) > 0 {
   133  			t.Fatalf("unexpected non-empty value got for key %q: %q", k, vv)
   134  		}
   135  	}
   136  }
   137  
   138  func TestCacheBigKeyValue(t *testing.T) {
   139  	c := New(1024)
   140  	defer c.Reset()
   141  
   142  	// Both key and value exceed 64Kb
   143  	k := make([]byte, 90*1024)
   144  	v := make([]byte, 100*1024)
   145  	c.Set(k, v)
   146  	vv := c.Get(nil, k)
   147  	if len(vv) > 0 {
   148  		t.Fatalf("unexpected non-empty value got for key %q: %q", k, vv)
   149  	}
   150  
   151  	// len(key) + len(value) > 64Kb
   152  	k = make([]byte, 40*1024)
   153  	v = make([]byte, 40*1024)
   154  	c.Set(k, v)
   155  	vv = c.Get(nil, k)
   156  	if len(vv) > 0 {
   157  		t.Fatalf("unexpected non-empty value got for key %q: %q", k, vv)
   158  	}
   159  }
   160  
   161  func TestCacheSetGetSerial(t *testing.T) {
   162  	itemsCount := 10000
   163  	c := New(30 * itemsCount)
   164  	defer c.Reset()
   165  	if err := testCacheGetSet(c, itemsCount); err != nil {
   166  		t.Fatalf("unexpected error: %s", err)
   167  	}
   168  }
   169  
   170  func TestCacheGetSetConcurrent(t *testing.T) {
   171  	itemsCount := 10000
   172  	const gorotines = 10
   173  	c := New(30 * itemsCount * gorotines)
   174  	defer c.Reset()
   175  
   176  	ch := make(chan error, gorotines)
   177  	for i := 0; i < gorotines; i++ {
   178  		go func() {
   179  			ch <- testCacheGetSet(c, itemsCount)
   180  		}()
   181  	}
   182  	for i := 0; i < gorotines; i++ {
   183  		select {
   184  		case err := <-ch:
   185  			if err != nil {
   186  				t.Fatalf("unexpected error: %s", err)
   187  			}
   188  		case <-time.After(5 * time.Second):
   189  			t.Fatalf("timeout")
   190  		}
   191  	}
   192  }
   193  
   194  func testCacheGetSet(c *Cache, itemsCount int) error {
   195  	for i := 0; i < itemsCount; i++ {
   196  		k := []byte(fmt.Sprintf("key %d", i))
   197  		v := []byte(fmt.Sprintf("value %d", i))
   198  		c.Set(k, v)
   199  		vv := c.Get(nil, k)
   200  		if string(vv) != string(v) {
   201  			return fmt.Errorf("unexpected value for key %q after insertion; got %q; want %q", k, vv, v)
   202  		}
   203  	}
   204  	misses := 0
   205  	for i := 0; i < itemsCount; i++ {
   206  		k := []byte(fmt.Sprintf("key %d", i))
   207  		vExpected := fmt.Sprintf("value %d", i)
   208  		v := c.Get(nil, k)
   209  		if string(v) != string(vExpected) {
   210  			if len(v) > 0 {
   211  				return fmt.Errorf("unexpected value for key %q after all insertions; got %q; want %q", k, v, vExpected)
   212  			}
   213  			misses++
   214  		}
   215  	}
   216  	if misses >= itemsCount/100 {
   217  		return fmt.Errorf("too many cache misses; got %d; want less than %d", misses, itemsCount/100)
   218  	}
   219  	return nil
   220  }
   221  
   222  func TestCacheResetUpdateStatsSetConcurrent(t *testing.T) {
   223  	c := New(12334)
   224  
   225  	stopCh := make(chan struct{})
   226  
   227  	// run workers for cache reset
   228  	var resettersWG sync.WaitGroup
   229  	for i := 0; i < 10; i++ {
   230  		resettersWG.Add(1)
   231  		go func() {
   232  			defer resettersWG.Done()
   233  			for {
   234  				select {
   235  				case <-stopCh:
   236  					return
   237  				default:
   238  					c.Reset()
   239  					runtime.Gosched()
   240  				}
   241  			}
   242  		}()
   243  	}
   244  
   245  	// run workers for update cache stats
   246  	var statsWG sync.WaitGroup
   247  	for i := 0; i < 10; i++ {
   248  		statsWG.Add(1)
   249  		go func() {
   250  			defer statsWG.Done()
   251  			var s Stats
   252  			for {
   253  				select {
   254  				case <-stopCh:
   255  					return
   256  				default:
   257  					c.UpdateStats(&s)
   258  					runtime.Gosched()
   259  				}
   260  			}
   261  		}()
   262  	}
   263  
   264  	// run workers for setting data to cache
   265  	var settersWG sync.WaitGroup
   266  	for i := 0; i < 10; i++ {
   267  		settersWG.Add(1)
   268  		go func() {
   269  			defer settersWG.Done()
   270  			for j := 0; j < 100; j++ {
   271  				key := []byte(fmt.Sprintf("key_%d", j))
   272  				value := []byte(fmt.Sprintf("value_%d", j))
   273  				c.Set(key, value)
   274  				runtime.Gosched()
   275  			}
   276  		}()
   277  	}
   278  
   279  	// wait for setters
   280  	settersWG.Wait()
   281  	close(stopCh)
   282  	statsWG.Wait()
   283  	resettersWG.Wait()
   284  }