1 // Copyright 2009 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.
17 type ReplacerTest struct {
23 var htmlEscaper = NewReplacer("&", "&", "<", "<", ">", ">", "\"", """)
25 // The http package's old HTML escaping function.
26 func oldhtmlEscape(s string) string {
27 s = Replace(s, "&", "&", -1)
28 s = Replace(s, "<", "<", -1)
29 s = Replace(s, ">", ">", -1)
30 s = Replace(s, "\"", """, -1)
31 s = Replace(s, "'", "'", -1)
35 var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i",
36 "longerst", "most long", "longer", "medium", "long", "short",
39 var capitalLetters = NewReplacer("a", "A", "b", "B")
41 var blankToXReplacer = NewReplacer("", "X", "o", "O")
43 var ReplacerTests = []ReplacerTest{
45 {htmlEscaper, "No changes", "No changes"},
46 {htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"},
47 {htmlEscaper, "&&&", "&&&"},
50 {replacer, "fooaaabar", "foo3[aaa]b1[a]r"},
51 {replacer, "long, longerst, longer", "short, most long, medium"},
52 {replacer, "XiX", "YiY"},
55 {capitalLetters, "brad", "BrAd"},
56 {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
58 // hitting "" special case
59 {blankToXReplacer, "oo", "XOXOX"},
62 func TestReplacer(t *testing.T) {
63 for i, tt := range ReplacerTests {
64 if s := tt.r.Replace(tt.in); s != tt.out {
65 t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, tt.out)
68 n, err := tt.r.WriteString(&buf, tt.in)
70 t.Errorf("%d. WriteString: %v", i, err)
75 t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt.in, got, tt.out)
79 t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)",
80 i, tt.in, n, len(tt.out), tt.out)
85 // pickAlgorithmTest is a test that verifies that given input for a
86 // Replacer that we pick the correct algorithm.
87 type pickAlgorithmTest struct {
89 want string // name of algorithm
92 var pickAlgorithmTests = []pickAlgorithmTest{
93 {capitalLetters, "*strings.byteReplacer"},
94 {NewReplacer("12", "123"), "*strings.genericReplacer"},
95 {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
96 {htmlEscaper, "*strings.byteStringReplacer"},
99 func TestPickAlgorithm(t *testing.T) {
100 for i, tt := range pickAlgorithmTests {
101 got := fmt.Sprintf("%T", tt.r.Replacer())
103 t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want)
108 func BenchmarkGenericMatch(b *testing.B) {
109 str := Repeat("A", 100) + Repeat("B", 100)
110 generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic
111 for i := 0; i < b.N; i++ {
116 func BenchmarkByteByteNoMatch(b *testing.B) {
117 str := Repeat("A", 100) + Repeat("B", 100)
118 for i := 0; i < b.N; i++ {
119 capitalLetters.Replace(str)
123 func BenchmarkByteByteMatch(b *testing.B) {
124 str := Repeat("a", 100) + Repeat("b", 100)
125 for i := 0; i < b.N; i++ {
126 capitalLetters.Replace(str)
130 func BenchmarkByteStringMatch(b *testing.B) {
131 str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">"
132 for i := 0; i < b.N; i++ {
133 htmlEscaper.Replace(str)
137 func BenchmarkHTMLEscapeNew(b *testing.B) {
138 str := "I <3 to escape HTML & other text too."
139 for i := 0; i < b.N; i++ {
140 htmlEscaper.Replace(str)
144 func BenchmarkHTMLEscapeOld(b *testing.B) {
145 str := "I <3 to escape HTML & other text too."
146 for i := 0; i < b.N; i++ {
151 // BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
152 func BenchmarkByteByteReplaces(b *testing.B) {
153 str := Repeat("a", 100) + Repeat("b", 100)
154 for i := 0; i < b.N; i++ {
155 Replace(Replace(str, "a", "A", -1), "b", "B", -1)
159 // BenchmarkByteByteMap compares byteByteImpl against Map.
160 func BenchmarkByteByteMap(b *testing.B) {
161 str := Repeat("a", 100) + Repeat("b", 100)
162 fn := func(r rune) rune {
171 for i := 0; i < b.N; i++ {