github.com/peterbourgon/diskv@v2.0.1+incompatible/basic_test.go (about) 1 package diskv 2 3 import ( 4 "bytes" 5 "errors" 6 "testing" 7 "time" 8 ) 9 10 func cmpBytes(a, b []byte) bool { 11 if len(a) != len(b) { 12 return false 13 } 14 for i := 0; i < len(a); i++ { 15 if a[i] != b[i] { 16 return false 17 } 18 } 19 return true 20 } 21 22 func (d *Diskv) isCached(key string) bool { 23 d.mu.RLock() 24 defer d.mu.RUnlock() 25 _, ok := d.cache[key] 26 return ok 27 } 28 29 func TestWriteReadErase(t *testing.T) { 30 d := New(Options{ 31 BasePath: "test-data", 32 CacheSizeMax: 1024, 33 }) 34 defer d.EraseAll() 35 k, v := "a", []byte{'b'} 36 if err := d.Write(k, v); err != nil { 37 t.Fatalf("write: %s", err) 38 } 39 if readVal, err := d.Read(k); err != nil { 40 t.Fatalf("read: %s", err) 41 } else if bytes.Compare(v, readVal) != 0 { 42 t.Fatalf("read: expected %s, got %s", v, readVal) 43 } 44 if err := d.Erase(k); err != nil { 45 t.Fatalf("erase: %s", err) 46 } 47 } 48 49 func TestWRECache(t *testing.T) { 50 d := New(Options{ 51 BasePath: "test-data", 52 CacheSizeMax: 1024, 53 }) 54 defer d.EraseAll() 55 k, v := "xxx", []byte{' ', ' ', ' '} 56 if d.isCached(k) { 57 t.Fatalf("key cached before Write and Read") 58 } 59 if err := d.Write(k, v); err != nil { 60 t.Fatalf("write: %s", err) 61 } 62 if d.isCached(k) { 63 t.Fatalf("key cached before Read") 64 } 65 if readVal, err := d.Read(k); err != nil { 66 t.Fatalf("read: %s", err) 67 } else if bytes.Compare(v, readVal) != 0 { 68 t.Fatalf("read: expected %s, got %s", v, readVal) 69 } 70 for i := 0; i < 10 && !d.isCached(k); i++ { 71 time.Sleep(10 * time.Millisecond) 72 } 73 if !d.isCached(k) { 74 t.Fatalf("key not cached after Read") 75 } 76 if err := d.Erase(k); err != nil { 77 t.Fatalf("erase: %s", err) 78 } 79 if d.isCached(k) { 80 t.Fatalf("key cached after Erase") 81 } 82 } 83 84 func TestStrings(t *testing.T) { 85 d := New(Options{ 86 BasePath: "test-data", 87 CacheSizeMax: 1024, 88 }) 89 defer d.EraseAll() 90 91 keys := map[string]bool{"a": false, "b": false, "c": false, "d": false} 92 v := []byte{'1'} 93 for k := range keys { 94 if err := d.Write(k, v); err != nil { 95 t.Fatalf("write: %s: %s", k, err) 96 } 97 } 98 99 for k := range d.Keys(nil) { 100 if _, present := keys[k]; present { 101 t.Logf("got: %s", k) 102 keys[k] = true 103 } else { 104 t.Fatalf("strings() returns unknown key: %s", k) 105 } 106 } 107 108 for k, found := range keys { 109 if !found { 110 t.Errorf("never got %s", k) 111 } 112 } 113 } 114 115 func TestZeroByteCache(t *testing.T) { 116 d := New(Options{ 117 BasePath: "test-data", 118 CacheSizeMax: 0, 119 }) 120 defer d.EraseAll() 121 122 k, v := "a", []byte{'1', '2', '3'} 123 if err := d.Write(k, v); err != nil { 124 t.Fatalf("Write: %s", err) 125 } 126 127 if d.isCached(k) { 128 t.Fatalf("key cached, expected not-cached") 129 } 130 131 if _, err := d.Read(k); err != nil { 132 t.Fatalf("Read: %s", err) 133 } 134 135 if d.isCached(k) { 136 t.Fatalf("key cached, expected not-cached") 137 } 138 } 139 140 func TestOneByteCache(t *testing.T) { 141 d := New(Options{ 142 BasePath: "test-data", 143 CacheSizeMax: 1, 144 }) 145 defer d.EraseAll() 146 147 k1, k2, v1, v2 := "a", "b", []byte{'1'}, []byte{'1', '2'} 148 if err := d.Write(k1, v1); err != nil { 149 t.Fatal(err) 150 } 151 152 if v, err := d.Read(k1); err != nil { 153 t.Fatal(err) 154 } else if !cmpBytes(v, v1) { 155 t.Fatalf("Read: expected %s, got %s", string(v1), string(v)) 156 } 157 158 for i := 0; i < 10 && !d.isCached(k1); i++ { 159 time.Sleep(10 * time.Millisecond) 160 } 161 if !d.isCached(k1) { 162 t.Fatalf("expected 1-byte value to be cached, but it wasn't") 163 } 164 165 if err := d.Write(k2, v2); err != nil { 166 t.Fatal(err) 167 } 168 if _, err := d.Read(k2); err != nil { 169 t.Fatalf("--> %s", err) 170 } 171 172 for i := 0; i < 10 && (!d.isCached(k1) || d.isCached(k2)); i++ { 173 time.Sleep(10 * time.Millisecond) // just wait for lazy-cache 174 } 175 if !d.isCached(k1) { 176 t.Fatalf("1-byte value was uncached for no reason") 177 } 178 179 if d.isCached(k2) { 180 t.Fatalf("2-byte value was cached, but cache max size is 1") 181 } 182 } 183 184 func TestStaleCache(t *testing.T) { 185 d := New(Options{ 186 BasePath: "test-data", 187 CacheSizeMax: 1, 188 }) 189 defer d.EraseAll() 190 191 k, first, second := "a", "first", "second" 192 if err := d.Write(k, []byte(first)); err != nil { 193 t.Fatal(err) 194 } 195 196 v, err := d.Read(k) 197 if err != nil { 198 t.Fatal(err) 199 } 200 if string(v) != first { 201 t.Errorf("expected '%s', got '%s'", first, v) 202 } 203 204 if err := d.Write(k, []byte(second)); err != nil { 205 t.Fatal(err) 206 } 207 208 v, err = d.Read(k) 209 if err != nil { 210 t.Fatal(err) 211 } 212 213 if string(v) != second { 214 t.Errorf("expected '%s', got '%s'", second, v) 215 } 216 } 217 218 func TestHas(t *testing.T) { 219 d := New(Options{ 220 BasePath: "test-data", 221 CacheSizeMax: 1024, 222 }) 223 defer d.EraseAll() 224 225 for k, v := range map[string]string{ 226 "a": "1", 227 "foo": "2", 228 "012345": "3", 229 } { 230 d.Write(k, []byte(v)) 231 } 232 233 d.Read("foo") // cache one of them 234 if !d.isCached("foo") { 235 t.Errorf("'foo' didn't get cached") 236 } 237 238 for _, tuple := range []struct { 239 key string 240 expected bool 241 }{ 242 {"a", true}, 243 {"b", false}, 244 {"foo", true}, 245 {"bar", false}, 246 {"01234", false}, 247 {"012345", true}, 248 {"0123456", false}, 249 } { 250 if expected, got := tuple.expected, d.Has(tuple.key); expected != got { 251 t.Errorf("Has(%s): expected %v, got %v", tuple.key, expected, got) 252 } 253 } 254 } 255 256 type BrokenReader struct{} 257 258 func (BrokenReader) Read(p []byte) (n int, err error) { 259 return 0, errors.New("failed to read") 260 } 261 262 func TestRemovesIncompleteFiles(t *testing.T) { 263 opts := Options{ 264 BasePath: "test-data", 265 CacheSizeMax: 1024, 266 } 267 d := New(opts) 268 defer d.EraseAll() 269 270 key, stream, sync := "key", BrokenReader{}, false 271 272 if err := d.WriteStream(key, stream, sync); err == nil { 273 t.Fatalf("Expected i/o copy error, none received.") 274 } 275 276 if _, err := d.Read(key); err == nil { 277 t.Fatal("Could read the key, but it shouldn't exist") 278 } 279 } 280 281 func TestTempDir(t *testing.T) { 282 opts := Options{ 283 BasePath: "test-data", 284 TempDir: "test-data-temp", 285 CacheSizeMax: 1024, 286 } 287 d := New(opts) 288 defer d.EraseAll() 289 290 k, v := "a", []byte{'b'} 291 if err := d.Write(k, v); err != nil { 292 t.Fatalf("write: %s", err) 293 } 294 if readVal, err := d.Read(k); err != nil { 295 t.Fatalf("read: %s", err) 296 } else if bytes.Compare(v, readVal) != 0 { 297 t.Fatalf("read: expected %s, got %s", v, readVal) 298 } 299 if err := d.Erase(k); err != nil { 300 t.Fatalf("erase: %s", err) 301 } 302 } 303 304 type CrashingReader struct{} 305 306 func (CrashingReader) Read(p []byte) (n int, err error) { 307 panic("System has crashed while reading the stream") 308 } 309 310 func TestAtomicWrite(t *testing.T) { 311 opts := Options{ 312 BasePath: "test-data", 313 // Test would fail if TempDir is not set here. 314 TempDir: "test-data-temp", 315 CacheSizeMax: 1024, 316 } 317 d := New(opts) 318 defer d.EraseAll() 319 320 key := "key" 321 func() { 322 defer func() { 323 recover() // Ignore panicking error 324 }() 325 326 stream := CrashingReader{} 327 d.WriteStream(key, stream, false) 328 }() 329 330 if d.Has(key) { 331 t.Fatal("Has key, but it shouldn't exist") 332 } 333 if _, ok := <-d.Keys(nil); ok { 334 t.Fatal("Store isn't empty") 335 } 336 }