github.com/df-mc/goleveldb@v1.1.9/leveldb/storage/file_storage_test.go (about) 1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> 2 // All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 package storage 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "math/rand" 13 "os" 14 "path/filepath" 15 "strings" 16 "testing" 17 ) 18 19 var cases = []struct { 20 oldName []string 21 name string 22 ftype FileType 23 num int64 24 }{ 25 {nil, "000100.log", TypeJournal, 100}, 26 {nil, "000000.log", TypeJournal, 0}, 27 {[]string{"000000.sst"}, "000000.ldb", TypeTable, 0}, 28 {nil, "MANIFEST-000002", TypeManifest, 2}, 29 {nil, "MANIFEST-000007", TypeManifest, 7}, 30 {nil, "9223372036854775807.log", TypeJournal, 9223372036854775807}, 31 {nil, "000100.tmp", TypeTemp, 100}, 32 } 33 34 var invalidCases = []string{ 35 "", 36 "foo", 37 "foo-dx-100.log", 38 ".log", 39 "", 40 "manifest", 41 "CURREN", 42 "CURRENTX", 43 "MANIFES", 44 "MANIFEST", 45 "MANIFEST-", 46 "XMANIFEST-3", 47 "MANIFEST-3x", 48 "LOC", 49 "LOCKx", 50 "LO", 51 "LOGx", 52 "18446744073709551616.log", 53 "184467440737095516150.log", 54 "100", 55 "100.", 56 "100.lop", 57 } 58 59 func tempDir(t *testing.T) string { 60 dir, err := ioutil.TempDir("", "goleveldb-") 61 if err != nil { 62 t.Fatal(t) 63 } 64 t.Log("Using temp-dir:", dir) 65 return dir 66 } 67 68 func TestFileStorage_CreateFileName(t *testing.T) { 69 for _, c := range cases { 70 if name := fsGenName(FileDesc{c.ftype, c.num}); name != c.name { 71 t.Errorf("invalid filename got '%s', want '%s'", name, c.name) 72 } 73 } 74 } 75 76 func TestFileStorage_MetaSetGet(t *testing.T) { 77 temp := tempDir(t) 78 fs, err := OpenFile(temp, false) 79 if err != nil { 80 t.Fatal("OpenFile: got error: ", err) 81 } 82 83 for i := 0; i < 10; i++ { 84 num := rand.Int63() 85 fd := FileDesc{Type: TypeManifest, Num: num} 86 w, err := fs.Create(fd) 87 if err != nil { 88 t.Fatalf("Create(%d): got error: %v", i, err) 89 } 90 w.Write([]byte("TEST")) 91 w.Close() 92 if err := fs.SetMeta(fd); err != nil { 93 t.Fatalf("SetMeta(%d): got error: %v", i, err) 94 } 95 rfd, err := fs.GetMeta() 96 if err != nil { 97 t.Fatalf("GetMeta(%d): got error: %v", i, err) 98 } 99 if fd != rfd { 100 t.Fatalf("Invalid meta (%d): got '%s', want '%s'", i, rfd, fd) 101 } 102 } 103 os.RemoveAll(temp) 104 } 105 106 func TestFileStorage_Meta(t *testing.T) { 107 type current struct { 108 num int64 109 backup bool 110 current bool 111 manifest bool 112 corrupt bool 113 } 114 type testCase struct { 115 currents []current 116 notExist bool 117 corrupt bool 118 expect int64 119 } 120 cases := []testCase{ 121 { 122 currents: []current{ 123 {num: 2, backup: true, manifest: true}, 124 {num: 1, current: true}, 125 }, 126 expect: 2, 127 }, 128 { 129 currents: []current{ 130 {num: 2, backup: true, manifest: true}, 131 {num: 1, current: true, manifest: true}, 132 }, 133 expect: 1, 134 }, 135 { 136 currents: []current{ 137 {num: 2, manifest: true}, 138 {num: 3, manifest: true}, 139 {num: 4, current: true, manifest: true}, 140 }, 141 expect: 4, 142 }, 143 { 144 currents: []current{ 145 {num: 2, manifest: true}, 146 {num: 3, manifest: true}, 147 {num: 4, current: true, manifest: true, corrupt: true}, 148 }, 149 expect: 3, 150 }, 151 { 152 currents: []current{ 153 {num: 2, manifest: true}, 154 {num: 3, manifest: true}, 155 {num: 5, current: true, manifest: true, corrupt: true}, 156 {num: 4, backup: true, manifest: true}, 157 }, 158 expect: 4, 159 }, 160 { 161 currents: []current{ 162 {num: 4, manifest: true}, 163 {num: 3, manifest: true}, 164 {num: 2, current: true, manifest: true}, 165 }, 166 expect: 4, 167 }, 168 { 169 currents: []current{ 170 {num: 4, manifest: true, corrupt: true}, 171 {num: 3, manifest: true}, 172 {num: 2, current: true, manifest: true}, 173 }, 174 expect: 3, 175 }, 176 { 177 currents: []current{ 178 {num: 4, manifest: true, corrupt: true}, 179 {num: 3, manifest: true, corrupt: true}, 180 {num: 2, current: true, manifest: true}, 181 }, 182 expect: 2, 183 }, 184 { 185 currents: []current{ 186 {num: 4}, 187 {num: 3, manifest: true}, 188 {num: 2, current: true, manifest: true}, 189 }, 190 expect: 3, 191 }, 192 { 193 currents: []current{ 194 {num: 4}, 195 {num: 3, manifest: true}, 196 {num: 6, current: true}, 197 {num: 5, backup: true, manifest: true}, 198 }, 199 expect: 5, 200 }, 201 { 202 currents: []current{ 203 {num: 4}, 204 {num: 3}, 205 {num: 6, current: true}, 206 {num: 5, backup: true}, 207 }, 208 notExist: true, 209 }, 210 { 211 currents: []current{ 212 {num: 4, corrupt: true}, 213 {num: 3}, 214 {num: 6, current: true}, 215 {num: 5, backup: true}, 216 }, 217 corrupt: true, 218 }, 219 } 220 for i, tc := range cases { 221 t.Logf("Test-%d", i) 222 temp := tempDir(t) 223 fs, err := OpenFile(temp, false) 224 if err != nil { 225 t.Fatal("OpenFile: got error: ", err) 226 } 227 for _, cur := range tc.currents { 228 var curName string 229 switch { 230 case cur.current: 231 curName = "CURRENT" 232 case cur.backup: 233 curName = "CURRENT.bak" 234 default: 235 curName = fmt.Sprintf("CURRENT.%d", cur.num) 236 } 237 fd := FileDesc{Type: TypeManifest, Num: cur.num} 238 content := fmt.Sprintf("%s\n", fsGenName(fd)) 239 if cur.corrupt { 240 content = content[:len(content)-1-rand.Intn(3)] 241 } 242 if err := ioutil.WriteFile(filepath.Join(temp, curName), []byte(content), 0644); err != nil { 243 t.Fatal(err) 244 } 245 if cur.manifest { 246 w, err := fs.Create(fd) 247 if err != nil { 248 t.Fatal(err) 249 } 250 if _, err := w.Write([]byte("TEST")); err != nil { 251 t.Fatal(err) 252 } 253 w.Close() 254 } 255 } 256 ret, err := fs.GetMeta() 257 if tc.notExist { 258 if err != os.ErrNotExist { 259 t.Fatalf("expect ErrNotExist, got: %v", err) 260 } 261 } else if tc.corrupt { 262 if !isCorrupted(err) { 263 t.Fatalf("expect ErrCorrupted, got: %v", err) 264 } 265 } else { 266 if err != nil { 267 t.Fatal(err) 268 } 269 if ret.Type != TypeManifest { 270 t.Fatalf("expecting manifest, got: %s", ret.Type) 271 } 272 if ret.Num != tc.expect { 273 t.Fatalf("invalid num, expect=%d got=%d", tc.expect, ret.Num) 274 } 275 fis, err := ioutil.ReadDir(temp) 276 if err != nil { 277 t.Fatal(err) 278 } 279 for _, fi := range fis { 280 if strings.HasPrefix(fi.Name(), "CURRENT") { 281 switch fi.Name() { 282 case "CURRENT", "CURRENT.bak": 283 default: 284 t.Fatalf("found rouge CURRENT file: %s", fi.Name()) 285 } 286 } 287 t.Logf("-> %s", fi.Name()) 288 } 289 } 290 os.RemoveAll(temp) 291 } 292 } 293 294 func TestFileStorage_ParseFileName(t *testing.T) { 295 for _, c := range cases { 296 for _, name := range append([]string{c.name}, c.oldName...) { 297 fd, ok := fsParseName(name) 298 if !ok { 299 t.Errorf("cannot parse filename '%s'", name) 300 continue 301 } 302 if fd.Type != c.ftype { 303 t.Errorf("filename '%s' invalid type got '%d', want '%d'", name, fd.Type, c.ftype) 304 } 305 if fd.Num != c.num { 306 t.Errorf("filename '%s' invalid number got '%d', want '%d'", name, fd.Num, c.num) 307 } 308 } 309 } 310 } 311 312 func TestFileStorage_InvalidFileName(t *testing.T) { 313 for _, name := range invalidCases { 314 if fsParseNamePtr(name, nil) { 315 t.Errorf("filename '%s' should be invalid", name) 316 } 317 } 318 } 319 320 func TestFileStorage_Locking(t *testing.T) { 321 temp := tempDir(t) 322 defer os.RemoveAll(temp) 323 324 p1, err := OpenFile(temp, false) 325 if err != nil { 326 t.Fatal("OpenFile(1): got error: ", err) 327 } 328 329 p2, err := OpenFile(temp, false) 330 if err != nil { 331 t.Logf("OpenFile(2): got error: %s (expected)", err) 332 } else { 333 p2.Close() 334 p1.Close() 335 t.Fatal("OpenFile(2): expect error") 336 } 337 338 p1.Close() 339 340 p3, err := OpenFile(temp, false) 341 if err != nil { 342 t.Fatal("OpenFile(3): got error: ", err) 343 } 344 defer p3.Close() 345 346 l, err := p3.Lock() 347 if err != nil { 348 t.Fatal("storage lock failed(1): ", err) 349 } 350 _, err = p3.Lock() 351 if err == nil { 352 t.Fatal("expect error for second storage lock attempt") 353 } else { 354 t.Logf("storage lock got error: %s (expected)", err) 355 } 356 l.Unlock() 357 _, err = p3.Lock() 358 if err != nil { 359 t.Fatal("storage lock failed(2): ", err) 360 } 361 } 362 363 func TestFileStorage_ReadOnlyLocking(t *testing.T) { 364 temp := tempDir(t) 365 defer os.RemoveAll(temp) 366 367 p1, err := OpenFile(temp, false) 368 if err != nil { 369 t.Fatal("OpenFile(1): got error: ", err) 370 } 371 372 _, err = OpenFile(temp, true) 373 if err != nil { 374 t.Logf("OpenFile(2): got error: %s (expected)", err) 375 } else { 376 t.Fatal("OpenFile(2): expect error") 377 } 378 379 p1.Close() 380 381 p3, err := OpenFile(temp, true) 382 if err != nil { 383 t.Fatal("OpenFile(3): got error: ", err) 384 } 385 386 p4, err := OpenFile(temp, true) 387 if err != nil { 388 t.Fatal("OpenFile(4): got error: ", err) 389 } 390 391 _, err = OpenFile(temp, false) 392 if err != nil { 393 t.Logf("OpenFile(5): got error: %s (expected)", err) 394 } else { 395 t.Fatal("OpenFile(2): expect error") 396 } 397 398 p3.Close() 399 p4.Close() 400 }