1package govarint
2
3import "bytes"
4import "io"
5import "math/rand"
6import "testing"
7
8var fourU32 = []uint32{
9	0,
10	1,
11	0,
12	256,
13}
14
15var fiveU32 = []uint32{
16	42,
17	4294967196,
18	384,
19	9716053,
20	1024 + 256 + 3,
21}
22
23var testU32 = []uint32{
24	0,
25	1,
26	2,
27	10,
28	20,
29	63,
30	64,
31	65,
32	127,
33	128,
34	129,
35	255,
36	256,
37	257,
38}
39
40var testU64 = []uint64{
41	0,
42	1,
43	2,
44	10,
45	20,
46	63,
47	64,
48	65,
49	127,
50	128,
51	129,
52	255,
53	256,
54	257,
55	///
56	1<<32 - 1,
57	1 << 32,
58	1 << 33,
59	1 << 42,
60	1<<63 - 1,
61	1 << 63,
62}
63
64func TestEncodeAndDecodeU32(t *testing.T) {
65	for _, expected := range testU32 {
66		var buf bytes.Buffer
67		enc := NewU32Base128Encoder(&buf)
68		enc.PutU32(expected)
69		enc.Close()
70		dec := NewU32Base128Decoder(&buf)
71		x, err := dec.GetU32()
72		if x != expected || err != nil {
73			t.Errorf("ReadUvarint(%v): got x = %d, expected = %d, err = %s", buf, x, expected, err)
74		}
75	}
76	var buf bytes.Buffer
77	enc := NewU32Base128Encoder(&buf)
78	for _, expected := range testU32 {
79		enc.PutU32(expected)
80	}
81	enc.Close()
82	dec := NewU32Base128Decoder(&buf)
83	i := 0
84	for {
85		x, err := dec.GetU32()
86		if err == io.EOF {
87			break
88		}
89		if x != testU32[i] || err != nil {
90			t.Errorf("ReadUvarint(%v): got x = %d, expected = %d, err = %s", buf, x, testU32[i], err)
91		}
92		i += 1
93	}
94	if i != len(testU32) {
95		t.Errorf("Only %d integers were decoded when %d were encoded", i, len(testU32))
96	}
97}
98
99func TestEncodeAndDecodeU64(t *testing.T) {
100	for _, expected := range testU64 {
101		var buf bytes.Buffer
102		enc := NewU64Base128Encoder(&buf)
103		enc.PutU64(expected)
104		enc.Close()
105		dec := NewU64Base128Decoder(&buf)
106		x, err := dec.GetU64()
107		if x != expected || err != nil {
108			t.Errorf("ReadUvarint(%v): got x = %d, expected = %d, err = %s", buf, x, expected, err)
109		}
110	}
111}
112
113func TestU32GroupVarintFour(t *testing.T) {
114	var buf bytes.Buffer
115	enc := NewU32GroupVarintEncoder(&buf)
116	for _, expected := range fourU32 {
117		enc.PutU32(expected)
118	}
119	enc.Close()
120	dec := NewU32GroupVarintDecoder(&buf)
121	i := 0
122	for {
123		x, err := dec.GetU32()
124		if err == io.EOF {
125			break
126		}
127		if err != nil && x != fourU32[i] {
128			t.Errorf("ReadUvarint(%v): got x = %d, expected = %d, err = %s", buf, x, testU32[i], err)
129		}
130		i += 1
131	}
132	if i != len(fourU32) {
133		t.Errorf("%d integers were decoded when %d were encoded", i, len(fourU32))
134	}
135}
136
137func TestU32GroupVarintFive(t *testing.T) {
138	var buf bytes.Buffer
139	enc := NewU32GroupVarintEncoder(&buf)
140	for _, expected := range fiveU32 {
141		enc.PutU32(expected)
142	}
143	enc.Close()
144	dec := NewU32GroupVarintDecoder(&buf)
145	i := 0
146	for {
147		x, err := dec.GetU32()
148		if err == io.EOF {
149			break
150		}
151		if err != nil && x != fiveU32[i] {
152			t.Errorf("ReadUvarint(%v): got x = %d, expected = %d, err = %s", buf, x, testU32[i], err)
153		}
154		i += 1
155	}
156	if i != len(fiveU32) {
157		t.Errorf("%d integers were decoded when %d were encoded", i, len(fiveU32))
158	}
159}
160
161func TestU32GroupVarint14(t *testing.T) {
162	var buf bytes.Buffer
163	for length := 0; length < len(testU32); length++ {
164		subset := testU32[:length]
165		enc := NewU32GroupVarintEncoder(&buf)
166		for _, expected := range subset {
167			enc.PutU32(expected)
168		}
169		enc.Close()
170		dec := NewU32GroupVarintDecoder(&buf)
171		i := 0
172		for {
173			x, err := dec.GetU32()
174			if err == io.EOF {
175				break
176			}
177			if err != nil && x != subset[i] {
178				t.Errorf("ReadUvarint(%v): got x = %d, expected = %d, err = %s", buf, x, subset[i], err)
179			}
180			i += 1
181		}
182		if i != len(subset) {
183			t.Errorf("%d integers were decoded when %d were encoded", i, len(subset))
184		}
185	}
186}
187
188func generateRandomU14() (uint64, []uint32) {
189	// Need to be aware to make it fair for Base128
190	// Base128 has 7 usable bits per byte
191	rand.Seed(42)
192	testSize := 1000000
193	data := make([]uint32, testSize, testSize)
194	total := uint64(0)
195	for i := range data {
196		data[i] = rand.Uint32() % 16384
197		total += uint64(data[i])
198	}
199	return total, data
200}
201
202func speedTest(b *testing.B, dec U32VarintDecoder, readBuf *bytes.Reader, expectedTotal uint64) {
203	total := uint64(0)
204	idx := 0
205	for {
206		x, err := dec.GetU32()
207		if err == io.EOF {
208			break
209		}
210		if err != nil {
211			b.Errorf("Hit err: %v", err)
212		}
213		total += uint64(x)
214		idx += 1
215	}
216	if total != expectedTotal {
217		b.Errorf("Total was %d when %d was expected, having read %d integers", total, expectedTotal, idx)
218	}
219}
220
221func BenchmarkBase128(b *testing.B) {
222	b.StopTimer()
223	//
224	var buf bytes.Buffer
225	enc := NewU32Base128Encoder(&buf)
226	expectedTotal, data := generateRandomU14()
227	for _, expected := range data {
228		enc.PutU32(expected)
229	}
230	enc.Close()
231	//
232	readBuf := bytes.NewReader(buf.Bytes())
233	b.StartTimer()
234	for i := 0; i < b.N; i++ {
235		readBuf.Seek(0, 0)
236		dec := NewU32Base128Decoder(readBuf)
237		speedTest(b, dec, readBuf, expectedTotal)
238	}
239}
240
241func BenchmarkGroupVarint(b *testing.B) {
242	b.StopTimer()
243	//
244	var buf bytes.Buffer
245	enc := NewU32GroupVarintEncoder(&buf)
246	expectedTotal, data := generateRandomU14()
247	for _, expected := range data {
248		enc.PutU32(expected)
249	}
250	enc.Close()
251	//
252	readBuf := bytes.NewReader(buf.Bytes())
253	b.StartTimer()
254	for i := 0; i < b.N; i++ {
255		readBuf.Seek(0, 0)
256		dec := NewU32GroupVarintDecoder(readBuf)
257		speedTest(b, dec, readBuf, expectedTotal)
258	}
259}
260