github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/runtime/string_test.go (about)

     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  }