summaryrefslogtreecommitdiff
path: root/libgo/go/runtime/string_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/string_test.go')
-rw-r--r--libgo/go/runtime/string_test.go219
1 files changed, 179 insertions, 40 deletions
diff --git a/libgo/go/runtime/string_test.go b/libgo/go/runtime/string_test.go
index 64abd57d28..ee306999e2 100644
--- a/libgo/go/runtime/string_test.go
+++ b/libgo/go/runtime/string_test.go
@@ -5,10 +5,15 @@
package runtime_test
import (
+ "runtime"
"strings"
"testing"
)
+// Strings and slices that don't escape and fit into tmpBuf are stack allocated,
+// which defeats using AllocsPerRun to test other optimizations.
+const sizeNoStack = 100
+
func BenchmarkCompareStringEqual(b *testing.B) {
bytes := []byte("Hello Gophers!")
s1, s2 := string(bytes), string(bytes)
@@ -77,26 +82,59 @@ func BenchmarkCompareStringBig(b *testing.B) {
b.SetBytes(int64(len(s1)))
}
-func BenchmarkRuneIterate(b *testing.B) {
- bytes := make([]byte, 100)
- for i := range bytes {
- bytes[i] = byte('A')
- }
- s := string(bytes)
+func BenchmarkConcatStringAndBytes(b *testing.B) {
+ s1 := []byte("Gophers!")
for i := 0; i < b.N; i++ {
- for range s {
- }
+ _ = "Hello " + string(s1)
}
}
-func BenchmarkRuneIterate2(b *testing.B) {
- bytes := make([]byte, 100)
- for i := range bytes {
- bytes[i] = byte('A')
- }
- s := string(bytes)
+var stringdata = []struct{ name, data string }{
+ {"ASCII", "01234567890"},
+ {"Japanese", "日本語日本語日本語"},
+ {"MixedLength", "$Ѐࠀက퀀𐀀\U00040000\U0010FFFF"},
+}
+
+func BenchmarkRuneIterate(b *testing.B) {
+ b.Run("range", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for range sd.data {
+ }
+ }
+ })
+ }
+ })
+ b.Run("range1", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _ = range sd.data {
+ }
+ }
+ })
+ }
+ })
+ b.Run("range2", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, _ = range sd.data {
+ }
+ }
+ })
+ }
+ })
+}
+
+func BenchmarkArrayEqual(b *testing.B) {
+ a1 := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
+ a2 := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
+ b.ResetTimer()
for i := 0; i < b.N; i++ {
- for range s {
+ if a1 != a2 {
+ b.Fatal("not equal")
}
}
}
@@ -134,23 +172,8 @@ func TestLargeStringConcat(t *testing.T) {
}
}
-/*
-func TestGostringnocopy(t *testing.T) {
- max := *runtime.Maxstring
- b := make([]byte, max+10)
- for i := uintptr(0); i < max+9; i++ {
- b[i] = 'a'
- }
- _ = runtime.Gostringnocopy(&b[0])
- newmax := *runtime.Maxstring
- if newmax != max+9 {
- t.Errorf("want %d, got %d", max+9, newmax)
- }
-}
-*/
-
func TestCompareTempString(t *testing.T) {
- s := "foo"
+ s := strings.Repeat("x", sizeNoStack)
b := []byte(s)
n := testing.AllocsPerRun(1000, func() {
if string(b) != s {
@@ -161,7 +184,8 @@ func TestCompareTempString(t *testing.T) {
t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
}
})
- if n != 0 {
+ // was n != 0, changed for gccgo.
+ if n > 2 {
t.Fatalf("want 0 allocs, got %v", n)
}
}
@@ -207,13 +231,15 @@ func TestIntStringAllocs(t *testing.T) {
t.Fatalf("bad")
}
})
- if n != 0 {
+ // was n != 0, changed for gccgo, which currently does one
+ // allocation for each call to string(unknown).
+ if n > 2 {
t.Fatalf("want 0 allocs, got %v", n)
}
}
func TestRangeStringCast(t *testing.T) {
- s := "abc"
+ s := strings.Repeat("x", sizeNoStack)
n := testing.AllocsPerRun(1000, func() {
for i, c := range []byte(s) {
if c != s[i] {
@@ -221,22 +247,135 @@ func TestRangeStringCast(t *testing.T) {
}
}
})
- if n != 0 {
+ // was n != 0, changed for gccgo.
+ if n > 1 {
t.Fatalf("want 0 allocs, got %v", n)
}
}
+func isZeroed(b []byte) bool {
+ for _, x := range b {
+ if x != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+func isZeroedR(r []rune) bool {
+ for _, x := range r {
+ if x != 0 {
+ return false
+ }
+ }
+ return true
+}
+
func TestString2Slice(t *testing.T) {
// Make sure we don't return slices that expose
// an unzeroed section of stack-allocated temp buf
- // between len and cap. See issue 14232.
+ // between len and cap. See issue 14232.
s := "foož"
b := ([]byte)(s)
- if cap(b) != 5 {
- t.Errorf("want cap of 5, got %d", cap(b))
+ if !isZeroed(b[len(b):cap(b)]) {
+ t.Errorf("extra bytes not zeroed")
}
r := ([]rune)(s)
- if cap(r) != 4 {
- t.Errorf("want cap of 4, got %d", cap(r))
+ if !isZeroedR(r[len(r):cap(r)]) {
+ t.Errorf("extra runes not zeroed")
+ }
+}
+
+const intSize = 32 << (^uint(0) >> 63)
+
+type atoi64Test struct {
+ in string
+ out int64
+ ok bool
+}
+
+var atoi64tests = []atoi64Test{
+ {"", 0, false},
+ {"0", 0, true},
+ {"-0", 0, true},
+ {"1", 1, true},
+ {"-1", -1, true},
+ {"12345", 12345, true},
+ {"-12345", -12345, true},
+ {"012345", 12345, true},
+ {"-012345", -12345, true},
+ {"12345x", 0, false},
+ {"-12345x", 0, false},
+ {"98765432100", 98765432100, true},
+ {"-98765432100", -98765432100, true},
+ {"20496382327982653440", 0, false},
+ {"-20496382327982653440", 0, false},
+ {"9223372036854775807", 1<<63 - 1, true},
+ {"-9223372036854775807", -(1<<63 - 1), true},
+ {"9223372036854775808", 0, false},
+ {"-9223372036854775808", -1 << 63, true},
+ {"9223372036854775809", 0, false},
+ {"-9223372036854775809", 0, false},
+}
+
+func TestAtoi(t *testing.T) {
+ switch intSize {
+ case 32:
+ for i := range atoi32tests {
+ test := &atoi32tests[i]
+ out, ok := runtime.Atoi(test.in)
+ if test.out != int32(out) || test.ok != ok {
+ t.Errorf("atoi(%q) = (%v, %v) want (%v, %v)",
+ test.in, out, ok, test.out, test.ok)
+ }
+ }
+ case 64:
+ for i := range atoi64tests {
+ test := &atoi64tests[i]
+ out, ok := runtime.Atoi(test.in)
+ if test.out != int64(out) || test.ok != ok {
+ t.Errorf("atoi(%q) = (%v, %v) want (%v, %v)",
+ test.in, out, ok, test.out, test.ok)
+ }
+ }
+ }
+}
+
+type atoi32Test struct {
+ in string
+ out int32
+ ok bool
+}
+
+var atoi32tests = []atoi32Test{
+ {"", 0, false},
+ {"0", 0, true},
+ {"-0", 0, true},
+ {"1", 1, true},
+ {"-1", -1, true},
+ {"12345", 12345, true},
+ {"-12345", -12345, true},
+ {"012345", 12345, true},
+ {"-012345", -12345, true},
+ {"12345x", 0, false},
+ {"-12345x", 0, false},
+ {"987654321", 987654321, true},
+ {"-987654321", -987654321, true},
+ {"2147483647", 1<<31 - 1, true},
+ {"-2147483647", -(1<<31 - 1), true},
+ {"2147483648", 0, false},
+ {"-2147483648", -1 << 31, true},
+ {"2147483649", 0, false},
+ {"-2147483649", 0, false},
+}
+
+func TestAtoi32(t *testing.T) {
+ for i := range atoi32tests {
+ test := &atoi32tests[i]
+ out, ok := runtime.Atoi32(test.in)
+ if test.out != out || test.ok != ok {
+ t.Errorf("atoi32(%q) = (%v, %v) want (%v, %v)",
+ test.in, out, ok, test.out, test.ok)
+ }
}
}