github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/nbs/manifest_cache_test.go (about)

     1  // Copyright 2019 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // This file incorporates work covered by the following copyright and
    16  // permission notice:
    17  //
    18  // Copyright 2016 Attic Labs, Inc. All rights reserved.
    19  // Licensed under the Apache License, version 2.0:
    20  // http://www.apache.org/licenses/LICENSE-2.0
    21  
    22  package nbs
    23  
    24  import (
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestSizeCache(t *testing.T) {
    33  	defSize := manifestContents{}.size()
    34  
    35  	t.Run("GetAndPut", func(t *testing.T) {
    36  		assert := assert.New(t)
    37  
    38  		c := newManifestCache(2 * defSize)
    39  		t1 := time.Now()
    40  		dbA, contentsA := "dbA", manifestContents{lock: computeAddr([]byte("lockA"))}
    41  		dbB, contentsB := "dbB", manifestContents{lock: computeAddr([]byte("lockB"))}
    42  
    43  		err := c.Put(dbA, contentsA, t1)
    44  		require.NoError(t, err)
    45  		err = c.Put(dbB, contentsB, t1)
    46  		require.NoError(t, err)
    47  
    48  		cont, _, present := c.Get(dbA)
    49  		assert.True(present)
    50  		assert.Equal(contentsA, cont)
    51  
    52  		cont, _, present = c.Get(dbB)
    53  		assert.True(present)
    54  		assert.Equal(contentsB, cont)
    55  	})
    56  
    57  	t.Run("PutDropsLRU", func(t *testing.T) {
    58  		assert := assert.New(t)
    59  
    60  		capacity := uint64(5)
    61  		c := newManifestCache(capacity * defSize)
    62  		keys := []string{"db1", "db2", "db3", "db4", "db5", "db6", "db7", "db8", "db9"}
    63  		for i, v := range keys {
    64  			err := c.Put(v, manifestContents{}, time.Now())
    65  			require.NoError(t, err)
    66  			expected := uint64(i + 1)
    67  			if expected >= capacity {
    68  				expected = capacity
    69  			}
    70  			assert.Equal(expected*defSize, c.totalSize)
    71  		}
    72  
    73  		lru := len(keys) - int(capacity)
    74  		for _, db := range keys[:lru] {
    75  			_, _, present := c.Get(db)
    76  			assert.False(present)
    77  		}
    78  		for _, db := range keys[lru:] {
    79  			_, _, present := c.Get(db)
    80  			assert.True(present)
    81  		}
    82  
    83  		// Bump |keys[lru]| to the back of the queue, making |keys[lru+1]| the next one to be dropped
    84  		_, _, ok := c.Get(keys[lru])
    85  		assert.True(ok)
    86  		lru++
    87  		err := c.Put("novel", manifestContents{}, time.Now())
    88  		require.NoError(t, err)
    89  		_, _, ok = c.Get(keys[lru])
    90  		assert.False(ok)
    91  		// |keys[lru]| is gone, so |keys[lru+1]| is next
    92  		lru++
    93  
    94  		// Putting a bigger value will dump multiple existing entries
    95  		err = c.Put("big", manifestContents{vers: "big version"}, time.Now())
    96  		require.NoError(t, err)
    97  		_, _, ok = c.Get(keys[lru])
    98  		assert.False(ok)
    99  		lru++
   100  		_, _, ok = c.Get(keys[lru])
   101  		assert.False(ok)
   102  		lru++
   103  
   104  		// Make sure expected stuff is still in the cache
   105  		for i := lru; i < len(keys); i++ {
   106  			_, _, ok := c.Get(keys[i])
   107  			assert.True(ok)
   108  		}
   109  		for _, key := range []string{"novel", "big"} {
   110  			_, _, ok := c.Get(key)
   111  			assert.True(ok)
   112  		}
   113  	})
   114  
   115  	t.Run("TooLargeValue", func(t *testing.T) {
   116  		c := newManifestCache(16)
   117  		err := c.Put("db", manifestContents{}, time.Now())
   118  		require.NoError(t, err)
   119  		_, _, ok := c.Get("db")
   120  		assert.False(t, ok)
   121  	})
   122  
   123  	t.Run("ZeroSizeCache", func(t *testing.T) {
   124  		c := newManifestCache(0)
   125  		err := c.Put("db", manifestContents{}, time.Now())
   126  		require.NoError(t, err)
   127  		_, _, ok := c.Get("db")
   128  		assert.False(t, ok)
   129  	})
   130  
   131  }