1// Copyright 2015 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// string_ssa.go tests string operations.
6package main
7
8import "testing"
9
10//go:noinline
11func testStringSlice1_ssa(a string, i, j int) string {
12	return a[i:]
13}
14
15//go:noinline
16func testStringSlice2_ssa(a string, i, j int) string {
17	return a[:j]
18}
19
20//go:noinline
21func testStringSlice12_ssa(a string, i, j int) string {
22	return a[i:j]
23}
24
25func testStringSlice(t *testing.T) {
26	tests := [...]struct {
27		fn        func(string, int, int) string
28		s         string
29		low, high int
30		want      string
31	}{
32		// -1 means the value is not used.
33		{testStringSlice1_ssa, "foobar", 0, -1, "foobar"},
34		{testStringSlice1_ssa, "foobar", 3, -1, "bar"},
35		{testStringSlice1_ssa, "foobar", 6, -1, ""},
36		{testStringSlice2_ssa, "foobar", -1, 0, ""},
37		{testStringSlice2_ssa, "foobar", -1, 3, "foo"},
38		{testStringSlice2_ssa, "foobar", -1, 6, "foobar"},
39		{testStringSlice12_ssa, "foobar", 0, 6, "foobar"},
40		{testStringSlice12_ssa, "foobar", 0, 0, ""},
41		{testStringSlice12_ssa, "foobar", 6, 6, ""},
42		{testStringSlice12_ssa, "foobar", 1, 5, "ooba"},
43		{testStringSlice12_ssa, "foobar", 3, 3, ""},
44		{testStringSlice12_ssa, "", 0, 0, ""},
45	}
46
47	for i, test := range tests {
48		if got := test.fn(test.s, test.low, test.high); test.want != got {
49			t.Errorf("#%d %s[%d,%d] = %s, want %s", i, test.s, test.low, test.high, got, test.want)
50		}
51	}
52}
53
54type prefix struct {
55	prefix string
56}
57
58func (p *prefix) slice_ssa() {
59	p.prefix = p.prefix[:3]
60}
61
62//go:noinline
63func testStructSlice(t *testing.T) {
64	p := &prefix{"prefix"}
65	p.slice_ssa()
66	if "pre" != p.prefix {
67		t.Errorf("wrong field slice: wanted %s got %s", "pre", p.prefix)
68	}
69}
70
71func testStringSlicePanic(t *testing.T) {
72	defer func() {
73		if r := recover(); r != nil {
74			//println("panicked as expected")
75		}
76	}()
77
78	str := "foobar"
79	t.Errorf("got %s and expected to panic, but didn't", testStringSlice12_ssa(str, 3, 9))
80}
81
82const _Accuracy_name = "BelowExactAbove"
83
84var _Accuracy_index = [...]uint8{0, 5, 10, 15}
85
86//go:noinline
87func testSmallIndexType_ssa(i int) string {
88	return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]]
89}
90
91func testSmallIndexType(t *testing.T) {
92	tests := []struct {
93		i    int
94		want string
95	}{
96		{0, "Below"},
97		{1, "Exact"},
98		{2, "Above"},
99	}
100
101	for i, test := range tests {
102		if got := testSmallIndexType_ssa(test.i); got != test.want {
103			t.Errorf("#%d got %s wanted %s", i, got, test.want)
104		}
105	}
106}
107
108//go:noinline
109func testInt64Index_ssa(s string, i int64) byte {
110	return s[i]
111}
112
113//go:noinline
114func testInt64Slice_ssa(s string, i, j int64) string {
115	return s[i:j]
116}
117
118func testInt64Index(t *testing.T) {
119	tests := []struct {
120		i int64
121		j int64
122		b byte
123		s string
124	}{
125		{0, 5, 'B', "Below"},
126		{5, 10, 'E', "Exact"},
127		{10, 15, 'A', "Above"},
128	}
129
130	str := "BelowExactAbove"
131	for i, test := range tests {
132		if got := testInt64Index_ssa(str, test.i); got != test.b {
133			t.Errorf("#%d got %d wanted %d", i, got, test.b)
134		}
135		if got := testInt64Slice_ssa(str, test.i, test.j); got != test.s {
136			t.Errorf("#%d got %s wanted %s", i, got, test.s)
137		}
138	}
139}
140
141func testInt64IndexPanic(t *testing.T) {
142	defer func() {
143		if r := recover(); r != nil {
144			//println("panicked as expected")
145		}
146	}()
147
148	str := "foobar"
149	t.Errorf("got %d and expected to panic, but didn't", testInt64Index_ssa(str, 1<<32+1))
150}
151
152func testInt64SlicePanic(t *testing.T) {
153	defer func() {
154		if r := recover(); r != nil {
155			//println("panicked as expected")
156		}
157	}()
158
159	str := "foobar"
160	t.Errorf("got %s and expected to panic, but didn't", testInt64Slice_ssa(str, 1<<32, 1<<32+1))
161}
162
163//go:noinline
164func testStringElem_ssa(s string, i int) byte {
165	return s[i]
166}
167
168func testStringElem(t *testing.T) {
169	tests := []struct {
170		s string
171		i int
172		n byte
173	}{
174		{"foobar", 3, 98},
175		{"foobar", 0, 102},
176		{"foobar", 5, 114},
177	}
178	for _, test := range tests {
179		if got := testStringElem_ssa(test.s, test.i); got != test.n {
180			t.Errorf("testStringElem \"%s\"[%d] = %d, wanted %d", test.s, test.i, got, test.n)
181		}
182	}
183}
184
185//go:noinline
186func testStringElemConst_ssa(i int) byte {
187	s := "foobar"
188	return s[i]
189}
190
191func testStringElemConst(t *testing.T) {
192	if got := testStringElemConst_ssa(3); got != 98 {
193		t.Errorf("testStringElemConst= %d, wanted 98", got)
194	}
195}
196
197func TestString(t *testing.T) {
198	testStringSlice(t)
199	testStringSlicePanic(t)
200	testStructSlice(t)
201	testSmallIndexType(t)
202	testStringElem(t)
203	testStringElemConst(t)
204	testInt64Index(t)
205	testInt64IndexPanic(t)
206	testInt64SlicePanic(t)
207}
208