1
2
3
4
5
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 if _, err := w.Write([]byte("TEST")); err != nil {
91 t.Fatalf("Write(%d): got error: %v", i, err)
92 }
93 w.Close()
94 if err := fs.SetMeta(fd); err != nil {
95 t.Fatalf("SetMeta(%d): got error: %v", i, err)
96 }
97 rfd, err := fs.GetMeta()
98 if err != nil {
99 t.Fatalf("GetMeta(%d): got error: %v", i, err)
100 }
101 if fd != rfd {
102 t.Fatalf("Invalid meta (%d): got '%s', want '%s'", i, rfd, fd)
103 }
104 }
105 os.RemoveAll(temp)
106 }
107
108 func TestFileStorage_Meta(t *testing.T) {
109 type current struct {
110 num int64
111 backup bool
112 current bool
113 manifest bool
114 corrupt bool
115 }
116 type testCase struct {
117 currents []current
118 notExist bool
119 corrupt bool
120 expect int64
121 }
122 cases := []testCase{
123 {
124 currents: []current{
125 {num: 2, backup: true, manifest: true},
126 {num: 1, current: true},
127 },
128 expect: 2,
129 },
130 {
131 currents: []current{
132 {num: 2, backup: true, manifest: true},
133 {num: 1, current: true, manifest: true},
134 },
135 expect: 1,
136 },
137 {
138 currents: []current{
139 {num: 2, manifest: true},
140 {num: 3, manifest: true},
141 {num: 4, current: true, manifest: true},
142 },
143 expect: 4,
144 },
145 {
146 currents: []current{
147 {num: 2, manifest: true},
148 {num: 3, manifest: true},
149 {num: 4, current: true, manifest: true, corrupt: true},
150 },
151 expect: 3,
152 },
153 {
154 currents: []current{
155 {num: 2, manifest: true},
156 {num: 3, manifest: true},
157 {num: 5, current: true, manifest: true, corrupt: true},
158 {num: 4, backup: true, manifest: true},
159 },
160 expect: 4,
161 },
162 {
163 currents: []current{
164 {num: 4, manifest: true},
165 {num: 3, manifest: true},
166 {num: 2, current: true, manifest: true},
167 },
168 expect: 4,
169 },
170 {
171 currents: []current{
172 {num: 4, manifest: true, corrupt: true},
173 {num: 3, manifest: true},
174 {num: 2, current: true, manifest: true},
175 },
176 expect: 3,
177 },
178 {
179 currents: []current{
180 {num: 4, manifest: true, corrupt: true},
181 {num: 3, manifest: true, corrupt: true},
182 {num: 2, current: true, manifest: true},
183 },
184 expect: 2,
185 },
186 {
187 currents: []current{
188 {num: 4},
189 {num: 3, manifest: true},
190 {num: 2, current: true, manifest: true},
191 },
192 expect: 3,
193 },
194 {
195 currents: []current{
196 {num: 4},
197 {num: 3, manifest: true},
198 {num: 6, current: true},
199 {num: 5, backup: true, manifest: true},
200 },
201 expect: 5,
202 },
203 {
204 currents: []current{
205 {num: 4},
206 {num: 3},
207 {num: 6, current: true},
208 {num: 5, backup: true},
209 },
210 notExist: true,
211 },
212 {
213 currents: []current{
214 {num: 4, corrupt: true},
215 {num: 3},
216 {num: 6, current: true},
217 {num: 5, backup: true},
218 },
219 corrupt: true,
220 },
221 }
222 for i, tc := range cases {
223 t.Logf("Test-%d", i)
224 temp := tempDir(t)
225 fs, err := OpenFile(temp, false)
226 if err != nil {
227 t.Fatal("OpenFile: got error: ", err)
228 }
229 for _, cur := range tc.currents {
230 var curName string
231 switch {
232 case cur.current:
233 curName = "CURRENT"
234 case cur.backup:
235 curName = "CURRENT.bak"
236 default:
237 curName = fmt.Sprintf("CURRENT.%d", cur.num)
238 }
239 fd := FileDesc{Type: TypeManifest, Num: cur.num}
240 content := fmt.Sprintf("%s\n", fsGenName(fd))
241 if cur.corrupt {
242 content = content[:len(content)-1-rand.Intn(3)]
243 }
244 if err := ioutil.WriteFile(filepath.Join(temp, curName), []byte(content), 0644); err != nil {
245 t.Fatal(err)
246 }
247 if cur.manifest {
248 w, err := fs.Create(fd)
249 if err != nil {
250 t.Fatal(err)
251 }
252 if _, err := w.Write([]byte("TEST")); err != nil {
253 t.Fatal(err)
254 }
255 w.Close()
256 }
257 }
258 ret, err := fs.GetMeta()
259 if tc.notExist {
260 if err != os.ErrNotExist {
261 t.Fatalf("expect ErrNotExist, got: %v", err)
262 }
263 } else if tc.corrupt {
264 if !isCorrupted(err) {
265 t.Fatalf("expect ErrCorrupted, got: %v", err)
266 }
267 } else {
268 if err != nil {
269 t.Fatal(err)
270 }
271 if ret.Type != TypeManifest {
272 t.Fatalf("expecting manifest, got: %s", ret.Type)
273 }
274 if ret.Num != tc.expect {
275 t.Fatalf("invalid num, expect=%d got=%d", tc.expect, ret.Num)
276 }
277 fis, err := ioutil.ReadDir(temp)
278 if err != nil {
279 t.Fatal(err)
280 }
281 for _, fi := range fis {
282 if strings.HasPrefix(fi.Name(), "CURRENT") {
283 switch fi.Name() {
284 case "CURRENT", "CURRENT.bak":
285 default:
286 t.Fatalf("found rouge CURRENT file: %s", fi.Name())
287 }
288 }
289 t.Logf("-> %s", fi.Name())
290 }
291 }
292 os.RemoveAll(temp)
293 }
294 }
295
296 func TestFileStorage_ParseFileName(t *testing.T) {
297 for _, c := range cases {
298 for _, name := range append([]string{c.name}, c.oldName...) {
299 fd, ok := fsParseName(name)
300 if !ok {
301 t.Errorf("cannot parse filename '%s'", name)
302 continue
303 }
304 if fd.Type != c.ftype {
305 t.Errorf("filename '%s' invalid type got '%d', want '%d'", name, fd.Type, c.ftype)
306 }
307 if fd.Num != c.num {
308 t.Errorf("filename '%s' invalid number got '%d', want '%d'", name, fd.Num, c.num)
309 }
310 }
311 }
312 }
313
314 func TestFileStorage_InvalidFileName(t *testing.T) {
315 for _, name := range invalidCases {
316 if fsParseNamePtr(name, nil) {
317 t.Errorf("filename '%s' should be invalid", name)
318 }
319 }
320 }
321
322 func TestFileStorage_Locking(t *testing.T) {
323 temp := tempDir(t)
324 defer os.RemoveAll(temp)
325
326 p1, err := OpenFile(temp, false)
327 if err != nil {
328 t.Fatal("OpenFile(1): got error: ", err)
329 }
330
331 p2, err := OpenFile(temp, false)
332 if err != nil {
333 t.Logf("OpenFile(2): got error: %s (expected)", err)
334 } else {
335 p2.Close()
336 p1.Close()
337 t.Fatal("OpenFile(2): expect error")
338 }
339
340 p1.Close()
341
342 p3, err := OpenFile(temp, false)
343 if err != nil {
344 t.Fatal("OpenFile(3): got error: ", err)
345 }
346 defer p3.Close()
347
348 l, err := p3.Lock()
349 if err != nil {
350 t.Fatal("storage lock failed(1): ", err)
351 }
352 _, err = p3.Lock()
353 if err == nil {
354 t.Fatal("expect error for second storage lock attempt")
355 } else {
356 t.Logf("storage lock got error: %s (expected)", err)
357 }
358 l.Unlock()
359 _, err = p3.Lock()
360 if err != nil {
361 t.Fatal("storage lock failed(2): ", err)
362 }
363 }
364
365 func TestFileStorage_ReadOnlyLocking(t *testing.T) {
366 temp := tempDir(t)
367 defer os.RemoveAll(temp)
368
369 p1, err := OpenFile(temp, false)
370 if err != nil {
371 t.Fatal("OpenFile(1): got error: ", err)
372 }
373
374 _, err = OpenFile(temp, true)
375 if err != nil {
376 t.Logf("OpenFile(2): got error: %s (expected)", err)
377 } else {
378 t.Fatal("OpenFile(2): expect error")
379 }
380
381 p1.Close()
382
383 p3, err := OpenFile(temp, true)
384 if err != nil {
385 t.Fatal("OpenFile(3): got error: ", err)
386 }
387
388 p4, err := OpenFile(temp, true)
389 if err != nil {
390 t.Fatal("OpenFile(4): got error: ", err)
391 }
392
393 _, err = OpenFile(temp, false)
394 if err != nil {
395 t.Logf("OpenFile(5): got error: %s (expected)", err)
396 } else {
397 t.Fatal("OpenFile(2): expect error")
398 }
399
400 p3.Close()
401 p4.Close()
402 }
403
View as plain text