github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/go/util/sizecache/size_cache_test.go (about)

     1  // Copyright 2016 Attic Labs, Inc. All rights reserved.
     2  // Licensed under the Apache License, version 2.0:
     3  // http://www.apache.org/licenses/LICENSE-2.0
     4  
     5  package sizecache
     6  
     7  import (
     8  	"fmt"
     9  	"sort"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/attic-labs/noms/go/hash"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func hashFromString(s string) hash.Hash {
    18  	return hash.Of([]byte(s))
    19  }
    20  
    21  func TestSizeCache(t *testing.T) {
    22  	assert := assert.New(t)
    23  	defSize := uint64(200)
    24  
    25  	c := New(1024)
    26  	for i, v := range []string{"data-1", "data-2", "data-3", "data-4", "data-5", "data-6", "data-7", "data-8", "data-9"} {
    27  		c.Add(hashFromString(v), defSize, v)
    28  		maxElements := uint64(i + 1)
    29  		if maxElements >= uint64(5) {
    30  			maxElements = uint64(5)
    31  		}
    32  		assert.Equal(maxElements*defSize, c.totalSize)
    33  	}
    34  
    35  	_, ok := c.Get(hashFromString("data-1"))
    36  	assert.False(ok)
    37  	assert.Equal(hashFromString("data-5"), c.lru.Front().Value)
    38  
    39  	v, ok := c.Get(hashFromString("data-5"))
    40  	assert.True(ok)
    41  	assert.Equal("data-5", v.(string))
    42  	assert.Equal(hashFromString("data-5"), c.lru.Back().Value)
    43  	assert.Equal(hashFromString("data-6"), c.lru.Front().Value)
    44  
    45  	c.Add(hashFromString("data-7"), defSize, "data-7")
    46  	assert.Equal(hashFromString("data-7"), c.lru.Back().Value)
    47  	assert.Equal(uint64(1000), c.totalSize)
    48  
    49  	c.Add(hashFromString("no-data"), 0, nil)
    50  	v, ok = c.Get(hashFromString("no-data"))
    51  	assert.True(ok)
    52  	assert.Nil(v)
    53  	assert.Equal(hashFromString("no-data"), c.lru.Back().Value)
    54  	assert.Equal(uint64(1000), c.totalSize)
    55  	assert.Equal(6, c.lru.Len())
    56  	assert.Equal(6, len(c.cache))
    57  
    58  	for _, v := range []string{"data-5", "data-6", "data-7", "data-8", "data-9"} {
    59  		c.Get(hashFromString(v))
    60  		assert.Equal(hashFromString(v), c.lru.Back().Value)
    61  	}
    62  	assert.Equal(hashFromString("no-data"), c.lru.Front().Value)
    63  
    64  	c.Add(hashFromString("data-10"), 200, "data-10")
    65  	assert.Equal(uint64(1000), c.totalSize)
    66  	assert.Equal(5, c.lru.Len())
    67  	assert.Equal(5, len(c.cache))
    68  
    69  	_, ok = c.Get(hashFromString("no-data"))
    70  	assert.False(ok)
    71  	_, ok = c.Get(hashFromString("data-5"))
    72  	assert.False(ok)
    73  
    74  	c.Drop(hashFromString("data-10"))
    75  	assert.Equal(uint64(800), c.totalSize)
    76  	assert.Equal(4, c.lru.Len())
    77  	assert.Equal(4, len(c.cache))
    78  }
    79  
    80  func TestSizeCacheWithExpiry(t *testing.T) {
    81  	expired := []string{}
    82  	expire := func(key interface{}) {
    83  		expired = append(expired, key.(string))
    84  	}
    85  
    86  	c := NewWithExpireCallback(5, expire)
    87  	data := []string{"a", "b", "c", "d", "e"}
    88  	for i, k := range data {
    89  		c.Add(k, 1, i)
    90  	}
    91  
    92  	c.Add("big", 5, "thing")
    93  	sort.Sort(sort.StringSlice(expired))
    94  	assert.Equal(t, data, expired)
    95  }
    96  
    97  func concurrencySizeCacheTest(data []string) {
    98  	dchan := make(chan string, 128)
    99  	go func() {
   100  		for _, d := range data {
   101  			dchan <- d
   102  		}
   103  		close(dchan)
   104  	}()
   105  
   106  	cache := New(25)
   107  	wg := sync.WaitGroup{}
   108  
   109  	for i := 0; i < 3; i++ {
   110  		wg.Add(1)
   111  		go func() {
   112  			for d := range dchan {
   113  				cache.Add(d, uint64(len(d)), d)
   114  			}
   115  			wg.Done()
   116  		}()
   117  	}
   118  	wg.Wait()
   119  }
   120  
   121  // I can't guarantee this will fail if the code isn't correct, but in the
   122  // previous version of SizeCache, this was able to reliably repro bug #2663.
   123  func TestConcurrency(t *testing.T) {
   124  	assert := assert.New(t)
   125  	generateDataStrings := func(numStrings, numValues int) []string {
   126  		l := []string{}
   127  		for i := 0; len(l) < numStrings; i++ {
   128  			for j := 0; j < numValues && len(l) < numStrings; j++ {
   129  				l = append(l, fmt.Sprintf("data-%d", i))
   130  			}
   131  		}
   132  		return l
   133  	}
   134  
   135  	data := generateDataStrings(50, 3)
   136  	for i := 0; i < 100; i++ {
   137  		assert.NotPanics(func() { concurrencySizeCacheTest(data) })
   138  	}
   139  }
   140  
   141  func TestTooLargeValue(t *testing.T) {
   142  	assert := assert.New(t)
   143  
   144  	c := New(1024)
   145  	c.Add(hashFromString("big-data"), 2048, "big-data")
   146  	_, ok := c.Get(hashFromString("big-data"))
   147  	assert.False(ok)
   148  }
   149  
   150  func TestZeroSizeCache(t *testing.T) {
   151  	assert := assert.New(t)
   152  
   153  	c := New(0)
   154  	c.Add(hashFromString("data1"), 200, "data1")
   155  	_, ok := c.Get(hashFromString("data1"))
   156  	assert.False(ok)
   157  }