Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package strings_test | 5 package strings_test |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "log" | |
11 . "strings" | 10 . "strings" |
12 "testing" | 11 "testing" |
13 ) | 12 ) |
14 | 13 |
15 var _ = log.Printf | 14 var htmlEscaper = NewReplacer( |
16 | 15 » "&", "&", |
17 type ReplacerTest struct { | 16 » "<", "<", |
18 » r *Replacer | 17 » ">", ">", |
19 » in string | 18 » `"`, """, |
20 » out string | 19 » "'", "'", |
21 } | 20 ) |
22 | 21 |
23 var htmlEscaper = NewReplacer("&", "&", "<", "<", ">", ">", "\"", "&qu ot;", "'", "'") | 22 var htmlUnescaper = NewReplacer( |
24 var htmlUnescaper = NewReplacer("&", "&", "<", "<", ">", ">", """ , `"`, "'", "'") | 23 » "&", "&", |
24 » "<", "<", | |
25 » ">", ">", | |
26 » """, `"`, | |
27 » "'", "'", | |
28 ) | |
25 | 29 |
26 // The http package's old HTML escaping function. | 30 // The http package's old HTML escaping function. |
27 func oldhtmlEscape(s string) string { | 31 func oldHTMLEscape(s string) string { |
28 s = Replace(s, "&", "&", -1) | 32 s = Replace(s, "&", "&", -1) |
29 s = Replace(s, "<", "<", -1) | 33 s = Replace(s, "<", "<", -1) |
30 s = Replace(s, ">", ">", -1) | 34 s = Replace(s, ">", ">", -1) |
31 » s = Replace(s, "\"", """, -1) | 35 » s = Replace(s, `"`, """, -1) |
32 s = Replace(s, "'", "'", -1) | 36 s = Replace(s, "'", "'", -1) |
33 return s | 37 return s |
34 } | 38 } |
35 | 39 |
36 var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i" , | |
37 "longerst", "most long", "longer", "medium", "long", "short", | |
38 "X", "Y", "Y", "Z") | |
39 | |
40 var capitalLetters = NewReplacer("a", "A", "b", "B") | 40 var capitalLetters = NewReplacer("a", "A", "b", "B") |
41 | 41 |
42 var blankToXReplacer = NewReplacer("", "X", "o", "O") | 42 // TestReplacer tests the replacer implementations. |
43 | |
44 var ReplacerTests = []ReplacerTest{ | |
45 » // byte->string | |
46 » {htmlEscaper, "No changes", "No changes"}, | |
47 » {htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"}, | |
48 » {htmlEscaper, "&&&", "&&&"}, | |
49 | |
50 » // generic | |
51 » {replacer, "fooaaabar", "foo3[aaa]b1[a]r"}, | |
52 » {replacer, "long, longerst, longer", "short, most long, medium"}, | |
53 » {replacer, "XiX", "YiY"}, | |
54 | |
55 » // byte->byte | |
56 » {capitalLetters, "brad", "BrAd"}, | |
57 » {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)}, | |
58 | |
59 » // hitting "" special case | |
60 » {blankToXReplacer, "oo", "XOXOX"}, | |
61 } | |
62 | |
63 func TestReplacer(t *testing.T) { | 43 func TestReplacer(t *testing.T) { |
64 » for i, tt := range ReplacerTests { | 44 » type testCase struct { |
65 » » if s := tt.r.Replace(tt.in); s != tt.out { | 45 » » r *Replacer |
66 » » » t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, t t.out) | 46 » » in, out string |
47 » } | |
48 » var testCases []testCase | |
49 | |
50 » // str converts 0xff to "\xff". This isn't just string(b) since that con verts to UTF-8. | |
51 » str := func(b byte) string { | |
52 » » return string([]byte{b}) | |
53 » } | |
54 » var s []string | |
55 | |
56 » // inc maps "\x00"->"\x01", ..., "a"->"b", "b"->"c", ..., "\xff"->"\x00" . | |
57 » s = nil | |
58 » for i := 0; i < 256; i++ { | |
59 » » s = append(s, str(byte(i)), str(byte(i+1))) | |
60 » } | |
61 » inc := NewReplacer(s...) | |
62 | |
63 » // Test cases with 1-byte old strings, 1-byte new strings. | |
64 » testCases = append(testCases, | |
65 » » testCase{capitalLetters, "brad", "BrAd"}, | |
66 » » testCase{capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)}, | |
67 » » testCase{capitalLetters, "", ""}, | |
68 | |
69 » » testCase{inc, "brad", "csbe"}, | |
70 » » testCase{inc, "\x00\xff", "\x01\x00"}, | |
71 » » testCase{inc, "", ""}, | |
72 | |
73 » » testCase{NewReplacer("a", "1", "a", "2"), "brad", "br1d"}, | |
74 » ) | |
75 | |
76 » // repeat maps "a"->"a", "b"->"bb", "c"->"ccc", ... | |
77 » s = nil | |
78 » for i := 0; i < 256; i++ { | |
79 » » n := i + 1 - 'a' | |
80 » » if n < 1 { | |
81 » » » n = 1 | |
82 » » } | |
83 » » s = append(s, str(byte(i)), Repeat(str(byte(i)), n)) | |
84 » } | |
85 » repeat := NewReplacer(s...) | |
86 | |
87 » // Test cases with 1-byte old strings, variable length new strings. | |
88 » testCases = append(testCases, | |
89 » » testCase{htmlEscaper, "No changes", "No changes"}, | |
90 » » testCase{htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"}, | |
91 » » testCase{htmlEscaper, "&&&", "&&&"}, | |
92 » » testCase{htmlEscaper, "", ""}, | |
93 | |
94 » » testCase{repeat, "brad", "bbrrrrrrrrrrrrrrrrrradddd"}, | |
95 » » testCase{repeat, "abba", "abbbba"}, | |
96 » » testCase{repeat, "", ""}, | |
97 | |
98 » » testCase{NewReplacer("a", "11", "a", "22"), "brad", "br11d"}, | |
99 » ) | |
100 | |
101 » // The remaining test cases have variable length old strings. | |
102 | |
103 » testCases = append(testCases, | |
104 » » testCase{htmlUnescaper, "&amp;", "&"}, | |
105 » » testCase{htmlUnescaper, "<b>HTML's neat</b>", " <b>HTML's neat</b>"}, | |
106 » » testCase{htmlUnescaper, "", ""}, | |
107 | |
108 » » testCase{NewReplacer("a", "1", "a", "2", "xxx", "xxx"), "brad", "br1d"}, | |
109 | |
110 » » testCase{NewReplacer("a", "1", "aa", "2", "aaa", "3"), "aaaa", " 1111"}, | |
111 | |
112 » » testCase{NewReplacer("aaa", "3", "aa", "2", "a", "1"), "aaaa", " 31"}, | |
113 » ) | |
114 | |
115 » // gen1 has multiple old strings of variable length. There is no | |
116 » // overall non-empty common prefix, but some pairwise common prefixes. | |
117 » gen1 := NewReplacer( | |
118 » » "aaa", "3[aaa]", | |
119 » » "aa", "2[aa]", | |
120 » » "a", "1[a]", | |
121 » » "i", "i", | |
122 » » "longerst", "most long", | |
123 » » "longer", "medium", | |
124 » » "long", "short", | |
125 » » "xx", "xx", | |
126 » » "x", "X", | |
127 » » "X", "Y", | |
128 » » "Y", "Z", | |
129 » ) | |
130 » testCases = append(testCases, | |
131 » » testCase{gen1, "fooaaabar", "foo3[aaa]b1[a]r"}, | |
132 » » testCase{gen1, "long, longerst, longer", "short, most long, medi um"}, | |
133 » » testCase{gen1, "xxxxx", "xxxxX"}, | |
134 » » testCase{gen1, "XiX", "YiY"}, | |
135 » » testCase{gen1, "", ""}, | |
136 » ) | |
137 | |
138 » // gen2 has multiple old strings with no pairwise common prefix. | |
139 » gen2 := NewReplacer( | |
140 » » "roses", "red", | |
141 » » "violets", "blue", | |
142 » » "sugar", "sweet", | |
143 » ) | |
144 » testCases = append(testCases, | |
145 » » testCase{gen2, "roses are red, violets are blue...", "red are re d, blue are blue..."}, | |
146 » » testCase{gen2, "", ""}, | |
147 » ) | |
148 | |
149 » // gen3 has multiple old strings with an overall common prefix. | |
150 » gen3 := NewReplacer( | |
151 » » "abracadabra", "poof", | |
152 » » "abracadabrakazam", "splat", | |
153 » » "abraham", "lincoln", | |
154 » » "abrasion", "scrape", | |
155 » » "abraham", "isaac", | |
156 » ) | |
157 » testCases = append(testCases, | |
158 » » testCase{gen3, "abracadabrakazam abraham", "poofkazam lincoln"}, | |
159 » » testCase{gen3, "abrasion abracad", "scrape abracad"}, | |
160 » » testCase{gen3, "abba abram abrasive", "abba abram abrasive"}, | |
161 » » testCase{gen3, "", ""}, | |
162 » ) | |
163 | |
164 » // foo{1,2,3,4} have multiple old strings with an overall common prefix | |
165 » // and 1- or 2- byte extensions from the common prefix. | |
166 » foo1 := NewReplacer( | |
167 » » "foo1", "A", | |
168 » » "foo2", "B", | |
169 » » "foo3", "C", | |
170 » ) | |
171 » foo2 := NewReplacer( | |
172 » » "foo1", "A", | |
173 » » "foo2", "B", | |
174 » » "foo31", "C", | |
175 » » "foo32", "D", | |
176 » ) | |
177 » foo3 := NewReplacer( | |
178 » » "foo11", "A", | |
179 » » "foo12", "B", | |
180 » » "foo31", "C", | |
181 » » "foo32", "D", | |
182 » ) | |
183 » foo4 := NewReplacer( | |
184 » » "foo12", "B", | |
185 » » "foo32", "D", | |
186 » ) | |
187 » testCases = append(testCases, | |
188 » » testCase{foo1, "fofoofoo12foo32oo", "fofooA2C2oo"}, | |
189 » » testCase{foo1, "", ""}, | |
190 | |
191 » » testCase{foo2, "fofoofoo12foo32oo", "fofooA2Doo"}, | |
192 » » testCase{foo2, "", ""}, | |
193 | |
194 » » testCase{foo3, "fofoofoo12foo32oo", "fofooBDoo"}, | |
195 » » testCase{foo3, "", ""}, | |
196 | |
197 » » testCase{foo4, "fofoofoo12foo32oo", "fofooBDoo"}, | |
198 » » testCase{foo4, "", ""}, | |
199 » ) | |
200 | |
201 » // genAll maps "\x00\x01\x02...\xfe\xff" to "[all]", amongst other thing s. | |
202 » allBytes := make([]byte, 256) | |
203 » for i := range allBytes { | |
204 » » allBytes[i] = byte(i) | |
205 » } | |
206 » allString := string(allBytes) | |
207 » genAll := NewReplacer( | |
208 » » allString, "[all]", | |
209 » » "\xff", "[ff]", | |
210 » » "\x00", "[00]", | |
211 » ) | |
212 » testCases = append(testCases, | |
213 » » testCase{genAll, allString, "[all]"}, | |
214 » » testCase{genAll, "a\xff" + allString + "\x00", "a[ff][all][00]"} , | |
215 » » testCase{genAll, "", ""}, | |
216 » ) | |
217 | |
218 » // Test cases with empty old strings. | |
219 | |
220 » blankToX1 := NewReplacer("", "X") | |
221 » blankToX2 := NewReplacer("", "X", "", "") | |
222 » blankHighPriority := NewReplacer("", "X", "o", "O") | |
223 » blankLowPriority := NewReplacer("o", "O", "", "X") | |
224 » blankNoOp1 := NewReplacer("", "") | |
225 » blankNoOp2 := NewReplacer("", "", "", "A") | |
226 » blankFoo := NewReplacer("", "X", "foobar", "R", "foobaz", "Z") | |
227 » testCases = append(testCases, | |
228 » » testCase{blankToX1, "foo", "XfXoXoX"}, | |
229 » » testCase{blankToX1, "", "X"}, | |
230 | |
231 » » testCase{blankToX2, "foo", "XfXoXoX"}, | |
232 » » testCase{blankToX2, "", "X"}, | |
233 | |
234 » » testCase{blankHighPriority, "oo", "XOXOX"}, | |
235 » » testCase{blankHighPriority, "ii", "XiXiX"}, | |
236 » » testCase{blankHighPriority, "iooi", "XiXOXOXiX"}, | |
nigeltao
2012/09/17 01:49:24
I'd also add an "oiio" test.
| |
237 » » testCase{blankHighPriority, "", "X"}, | |
238 | |
239 » » testCase{blankLowPriority, "oo", "OOX"}, | |
240 » » testCase{blankLowPriority, "ii", "XiXiX"}, | |
241 » » testCase{blankLowPriority, "iooi", "XiOOXiX"}, | |
242 » » testCase{blankLowPriority, "", "X"}, | |
243 | |
244 » » testCase{blankNoOp1, "foo", "foo"}, | |
245 » » testCase{blankNoOp1, "", ""}, | |
246 | |
247 » » testCase{blankNoOp2, "foo", "foo"}, | |
248 » » testCase{blankNoOp2, "", ""}, | |
249 | |
250 » » testCase{blankFoo, "foobarfoobaz", "XRXZX"}, | |
251 » » testCase{blankFoo, "foobar-foobaz", "XRX-XZX"}, | |
252 » » testCase{blankFoo, "", "X"}, | |
253 » ) | |
254 | |
255 » // No-arg test cases. | |
256 | |
257 » nop := NewReplacer() | |
258 » testCases = append(testCases, | |
259 » » testCase{nop, "abc", "abc"}, | |
260 » » testCase{nop, "", ""}, | |
261 » ) | |
262 | |
263 » // Run the test cases. | |
264 | |
265 » for i, tc := range testCases { | |
266 » » if s := tc.r.Replace(tc.in); s != tc.out { | |
267 » » » t.Errorf("%d. Replace(%q) = %q, want %q", i, tc.in, s, t c.out) | |
67 } | 268 } |
68 var buf bytes.Buffer | 269 var buf bytes.Buffer |
69 » » n, err := tt.r.WriteString(&buf, tt.in) | 270 » » n, err := tc.r.WriteString(&buf, tc.in) |
70 if err != nil { | 271 if err != nil { |
71 t.Errorf("%d. WriteString: %v", i, err) | 272 t.Errorf("%d. WriteString: %v", i, err) |
72 continue | 273 continue |
73 } | 274 } |
74 got := buf.String() | 275 got := buf.String() |
75 » » if got != tt.out { | 276 » » if got != tc.out { |
76 » » » t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt. in, got, tt.out) | 277 » » » t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tc. in, got, tc.out) |
77 continue | 278 continue |
78 } | 279 } |
79 » » if n != len(tt.out) { | 280 » » if n != len(tc.out) { |
80 t.Errorf("%d. WriteString(%q) wrote correct string but r eported %d bytes; want %d (%q)", | 281 t.Errorf("%d. WriteString(%q) wrote correct string but r eported %d bytes; want %d (%q)", |
81 » » » » i, tt.in, n, len(tt.out), tt.out) | 282 » » » » i, tc.in, n, len(tc.out), tc.out) |
82 » » } | 283 » » } |
83 » } | 284 » } |
84 } | 285 } |
85 | 286 |
86 // pickAlgorithmTest is a test that verifies that given input for a | 287 // TestPickAlgorithm tests that NewReplacer picks the correct algorithm. |
87 // Replacer that we pick the correct algorithm. | |
88 type pickAlgorithmTest struct { | |
89 » r *Replacer | |
90 » want string // name of algorithm | |
91 } | |
92 | |
93 var pickAlgorithmTests = []pickAlgorithmTest{ | |
94 » {capitalLetters, "*strings.byteReplacer"}, | |
95 » {NewReplacer("12", "123"), "*strings.genericReplacer"}, | |
96 » {NewReplacer("1", "12"), "*strings.byteStringReplacer"}, | |
97 » {htmlEscaper, "*strings.byteStringReplacer"}, | |
98 } | |
99 | |
100 func TestPickAlgorithm(t *testing.T) { | 288 func TestPickAlgorithm(t *testing.T) { |
101 » for i, tt := range pickAlgorithmTests { | 289 » testCases := []struct { |
102 » » got := fmt.Sprintf("%T", tt.r.Replacer()) | 290 » » r *Replacer |
103 » » if got != tt.want { | 291 » » want string |
104 » » » t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want) | 292 » }{ |
293 » » {capitalLetters, "*strings.byteReplacer"}, | |
294 » » {htmlEscaper, "*strings.byteStringReplacer"}, | |
295 » » {NewReplacer("12", "123"), "*strings.genericReplacer"}, | |
296 » » {NewReplacer("1", "12"), "*strings.byteStringReplacer"}, | |
297 » » {NewReplacer("a", "1", "b", "12", "cde", "123"), "*strings.gener icReplacer"}, | |
298 » } | |
299 » for i, tc := range testCases { | |
300 » » got := fmt.Sprintf("%T", tc.r.Replacer()) | |
301 » » if got != tc.want { | |
302 » » » t.Errorf("%d. algorithm = %s, want %s", i, got, tc.want) | |
303 » » } | |
304 » } | |
305 } | |
306 | |
307 // TestGenericTrieBuilding verifies the structure of the generated trie. There | |
308 // is one node per line, and the key ending with the current line is in the | |
309 // trie if it ends with a "+". | |
310 func TestGenericTrieBuilding(t *testing.T) { | |
311 » testCases := []struct{ in, out string }{ | |
312 » » {"abc;abdef;abdefgh;xx;xy;z", `- | |
313 » » » a- | |
314 » » » .b- | |
315 » » » ..c+ | |
316 » » » ..d- | |
317 » » » ...ef+ | |
318 » » » .....gh+ | |
319 » » » x- | |
320 » » » .x+ | |
321 » » » .y+ | |
322 » » » z+ | |
323 » » » `}, | |
324 » » {"abracadabra;abracadabrakazam;abraham;abrasion", `- | |
325 » » » a- | |
326 » » » .bra- | |
327 » » » ....c- | |
328 » » » .....adabra+ | |
329 » » » ...........kazam+ | |
330 » » » ....h- | |
331 » » » .....am+ | |
332 » » » ....s- | |
333 » » » .....ion+ | |
334 » » » `}, | |
335 » » {"aaa;aa;a;i;longerst;longer;long;xx;x;X;Y", `- | |
336 » » » X+ | |
337 » » » Y+ | |
338 » » » a+ | |
339 » » » .a+ | |
340 » » » ..a+ | |
341 » » » i+ | |
342 » » » l- | |
343 » » » .ong+ | |
344 » » » ....er+ | |
345 » » » ......st+ | |
346 » » » x+ | |
347 » » » .x+ | |
348 » » » `}, | |
349 » » {"foo;;foo;foo1", `+ | |
350 » » » f- | |
351 » » » .oo+ | |
352 » » » ...1+ | |
353 » » » `}, | |
354 » } | |
355 | |
356 » for _, tc := range testCases { | |
357 » » keys := Split(tc.in, ";") | |
358 » » args := make([]string, len(keys)*2) | |
359 » » for i, key := range keys { | |
360 » » » args[i*2] = key | |
361 » » } | |
362 | |
363 » » got := NewReplacer(args...).PrintTrie() | |
364 » » // Remove tabs from tc.out | |
365 » » wantbuf := make([]byte, 0, len(tc.out)) | |
366 » » for i := 0; i < len(tc.out); i++ { | |
367 » » » if tc.out[i] != '\t' { | |
368 » » » » wantbuf = append(wantbuf, tc.out[i]) | |
369 » » » } | |
370 » » } | |
371 » » want := string(wantbuf) | |
372 | |
373 » » if got != want { | |
374 » » » t.Errorf("PrintTrie(%q)\ngot\n%swant\n%s", tc.in, got, w ant) | |
105 } | 375 } |
106 } | 376 } |
107 } | 377 } |
108 | 378 |
109 func BenchmarkGenericNoMatch(b *testing.B) { | 379 func BenchmarkGenericNoMatch(b *testing.B) { |
110 str := Repeat("A", 100) + Repeat("B", 100) | 380 str := Repeat("A", 100) + Repeat("B", 100) |
111 generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengt hs forces generic | 381 generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengt hs forces generic |
112 for i := 0; i < b.N; i++ { | 382 for i := 0; i < b.N; i++ { |
113 generic.Replace(str) | 383 generic.Replace(str) |
114 } | 384 } |
115 } | 385 } |
116 | 386 |
117 var html = Repeat("It's <b>HTML</b>!", 10) | 387 func BenchmarkGenericMatch1(b *testing.B) { |
nigeltao
2012/09/04 04:29:59
Make this a local variable in BenchmarkGenericMatc
Eric Roshan Eisner
2012/09/04 06:27:52
Done.
| |
118 | 388 » str := Repeat("a", 100) + Repeat("b", 100) |
119 func BenchmarkGenericMatch(b *testing.B) { | 389 » generic := NewReplacer("a", "A", "b", "B", "12", "123") |
120 » for i := 0; i < b.N; i++ { | 390 » for i := 0; i < b.N; i++ { |
121 » » htmlUnescaper.Replace(html) | 391 » » generic.Replace(str) |
392 » } | |
393 } | |
394 | |
395 func BenchmarkGenericMatch2(b *testing.B) { | |
396 » str := Repeat("It's <b>HTML</b>!", 100) | |
397 » for i := 0; i < b.N; i++ { | |
398 » » htmlUnescaper.Replace(str) | |
122 } | 399 } |
123 } | 400 } |
124 | 401 |
125 func BenchmarkByteByteNoMatch(b *testing.B) { | 402 func BenchmarkByteByteNoMatch(b *testing.B) { |
126 str := Repeat("A", 100) + Repeat("B", 100) | 403 str := Repeat("A", 100) + Repeat("B", 100) |
127 for i := 0; i < b.N; i++ { | 404 for i := 0; i < b.N; i++ { |
128 capitalLetters.Replace(str) | 405 capitalLetters.Replace(str) |
129 } | 406 } |
130 } | 407 } |
131 | 408 |
(...skipping 14 matching lines...) Expand all Loading... | |
146 func BenchmarkHTMLEscapeNew(b *testing.B) { | 423 func BenchmarkHTMLEscapeNew(b *testing.B) { |
147 str := "I <3 to escape HTML & other text too." | 424 str := "I <3 to escape HTML & other text too." |
148 for i := 0; i < b.N; i++ { | 425 for i := 0; i < b.N; i++ { |
149 htmlEscaper.Replace(str) | 426 htmlEscaper.Replace(str) |
150 } | 427 } |
151 } | 428 } |
152 | 429 |
153 func BenchmarkHTMLEscapeOld(b *testing.B) { | 430 func BenchmarkHTMLEscapeOld(b *testing.B) { |
154 str := "I <3 to escape HTML & other text too." | 431 str := "I <3 to escape HTML & other text too." |
155 for i := 0; i < b.N; i++ { | 432 for i := 0; i < b.N; i++ { |
156 » » oldhtmlEscape(str) | 433 » » oldHTMLEscape(str) |
157 } | 434 } |
158 } | 435 } |
159 | 436 |
160 // BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces. | 437 // BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces. |
161 func BenchmarkByteByteReplaces(b *testing.B) { | 438 func BenchmarkByteByteReplaces(b *testing.B) { |
162 str := Repeat("a", 100) + Repeat("b", 100) | 439 str := Repeat("a", 100) + Repeat("b", 100) |
163 for i := 0; i < b.N; i++ { | 440 for i := 0; i < b.N; i++ { |
164 Replace(Replace(str, "a", "A", -1), "b", "B", -1) | 441 Replace(Replace(str, "a", "A", -1), "b", "B", -1) |
165 } | 442 } |
166 } | 443 } |
167 | 444 |
168 // BenchmarkByteByteMap compares byteByteImpl against Map. | 445 // BenchmarkByteByteMap compares byteByteImpl against Map. |
169 func BenchmarkByteByteMap(b *testing.B) { | 446 func BenchmarkByteByteMap(b *testing.B) { |
170 str := Repeat("a", 100) + Repeat("b", 100) | 447 str := Repeat("a", 100) + Repeat("b", 100) |
171 fn := func(r rune) rune { | 448 fn := func(r rune) rune { |
172 switch r { | 449 switch r { |
173 case 'a': | 450 case 'a': |
174 return 'A' | 451 return 'A' |
175 case 'b': | 452 case 'b': |
176 return 'B' | 453 return 'B' |
177 } | 454 } |
178 return r | 455 return r |
179 } | 456 } |
180 for i := 0; i < b.N; i++ { | 457 for i := 0; i < b.N; i++ { |
181 Map(fn, str) | 458 Map(fn, str) |
182 } | 459 } |
183 } | 460 } |
LEFT | RIGHT |