compare_test.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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. package bytes_test
  5. import (
  6. . "bytes"
  7. "internal/testenv"
  8. "testing"
  9. )
  10. var compareTests = []struct {
  11. a, b []byte
  12. i int
  13. }{
  14. {[]byte(""), []byte(""), 0},
  15. {[]byte("a"), []byte(""), 1},
  16. {[]byte(""), []byte("a"), -1},
  17. {[]byte("abc"), []byte("abc"), 0},
  18. {[]byte("abd"), []byte("abc"), 1},
  19. {[]byte("abc"), []byte("abd"), -1},
  20. {[]byte("ab"), []byte("abc"), -1},
  21. {[]byte("abc"), []byte("ab"), 1},
  22. {[]byte("x"), []byte("ab"), 1},
  23. {[]byte("ab"), []byte("x"), -1},
  24. {[]byte("x"), []byte("a"), 1},
  25. {[]byte("b"), []byte("x"), -1},
  26. // test runtime·memeq's chunked implementation
  27. {[]byte("abcdefgh"), []byte("abcdefgh"), 0},
  28. {[]byte("abcdefghi"), []byte("abcdefghi"), 0},
  29. {[]byte("abcdefghi"), []byte("abcdefghj"), -1},
  30. {[]byte("abcdefghj"), []byte("abcdefghi"), 1},
  31. // nil tests
  32. {nil, nil, 0},
  33. {[]byte(""), nil, 0},
  34. {nil, []byte(""), 0},
  35. {[]byte("a"), nil, 1},
  36. {nil, []byte("a"), -1},
  37. }
  38. func TestCompare(t *testing.T) {
  39. for _, tt := range compareTests {
  40. numShifts := 16
  41. buffer := make([]byte, len(tt.b)+numShifts)
  42. // vary the input alignment of tt.b
  43. for offset := 0; offset <= numShifts; offset++ {
  44. shiftedB := buffer[offset : len(tt.b)+offset]
  45. copy(shiftedB, tt.b)
  46. cmp := Compare(tt.a, shiftedB)
  47. if cmp != tt.i {
  48. t.Errorf(`Compare(%q, %q), offset %d = %v; want %v`, tt.a, tt.b, offset, cmp, tt.i)
  49. }
  50. }
  51. }
  52. }
  53. func TestCompareIdenticalSlice(t *testing.T) {
  54. var b = []byte("Hello Gophers!")
  55. if Compare(b, b) != 0 {
  56. t.Error("b != b")
  57. }
  58. if Compare(b, b[:1]) != 1 {
  59. t.Error("b > b[:1] failed")
  60. }
  61. }
  62. func TestCompareBytes(t *testing.T) {
  63. lengths := make([]int, 0) // lengths to test in ascending order
  64. for i := 0; i <= 128; i++ {
  65. lengths = append(lengths, i)
  66. }
  67. lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097)
  68. if !testing.Short() || testenv.Builder() != "" {
  69. lengths = append(lengths, 65535, 65536, 65537, 99999)
  70. }
  71. n := lengths[len(lengths)-1]
  72. a := make([]byte, n+1)
  73. b := make([]byte, n+1)
  74. for _, len := range lengths {
  75. // randomish but deterministic data. No 0 or 255.
  76. for i := 0; i < len; i++ {
  77. a[i] = byte(1 + 31*i%254)
  78. b[i] = byte(1 + 31*i%254)
  79. }
  80. // data past the end is different
  81. for i := len; i <= n; i++ {
  82. a[i] = 8
  83. b[i] = 9
  84. }
  85. cmp := Compare(a[:len], b[:len])
  86. if cmp != 0 {
  87. t.Errorf(`CompareIdentical(%d) = %d`, len, cmp)
  88. }
  89. if len > 0 {
  90. cmp = Compare(a[:len-1], b[:len])
  91. if cmp != -1 {
  92. t.Errorf(`CompareAshorter(%d) = %d`, len, cmp)
  93. }
  94. cmp = Compare(a[:len], b[:len-1])
  95. if cmp != 1 {
  96. t.Errorf(`CompareBshorter(%d) = %d`, len, cmp)
  97. }
  98. }
  99. for k := 0; k < len; k++ {
  100. b[k] = a[k] - 1
  101. cmp = Compare(a[:len], b[:len])
  102. if cmp != 1 {
  103. t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp)
  104. }
  105. b[k] = a[k] + 1
  106. cmp = Compare(a[:len], b[:len])
  107. if cmp != -1 {
  108. t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp)
  109. }
  110. b[k] = a[k]
  111. }
  112. }
  113. }
  114. func TestEndianBaseCompare(t *testing.T) {
  115. // This test compares byte slices that are almost identical, except one
  116. // difference that for some j, a[j]>b[j] and a[j+1]<b[j+1]. If the implementation
  117. // compares large chunks with wrong endianness, it gets wrong result.
  118. // no vector register is larger than 512 bytes for now
  119. const maxLength = 512
  120. a := make([]byte, maxLength)
  121. b := make([]byte, maxLength)
  122. // randomish but deterministic data. No 0 or 255.
  123. for i := 0; i < maxLength; i++ {
  124. a[i] = byte(1 + 31*i%254)
  125. b[i] = byte(1 + 31*i%254)
  126. }
  127. for i := 2; i <= maxLength; i <<= 1 {
  128. for j := 0; j < i-1; j++ {
  129. a[j] = b[j] - 1
  130. a[j+1] = b[j+1] + 1
  131. cmp := Compare(a[:i], b[:i])
  132. if cmp != -1 {
  133. t.Errorf(`CompareBbigger(%d,%d) = %d`, i, j, cmp)
  134. }
  135. a[j] = b[j] + 1
  136. a[j+1] = b[j+1] - 1
  137. cmp = Compare(a[:i], b[:i])
  138. if cmp != 1 {
  139. t.Errorf(`CompareAbigger(%d,%d) = %d`, i, j, cmp)
  140. }
  141. a[j] = b[j]
  142. a[j+1] = b[j+1]
  143. }
  144. }
  145. }
  146. func BenchmarkCompareBytesEqual(b *testing.B) {
  147. b1 := []byte("Hello Gophers!")
  148. b2 := []byte("Hello Gophers!")
  149. for i := 0; i < b.N; i++ {
  150. if Compare(b1, b2) != 0 {
  151. b.Fatal("b1 != b2")
  152. }
  153. }
  154. }
  155. func BenchmarkCompareBytesToNil(b *testing.B) {
  156. b1 := []byte("Hello Gophers!")
  157. var b2 []byte
  158. for i := 0; i < b.N; i++ {
  159. if Compare(b1, b2) != 1 {
  160. b.Fatal("b1 > b2 failed")
  161. }
  162. }
  163. }
  164. func BenchmarkCompareBytesEmpty(b *testing.B) {
  165. b1 := []byte("")
  166. b2 := b1
  167. for i := 0; i < b.N; i++ {
  168. if Compare(b1, b2) != 0 {
  169. b.Fatal("b1 != b2")
  170. }
  171. }
  172. }
  173. func BenchmarkCompareBytesIdentical(b *testing.B) {
  174. b1 := []byte("Hello Gophers!")
  175. b2 := b1
  176. for i := 0; i < b.N; i++ {
  177. if Compare(b1, b2) != 0 {
  178. b.Fatal("b1 != b2")
  179. }
  180. }
  181. }
  182. func BenchmarkCompareBytesSameLength(b *testing.B) {
  183. b1 := []byte("Hello Gophers!")
  184. b2 := []byte("Hello, Gophers")
  185. for i := 0; i < b.N; i++ {
  186. if Compare(b1, b2) != -1 {
  187. b.Fatal("b1 < b2 failed")
  188. }
  189. }
  190. }
  191. func BenchmarkCompareBytesDifferentLength(b *testing.B) {
  192. b1 := []byte("Hello Gophers!")
  193. b2 := []byte("Hello, Gophers!")
  194. for i := 0; i < b.N; i++ {
  195. if Compare(b1, b2) != -1 {
  196. b.Fatal("b1 < b2 failed")
  197. }
  198. }
  199. }
  200. func BenchmarkCompareBytesBigUnaligned(b *testing.B) {
  201. b.StopTimer()
  202. b1 := make([]byte, 0, 1<<20)
  203. for len(b1) < 1<<20 {
  204. b1 = append(b1, "Hello Gophers!"...)
  205. }
  206. b2 := append([]byte("hello"), b1...)
  207. b.StartTimer()
  208. for i := 0; i < b.N; i++ {
  209. if Compare(b1, b2[len("hello"):]) != 0 {
  210. b.Fatal("b1 != b2")
  211. }
  212. }
  213. b.SetBytes(int64(len(b1)))
  214. }
  215. func BenchmarkCompareBytesBig(b *testing.B) {
  216. b.StopTimer()
  217. b1 := make([]byte, 0, 1<<20)
  218. for len(b1) < 1<<20 {
  219. b1 = append(b1, "Hello Gophers!"...)
  220. }
  221. b2 := append([]byte{}, b1...)
  222. b.StartTimer()
  223. for i := 0; i < b.N; i++ {
  224. if Compare(b1, b2) != 0 {
  225. b.Fatal("b1 != b2")
  226. }
  227. }
  228. b.SetBytes(int64(len(b1)))
  229. }
  230. func BenchmarkCompareBytesBigIdentical(b *testing.B) {
  231. b.StopTimer()
  232. b1 := make([]byte, 0, 1<<20)
  233. for len(b1) < 1<<20 {
  234. b1 = append(b1, "Hello Gophers!"...)
  235. }
  236. b2 := b1
  237. b.StartTimer()
  238. for i := 0; i < b.N; i++ {
  239. if Compare(b1, b2) != 0 {
  240. b.Fatal("b1 != b2")
  241. }
  242. }
  243. b.SetBytes(int64(len(b1)))
  244. }