Home | History | Annotate | Download | only in runtime
      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.
      4 
      5 package runtime_test
      6 
      7 import (
      8 	"runtime"
      9 	"strings"
     10 	"testing"
     11 )
     12 
     13 func BenchmarkCompareStringEqual(b *testing.B) {
     14 	bytes := []byte("Hello Gophers!")
     15 	s1, s2 := string(bytes), string(bytes)
     16 	for i := 0; i < b.N; i++ {
     17 		if s1 != s2 {
     18 			b.Fatal("s1 != s2")
     19 		}
     20 	}
     21 }
     22 
     23 func BenchmarkCompareStringIdentical(b *testing.B) {
     24 	s1 := "Hello Gophers!"
     25 	s2 := s1
     26 	for i := 0; i < b.N; i++ {
     27 		if s1 != s2 {
     28 			b.Fatal("s1 != s2")
     29 		}
     30 	}
     31 }
     32 
     33 func BenchmarkCompareStringSameLength(b *testing.B) {
     34 	s1 := "Hello Gophers!"
     35 	s2 := "Hello, Gophers"
     36 	for i := 0; i < b.N; i++ {
     37 		if s1 == s2 {
     38 			b.Fatal("s1 == s2")
     39 		}
     40 	}
     41 }
     42 
     43 func BenchmarkCompareStringDifferentLength(b *testing.B) {
     44 	s1 := "Hello Gophers!"
     45 	s2 := "Hello, Gophers!"
     46 	for i := 0; i < b.N; i++ {
     47 		if s1 == s2 {
     48 			b.Fatal("s1 == s2")
     49 		}
     50 	}
     51 }
     52 
     53 func BenchmarkCompareStringBigUnaligned(b *testing.B) {
     54 	bytes := make([]byte, 0, 1<<20)
     55 	for len(bytes) < 1<<20 {
     56 		bytes = append(bytes, "Hello Gophers!"...)
     57 	}
     58 	s1, s2 := string(bytes), "hello"+string(bytes)
     59 	for i := 0; i < b.N; i++ {
     60 		if s1 != s2[len("hello"):] {
     61 			b.Fatal("s1 != s2")
     62 		}
     63 	}
     64 	b.SetBytes(int64(len(s1)))
     65 }
     66 
     67 func BenchmarkCompareStringBig(b *testing.B) {
     68 	bytes := make([]byte, 0, 1<<20)
     69 	for len(bytes) < 1<<20 {
     70 		bytes = append(bytes, "Hello Gophers!"...)
     71 	}
     72 	s1, s2 := string(bytes), string(bytes)
     73 	for i := 0; i < b.N; i++ {
     74 		if s1 != s2 {
     75 			b.Fatal("s1 != s2")
     76 		}
     77 	}
     78 	b.SetBytes(int64(len(s1)))
     79 }
     80 
     81 func BenchmarkRuneIterate(b *testing.B) {
     82 	bytes := make([]byte, 100)
     83 	for i := range bytes {
     84 		bytes[i] = byte('A')
     85 	}
     86 	s := string(bytes)
     87 	for i := 0; i < b.N; i++ {
     88 		for range s {
     89 		}
     90 	}
     91 }
     92 
     93 func BenchmarkRuneIterate2(b *testing.B) {
     94 	bytes := make([]byte, 100)
     95 	for i := range bytes {
     96 		bytes[i] = byte('A')
     97 	}
     98 	s := string(bytes)
     99 	for i := 0; i < b.N; i++ {
    100 		for range s {
    101 		}
    102 	}
    103 }
    104 
    105 func TestStringW(t *testing.T) {
    106 	strings := []string{
    107 		"hello",
    108 		"a\u5566\u7788b",
    109 	}
    110 
    111 	for _, s := range strings {
    112 		var b []uint16
    113 		for _, c := range s {
    114 			b = append(b, uint16(c))
    115 			if c != rune(uint16(c)) {
    116 				t.Errorf("bad test: stringW can't handle >16 bit runes")
    117 			}
    118 		}
    119 		b = append(b, 0)
    120 		r := runtime.GostringW(b)
    121 		if r != s {
    122 			t.Errorf("gostringW(%v) = %s, want %s", b, r, s)
    123 		}
    124 	}
    125 }
    126 
    127 func TestLargeStringConcat(t *testing.T) {
    128 	output := executeTest(t, largeStringConcatSource, nil)
    129 	want := "panic: " + strings.Repeat("0", 1<<10) + strings.Repeat("1", 1<<10) +
    130 		strings.Repeat("2", 1<<10) + strings.Repeat("3", 1<<10)
    131 	if !strings.HasPrefix(output, want) {
    132 		t.Fatalf("output does not start with %q:\n%s", want, output)
    133 	}
    134 }
    135 
    136 var largeStringConcatSource = `
    137 package main
    138 import "strings"
    139 func main() {
    140 	s0 := strings.Repeat("0", 1<<10)
    141 	s1 := strings.Repeat("1", 1<<10)
    142 	s2 := strings.Repeat("2", 1<<10)
    143 	s3 := strings.Repeat("3", 1<<10)
    144 	s := s0 + s1 + s2 + s3
    145 	panic(s)
    146 }
    147 `
    148 
    149 func TestGostringnocopy(t *testing.T) {
    150 	max := *runtime.Maxstring
    151 	b := make([]byte, max+10)
    152 	for i := uintptr(0); i < max+9; i++ {
    153 		b[i] = 'a'
    154 	}
    155 	_ = runtime.Gostringnocopy(&b[0])
    156 	newmax := *runtime.Maxstring
    157 	if newmax != max+9 {
    158 		t.Errorf("want %d, got %d", max+9, newmax)
    159 	}
    160 }
    161 
    162 func TestCompareTempString(t *testing.T) {
    163 	s := "foo"
    164 	b := []byte(s)
    165 	n := testing.AllocsPerRun(1000, func() {
    166 		if string(b) != s {
    167 			t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
    168 		}
    169 		if string(b) == s {
    170 		} else {
    171 			t.Fatalf("strings are not equal: '%v' and '%v'", string(b), s)
    172 		}
    173 	})
    174 	if n != 0 {
    175 		t.Fatalf("want 0 allocs, got %v", n)
    176 	}
    177 }
    178 
    179 func TestStringOnStack(t *testing.T) {
    180 	s := ""
    181 	for i := 0; i < 3; i++ {
    182 		s = "a" + s + "b" + s + "c"
    183 	}
    184 
    185 	if want := "aaabcbabccbaabcbabccc"; s != want {
    186 		t.Fatalf("want: '%v', got '%v'", want, s)
    187 	}
    188 }
    189 
    190 func TestIntString(t *testing.T) {
    191 	// Non-escaping result of intstring.
    192 	s := ""
    193 	for i := 0; i < 4; i++ {
    194 		s += string(i+'0') + string(i+'0'+1)
    195 	}
    196 	if want := "01122334"; s != want {
    197 		t.Fatalf("want '%v', got '%v'", want, s)
    198 	}
    199 
    200 	// Escaping result of intstring.
    201 	var a [4]string
    202 	for i := 0; i < 4; i++ {
    203 		a[i] = string(i + '0')
    204 	}
    205 	s = a[0] + a[1] + a[2] + a[3]
    206 	if want := "0123"; s != want {
    207 		t.Fatalf("want '%v', got '%v'", want, s)
    208 	}
    209 }
    210 
    211 func TestIntStringAllocs(t *testing.T) {
    212 	unknown := '0'
    213 	n := testing.AllocsPerRun(1000, func() {
    214 		s1 := string(unknown)
    215 		s2 := string(unknown + 1)
    216 		if s1 == s2 {
    217 			t.Fatalf("bad")
    218 		}
    219 	})
    220 	if n != 0 {
    221 		t.Fatalf("want 0 allocs, got %v", n)
    222 	}
    223 }
    224 
    225 func TestRangeStringCast(t *testing.T) {
    226 	s := "abc"
    227 	n := testing.AllocsPerRun(1000, func() {
    228 		for i, c := range []byte(s) {
    229 			if c != s[i] {
    230 				t.Fatalf("want '%c' at pos %v, got '%c'", s[i], i, c)
    231 			}
    232 		}
    233 	})
    234 	if n != 0 {
    235 		t.Fatalf("want 0 allocs, got %v", n)
    236 	}
    237 }
    238