summaryrefslogtreecommitdiff
path: root/libgo/go/bytes/bytes_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/bytes/bytes_test.go')
-rw-r--r--libgo/go/bytes/bytes_test.go194
1 files changed, 178 insertions, 16 deletions
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index c48f662e10d..26eac5e08c6 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -7,8 +7,10 @@ package bytes_test
import (
. "bytes"
"fmt"
+ "internal/testenv"
"math/rand"
"reflect"
+ "strings"
"testing"
"unicode"
"unicode/utf8"
@@ -165,8 +167,12 @@ var indexAnyTests = []BinOpTest{
{"abc", "xyz", -1},
{"abc", "xcz", 2},
{"ab☺c", "x☺yz", 2},
+ {"a☺b☻c☹d", "cx", len("a☺b☻")},
+ {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
{"aRegExp*", ".(|)*+?^$[]", 7},
{dots + dots + dots, " ", -1},
+ {"012abcba210", "\xffb", 4},
+ {"012\x80bcb\x80210", "\xffb", 3},
}
var lastIndexAnyTests = []BinOpTest{
@@ -178,18 +184,13 @@ var lastIndexAnyTests = []BinOpTest{
{"aaa", "a", 2},
{"abc", "xyz", -1},
{"abc", "ab", 1},
- {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+ {"ab☺c", "x☺yz", 2},
+ {"a☺b☻c☹d", "cx", len("a☺b☻")},
+ {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
{"a.RegExp*", ".(|)*+?^$[]", 8},
{dots + dots + dots, " ", -1},
-}
-
-var indexRuneTests = []BinOpTest{
- {"", "a", -1},
- {"", "☺", -1},
- {"foo", "☹", -1},
- {"foo", "o", 1},
- {"foo☺bar", "☺", 3},
- {"foo☺☻☹bar", "☹", 9},
+ {"012abcba210", "\xffb", 6},
+ {"012\x80bcb\x80210", "\xffb", 7},
}
// Execute f on each test case. funcName should be the name of f; it's used
@@ -346,13 +347,52 @@ func TestIndexByteSmall(t *testing.T) {
}
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)
+ tests := []struct {
+ in string
+ rune rune
+ want int
+ }{
+ {"", 'a', -1},
+ {"", '☺', -1},
+ {"foo", '☹', -1},
+ {"foo", 'o', 1},
+ {"foo☺bar", '☺', 3},
+ {"foo☺☻☹bar", '☹', 9},
+ {"a A x", 'A', 2},
+ {"some_text=some_value", '=', 9},
+ {"☺a", 'a', 3},
+ {"a☻☺b", '☺', 4},
+
+ // RuneError should match any invalid UTF-8 byte sequence.
+ {"�", '�', 0},
+ {"\xff", '�', 0},
+ {"☻x�", '�', len("☻x")},
+ {"☻x\xe2\x98", '�', len("☻x")},
+ {"☻x\xe2\x98�", '�', len("☻x")},
+ {"☻x\xe2\x98x", '�', len("☻x")},
+
+ // Invalid rune values should never match.
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", -1, -1},
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", utf8.MaxRune + 1, -1},
+ }
+ for _, tt := range tests {
+ if got := IndexRune([]byte(tt.in), tt.rune); got != tt.want {
+ t.Errorf("IndexRune(%q, %d) = %v; want %v", tt.in, tt.rune, got, tt.want)
+ }
+ }
+
+ haystack := []byte("test世界")
+ allocs := testing.AllocsPerRun(1000, func() {
+ if i := IndexRune(haystack, 's'); i != 2 {
+ t.Fatalf("'s' at %d; want 2", i)
+ }
+ if i := IndexRune(haystack, '世'); i != 4 {
+ t.Fatalf("'世' at %d; want 4", i)
}
+ })
+ if allocs != 0 {
+ t.Errorf("expected no allocations, got %f", allocs)
}
}
@@ -370,6 +410,9 @@ func valName(x int) string {
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
for _, n := range sizes {
+ if isRaceBuilder && n > 4<<10 {
+ continue
+ }
b.Run(valName(n), func(b *testing.B) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
@@ -382,6 +425,8 @@ func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
+var isRaceBuilder = strings.HasSuffix(testenv.Builder(), "-race")
+
func BenchmarkIndexByte(b *testing.B) {
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
}
@@ -404,6 +449,44 @@ func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
}
}
+func BenchmarkIndexRune(b *testing.B) {
+ benchBytes(b, indexSizes, bmIndexRune(IndexRune))
+}
+
+func BenchmarkIndexRuneASCII(b *testing.B) {
+ benchBytes(b, indexSizes, bmIndexRuneASCII(IndexRune))
+}
+
+func bmIndexRuneASCII(index func([]byte, rune) int) func(b *testing.B, n int) {
+ return func(b *testing.B, n int) {
+ 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 bmIndexRune(index func([]byte, rune) int) func(b *testing.B, n int) {
+ return func(b *testing.B, n int) {
+ buf := bmbuf[0:n]
+ utf8.EncodeRune(buf[n-3:], '世')
+ for i := 0; i < b.N; i++ {
+ j := index(buf, '世')
+ if j != n-3 {
+ b.Fatal("bad index", j)
+ }
+ }
+ buf[n-3] = '\x00'
+ buf[n-2] = '\x00'
+ buf[n-1] = '\x00'
+ }
+}
+
func BenchmarkEqual(b *testing.B) {
b.Run("0", func(b *testing.B) {
var buf [4]byte
@@ -844,6 +927,54 @@ func TestRepeat(t *testing.T) {
}
}
+func repeat(b []byte, count int) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch v := r.(type) {
+ case error:
+ err = v
+ default:
+ err = fmt.Errorf("%s", v)
+ }
+ }
+ }()
+
+ Repeat(b, count)
+
+ return
+}
+
+// See Issue golang.org/issue/16237
+func TestRepeatCatchesOverflow(t *testing.T) {
+ tests := [...]struct {
+ s string
+ count int
+ errStr string
+ }{
+ 0: {"--", -2147483647, "negative"},
+ 1: {"", int(^uint(0) >> 1), ""},
+ 2: {"-", 10, ""},
+ 3: {"gopher", 0, ""},
+ 4: {"-", -1, "negative"},
+ 5: {"--", -102, "negative"},
+ 6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
+ }
+
+ for i, tt := range tests {
+ err := repeat([]byte(tt.s), tt.count)
+ if tt.errStr == "" {
+ if err != nil {
+ t.Errorf("#%d panicked %v", i, err)
+ }
+ continue
+ }
+
+ if err == nil || !strings.Contains(err.Error(), tt.errStr) {
+ t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
+ }
+ }
+}
+
func runesEqual(a, b []rune) bool {
if len(a) != len(b) {
return false
@@ -906,6 +1037,9 @@ var trimTests = []TrimTest{
{"Trim", "* listitem", " *", "listitem"},
{"Trim", `"quote"`, `"`, "quote"},
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+ {"Trim", "\x80test\xff", "\xff", "test"},
+ {"Trim", " Ġ ", " ", "Ġ"},
+ {"Trim", " Ġİ0", "0 ", "Ġİ"},
//empty string tests
{"Trim", "abba", "", "abba"},
{"Trim", "", "123", ""},
@@ -1325,3 +1459,31 @@ func BenchmarkBytesCompare(b *testing.B) {
})
}
}
+
+func BenchmarkIndexAnyASCII(b *testing.B) {
+ x := Repeat([]byte{'#'}, 4096) // Never matches set
+ cs := "0123456789abcdef"
+ for k := 1; k <= 4096; k <<= 4 {
+ for j := 1; j <= 16; j <<= 1 {
+ b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ IndexAny(x[:k], cs[:j])
+ }
+ })
+ }
+ }
+}
+
+func BenchmarkTrimASCII(b *testing.B) {
+ cs := "0123456789abcdef"
+ for k := 1; k <= 4096; k <<= 4 {
+ for j := 1; j <= 16; j <<= 1 {
+ b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
+ x := Repeat([]byte(cs[:j]), k) // Always matches set
+ for i := 0; i < b.N; i++ {
+ Trim(x[:k], cs[:j])
+ }
+ })
+ }
+ }
+}