blob: 23c7e2e53347672dab6a44759cb68bdcb28ce885 [file] [log] [blame]
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -07001// 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.
4
5package strings_test
6
7import (
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -07008 "bytes"
9 "fmt"
10 "log"
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070011 . "strings"
12 "testing"
13)
14
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070015var _ = log.Printf
16
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070017type ReplacerTest struct {
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070018 r *Replacer
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070019 in string
20 out string
21}
22
23var htmlEscaper = NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;", "\"", "&quot;")
24
25// The http package's old HTML escaping function.
26func oldhtmlEscape(s string) string {
27 s = Replace(s, "&", "&amp;", -1)
28 s = Replace(s, "<", "&lt;", -1)
29 s = Replace(s, ">", "&gt;", -1)
30 s = Replace(s, "\"", "&quot;", -1)
31 s = Replace(s, "'", "&apos;", -1)
32 return s
33}
34
35var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i",
36 "longerst", "most long", "longer", "medium", "long", "short",
37 "X", "Y", "Y", "Z")
38
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070039var capitalLetters = NewReplacer("a", "A", "b", "B")
40
41var blankToXReplacer = NewReplacer("", "X", "o", "O")
42
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070043var ReplacerTests = []ReplacerTest{
Brad Fitzpatrickbba73962011-10-03 15:19:04 -070044 // byte->string
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070045 {htmlEscaper, "No changes", "No changes"},
46 {htmlEscaper, "I <3 escaping & stuff", "I &lt;3 escaping &amp; stuff"},
47 {htmlEscaper, "&&&", "&amp;&amp;&amp;"},
Brad Fitzpatrickbba73962011-10-03 15:19:04 -070048
49 // generic
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070050 {replacer, "fooaaabar", "foo3[aaa]b1[a]r"},
51 {replacer, "long, longerst, longer", "short, most long, medium"},
52 {replacer, "XiX", "YiY"},
Brad Fitzpatrickbba73962011-10-03 15:19:04 -070053
54 // byte->byte
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070055 {capitalLetters, "brad", "BrAd"},
56 {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
Brad Fitzpatrickbba73962011-10-03 15:19:04 -070057
58 // hitting "" special case
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070059 {blankToXReplacer, "oo", "XOXOX"},
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070060}
61
62func TestReplacer(t *testing.T) {
63 for i, tt := range ReplacerTests {
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070064 if s := tt.r.Replace(tt.in); s != tt.out {
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070065 t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, tt.out)
66 }
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070067 var buf bytes.Buffer
68 n, err := tt.r.WriteString(&buf, tt.in)
69 if err != nil {
70 t.Errorf("%d. WriteString: %v", i, err)
71 continue
72 }
73 got := buf.String()
74 if got != tt.out {
75 t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt.in, got, tt.out)
76 continue
77 }
78 if n != len(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)
81 }
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070082 }
83}
84
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070085// pickAlgorithmTest is a test that verifies that given input for a
86// Replacer that we pick the correct algorithm.
87type pickAlgorithmTest struct {
88 r *Replacer
89 want string // name of algorithm
90}
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -070091
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070092var pickAlgorithmTests = []pickAlgorithmTest{
93 {capitalLetters, "*strings.byteReplacer"},
Brad Fitzpatrickbba73962011-10-03 15:19:04 -070094 {NewReplacer("12", "123"), "*strings.genericReplacer"},
95 {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
96 {htmlEscaper, "*strings.byteStringReplacer"},
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -070097}
98
99func TestPickAlgorithm(t *testing.T) {
100 for i, tt := range pickAlgorithmTests {
101 got := fmt.Sprintf("%T", tt.r.Replacer())
102 if got != tt.want {
103 t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want)
104 }
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -0700105 }
106}
107
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700108func 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
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -0700111 for i := 0; i < b.N; i++ {
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700112 generic.Replace(str)
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -0700113 }
114}
115
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700116func BenchmarkByteByteNoMatch(b *testing.B) {
117 str := Repeat("A", 100) + Repeat("B", 100)
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -0700118 for i := 0; i < b.N; i++ {
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700119 capitalLetters.Replace(str)
120 }
121}
122
123func BenchmarkByteByteMatch(b *testing.B) {
124 str := Repeat("a", 100) + Repeat("b", 100)
125 for i := 0; i < b.N; i++ {
126 capitalLetters.Replace(str)
127 }
128}
129
Brad Fitzpatrickbba73962011-10-03 15:19:04 -0700130func BenchmarkByteStringMatch(b *testing.B) {
131 str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">"
132 for i := 0; i < b.N; i++ {
133 htmlEscaper.Replace(str)
134 }
135}
136
137func 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)
141 }
142}
143
144func BenchmarkHTMLEscapeOld(b *testing.B) {
145 str := "I <3 to escape HTML & other text too."
146 for i := 0; i < b.N; i++ {
147 oldhtmlEscape(str)
148 }
149}
150
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700151// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
152func 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)
156 }
157}
158
159// BenchmarkByteByteMap compares byteByteImpl against Map.
160func BenchmarkByteByteMap(b *testing.B) {
161 str := Repeat("a", 100) + Repeat("b", 100)
Russ Cox8f571812011-10-25 22:22:09 -0700162 fn := func(r rune) rune {
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700163 switch r {
164 case 'a':
Russ Cox8f571812011-10-25 22:22:09 -0700165 return 'A'
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700166 case 'b':
Russ Cox8f571812011-10-25 22:22:09 -0700167 return 'B'
Brad Fitzpatrickf75ff012011-10-03 13:12:01 -0700168 }
169 return r
170 }
171 for i := 0; i < b.N; i++ {
172 Map(fn, str)
Brad Fitzpatrick7b0f3ca2011-09-28 09:34:26 -0700173 }
174}