1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
package kv
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestStoreSimple(t *testing.T) {
tmpf, err := os.CreateTemp("", "lfstest1")
assert.Nil(t, err)
filename := tmpf.Name()
defer os.Remove(filename)
tmpf.Close()
kvs, err := NewStore(filename)
assert.Nil(t, err)
// We'll include storing custom structs
type customData struct {
Val1 string
Val2 int
}
// Needed to store custom struct
RegisterTypeForStorage(&customData{})
kvs.Set("stringVal", "This is a string value")
kvs.Set("intVal", 3)
kvs.Set("floatVal", 3.142)
kvs.Set("structVal", &customData{"structTest", 20})
s := kvs.Get("stringVal")
assert.Equal(t, "This is a string value", s)
i := kvs.Get("intVal")
assert.Equal(t, 3, i)
f := kvs.Get("floatVal")
assert.Equal(t, 3.142, f)
c := kvs.Get("structVal")
assert.Equal(t, c, &customData{"structTest", 20})
n := kvs.Get("noValue")
assert.Nil(t, n)
kvs.Remove("stringVal")
s = kvs.Get("stringVal")
assert.Nil(t, s)
// Set the string value again before saving
kvs.Set("stringVal", "This is a string value")
err = kvs.Save()
assert.Nil(t, err)
kvs = nil
// Now confirm that we can read it all back
kvs2, err := NewStore(filename)
assert.Nil(t, err)
s = kvs2.Get("stringVal")
assert.Equal(t, "This is a string value", s)
i = kvs2.Get("intVal")
assert.Equal(t, 3, i)
f = kvs2.Get("floatVal")
assert.Equal(t, 3.142, f)
c = kvs2.Get("structVal")
assert.Equal(t, c, &customData{"structTest", 20})
n = kvs2.Get("noValue")
assert.Nil(t, n)
// Test remove all
kvs2.RemoveAll()
s = kvs2.Get("stringVal")
assert.Nil(t, s)
i = kvs2.Get("intVal")
assert.Nil(t, i)
f = kvs2.Get("floatVal")
assert.Nil(t, f)
c = kvs2.Get("structVal")
assert.Nil(t, c)
err = kvs2.Save()
assert.Nil(t, err)
kvs2 = nil
// Now confirm that we can read blank & get nothing
kvs, err = NewStore(filename)
assert.Nil(t, err)
kvs.Visit(func(k string, v interface{}) bool {
// Should not be called
assert.Fail(t, "Should be no entries")
return true
})
}
func TestStoreOptimisticConflict(t *testing.T) {
tmpf, err := os.CreateTemp("", "lfstest2")
assert.Nil(t, err)
filename := tmpf.Name()
defer os.Remove(filename)
tmpf.Close()
kvs1, err := NewStore(filename)
assert.Nil(t, err)
kvs1.Set("key1", "value1")
kvs1.Set("key2", "value2")
kvs1.Set("key3", "value3")
err = kvs1.Save()
assert.Nil(t, err)
// Load second copy & modify
kvs2, err := NewStore(filename)
assert.Nil(t, err)
// New keys
kvs2.Set("key4", "value4_fromkvs2")
kvs2.Set("key5", "value5_fromkvs2")
// Modify a key too
kvs2.Set("key1", "value1_fromkvs2")
err = kvs2.Save()
assert.Nil(t, err)
// Now modify first copy & save; it should detect optimistic lock issue
// New item
kvs1.Set("key10", "value10")
// Overlapping item; since we save second this will overwrite one from kvs2
kvs1.Set("key4", "value4")
err = kvs1.Save()
assert.Nil(t, err)
// This should have merged changes from kvs2 in the process
v := kvs1.Get("key1")
assert.Equal(t, "value1_fromkvs2", v) // this one was modified by kvs2
v = kvs1.Get("key2")
assert.Equal(t, "value2", v)
v = kvs1.Get("key3")
assert.Equal(t, "value3", v)
v = kvs1.Get("key4")
assert.Equal(t, "value4", v) // we overwrote this so would not be merged
v = kvs1.Get("key5")
assert.Equal(t, "value5_fromkvs2", v)
}
func TestStoreReduceSize(t *testing.T) {
tmpf, err := os.CreateTemp("", "lfstest3")
assert.Nil(t, err)
filename := tmpf.Name()
defer os.Remove(filename)
tmpf.Close()
kvs, err := NewStore(filename)
assert.Nil(t, err)
kvs.Set("key1", "I woke up in a Soho doorway")
kvs.Set("key2", "A policeman knew my name")
kvs.Set("key3", "He said 'You can go sleep at home tonight")
kvs.Set("key4", "If you can get up and walk away'")
assert.NotNil(t, kvs.Get("key1"))
assert.NotNil(t, kvs.Get("key2"))
assert.NotNil(t, kvs.Get("key3"))
assert.NotNil(t, kvs.Get("key4"))
assert.Nil(t, kvs.Save())
stat1, _ := os.Stat(filename)
// Remove all but 1 key & save smaller version
kvs.Remove("key2")
kvs.Remove("key3")
kvs.Remove("key4")
assert.Nil(t, kvs.Save())
// Now reload fresh & prove works
kvs = nil
kvs, err = NewStore(filename)
assert.Nil(t, err)
assert.NotNil(t, kvs.Get("key1"))
assert.Nil(t, kvs.Get("key2"))
assert.Nil(t, kvs.Get("key3"))
assert.Nil(t, kvs.Get("key4"))
stat2, _ := os.Stat(filename)
assert.True(t, stat2.Size() < stat1.Size(), "Size should have reduced, was %d now %d", stat1.Size(), stat2.Size())
}
|