runtime: scan register backing store on ia64
[official-gcc.git] / libgo / go / runtime / string_test.go
blob555a7fc7ef94df8c51e125cc7077a5ea55b63b3c
1 // Copyright 2012 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.
5 package runtime_test
7 import (
8 "runtime"
9 "strconv"
10 "strings"
11 "testing"
14 // Strings and slices that don't escape and fit into tmpBuf are stack allocated,
15 // which defeats using AllocsPerRun to test other optimizations.
16 const sizeNoStack = 100
18 func BenchmarkCompareStringEqual(b *testing.B) {
19 bytes := []byte("Hello Gophers!")
20 s1, s2 := string(bytes), string(bytes)
21 for i := 0; i < b.N; i++ {
22 if s1 != s2 {
23 b.Fatal("s1 != s2")
28 func BenchmarkCompareStringIdentical(b *testing.B) {
29 s1 := "Hello Gophers!"
30 s2 := s1
31 for i := 0; i < b.N; i++ {
32 if s1 != s2 {
33 b.Fatal("s1 != s2")
38 func BenchmarkCompareStringSameLength(b *testing.B) {
39 s1 := "Hello Gophers!"
40 s2 := "Hello, Gophers"
41 for i := 0; i < b.N; i++ {
42 if s1 == s2 {
43 b.Fatal("s1 == s2")
48 func BenchmarkCompareStringDifferentLength(b *testing.B) {
49 s1 := "Hello Gophers!"
50 s2 := "Hello, Gophers!"
51 for i := 0; i < b.N; i++ {
52 if s1 == s2 {
53 b.Fatal("s1 == s2")
58 func BenchmarkCompareStringBigUnaligned(b *testing.B) {
59 bytes := make([]byte, 0, 1<<20)
60 for len(bytes) < 1<<20 {
61 bytes = append(bytes, "Hello Gophers!"...)
63 s1, s2 := string(bytes), "hello"+string(bytes)
64 for i := 0; i < b.N; i++ {
65 if s1 != s2[len("hello"):] {
66 b.Fatal("s1 != s2")
69 b.SetBytes(int64(len(s1)))
72 func BenchmarkCompareStringBig(b *testing.B) {
73 bytes := make([]byte, 0, 1<<20)
74 for len(bytes) < 1<<20 {
75 bytes = append(bytes, "Hello Gophers!"...)
77 s1, s2 := string(bytes), string(bytes)
78 for i := 0; i < b.N; i++ {
79 if s1 != s2 {
80 b.Fatal("s1 != s2")
83 b.SetBytes(int64(len(s1)))
86 func BenchmarkConcatStringAndBytes(b *testing.B) {
87 s1 := []byte("Gophers!")
88 for i := 0; i < b.N; i++ {
89 _ = "Hello " + string(s1)
93 var escapeString string
95 func BenchmarkSliceByteToString(b *testing.B) {
96 buf := []byte{'!'}
97 for n := 0; n < 8; n++ {
98 b.Run(strconv.Itoa(len(buf)), func(b *testing.B) {
99 for i := 0; i < b.N; i++ {
100 escapeString = string(buf)
103 buf = append(buf, buf...)
107 var stringdata = []struct{ name, data string }{
108 {"ASCII", "01234567890"},
109 {"Japanese", "日本語日本語日本語"},
110 {"MixedLength", "$Ѐࠀက퀀𐀀\U00040000\U0010FFFF"},
113 func BenchmarkRuneIterate(b *testing.B) {
114 b.Run("range", func(b *testing.B) {
115 for _, sd := range stringdata {
116 b.Run(sd.name, func(b *testing.B) {
117 for i := 0; i < b.N; i++ {
118 for range sd.data {
124 b.Run("range1", func(b *testing.B) {
125 for _, sd := range stringdata {
126 b.Run(sd.name, func(b *testing.B) {
127 for i := 0; i < b.N; i++ {
128 for _ = range sd.data {
134 b.Run("range2", func(b *testing.B) {
135 for _, sd := range stringdata {
136 b.Run(sd.name, func(b *testing.B) {
137 for i := 0; i < b.N; i++ {
138 for _, _ = range sd.data {
146 func BenchmarkArrayEqual(b *testing.B) {
147 a1 := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
148 a2 := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
149 b.ResetTimer()
150 for i := 0; i < b.N; i++ {
151 if a1 != a2 {
152 b.Fatal("not equal")
158 func TestStringW(t *testing.T) {
159 strings := []string{
160 "hello",
161 "a\u5566\u7788b",
164 for _, s := range strings {
165 var b []uint16
166 for _, c := range s {
167 b = append(b, uint16(c))
168 if c != rune(uint16(c)) {
169 t.Errorf("bad test: stringW can't handle >16 bit runes")
172 b = append(b, 0)
173 r := runtime.GostringW(b)
174 if r != s {
175 t.Errorf("gostringW(%v) = %s, want %s", b, r, s)
181 func TestLargeStringConcat(t *testing.T) {
182 output := runTestProg(t, "testprog", "stringconcat")
183 want := "panic: " + strings.Repeat("0", 1<<10) + strings.Repeat("1", 1<<10) +
184 strings.Repeat("2", 1<<10) + strings.Repeat("3", 1<<10)
185 if !strings.HasPrefix(output, want) {
186 t.Fatalf("output does not start with %q:\n%s", want, output)
190 func TestCompareTempString(t *testing.T) {
191 s := strings.Repeat("x", sizeNoStack)
192 b := []byte(s)
193 n := testing.AllocsPerRun(1000, func() {
194 if string(b) != s {
195 t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
197 if string(b) == s {
198 } else {
199 t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
202 // was n != 0, changed for gccgo.
203 if n > 2 {
204 t.Fatalf("want 0 allocs, got %v", n)
208 func TestStringOnStack(t *testing.T) {
209 s := ""
210 for i := 0; i < 3; i++ {
211 s = "a" + s + "b" + s + "c"
214 if want := "aaabcbabccbaabcbabccc"; s != want {
215 t.Fatalf("want: '%v', got '%v'", want, s)
219 func TestIntString(t *testing.T) {
220 // Non-escaping result of intstring.
221 s := ""
222 for i := 0; i < 4; i++ {
223 s += string(i+'0') + string(i+'0'+1)
225 if want := "01122334"; s != want {
226 t.Fatalf("want '%v', got '%v'", want, s)
229 // Escaping result of intstring.
230 var a [4]string
231 for i := 0; i < 4; i++ {
232 a[i] = string(i + '0')
234 s = a[0] + a[1] + a[2] + a[3]
235 if want := "0123"; s != want {
236 t.Fatalf("want '%v', got '%v'", want, s)
240 func TestIntStringAllocs(t *testing.T) {
241 unknown := '0'
242 n := testing.AllocsPerRun(1000, func() {
243 s1 := string(unknown)
244 s2 := string(unknown + 1)
245 if s1 == s2 {
246 t.Fatalf("bad")
249 // was n != 0, changed for gccgo, which currently does one
250 // allocation for each call to string(unknown).
251 if n > 2 {
252 t.Fatalf("want 0 allocs, got %v", n)
256 func TestRangeStringCast(t *testing.T) {
257 s := strings.Repeat("x", sizeNoStack)
258 n := testing.AllocsPerRun(1000, func() {
259 for i, c := range []byte(s) {
260 if c != s[i] {
261 t.Fatalf("want '%c' at pos %v, got '%c'", s[i], i, c)
265 // was n != 0, changed for gccgo.
266 if n > 1 {
267 t.Fatalf("want 0 allocs, got %v", n)
271 func isZeroed(b []byte) bool {
272 for _, x := range b {
273 if x != 0 {
274 return false
277 return true
280 func isZeroedR(r []rune) bool {
281 for _, x := range r {
282 if x != 0 {
283 return false
286 return true
289 func TestString2Slice(t *testing.T) {
290 // Make sure we don't return slices that expose
291 // an unzeroed section of stack-allocated temp buf
292 // between len and cap. See issue 14232.
293 s := "foož"
294 b := ([]byte)(s)
295 if !isZeroed(b[len(b):cap(b)]) {
296 t.Errorf("extra bytes not zeroed")
298 r := ([]rune)(s)
299 if !isZeroedR(r[len(r):cap(r)]) {
300 t.Errorf("extra runes not zeroed")
304 const intSize = 32 << (^uint(0) >> 63)
306 type atoi64Test struct {
307 in string
308 out int64
309 ok bool
312 var atoi64tests = []atoi64Test{
313 {"", 0, false},
314 {"0", 0, true},
315 {"-0", 0, true},
316 {"1", 1, true},
317 {"-1", -1, true},
318 {"12345", 12345, true},
319 {"-12345", -12345, true},
320 {"012345", 12345, true},
321 {"-012345", -12345, true},
322 {"12345x", 0, false},
323 {"-12345x", 0, false},
324 {"98765432100", 98765432100, true},
325 {"-98765432100", -98765432100, true},
326 {"20496382327982653440", 0, false},
327 {"-20496382327982653440", 0, false},
328 {"9223372036854775807", 1<<63 - 1, true},
329 {"-9223372036854775807", -(1<<63 - 1), true},
330 {"9223372036854775808", 0, false},
331 {"-9223372036854775808", -1 << 63, true},
332 {"9223372036854775809", 0, false},
333 {"-9223372036854775809", 0, false},
336 func TestAtoi(t *testing.T) {
337 switch intSize {
338 case 32:
339 for i := range atoi32tests {
340 test := &atoi32tests[i]
341 out, ok := runtime.Atoi(test.in)
342 if test.out != int32(out) || test.ok != ok {
343 t.Errorf("atoi(%q) = (%v, %v) want (%v, %v)",
344 test.in, out, ok, test.out, test.ok)
347 case 64:
348 for i := range atoi64tests {
349 test := &atoi64tests[i]
350 out, ok := runtime.Atoi(test.in)
351 if test.out != int64(out) || test.ok != ok {
352 t.Errorf("atoi(%q) = (%v, %v) want (%v, %v)",
353 test.in, out, ok, test.out, test.ok)
359 type atoi32Test struct {
360 in string
361 out int32
362 ok bool
365 var atoi32tests = []atoi32Test{
366 {"", 0, false},
367 {"0", 0, true},
368 {"-0", 0, true},
369 {"1", 1, true},
370 {"-1", -1, true},
371 {"12345", 12345, true},
372 {"-12345", -12345, true},
373 {"012345", 12345, true},
374 {"-012345", -12345, true},
375 {"12345x", 0, false},
376 {"-12345x", 0, false},
377 {"987654321", 987654321, true},
378 {"-987654321", -987654321, true},
379 {"2147483647", 1<<31 - 1, true},
380 {"-2147483647", -(1<<31 - 1), true},
381 {"2147483648", 0, false},
382 {"-2147483648", -1 << 31, true},
383 {"2147483649", 0, false},
384 {"-2147483649", 0, false},
387 func TestAtoi32(t *testing.T) {
388 for i := range atoi32tests {
389 test := &atoi32tests[i]
390 out, ok := runtime.Atoi32(test.in)
391 if test.out != out || test.ok != ok {
392 t.Errorf("atoi32(%q) = (%v, %v) want (%v, %v)",
393 test.in, out, ok, test.out, test.ok)