1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package bytes_test
6
7import (
8	. "bytes"
9	"testing"
10)
11
12var compareTests = []struct {
13	a, b []byte
14	i    int
15}{
16	{[]byte(""), []byte(""), 0},
17	{[]byte("a"), []byte(""), 1},
18	{[]byte(""), []byte("a"), -1},
19	{[]byte("abc"), []byte("abc"), 0},
20	{[]byte("abd"), []byte("abc"), 1},
21	{[]byte("abc"), []byte("abd"), -1},
22	{[]byte("ab"), []byte("abc"), -1},
23	{[]byte("abc"), []byte("ab"), 1},
24	{[]byte("x"), []byte("ab"), 1},
25	{[]byte("ab"), []byte("x"), -1},
26	{[]byte("x"), []byte("a"), 1},
27	{[]byte("b"), []byte("x"), -1},
28	// test runtime·memeq's chunked implementation
29	{[]byte("abcdefgh"), []byte("abcdefgh"), 0},
30	{[]byte("abcdefghi"), []byte("abcdefghi"), 0},
31	{[]byte("abcdefghi"), []byte("abcdefghj"), -1},
32	{[]byte("abcdefghj"), []byte("abcdefghi"), 1},
33	// nil tests
34	{nil, nil, 0},
35	{[]byte(""), nil, 0},
36	{nil, []byte(""), 0},
37	{[]byte("a"), nil, 1},
38	{nil, []byte("a"), -1},
39}
40
41func TestCompare(t *testing.T) {
42	for _, tt := range compareTests {
43		cmp := Compare(tt.a, tt.b)
44		if cmp != tt.i {
45			t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
46		}
47	}
48}
49
50func TestCompareIdenticalSlice(t *testing.T) {
51	var b = []byte("Hello Gophers!")
52	if Compare(b, b) != 0 {
53		t.Error("b != b")
54	}
55	if Compare(b, b[:1]) != 1 {
56		t.Error("b > b[:1] failed")
57	}
58}
59
60func TestCompareBytes(t *testing.T) {
61	n := 128
62	a := make([]byte, n+1)
63	b := make([]byte, n+1)
64	for len := 0; len < 128; len++ {
65		// randomish but deterministic data. No 0 or 255.
66		for i := 0; i < len; i++ {
67			a[i] = byte(1 + 31*i%254)
68			b[i] = byte(1 + 31*i%254)
69		}
70		// data past the end is different
71		for i := len; i <= n; i++ {
72			a[i] = 8
73			b[i] = 9
74		}
75		cmp := Compare(a[:len], b[:len])
76		if cmp != 0 {
77			t.Errorf(`CompareIdentical(%d) = %d`, len, cmp)
78		}
79		if len > 0 {
80			cmp = Compare(a[:len-1], b[:len])
81			if cmp != -1 {
82				t.Errorf(`CompareAshorter(%d) = %d`, len, cmp)
83			}
84			cmp = Compare(a[:len], b[:len-1])
85			if cmp != 1 {
86				t.Errorf(`CompareBshorter(%d) = %d`, len, cmp)
87			}
88		}
89		for k := 0; k < len; k++ {
90			b[k] = a[k] - 1
91			cmp = Compare(a[:len], b[:len])
92			if cmp != 1 {
93				t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp)
94			}
95			b[k] = a[k] + 1
96			cmp = Compare(a[:len], b[:len])
97			if cmp != -1 {
98				t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp)
99			}
100			b[k] = a[k]
101		}
102	}
103}
104
105func BenchmarkCompareBytesEqual(b *testing.B) {
106	b1 := []byte("Hello Gophers!")
107	b2 := []byte("Hello Gophers!")
108	for i := 0; i < b.N; i++ {
109		if Compare(b1, b2) != 0 {
110			b.Fatal("b1 != b2")
111		}
112	}
113}
114
115func BenchmarkCompareBytesToNil(b *testing.B) {
116	b1 := []byte("Hello Gophers!")
117	var b2 []byte
118	for i := 0; i < b.N; i++ {
119		if Compare(b1, b2) != 1 {
120			b.Fatal("b1 > b2 failed")
121		}
122	}
123}
124
125func BenchmarkCompareBytesEmpty(b *testing.B) {
126	b1 := []byte("")
127	b2 := b1
128	for i := 0; i < b.N; i++ {
129		if Compare(b1, b2) != 0 {
130			b.Fatal("b1 != b2")
131		}
132	}
133}
134
135func BenchmarkCompareBytesIdentical(b *testing.B) {
136	b1 := []byte("Hello Gophers!")
137	b2 := b1
138	for i := 0; i < b.N; i++ {
139		if Compare(b1, b2) != 0 {
140			b.Fatal("b1 != b2")
141		}
142	}
143}
144
145func BenchmarkCompareBytesSameLength(b *testing.B) {
146	b1 := []byte("Hello Gophers!")
147	b2 := []byte("Hello, Gophers")
148	for i := 0; i < b.N; i++ {
149		if Compare(b1, b2) != -1 {
150			b.Fatal("b1 < b2 failed")
151		}
152	}
153}
154
155func BenchmarkCompareBytesDifferentLength(b *testing.B) {
156	b1 := []byte("Hello Gophers!")
157	b2 := []byte("Hello, Gophers!")
158	for i := 0; i < b.N; i++ {
159		if Compare(b1, b2) != -1 {
160			b.Fatal("b1 < b2 failed")
161		}
162	}
163}
164
165func BenchmarkCompareBytesBigUnaligned(b *testing.B) {
166	b.StopTimer()
167	b1 := make([]byte, 0, 1<<20)
168	for len(b1) < 1<<20 {
169		b1 = append(b1, "Hello Gophers!"...)
170	}
171	b2 := append([]byte("hello"), b1...)
172	b.StartTimer()
173	for i := 0; i < b.N; i++ {
174		if Compare(b1, b2[len("hello"):]) != 0 {
175			b.Fatal("b1 != b2")
176		}
177	}
178	b.SetBytes(int64(len(b1)))
179}
180
181func BenchmarkCompareBytesBig(b *testing.B) {
182	b.StopTimer()
183	b1 := make([]byte, 0, 1<<20)
184	for len(b1) < 1<<20 {
185		b1 = append(b1, "Hello Gophers!"...)
186	}
187	b2 := append([]byte{}, b1...)
188	b.StartTimer()
189	for i := 0; i < b.N; i++ {
190		if Compare(b1, b2) != 0 {
191			b.Fatal("b1 != b2")
192		}
193	}
194	b.SetBytes(int64(len(b1)))
195}
196
197func BenchmarkCompareBytesBigIdentical(b *testing.B) {
198	b.StopTimer()
199	b1 := make([]byte, 0, 1<<20)
200	for len(b1) < 1<<20 {
201		b1 = append(b1, "Hello Gophers!"...)
202	}
203	b2 := b1
204	b.StartTimer()
205	for i := 0; i < b.N; i++ {
206		if Compare(b1, b2) != 0 {
207			b.Fatal("b1 != b2")
208		}
209	}
210	b.SetBytes(int64(len(b1)))
211}
212