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  }