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 }