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
7package leveldb
8
9import (
10	"bytes"
11	"testing"
12
13	"github.com/syndtr/goleveldb/leveldb/comparer"
14)
15
16var defaultIComparer = &iComparer{comparer.DefaultComparer}
17
18func ikey(key string, seq uint64, kt keyType) internalKey {
19	return makeInternalKey(nil, []byte(key), uint64(seq), kt)
20}
21
22func shortSep(a, b []byte) []byte {
23	dst := make([]byte, len(a))
24	dst = defaultIComparer.Separator(dst[:0], a, b)
25	if dst == nil {
26		return a
27	}
28	return dst
29}
30
31func shortSuccessor(b []byte) []byte {
32	dst := make([]byte, len(b))
33	dst = defaultIComparer.Successor(dst[:0], b)
34	if dst == nil {
35		return b
36	}
37	return dst
38}
39
40func testSingleKey(t *testing.T, key string, seq uint64, kt keyType) {
41	ik := ikey(key, seq, kt)
42
43	if !bytes.Equal(ik.ukey(), []byte(key)) {
44		t.Errorf("user key does not equal, got %v, want %v", string(ik.ukey()), key)
45	}
46
47	rseq, rt := ik.parseNum()
48	if rseq != seq {
49		t.Errorf("seq number does not equal, got %v, want %v", rseq, seq)
50	}
51	if rt != kt {
52		t.Errorf("type does not equal, got %v, want %v", rt, kt)
53	}
54
55	if rukey, rseq, rt, kerr := parseInternalKey(ik); kerr == nil {
56		if !bytes.Equal(rukey, []byte(key)) {
57			t.Errorf("user key does not equal, got %v, want %v", string(ik.ukey()), key)
58		}
59		if rseq != seq {
60			t.Errorf("seq number does not equal, got %v, want %v", rseq, seq)
61		}
62		if rt != kt {
63			t.Errorf("type does not equal, got %v, want %v", rt, kt)
64		}
65	} else {
66		t.Errorf("key error: %v", kerr)
67	}
68}
69
70func TestInternalKey_EncodeDecode(t *testing.T) {
71	keys := []string{"", "k", "hello", "longggggggggggggggggggggg"}
72	seqs := []uint64{
73		1, 2, 3,
74		(1 << 8) - 1, 1 << 8, (1 << 8) + 1,
75		(1 << 16) - 1, 1 << 16, (1 << 16) + 1,
76		(1 << 32) - 1, 1 << 32, (1 << 32) + 1,
77	}
78	for _, key := range keys {
79		for _, seq := range seqs {
80			testSingleKey(t, key, seq, keyTypeVal)
81			testSingleKey(t, "hello", 1, keyTypeDel)
82		}
83	}
84}
85
86func assertBytes(t *testing.T, want, got []byte) {
87	if !bytes.Equal(got, want) {
88		t.Errorf("assert failed, got %v, want %v", got, want)
89	}
90}
91
92func TestInternalKeyShortSeparator(t *testing.T) {
93	// When user keys are same
94	assertBytes(t, ikey("foo", 100, keyTypeVal),
95		shortSep(ikey("foo", 100, keyTypeVal),
96			ikey("foo", 99, keyTypeVal)))
97	assertBytes(t, ikey("foo", 100, keyTypeVal),
98		shortSep(ikey("foo", 100, keyTypeVal),
99			ikey("foo", 101, keyTypeVal)))
100	assertBytes(t, ikey("foo", 100, keyTypeVal),
101		shortSep(ikey("foo", 100, keyTypeVal),
102			ikey("foo", 100, keyTypeVal)))
103	assertBytes(t, ikey("foo", 100, keyTypeVal),
104		shortSep(ikey("foo", 100, keyTypeVal),
105			ikey("foo", 100, keyTypeDel)))
106
107	// When user keys are misordered
108	assertBytes(t, ikey("foo", 100, keyTypeVal),
109		shortSep(ikey("foo", 100, keyTypeVal),
110			ikey("bar", 99, keyTypeVal)))
111
112	// When user keys are different, but correctly ordered
113	assertBytes(t, ikey("g", uint64(keyMaxSeq), keyTypeSeek),
114		shortSep(ikey("foo", 100, keyTypeVal),
115			ikey("hello", 200, keyTypeVal)))
116
117	// When start user key is prefix of limit user key
118	assertBytes(t, ikey("foo", 100, keyTypeVal),
119		shortSep(ikey("foo", 100, keyTypeVal),
120			ikey("foobar", 200, keyTypeVal)))
121
122	// When limit user key is prefix of start user key
123	assertBytes(t, ikey("foobar", 100, keyTypeVal),
124		shortSep(ikey("foobar", 100, keyTypeVal),
125			ikey("foo", 200, keyTypeVal)))
126}
127
128func TestInternalKeyShortestSuccessor(t *testing.T) {
129	assertBytes(t, ikey("g", uint64(keyMaxSeq), keyTypeSeek),
130		shortSuccessor(ikey("foo", 100, keyTypeVal)))
131	assertBytes(t, ikey("\xff\xff", 100, keyTypeVal),
132		shortSuccessor(ikey("\xff\xff", 100, keyTypeVal)))
133}
134