OLD | NEW |
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" | 10 "log" |
11 . "strings" | 11 . "strings" |
12 "testing" | 12 "testing" |
13 ) | 13 ) |
14 | 14 |
15 var _ = log.Printf | 15 var _ = log.Printf |
16 | 16 |
17 type ReplacerTest struct { | 17 type ReplacerTest struct { |
18 r *Replacer | 18 r *Replacer |
19 in string | 19 in string |
20 out string | 20 out string |
21 } | 21 } |
22 | 22 |
23 var htmlEscaper = NewReplacer("&", "&", "<", "<", ">", ">", "\"", "&qu
ot;") | 23 var htmlEscaper = NewReplacer("&", "&", "<", "<", ">", ">", "\"", "&qu
ot;", "'", "'") |
| 24 var htmlUnescaper = NewReplacer("&", "&", "<", "<", ">", ">", """
, `"`, "'", "'") |
24 | 25 |
25 // The http package's old HTML escaping function. | 26 // The http package's old HTML escaping function. |
26 func oldhtmlEscape(s string) string { | 27 func oldhtmlEscape(s string) string { |
27 s = Replace(s, "&", "&", -1) | 28 s = Replace(s, "&", "&", -1) |
28 s = Replace(s, "<", "<", -1) | 29 s = Replace(s, "<", "<", -1) |
29 s = Replace(s, ">", ">", -1) | 30 s = Replace(s, ">", ">", -1) |
30 s = Replace(s, "\"", """, -1) | 31 s = Replace(s, "\"", """, -1) |
31 s = Replace(s, "'", "'", -1) | 32 s = Replace(s, "'", "'", -1) |
32 return s | 33 return s |
33 } | 34 } |
34 | 35 |
35 var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i"
, | 36 var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i"
, |
36 "longerst", "most long", "longer", "medium", "long", "short", | 37 "longerst", "most long", "longer", "medium", "long", "short", |
37 "X", "Y", "Y", "Z") | 38 "X", "Y", "Y", "Z") |
38 | 39 |
| 40 var genReplacer = NewReplacer( |
| 41 "abracadabra", "poof", |
| 42 "abracadabrakazam", "splat", // Should never trigger. |
| 43 "abraham", "lincoln", |
| 44 "abrasion", "scrape", |
| 45 "abraham", "isaac", // Should never trigger. |
| 46 ) |
| 47 |
39 var capitalLetters = NewReplacer("a", "A", "b", "B") | 48 var capitalLetters = NewReplacer("a", "A", "b", "B") |
40 | 49 |
41 var blankToXReplacer = NewReplacer("", "X", "o", "O") | 50 var blankToXReplacer = NewReplacer("", "X", "o", "O", "", "less important") |
42 | 51 |
43 var ReplacerTests = []ReplacerTest{ | 52 var ReplacerTests = []ReplacerTest{ |
44 // byte->string | 53 // byte->string |
45 {htmlEscaper, "No changes", "No changes"}, | 54 {htmlEscaper, "No changes", "No changes"}, |
46 {htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"}, | 55 {htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"}, |
47 {htmlEscaper, "&&&", "&&&"}, | 56 {htmlEscaper, "&&&", "&&&"}, |
48 | 57 |
49 // generic | 58 // generic |
50 » {replacer, "fooaaabar", "foo3[aaa]b1[a]r"}, | 59 » {htmlUnescaper, "&amp;", "&"}, |
| 60 » {htmlUnescaper, "<b>HTML's neat</b>", "<b>HTML's neat</
b>"}, |
| 61 |
| 62 » {replacer, "fooaaabarbaaz", "foo3[aaa]b1[a]rb2[aa]z"}, |
51 {replacer, "long, longerst, longer", "short, most long, medium"}, | 63 {replacer, "long, longerst, longer", "short, most long, medium"}, |
52 {replacer, "XiX", "YiY"}, | 64 {replacer, "XiX", "YiY"}, |
53 | 65 |
| 66 {genReplacer, "abracadabrakazam abraham", "poofkazam lincoln"}, |
| 67 {genReplacer, "abrasion abracad", "scrape abracad"}, |
| 68 {genReplacer, "abba abram abrasive", "abba abram abrasive"}, |
| 69 |
54 // byte->byte | 70 // byte->byte |
55 {capitalLetters, "brad", "BrAd"}, | 71 {capitalLetters, "brad", "BrAd"}, |
56 {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)}, | 72 {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)}, |
57 | 73 |
58 // hitting "" special case | 74 // hitting "" special case |
| 75 {blankToXReplacer, "", "X"}, |
59 {blankToXReplacer, "oo", "XOXOX"}, | 76 {blankToXReplacer, "oo", "XOXOX"}, |
| 77 {blankToXReplacer, "iioi", "XiXiXOXiX"}, |
| 78 {NewReplacer("", "", "", "X"), "a", "a"}, |
| 79 {NewReplacer("a", "A", "", "X"), "abba", "AXbXbAX"}, |
60 } | 80 } |
61 | 81 |
62 func TestReplacer(t *testing.T) { | 82 func TestReplacer(t *testing.T) { |
| 83 // Added here for initialization. |
| 84 var allBytes []byte |
| 85 for i := 0; i < 256; i++ { |
| 86 allBytes = append(allBytes, byte(i)) |
| 87 } |
| 88 allString := string(allBytes) |
| 89 bigReplacer := NewReplacer(allString, "[all]", |
| 90 "\xff", "[allbits]", "\x00", "[nobits]") |
| 91 |
| 92 ReplacerTests = append(ReplacerTests, |
| 93 ReplacerTest{bigReplacer, allString, "[all]"}, |
| 94 ReplacerTest{bigReplacer, "a\xff" + allString + "\x00", "a[allbi
ts][all][nobits]"}, |
| 95 ) |
| 96 |
63 for i, tt := range ReplacerTests { | 97 for i, tt := range ReplacerTests { |
64 if s := tt.r.Replace(tt.in); s != tt.out { | 98 if s := tt.r.Replace(tt.in); s != tt.out { |
65 t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, t
t.out) | 99 t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, t
t.out) |
66 } | 100 } |
67 var buf bytes.Buffer | 101 var buf bytes.Buffer |
68 n, err := tt.r.WriteString(&buf, tt.in) | 102 n, err := tt.r.WriteString(&buf, tt.in) |
69 if err != nil { | 103 if err != nil { |
70 t.Errorf("%d. WriteString: %v", i, err) | 104 t.Errorf("%d. WriteString: %v", i, err) |
71 continue | 105 continue |
72 } | 106 } |
(...skipping 25 matching lines...) Expand all Loading... |
98 | 132 |
99 func TestPickAlgorithm(t *testing.T) { | 133 func TestPickAlgorithm(t *testing.T) { |
100 for i, tt := range pickAlgorithmTests { | 134 for i, tt := range pickAlgorithmTests { |
101 got := fmt.Sprintf("%T", tt.r.Replacer()) | 135 got := fmt.Sprintf("%T", tt.r.Replacer()) |
102 if got != tt.want { | 136 if got != tt.want { |
103 t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want) | 137 t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want) |
104 } | 138 } |
105 } | 139 } |
106 } | 140 } |
107 | 141 |
108 func BenchmarkGenericMatch(b *testing.B) { | 142 func BenchmarkGenericNoMatch(b *testing.B) { |
109 str := Repeat("A", 100) + Repeat("B", 100) | 143 str := Repeat("A", 100) + Repeat("B", 100) |
110 generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengt
hs forces generic | 144 generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengt
hs forces generic |
| 145 b.SetBytes(int64(len(str))) |
111 for i := 0; i < b.N; i++ { | 146 for i := 0; i < b.N; i++ { |
112 generic.Replace(str) | 147 generic.Replace(str) |
113 } | 148 } |
114 } | 149 } |
115 | 150 |
| 151 func BenchmarkGenericMatch(b *testing.B) { |
| 152 html := Repeat("It's <b>HTML</b>!", 10) |
| 153 b.SetBytes(int64(len(html))) |
| 154 for i := 0; i < b.N; i++ { |
| 155 htmlUnescaper.Replace(html) |
| 156 } |
| 157 } |
| 158 |
116 func BenchmarkByteByteNoMatch(b *testing.B) { | 159 func BenchmarkByteByteNoMatch(b *testing.B) { |
117 str := Repeat("A", 100) + Repeat("B", 100) | 160 str := Repeat("A", 100) + Repeat("B", 100) |
| 161 b.SetBytes(int64(len(str))) |
118 for i := 0; i < b.N; i++ { | 162 for i := 0; i < b.N; i++ { |
119 capitalLetters.Replace(str) | 163 capitalLetters.Replace(str) |
120 } | 164 } |
121 } | 165 } |
122 | 166 |
123 func BenchmarkByteByteMatch(b *testing.B) { | 167 func BenchmarkByteByteMatch(b *testing.B) { |
124 str := Repeat("a", 100) + Repeat("b", 100) | 168 str := Repeat("a", 100) + Repeat("b", 100) |
| 169 b.SetBytes(int64(len(str))) |
125 for i := 0; i < b.N; i++ { | 170 for i := 0; i < b.N; i++ { |
126 capitalLetters.Replace(str) | 171 capitalLetters.Replace(str) |
127 } | 172 } |
128 } | 173 } |
129 | 174 |
130 func BenchmarkByteStringMatch(b *testing.B) { | 175 func BenchmarkByteStringMatch(b *testing.B) { |
131 str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">" | 176 str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">" |
| 177 b.SetBytes(int64(len(str))) |
132 for i := 0; i < b.N; i++ { | 178 for i := 0; i < b.N; i++ { |
133 htmlEscaper.Replace(str) | 179 htmlEscaper.Replace(str) |
134 } | 180 } |
135 } | 181 } |
136 | 182 |
137 func BenchmarkHTMLEscapeNew(b *testing.B) { | 183 func BenchmarkHTMLEscapeNew(b *testing.B) { |
138 str := "I <3 to escape HTML & other text too." | 184 str := "I <3 to escape HTML & other text too." |
| 185 b.SetBytes(int64(len(str))) |
139 for i := 0; i < b.N; i++ { | 186 for i := 0; i < b.N; i++ { |
140 htmlEscaper.Replace(str) | 187 htmlEscaper.Replace(str) |
141 } | 188 } |
142 } | 189 } |
143 | 190 |
144 func BenchmarkHTMLEscapeOld(b *testing.B) { | 191 func BenchmarkHTMLEscapeOld(b *testing.B) { |
145 str := "I <3 to escape HTML & other text too." | 192 str := "I <3 to escape HTML & other text too." |
| 193 b.SetBytes(int64(len(str))) |
146 for i := 0; i < b.N; i++ { | 194 for i := 0; i < b.N; i++ { |
147 oldhtmlEscape(str) | 195 oldhtmlEscape(str) |
148 } | 196 } |
149 } | 197 } |
150 | 198 |
151 // BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces. | 199 // BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces. |
152 func BenchmarkByteByteReplaces(b *testing.B) { | 200 func BenchmarkByteByteReplaces(b *testing.B) { |
153 str := Repeat("a", 100) + Repeat("b", 100) | 201 str := Repeat("a", 100) + Repeat("b", 100) |
| 202 b.SetBytes(int64(len(str))) |
154 for i := 0; i < b.N; i++ { | 203 for i := 0; i < b.N; i++ { |
155 Replace(Replace(str, "a", "A", -1), "b", "B", -1) | 204 Replace(Replace(str, "a", "A", -1), "b", "B", -1) |
156 } | 205 } |
157 } | 206 } |
158 | 207 |
159 // BenchmarkByteByteMap compares byteByteImpl against Map. | 208 // BenchmarkByteByteMap compares byteByteImpl against Map. |
160 func BenchmarkByteByteMap(b *testing.B) { | 209 func BenchmarkByteByteMap(b *testing.B) { |
161 str := Repeat("a", 100) + Repeat("b", 100) | 210 str := Repeat("a", 100) + Repeat("b", 100) |
162 fn := func(r rune) rune { | 211 fn := func(r rune) rune { |
163 switch r { | 212 switch r { |
164 case 'a': | 213 case 'a': |
165 return 'A' | 214 return 'A' |
166 case 'b': | 215 case 'b': |
167 return 'B' | 216 return 'B' |
168 } | 217 } |
169 return r | 218 return r |
170 } | 219 } |
| 220 b.SetBytes(int64(len(str))) |
171 for i := 0; i < b.N; i++ { | 221 for i := 0; i < b.N; i++ { |
172 Map(fn, str) | 222 Map(fn, str) |
173 } | 223 } |
174 } | 224 } |
OLD | NEW |