2020-10-21 23:31:15 +02:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
2020-11-02 20:35:04 +01:00
|
|
|
"io/ioutil"
|
2020-10-21 23:31:15 +02:00
|
|
|
"os"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
2020-11-21 01:26:32 +01:00
|
|
|
"time"
|
2020-10-21 23:31:15 +02:00
|
|
|
|
|
|
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
const cacheMaxBlobs = 3
|
|
|
|
|
2020-11-02 20:35:04 +01:00
|
|
|
func getTestLRUStore() (*LRUStore, *MemStore) {
|
|
|
|
m := NewMemStore()
|
|
|
|
return NewLRUStore("test", m, 3), m
|
2020-10-21 23:31:15 +02:00
|
|
|
}
|
|
|
|
|
2020-10-22 18:18:31 +02:00
|
|
|
func TestLRUStore_Eviction(t *testing.T) {
|
2020-11-02 20:35:04 +01:00
|
|
|
lru, mem := getTestLRUStore()
|
2020-10-21 23:31:15 +02:00
|
|
|
b := []byte("x")
|
2020-10-22 18:18:31 +02:00
|
|
|
err := lru.Put("one", b)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Put("two", b)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Put("three", b)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Put("four", b)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Put("five", b)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-11-02 20:35:04 +01:00
|
|
|
assert.Equal(t, cacheMaxBlobs, len(mem.Debug()))
|
2020-10-21 23:31:15 +02:00
|
|
|
|
|
|
|
for k, v := range map[string]bool{
|
|
|
|
"one": false,
|
|
|
|
"two": false,
|
|
|
|
"three": true,
|
|
|
|
"four": true,
|
|
|
|
"five": true,
|
|
|
|
"six": false,
|
|
|
|
} {
|
2020-10-22 18:18:31 +02:00
|
|
|
has, err := lru.Has(k)
|
2020-10-21 23:31:15 +02:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, v, has)
|
|
|
|
}
|
|
|
|
|
2020-10-22 18:18:31 +02:00
|
|
|
lru.Get("three") // touch so it stays in cache
|
|
|
|
lru.Put("six", b)
|
2020-10-21 23:31:15 +02:00
|
|
|
|
2020-11-02 20:35:04 +01:00
|
|
|
assert.Equal(t, cacheMaxBlobs, len(mem.Debug()))
|
2020-10-21 23:31:15 +02:00
|
|
|
|
|
|
|
for k, v := range map[string]bool{
|
|
|
|
"one": false,
|
|
|
|
"two": false,
|
|
|
|
"three": true,
|
|
|
|
"four": false,
|
|
|
|
"five": true,
|
|
|
|
"six": true,
|
|
|
|
} {
|
2020-10-22 18:18:31 +02:00
|
|
|
has, err := lru.Has(k)
|
2020-10-21 23:31:15 +02:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, v, has)
|
|
|
|
}
|
|
|
|
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Delete("three")
|
2020-10-21 23:31:15 +02:00
|
|
|
assert.NoError(t, err)
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Delete("five")
|
2020-10-21 23:31:15 +02:00
|
|
|
assert.NoError(t, err)
|
2020-10-22 18:18:31 +02:00
|
|
|
err = lru.Delete("six")
|
2020-10-21 23:31:15 +02:00
|
|
|
assert.NoError(t, err)
|
2020-11-02 20:35:04 +01:00
|
|
|
assert.Equal(t, 0, len(mem.Debug()))
|
2020-10-21 23:31:15 +02:00
|
|
|
}
|
|
|
|
|
2020-10-22 18:18:31 +02:00
|
|
|
func TestLRUStore_UnderlyingBlobMissing(t *testing.T) {
|
2020-11-02 20:35:04 +01:00
|
|
|
lru, mem := getTestLRUStore()
|
2020-10-21 23:31:15 +02:00
|
|
|
hash := "hash"
|
|
|
|
b := []byte("this is a blob of stuff")
|
2020-10-22 18:18:31 +02:00
|
|
|
err := lru.Put(hash, b)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-11-02 20:35:04 +01:00
|
|
|
err = mem.Delete(hash)
|
2020-10-21 23:31:15 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-10-22 18:18:31 +02:00
|
|
|
// hash still exists in lru
|
|
|
|
assert.True(t, lru.lru.Contains(hash))
|
|
|
|
|
|
|
|
blob, err := lru.Get(hash)
|
2020-10-21 23:31:15 +02:00
|
|
|
assert.Nil(t, blob)
|
|
|
|
assert.True(t, errors.Is(err, ErrBlobNotFound), "expected (%s) %s, got (%s) %s",
|
|
|
|
reflect.TypeOf(ErrBlobNotFound).String(), ErrBlobNotFound.Error(),
|
|
|
|
reflect.TypeOf(err).String(), err.Error())
|
2020-10-22 18:18:31 +02:00
|
|
|
|
|
|
|
// lru.Get() removes hash if underlying store doesn't have it
|
|
|
|
assert.False(t, lru.lru.Contains(hash))
|
2020-10-21 23:31:15 +02:00
|
|
|
}
|
2020-10-26 17:27:27 +01:00
|
|
|
|
|
|
|
func TestLRUStore_loadExisting(t *testing.T) {
|
2020-11-02 20:35:04 +01:00
|
|
|
tmpDir, err := ioutil.TempDir("", "reflector_test_*")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
d := NewDiskStore(tmpDir, 2)
|
2020-10-26 17:27:27 +01:00
|
|
|
|
|
|
|
hash := "hash"
|
|
|
|
b := []byte("this is a blob of stuff")
|
2020-11-02 20:35:04 +01:00
|
|
|
err = d.Put(hash, b)
|
2020-10-26 17:27:27 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
existing, err := d.list()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(existing), "blob should exist in cache")
|
|
|
|
assert.Equal(t, hash, existing[0])
|
|
|
|
|
2020-11-21 01:26:32 +01:00
|
|
|
lru := NewLRUStore("test", d, 3) // lru should load existing blobs when it's created
|
|
|
|
time.Sleep(100 * time.Millisecond) // async load so let's wait...
|
2020-10-26 17:27:27 +01:00
|
|
|
has, err := lru.Has(hash)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, has, "hash should be loaded from disk store but it's not")
|
|
|
|
}
|