1288 lines · 32.5 KB · Go
RawDownload
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file. package bytes_test import (	. "bytes"	"math/rand"	"reflect"	"testing"	"unicode"	"unicode/utf8") func eq(a, b []string) bool {	if len(a) != len(b) {		return false	}	for i := 0; i < len(a); i++ {		if a[i] != b[i] {			return false		}	}	return true} func sliceOfString(s [][]byte) []string {	result := make([]string, len(s))	for i, v := range s {		result[i] = string(v)	}	return result} // For ease of reading, the test cases use strings that are converted to byte// slices before invoking the functions. var abcd = "abcd"var faces = "☺☻☹"var commas = "1,2,3,4"var dots = "1....2....3....4" type BinOpTest struct {	a string	b string	i int} var equalTests = []struct {	a, b []byte	i    int}{	{[]byte(""), []byte(""), 0},	{[]byte("a"), []byte(""), 1},	{[]byte(""), []byte("a"), -1},	{[]byte("abc"), []byte("abc"), 0},	{[]byte("ab"), []byte("abc"), -1},	{[]byte("abc"), []byte("ab"), 1},	{[]byte("x"), []byte("ab"), 1},	{[]byte("ab"), []byte("x"), -1},	{[]byte("x"), []byte("a"), 1},	{[]byte("b"), []byte("x"), -1},	// test runtime·memeq's chunked implementation	{[]byte("abcdefgh"), []byte("abcdefgh"), 0},	{[]byte("abcdefghi"), []byte("abcdefghi"), 0},	{[]byte("abcdefghi"), []byte("abcdefghj"), -1},	// nil tests	{nil, nil, 0},	{[]byte(""), nil, 0},	{nil, []byte(""), 0},	{[]byte("a"), nil, 1},	{nil, []byte("a"), -1},} func TestEqual(t *testing.T) {	for _, tt := range compareTests {		eql := Equal(tt.a, tt.b)		if eql != (tt.i == 0) {			t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)		}		eql = EqualPortable(tt.a, tt.b)		if eql != (tt.i == 0) {			t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)		}	}} func TestEqualExhaustive(t *testing.T) {	var size = 128	if testing.Short() {		size = 32	}	a := make([]byte, size)	b := make([]byte, size)	b_init := make([]byte, size)	// randomish but deterministic data	for i := 0; i < size; i++ {		a[i] = byte(17 * i)		b_init[i] = byte(23*i + 100)	} 	for len := 0; len <= size; len++ {		for x := 0; x <= size-len; x++ {			for y := 0; y <= size-len; y++ {				copy(b, b_init)				copy(b[y:y+len], a[x:x+len])				if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) {					t.Errorf("Equal(%d, %d, %d) = false", len, x, y)				}			}		}	}} // make sure Equal returns false for minimally different strings.  The data// is all zeros except for a single one in one location.func TestNotEqual(t *testing.T) {	var size = 128	if testing.Short() {		size = 32	}	a := make([]byte, size)	b := make([]byte, size) 	for len := 0; len <= size; len++ {		for x := 0; x <= size-len; x++ {			for y := 0; y <= size-len; y++ {				for diffpos := x; diffpos < x+len; diffpos++ {					a[diffpos] = 1					if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) {						t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos)					}					a[diffpos] = 0				}			}		}	}} var indexTests = []BinOpTest{	{"", "", 0},	{"", "a", -1},	{"", "foo", -1},	{"fo", "foo", -1},	{"foo", "baz", -1},	{"foo", "foo", 0},	{"oofofoofooo", "f", 2},	{"oofofoofooo", "foo", 4},	{"barfoobarfoo", "foo", 3},	{"foo", "", 0},	{"foo", "o", 1},	{"abcABCabc", "A", 3},	// cases with one byte strings - test IndexByte and special case in Index()	{"", "a", -1},	{"x", "a", -1},	{"x", "x", 0},	{"abc", "a", 0},	{"abc", "b", 1},	{"abc", "c", 2},	{"abc", "x", -1},	{"barfoobarfooyyyzzzyyyzzzyyyzzzyyyxxxzzzyyy", "x", 33},	{"foofyfoobarfoobar", "y", 4},	{"oooooooooooooooooooooo", "r", -1},} var lastIndexTests = []BinOpTest{	{"", "", 0},	{"", "a", -1},	{"", "foo", -1},	{"fo", "foo", -1},	{"foo", "foo", 0},	{"foo", "f", 0},	{"oofofoofooo", "f", 7},	{"oofofoofooo", "foo", 7},	{"barfoobarfoo", "foo", 9},	{"foo", "", 3},	{"foo", "o", 2},	{"abcABCabc", "A", 3},	{"abcABCabc", "a", 6},} var indexAnyTests = []BinOpTest{	{"", "", -1},	{"", "a", -1},	{"", "abc", -1},	{"a", "", -1},	{"a", "a", 0},	{"aaa", "a", 0},	{"abc", "xyz", -1},	{"abc", "xcz", 2},	{"ab☺c", "x☺yz", 2},	{"aRegExp*", ".(|)*+?^$[]", 7},	{dots + dots + dots, " ", -1},} var lastIndexAnyTests = []BinOpTest{	{"", "", -1},	{"", "a", -1},	{"", "abc", -1},	{"a", "", -1},	{"a", "a", 0},	{"aaa", "a", 2},	{"abc", "xyz", -1},	{"abc", "ab", 1},	{"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},	{"a.RegExp*", ".(|)*+?^$[]", 8},	{dots + dots + dots, " ", -1},} var indexRuneTests = []BinOpTest{	{"", "a", -1},	{"", "☺", -1},	{"foo", "☹", -1},	{"foo", "o", 1},	{"foo☺bar", "☺", 3},	{"foo☺☻☹bar", "☹", 9},} // Execute f on each test case.  funcName should be the name of f; it's used// in failure reports.func runIndexTests(t *testing.T, f func(s, sep []byte) int, funcName string, testCases []BinOpTest) {	for _, test := range testCases {		a := []byte(test.a)		b := []byte(test.b)		actual := f(a, b)		if actual != test.i {			t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, b, actual, test.i)		}	}} func runIndexAnyTests(t *testing.T, f func(s []byte, chars string) int, funcName string, testCases []BinOpTest) {	for _, test := range testCases {		a := []byte(test.a)		actual := f(a, test.b)		if actual != test.i {			t.Errorf("%s(%q,%q) = %v; want %v", funcName, a, test.b, actual, test.i)		}	}} func TestIndex(t *testing.T)     { runIndexTests(t, Index, "Index", indexTests) }func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", lastIndexTests) }func TestIndexAny(t *testing.T)  { runIndexAnyTests(t, IndexAny, "IndexAny", indexAnyTests) }func TestLastIndexAny(t *testing.T) {	runIndexAnyTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests)} func TestIndexByte(t *testing.T) {	for _, tt := range indexTests {		if len(tt.b) != 1 {			continue		}		a := []byte(tt.a)		b := tt.b[0]		pos := IndexByte(a, b)		if pos != tt.i {			t.Errorf(`IndexByte(%q, '%c') = %v`, tt.a, b, pos)		}		posp := IndexBytePortable(a, b)		if posp != tt.i {			t.Errorf(`indexBytePortable(%q, '%c') = %v`, tt.a, b, posp)		}	}} func TestLastIndexByte(t *testing.T) {	testCases := []BinOpTest{		{"", "q", -1},		{"abcdef", "q", -1},		{"abcdefabcdef", "a", len("abcdef")},      // something in the middle		{"abcdefabcdef", "f", len("abcdefabcde")}, // last byte		{"zabcdefabcdef", "z", 0},                 // first byte		{"a☺b☻c☹d", "b", len("a☺")},               // non-ascii	}	for _, test := range testCases {		actual := LastIndexByte([]byte(test.a), test.b[0])		if actual != test.i {			t.Errorf("LastIndexByte(%q,%c) = %v; want %v", test.a, test.b[0], actual, test.i)		}	}} // test a larger buffer with different sizes and alignmentsfunc TestIndexByteBig(t *testing.T) {	var n = 1024	if testing.Short() {		n = 128	}	b := make([]byte, n)	for i := 0; i < n; i++ {		// different start alignments		b1 := b[i:]		for j := 0; j < len(b1); j++ {			b1[j] = 'x'			pos := IndexByte(b1, 'x')			if pos != j {				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)			}			b1[j] = 0			pos = IndexByte(b1, 'x')			if pos != -1 {				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)			}		}		// different end alignments		b1 = b[:i]		for j := 0; j < len(b1); j++ {			b1[j] = 'x'			pos := IndexByte(b1, 'x')			if pos != j {				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)			}			b1[j] = 0			pos = IndexByte(b1, 'x')			if pos != -1 {				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)			}		}		// different start and end alignments		b1 = b[i/2 : n-(i+1)/2]		for j := 0; j < len(b1); j++ {			b1[j] = 'x'			pos := IndexByte(b1, 'x')			if pos != j {				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)			}			b1[j] = 0			pos = IndexByte(b1, 'x')			if pos != -1 {				t.Errorf("IndexByte(%q, 'x') = %v", b1, pos)			}		}	}} func TestIndexRune(t *testing.T) {	for _, tt := range indexRuneTests {		a := []byte(tt.a)		r, _ := utf8.DecodeRuneInString(tt.b)		pos := IndexRune(a, r)		if pos != tt.i {			t.Errorf(`IndexRune(%q, '%c') = %v`, tt.a, r, pos)		}	}} var bmbuf []byte func BenchmarkIndexByte32(b *testing.B)          { bmIndexByte(b, IndexByte, 32) }func BenchmarkIndexByte4K(b *testing.B)          { bmIndexByte(b, IndexByte, 4<<10) }func BenchmarkIndexByte4M(b *testing.B)          { bmIndexByte(b, IndexByte, 4<<20) }func BenchmarkIndexByte64M(b *testing.B)         { bmIndexByte(b, IndexByte, 64<<20) }func BenchmarkIndexBytePortable32(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 32) }func BenchmarkIndexBytePortable4K(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 4<<10) }func BenchmarkIndexBytePortable4M(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 4<<20) }func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) } func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {	if len(bmbuf) < n {		bmbuf = make([]byte, n)	}	b.SetBytes(int64(n))	buf := bmbuf[0:n]	buf[n-1] = 'x'	for i := 0; i < b.N; i++ {		j := index(buf, 'x')		if j != n-1 {			b.Fatal("bad index", j)		}	}	buf[n-1] = '\x00'} func BenchmarkEqual0(b *testing.B) {	var buf [4]byte	buf1 := buf[0:0]	buf2 := buf[1:1]	for i := 0; i < b.N; i++ {		eq := Equal(buf1, buf2)		if !eq {			b.Fatal("bad equal")		}	}} func BenchmarkEqual1(b *testing.B)           { bmEqual(b, Equal, 1) }func BenchmarkEqual6(b *testing.B)           { bmEqual(b, Equal, 6) }func BenchmarkEqual9(b *testing.B)           { bmEqual(b, Equal, 9) }func BenchmarkEqual15(b *testing.B)          { bmEqual(b, Equal, 15) }func BenchmarkEqual16(b *testing.B)          { bmEqual(b, Equal, 16) }func BenchmarkEqual20(b *testing.B)          { bmEqual(b, Equal, 20) }func BenchmarkEqual32(b *testing.B)          { bmEqual(b, Equal, 32) }func BenchmarkEqual4K(b *testing.B)          { bmEqual(b, Equal, 4<<10) }func BenchmarkEqual4M(b *testing.B)          { bmEqual(b, Equal, 4<<20) }func BenchmarkEqual64M(b *testing.B)         { bmEqual(b, Equal, 64<<20) }func BenchmarkEqualPort1(b *testing.B)       { bmEqual(b, EqualPortable, 1) }func BenchmarkEqualPort6(b *testing.B)       { bmEqual(b, EqualPortable, 6) }func BenchmarkEqualPort32(b *testing.B)      { bmEqual(b, EqualPortable, 32) }func BenchmarkEqualPort4K(b *testing.B)      { bmEqual(b, EqualPortable, 4<<10) }func BenchmarkEqualPortable4M(b *testing.B)  { bmEqual(b, EqualPortable, 4<<20) }func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) } func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {	if len(bmbuf) < 2*n {		bmbuf = make([]byte, 2*n)	}	b.SetBytes(int64(n))	buf1 := bmbuf[0:n]	buf2 := bmbuf[n : 2*n]	buf1[n-1] = 'x'	buf2[n-1] = 'x'	for i := 0; i < b.N; i++ {		eq := equal(buf1, buf2)		if !eq {			b.Fatal("bad equal")		}	}	buf1[n-1] = '\x00'	buf2[n-1] = '\x00'} func BenchmarkIndex32(b *testing.B)  { bmIndex(b, Index, 32) }func BenchmarkIndex4K(b *testing.B)  { bmIndex(b, Index, 4<<10) }func BenchmarkIndex4M(b *testing.B)  { bmIndex(b, Index, 4<<20) }func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) } func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {	if len(bmbuf) < n {		bmbuf = make([]byte, n)	}	b.SetBytes(int64(n))	buf := bmbuf[0:n]	buf[n-1] = 'x'	for i := 0; i < b.N; i++ {		j := index(buf, buf[n-7:])		if j != n-7 {			b.Fatal("bad index", j)		}	}	buf[n-1] = '\x00'} func BenchmarkIndexEasy32(b *testing.B)  { bmIndexEasy(b, Index, 32) }func BenchmarkIndexEasy4K(b *testing.B)  { bmIndexEasy(b, Index, 4<<10) }func BenchmarkIndexEasy4M(b *testing.B)  { bmIndexEasy(b, Index, 4<<20) }func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) } func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {	if len(bmbuf) < n {		bmbuf = make([]byte, n)	}	b.SetBytes(int64(n))	buf := bmbuf[0:n]	buf[n-1] = 'x'	buf[n-7] = 'x'	for i := 0; i < b.N; i++ {		j := index(buf, buf[n-7:])		if j != n-7 {			b.Fatal("bad index", j)		}	}	buf[n-1] = '\x00'	buf[n-7] = '\x00'} func BenchmarkCount32(b *testing.B)  { bmCount(b, Count, 32) }func BenchmarkCount4K(b *testing.B)  { bmCount(b, Count, 4<<10) }func BenchmarkCount4M(b *testing.B)  { bmCount(b, Count, 4<<20) }func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) } func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {	if len(bmbuf) < n {		bmbuf = make([]byte, n)	}	b.SetBytes(int64(n))	buf := bmbuf[0:n]	buf[n-1] = 'x'	for i := 0; i < b.N; i++ {		j := count(buf, buf[n-7:])		if j != 1 {			b.Fatal("bad count", j)		}	}	buf[n-1] = '\x00'} func BenchmarkCountEasy32(b *testing.B)  { bmCountEasy(b, Count, 32) }func BenchmarkCountEasy4K(b *testing.B)  { bmCountEasy(b, Count, 4<<10) }func BenchmarkCountEasy4M(b *testing.B)  { bmCountEasy(b, Count, 4<<20) }func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) } func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {	if len(bmbuf) < n {		bmbuf = make([]byte, n)	}	b.SetBytes(int64(n))	buf := bmbuf[0:n]	buf[n-1] = 'x'

Lines 1–500 of 1288.