1//  Copyright (c) 2014 Couchbase, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// 		http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package numeric
16
17import (
18	"reflect"
19	"testing"
20)
21
22var tests = []struct {
23	input  int64
24	shift  uint
25	output PrefixCoded
26}{
27	{
28		input:  1,
29		shift:  0,
30		output: PrefixCoded{0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1},
31	},
32	{
33		input:  -1,
34		shift:  0,
35		output: PrefixCoded{0x20, 0x0, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f},
36	},
37	{
38		input:  -94582,
39		shift:  0,
40		output: PrefixCoded{0x20, 0x0, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7a, 0x1d, 0xa},
41	},
42	{
43		input:  314729851,
44		shift:  0,
45		output: PrefixCoded{0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x16, 0x9, 0x4a, 0x7b},
46	},
47	{
48		input:  314729851,
49		shift:  4,
50		output: PrefixCoded{0x24, 0x8, 0x0, 0x0, 0x0, 0x0, 0x9, 0x30, 0x4c, 0x57},
51	},
52	{
53		input:  314729851,
54		shift:  8,
55		output: PrefixCoded{0x28, 0x40, 0x0, 0x0, 0x0, 0x0, 0x4b, 0x4, 0x65},
56	},
57	{
58		input:  314729851,
59		shift:  16,
60		output: PrefixCoded{0x30, 0x20, 0x0, 0x0, 0x0, 0x0, 0x25, 0x42},
61	},
62	{
63		input:  314729851,
64		shift:  32,
65		output: PrefixCoded{0x40, 0x8, 0x0, 0x0, 0x0, 0x0},
66	},
67	{
68		input:  1234729851,
69		shift:  32,
70		output: PrefixCoded{0x40, 0x8, 0x0, 0x0, 0x0, 0x0},
71	},
72}
73
74// these array encoding values have been verified manually
75// against the lucene implementation
76func TestPrefixCoded(t *testing.T) {
77
78	for _, test := range tests {
79		actual, err := NewPrefixCodedInt64(test.input, test.shift)
80		if err != nil {
81			t.Error(err)
82		}
83		if !reflect.DeepEqual(actual, test.output) {
84			t.Errorf("expected %#v, got %#v", test.output, actual)
85		}
86		checkedShift, err := actual.Shift()
87		if err != nil {
88			t.Error(err)
89		}
90		if checkedShift != test.shift {
91			t.Errorf("expected %d, got %d", test.shift, checkedShift)
92		}
93		// if the shift was 0, make sure we can go back to the original
94		if test.shift == 0 {
95			backToLong, err := actual.Int64()
96			if err != nil {
97				t.Error(err)
98			}
99			if backToLong != test.input {
100				t.Errorf("expected %v, got %v", test.input, backToLong)
101			}
102		}
103	}
104}
105
106func TestPrefixCodedValid(t *testing.T) {
107	// all of the shared tests should be valid
108	for _, test := range tests {
109		valid, _ := ValidPrefixCodedTerm(string(test.output))
110		if !valid {
111			t.Errorf("expected %s to be valid prefix coded, is not", string(test.output))
112		}
113	}
114
115	invalidTests := []struct {
116		data PrefixCoded
117	}{
118		// first byte invalid skip (too low)
119		{
120			data: PrefixCoded{0x19, 'c', 'a', 't'},
121		},
122		// first byte invalid skip (too high)
123		{
124			data: PrefixCoded{0x20 + 64, 'c'},
125		},
126		// length of trailing bytes wrong (too long)
127		{
128			data: PrefixCoded{0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1},
129		},
130		// length of trailing bytes wrong (too short)
131		{
132			data: PrefixCoded{0x20 + 63},
133		},
134	}
135
136	// all of the shared tests should be valid
137	for _, test := range invalidTests {
138		valid, _ := ValidPrefixCodedTerm(string(test.data))
139		if valid {
140			t.Errorf("expected %s to be invalid prefix coded, it is", string(test.data))
141		}
142	}
143}
144
145func BenchmarkTestPrefixCoded(b *testing.B) {
146
147	for i := 0; i < b.N; i++ {
148		for _, test := range tests {
149			actual, err := NewPrefixCodedInt64(test.input, test.shift)
150			if err != nil {
151				b.Error(err)
152			}
153			if !reflect.DeepEqual(actual, test.output) {
154				b.Errorf("expected %#v, got %#v", test.output, actual)
155			}
156		}
157	}
158}
159