github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/lru/disk_lru_test.go (about)

     1  package lru
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/keybase/client/go/libkb"
     9  	"github.com/keybase/clockwork"
    10  	"github.com/stretchr/testify/require"
    11  	"golang.org/x/net/context"
    12  )
    13  
    14  func TestDiskLRUBasic(t *testing.T) {
    15  	tc := libkb.SetupTest(t, "TestDiskLRU", 1)
    16  	defer tc.Cleanup()
    17  
    18  	ctx := context.TODO()
    19  	l := NewDiskLRU("mike", 1, 10)
    20  
    21  	k := "mikem:square_360"
    22  	v := "Library/Caches/473847384738.jpg"
    23  	_, err := l.Put(ctx, tc.G, k, v)
    24  	require.NoError(t, err)
    25  
    26  	found, getRes, err := l.Get(ctx, tc.G, k)
    27  	require.NoError(t, err)
    28  	require.True(t, found)
    29  	require.Equal(t, v, getRes.Value.(string))
    30  
    31  	l.ClearMemory(ctx, tc.G)
    32  	found, getRes, err = l.Get(ctx, tc.G, k)
    33  	require.NoError(t, err)
    34  	require.True(t, found)
    35  	require.Equal(t, v, getRes.Value.(string))
    36  
    37  	err = l.Remove(ctx, tc.G, k)
    38  	require.NoError(t, err)
    39  	found, getRes, err = l.Get(ctx, tc.G, k)
    40  	require.NoError(t, err)
    41  	require.False(t, found)
    42  
    43  	found, getRes, err = l.Get(ctx, tc.G, "missing")
    44  	require.NoError(t, err)
    45  	require.False(t, found)
    46  }
    47  
    48  func TestDiskLRUVersion(t *testing.T) {
    49  	tc := libkb.SetupTest(t, "TestDiskLRU", 1)
    50  	defer tc.Cleanup()
    51  
    52  	ctx := context.TODO()
    53  	l := NewDiskLRU("mike", 1, 10)
    54  	l2 := NewDiskLRU("mike", 2, 10)
    55  
    56  	k := "mikem:square_360"
    57  	v := "Library/Caches/473847384738.jpg"
    58  	_, err := l.Put(ctx, tc.G, k, v)
    59  	require.NoError(t, err)
    60  	found, getRes, err := l.Get(ctx, tc.G, k)
    61  	require.NoError(t, err)
    62  	require.True(t, found)
    63  	require.Equal(t, v, getRes.Value.(string))
    64  	found, getRes, err = l2.Get(ctx, tc.G, k)
    65  	require.NoError(t, err)
    66  	require.False(t, found)
    67  }
    68  
    69  func TestDiskLRUEvict(t *testing.T) {
    70  	tc := libkb.SetupTest(t, "TestDiskLRU", 1)
    71  	defer tc.Cleanup()
    72  
    73  	ctx := context.TODO()
    74  	l := NewDiskLRU("mike", 1, 2)
    75  	clock := clockwork.NewFakeClock()
    76  	tc.G.SetClock(clock)
    77  	initialTime := clock.Now()
    78  	kold := "oldest"
    79  	vold := "Library/Caches/473847384738.jpg"
    80  	evict, err := l.Put(ctx, tc.G, kold, vold)
    81  	require.NoError(t, err)
    82  	require.Nil(t, evict)
    83  	kmiddle := "middle"
    84  	vmiddle := "middleV"
    85  	evict, err = l.Put(ctx, tc.G, kmiddle, vmiddle)
    86  	require.NoError(t, err)
    87  	require.Nil(t, evict)
    88  	knew := "new"
    89  	vnew := "newv"
    90  	evict, err = l.Put(ctx, tc.G, knew, vnew)
    91  	require.NoError(t, err)
    92  	require.NotNil(t, evict)
    93  	require.Equal(t, kold, evict.Key)
    94  	require.Equal(t, initialTime, evict.Ctime)
    95  
    96  	// Promote kmiddle
    97  	clock.Advance(time.Hour)
    98  	found, getRes, err := l.Get(ctx, tc.G, kmiddle)
    99  	require.NoError(t, err)
   100  	require.True(t, found)
   101  	require.Equal(t, kmiddle, getRes.Key)
   102  	require.Equal(t, getRes.LastAccessed, clock.Now())
   103  
   104  	evict, err = l.Put(ctx, tc.G, kold, vold)
   105  	require.NoError(t, err)
   106  	require.NotNil(t, evict)
   107  	require.Equal(t, knew, evict.Key)
   108  }
   109  
   110  func TestDiskLRUFlush(t *testing.T) {
   111  	tc := libkb.SetupTest(t, "TestDiskLRU", 1)
   112  	defer tc.Cleanup()
   113  
   114  	ctx := context.TODO()
   115  	l := NewDiskLRU("mike", 1, 2)
   116  	clock := clockwork.NewFakeClock()
   117  	tc.G.SetClock(clock)
   118  
   119  	l.lastFlush = clock.Now()
   120  	l.flushCh = make(chan struct{}, 5)
   121  	k := "mikem:square_360"
   122  	v := "Library/Caches/473847384738.jpg"
   123  	_, err := l.Put(ctx, tc.G, k, v)
   124  	require.NoError(t, err)
   125  	select {
   126  	case <-l.flushCh:
   127  	case <-time.After(20 * time.Second):
   128  		require.Fail(t, "no flush")
   129  	}
   130  	get := func() {
   131  		found, getRes, err := l.Get(ctx, tc.G, k)
   132  		require.NoError(t, err)
   133  		require.True(t, found)
   134  		require.Equal(t, v, getRes.Value.(string))
   135  	}
   136  	get()
   137  	select {
   138  	case <-l.flushCh:
   139  		require.Fail(t, "no flush")
   140  	default:
   141  	}
   142  	clock.Advance(time.Hour)
   143  	get()
   144  	select {
   145  	case <-l.flushCh:
   146  	case <-time.After(20 * time.Second):
   147  		require.Fail(t, "no flush")
   148  	}
   149  }
   150  
   151  func TestDiskLRUClean(t *testing.T) {
   152  	tc := libkb.SetupTest(t, "TestDiskLRUCleaner", 1)
   153  	defer tc.Cleanup()
   154  
   155  	ctx := context.TODO()
   156  	cacheDir, err := os.MkdirTemp("", "")
   157  	require.NoError(t, err)
   158  	defer os.RemoveAll(cacheDir)
   159  	l := NewDiskLRU("josh", 1, 10)
   160  
   161  	file, err := os.CreateTemp(cacheDir, "tmpfile")
   162  	require.NoError(t, err)
   163  	data, err := libkb.RandBytes(1024 * 1024)
   164  	require.NoError(t, err)
   165  	_, err = file.Write(data)
   166  	require.NoError(t, err)
   167  	file.Close()
   168  
   169  	// File is not cleaned since it is in the LRU
   170  	k := "mikem:square_360"
   171  	v := file.Name()
   172  	_, err = l.Put(ctx, tc.G, k, v)
   173  	require.NoError(t, err)
   174  	mctx := libkb.NewMetaContextForTest(tc)
   175  	err = l.CleanOutOfSync(mctx, cacheDir)
   176  	require.NoError(t, err)
   177  	exists, err := libkb.FileExists(file.Name())
   178  	require.NoError(t, err)
   179  	require.True(t, exists)
   180  
   181  	// File is cleaned now that the lru no longer has that key.
   182  	err = l.Remove(ctx, tc.G, k)
   183  	require.NoError(t, err)
   184  	err = l.CleanOutOfSync(mctx, cacheDir)
   185  	require.NoError(t, err)
   186  	exists, err = libkb.FileExists(file.Name())
   187  	require.NoError(t, err)
   188  	require.False(t, exists)
   189  }