github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/internal/manifest/version_test.go (about)

     1  // Copyright 2012 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package manifest
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  	"sync"
    11  	"testing"
    12  
    13  	"github.com/petermattis/pebble/internal/base"
    14  )
    15  
    16  func ikey(s string) InternalKey {
    17  	return base.MakeInternalKey([]byte(s), 0, base.InternalKeyKindSet)
    18  }
    19  
    20  func TestIkeyRange(t *testing.T) {
    21  	testCases := []struct {
    22  		input, want string
    23  	}{
    24  		{
    25  			"",
    26  			"-",
    27  		},
    28  		{
    29  			"a-e",
    30  			"a-e",
    31  		},
    32  		{
    33  			"a-e a-e",
    34  			"a-e",
    35  		},
    36  		{
    37  			"c-g a-e",
    38  			"a-g",
    39  		},
    40  		{
    41  			"a-e c-g a-e",
    42  			"a-g",
    43  		},
    44  		{
    45  			"b-d f-g",
    46  			"b-g",
    47  		},
    48  		{
    49  			"d-e b-d",
    50  			"b-e",
    51  		},
    52  		{
    53  			"e-e",
    54  			"e-e",
    55  		},
    56  		{
    57  			"f-g e-e d-e c-g b-d a-e",
    58  			"a-g",
    59  		},
    60  	}
    61  	for _, tc := range testCases {
    62  		var f []FileMetadata
    63  		if tc.input != "" {
    64  			for _, s := range strings.Split(tc.input, " ") {
    65  				f = append(f, FileMetadata{
    66  					Smallest: ikey(s[0:1]),
    67  					Largest:  ikey(s[2:3]),
    68  				})
    69  			}
    70  		}
    71  
    72  		smallest0, largest0 := KeyRange(base.DefaultComparer.Compare, f, nil)
    73  		got0 := string(smallest0.UserKey) + "-" + string(largest0.UserKey)
    74  		if got0 != tc.want {
    75  			t.Errorf("first []fileMetadata is %v\ngot  %s\nwant %s", tc.input, got0, tc.want)
    76  		}
    77  
    78  		smallest1, largest1 := KeyRange(base.DefaultComparer.Compare, nil, f)
    79  		got1 := string(smallest1.UserKey) + "-" + string(largest1.UserKey)
    80  		if got1 != tc.want {
    81  			t.Errorf("second []fileMetadata is %v\ngot  %s\nwant %s", tc.input, got1, tc.want)
    82  		}
    83  	}
    84  }
    85  
    86  func TestOverlaps(t *testing.T) {
    87  	m00 := FileMetadata{
    88  		FileNum:  700,
    89  		Size:     1,
    90  		Smallest: base.ParseInternalKey("b.SET.7008"),
    91  		Largest:  base.ParseInternalKey("e.SET.7009"),
    92  	}
    93  	m01 := FileMetadata{
    94  		FileNum:  701,
    95  		Size:     1,
    96  		Smallest: base.ParseInternalKey("c.SET.7018"),
    97  		Largest:  base.ParseInternalKey("f.SET.7019"),
    98  	}
    99  	m02 := FileMetadata{
   100  		FileNum:  702,
   101  		Size:     1,
   102  		Smallest: base.ParseInternalKey("f.SET.7028"),
   103  		Largest:  base.ParseInternalKey("g.SET.7029"),
   104  	}
   105  	m03 := FileMetadata{
   106  		FileNum:  703,
   107  		Size:     1,
   108  		Smallest: base.ParseInternalKey("x.SET.7038"),
   109  		Largest:  base.ParseInternalKey("y.SET.7039"),
   110  	}
   111  	m04 := FileMetadata{
   112  		FileNum:  704,
   113  		Size:     1,
   114  		Smallest: base.ParseInternalKey("n.SET.7048"),
   115  		Largest:  base.ParseInternalKey("p.SET.7049"),
   116  	}
   117  	m05 := FileMetadata{
   118  		FileNum:  705,
   119  		Size:     1,
   120  		Smallest: base.ParseInternalKey("p.SET.7058"),
   121  		Largest:  base.ParseInternalKey("p.SET.7059"),
   122  	}
   123  	m06 := FileMetadata{
   124  		FileNum:  706,
   125  		Size:     1,
   126  		Smallest: base.ParseInternalKey("p.SET.7068"),
   127  		Largest:  base.ParseInternalKey("u.SET.7069"),
   128  	}
   129  	m07 := FileMetadata{
   130  		FileNum:  707,
   131  		Size:     1,
   132  		Smallest: base.ParseInternalKey("r.SET.7078"),
   133  		Largest:  base.ParseInternalKey("s.SET.7079"),
   134  	}
   135  
   136  	m10 := FileMetadata{
   137  		FileNum:  710,
   138  		Size:     1,
   139  		Smallest: base.ParseInternalKey("d.SET.7108"),
   140  		Largest:  base.ParseInternalKey("g.SET.7109"),
   141  	}
   142  	m11 := FileMetadata{
   143  		FileNum:  711,
   144  		Size:     1,
   145  		Smallest: base.ParseInternalKey("g.SET.7118"),
   146  		Largest:  base.ParseInternalKey("j.SET.7119"),
   147  	}
   148  	m12 := FileMetadata{
   149  		FileNum:  712,
   150  		Size:     1,
   151  		Smallest: base.ParseInternalKey("n.SET.7128"),
   152  		Largest:  base.ParseInternalKey("p.SET.7129"),
   153  	}
   154  	m13 := FileMetadata{
   155  		FileNum:  713,
   156  		Size:     1,
   157  		Smallest: base.ParseInternalKey("p.SET.7138"),
   158  		Largest:  base.ParseInternalKey("p.SET.7139"),
   159  	}
   160  	m14 := FileMetadata{
   161  		FileNum:  714,
   162  		Size:     1,
   163  		Smallest: base.ParseInternalKey("p.SET.7148"),
   164  		Largest:  base.ParseInternalKey("u.SET.7149"),
   165  	}
   166  
   167  	v := Version{
   168  		Files: [NumLevels][]FileMetadata{
   169  			0: {m00, m01, m02, m03, m04, m05, m06, m07},
   170  			1: {m10, m11, m12, m13, m14},
   171  		},
   172  	}
   173  
   174  	testCases := []struct {
   175  		level        int
   176  		ukey0, ukey1 string
   177  		want         string
   178  	}{
   179  		// Level 0: m00=b-e, m01=c-f, m02=f-g, m03=x-y, m04=n-p, m05=p-p, m06=p-u, m07=r-s.
   180  		// Note that:
   181  		//   - the slice isn't sorted (e.g. m02=f-g, m03=x-y, m04=n-p),
   182  		//   - m00 and m01 overlap (not just touch),
   183  		//   - m06 contains m07,
   184  		//   - m00, m01 and m02 transitively overlap/touch each other, and
   185  		//   - m04, m05, m06 and m07 transitively overlap/touch each other.
   186  		{0, "a", "a", ""},
   187  		{0, "a", "b", "m00 m01 m02"},
   188  		{0, "a", "d", "m00 m01 m02"},
   189  		{0, "a", "e", "m00 m01 m02"},
   190  		{0, "a", "g", "m00 m01 m02"},
   191  		{0, "a", "z", "m00 m01 m02 m03 m04 m05 m06 m07"},
   192  		{0, "c", "e", "m00 m01 m02"},
   193  		{0, "d", "d", "m00 m01 m02"},
   194  		{0, "g", "n", "m00 m01 m02 m04 m05 m06 m07"},
   195  		{0, "h", "i", ""},
   196  		{0, "h", "o", "m04 m05 m06 m07"},
   197  		{0, "h", "u", "m04 m05 m06 m07"},
   198  		{0, "k", "l", ""},
   199  		{0, "k", "o", "m04 m05 m06 m07"},
   200  		{0, "k", "p", "m04 m05 m06 m07"},
   201  		{0, "n", "o", "m04 m05 m06 m07"},
   202  		{0, "n", "z", "m03 m04 m05 m06 m07"},
   203  		{0, "o", "z", "m03 m04 m05 m06 m07"},
   204  		{0, "p", "z", "m03 m04 m05 m06 m07"},
   205  		{0, "q", "z", "m03 m04 m05 m06 m07"},
   206  		{0, "r", "s", "m04 m05 m06 m07"},
   207  		{0, "r", "z", "m03 m04 m05 m06 m07"},
   208  		{0, "s", "z", "m03 m04 m05 m06 m07"},
   209  		{0, "u", "z", "m03 m04 m05 m06 m07"},
   210  		{0, "y", "z", "m03"},
   211  		{0, "z", "z", ""},
   212  
   213  		// Level 1: m10=d-g, m11=g-j, m12=n-p, m13=p-p, m14=p-u.
   214  		{1, "a", "a", ""},
   215  		{1, "a", "b", ""},
   216  		{1, "a", "d", "m10"},
   217  		{1, "a", "e", "m10"},
   218  		{1, "a", "g", "m10 m11"},
   219  		{1, "a", "z", "m10 m11 m12 m13 m14"},
   220  		{1, "c", "e", "m10"},
   221  		{1, "d", "d", "m10"},
   222  		{1, "g", "n", "m10 m11 m12"},
   223  		{1, "h", "i", "m11"},
   224  		{1, "h", "o", "m11 m12"},
   225  		{1, "h", "u", "m11 m12 m13 m14"},
   226  		{1, "k", "l", ""},
   227  		{1, "k", "o", "m12"},
   228  		{1, "k", "p", "m12 m13 m14"},
   229  		{1, "n", "o", "m12"},
   230  		{1, "n", "z", "m12 m13 m14"},
   231  		{1, "o", "z", "m12 m13 m14"},
   232  		{1, "p", "z", "m12 m13 m14"},
   233  		{1, "q", "z", "m14"},
   234  		{1, "r", "s", "m14"},
   235  		{1, "r", "z", "m14"},
   236  		{1, "s", "z", "m14"},
   237  		{1, "u", "z", "m14"},
   238  		{1, "y", "z", ""},
   239  		{1, "z", "z", ""},
   240  
   241  		// Level 2: empty.
   242  		{2, "a", "z", ""},
   243  	}
   244  
   245  	cmp := base.DefaultComparer.Compare
   246  	for _, tc := range testCases {
   247  		o := v.Overlaps(tc.level, cmp, []byte(tc.ukey0), []byte(tc.ukey1))
   248  		s := make([]string, len(o))
   249  		for i, meta := range o {
   250  			s[i] = fmt.Sprintf("m%02d", meta.FileNum%100)
   251  		}
   252  		got := strings.Join(s, " ")
   253  		if got != tc.want {
   254  			t.Errorf("level=%d, range=%s-%s\ngot  %v\nwant %v", tc.level, tc.ukey0, tc.ukey1, got, tc.want)
   255  		}
   256  	}
   257  }
   258  
   259  func TestVersionUnref(t *testing.T) {
   260  	list := &VersionList{}
   261  	list.Init(&sync.Mutex{})
   262  	v := &Version{Deleted: func([]uint64) {}}
   263  	v.Ref()
   264  	list.PushBack(v)
   265  	v.Unref()
   266  	if !list.Empty() {
   267  		t.Fatalf("expected version list to be empty")
   268  	}
   269  }