Source file
src/strconv/quote_test.go
1
2
3
4
5 package strconv_test
6
7 import (
8 . "strconv"
9 "strings"
10 "testing"
11 "unicode"
12 )
13
14
15 func TestIsPrint(t *testing.T) {
16 n := 0
17 for r := rune(0); r <= unicode.MaxRune; r++ {
18 if IsPrint(r) != unicode.IsPrint(r) {
19 t.Errorf("IsPrint(%U)=%t incorrect", r, IsPrint(r))
20 n++
21 if n > 10 {
22 return
23 }
24 }
25 }
26 }
27
28
29 func TestIsGraphic(t *testing.T) {
30 n := 0
31 for r := rune(0); r <= unicode.MaxRune; r++ {
32 if IsGraphic(r) != unicode.IsGraphic(r) {
33 t.Errorf("IsGraphic(%U)=%t incorrect", r, IsGraphic(r))
34 n++
35 if n > 10 {
36 return
37 }
38 }
39 }
40 }
41
42 type quoteTest struct {
43 in string
44 out string
45 ascii string
46 graphic string
47 }
48
49 var quotetests = []quoteTest{
50 {"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`},
51 {"\\", `"\\"`, `"\\"`, `"\\"`},
52 {"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`, `"abc\xffdef"`},
53 {"\u263a", `"☺"`, `"\u263a"`, `"☺"`},
54 {"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`, `"\U0010ffff"`},
55 {"\x04", `"\x04"`, `"\x04"`, `"\x04"`},
56
57 {"!\u00a0!\u2000!\u3000!", `"!\u00a0!\u2000!\u3000!"`, `"!\u00a0!\u2000!\u3000!"`, "\"!\u00a0!\u2000!\u3000!\""},
58 {"\x7f", `"\x7f"`, `"\x7f"`, `"\x7f"`},
59 }
60
61 func TestQuote(t *testing.T) {
62 for _, tt := range quotetests {
63 if out := Quote(tt.in); out != tt.out {
64 t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
65 }
66 if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
67 t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
68 }
69 }
70 }
71
72 func TestQuoteToASCII(t *testing.T) {
73 for _, tt := range quotetests {
74 if out := QuoteToASCII(tt.in); out != tt.ascii {
75 t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii)
76 }
77 if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
78 t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
79 }
80 }
81 }
82
83 func TestQuoteToGraphic(t *testing.T) {
84 for _, tt := range quotetests {
85 if out := QuoteToGraphic(tt.in); out != tt.graphic {
86 t.Errorf("QuoteToGraphic(%s) = %s, want %s", tt.in, out, tt.graphic)
87 }
88 if out := AppendQuoteToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic {
89 t.Errorf("AppendQuoteToGraphic(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic)
90 }
91 }
92 }
93
94 func BenchmarkQuote(b *testing.B) {
95 for i := 0; i < b.N; i++ {
96 Quote("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v")
97 }
98 }
99
100 func BenchmarkQuoteRune(b *testing.B) {
101 for i := 0; i < b.N; i++ {
102 QuoteRune('\a')
103 }
104 }
105
106 var benchQuoteBuf []byte
107
108 func BenchmarkAppendQuote(b *testing.B) {
109 for i := 0; i < b.N; i++ {
110 benchQuoteBuf = AppendQuote(benchQuoteBuf[:0], "\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v")
111 }
112 }
113
114 var benchQuoteRuneBuf []byte
115
116 func BenchmarkAppendQuoteRune(b *testing.B) {
117 for i := 0; i < b.N; i++ {
118 benchQuoteRuneBuf = AppendQuoteRune(benchQuoteRuneBuf[:0], '\a')
119 }
120 }
121
122 type quoteRuneTest struct {
123 in rune
124 out string
125 ascii string
126 graphic string
127 }
128
129 var quoterunetests = []quoteRuneTest{
130 {'a', `'a'`, `'a'`, `'a'`},
131 {'\a', `'\a'`, `'\a'`, `'\a'`},
132 {'\\', `'\\'`, `'\\'`, `'\\'`},
133 {0xFF, `'ÿ'`, `'\u00ff'`, `'ÿ'`},
134 {0x263a, `'☺'`, `'\u263a'`, `'☺'`},
135 {0xdead, `'�'`, `'\ufffd'`, `'�'`},
136 {0xfffd, `'�'`, `'\ufffd'`, `'�'`},
137 {0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`},
138 {0x0010ffff + 1, `'�'`, `'\ufffd'`, `'�'`},
139 {0x04, `'\x04'`, `'\x04'`, `'\x04'`},
140
141 {'\u00a0', `'\u00a0'`, `'\u00a0'`, "'\u00a0'"},
142 {'\u2000', `'\u2000'`, `'\u2000'`, "'\u2000'"},
143 {'\u3000', `'\u3000'`, `'\u3000'`, "'\u3000'"},
144 }
145
146 func TestQuoteRune(t *testing.T) {
147 for _, tt := range quoterunetests {
148 if out := QuoteRune(tt.in); out != tt.out {
149 t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
150 }
151 if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
152 t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
153 }
154 }
155 }
156
157 func TestQuoteRuneToASCII(t *testing.T) {
158 for _, tt := range quoterunetests {
159 if out := QuoteRuneToASCII(tt.in); out != tt.ascii {
160 t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii)
161 }
162 if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
163 t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
164 }
165 }
166 }
167
168 func TestQuoteRuneToGraphic(t *testing.T) {
169 for _, tt := range quoterunetests {
170 if out := QuoteRuneToGraphic(tt.in); out != tt.graphic {
171 t.Errorf("QuoteRuneToGraphic(%U) = %s, want %s", tt.in, out, tt.graphic)
172 }
173 if out := AppendQuoteRuneToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic {
174 t.Errorf("AppendQuoteRuneToGraphic(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic)
175 }
176 }
177 }
178
179 type canBackquoteTest struct {
180 in string
181 out bool
182 }
183
184 var canbackquotetests = []canBackquoteTest{
185 {"`", false},
186 {string(rune(0)), false},
187 {string(rune(1)), false},
188 {string(rune(2)), false},
189 {string(rune(3)), false},
190 {string(rune(4)), false},
191 {string(rune(5)), false},
192 {string(rune(6)), false},
193 {string(rune(7)), false},
194 {string(rune(8)), false},
195 {string(rune(9)), true},
196 {string(rune(10)), false},
197 {string(rune(11)), false},
198 {string(rune(12)), false},
199 {string(rune(13)), false},
200 {string(rune(14)), false},
201 {string(rune(15)), false},
202 {string(rune(16)), false},
203 {string(rune(17)), false},
204 {string(rune(18)), false},
205 {string(rune(19)), false},
206 {string(rune(20)), false},
207 {string(rune(21)), false},
208 {string(rune(22)), false},
209 {string(rune(23)), false},
210 {string(rune(24)), false},
211 {string(rune(25)), false},
212 {string(rune(26)), false},
213 {string(rune(27)), false},
214 {string(rune(28)), false},
215 {string(rune(29)), false},
216 {string(rune(30)), false},
217 {string(rune(31)), false},
218 {string(rune(0x7F)), false},
219 {`' !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, true},
220 {`0123456789`, true},
221 {`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true},
222 {`abcdefghijklmnopqrstuvwxyz`, true},
223 {`☺`, true},
224 {"\x80", false},
225 {"a\xe0\xa0z", false},
226 {"\ufeffabc", false},
227 {"a\ufeffz", false},
228 }
229
230 func TestCanBackquote(t *testing.T) {
231 for _, tt := range canbackquotetests {
232 if out := CanBackquote(tt.in); out != tt.out {
233 t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
234 }
235 }
236 }
237
238 type unQuoteTest struct {
239 in string
240 out string
241 }
242
243 var unquotetests = []unQuoteTest{
244 {`""`, ""},
245 {`"a"`, "a"},
246 {`"abc"`, "abc"},
247 {`"☺"`, "☺"},
248 {`"hello world"`, "hello world"},
249 {`"\xFF"`, "\xFF"},
250 {`"\377"`, "\377"},
251 {`"\u1234"`, "\u1234"},
252 {`"\U00010111"`, "\U00010111"},
253 {`"\U0001011111"`, "\U0001011111"},
254 {`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""},
255 {`"'"`, "'"},
256
257 {`'a'`, "a"},
258 {`'☹'`, "☹"},
259 {`'\a'`, "\a"},
260 {`'\x10'`, "\x10"},
261 {`'\377'`, "\377"},
262 {`'\u1234'`, "\u1234"},
263 {`'\U00010111'`, "\U00010111"},
264 {`'\t'`, "\t"},
265 {`' '`, " "},
266 {`'\''`, "'"},
267 {`'"'`, "\""},
268
269 {"``", ``},
270 {"`a`", `a`},
271 {"`abc`", `abc`},
272 {"`☺`", `☺`},
273 {"`hello world`", `hello world`},
274 {"`\\xFF`", `\xFF`},
275 {"`\\377`", `\377`},
276 {"`\\`", `\`},
277 {"`\n`", "\n"},
278 {"` `", ` `},
279 {"` `", ` `},
280 {"`a\rb`", "ab"},
281 }
282
283 var misquoted = []string{
284 ``,
285 `"`,
286 `"a`,
287 `"'`,
288 `b"`,
289 `"\"`,
290 `"\9"`,
291 `"\19"`,
292 `"\129"`,
293 `'\'`,
294 `'\9'`,
295 `'\19'`,
296 `'\129'`,
297 `'ab'`,
298 `"\x1!"`,
299 `"\U12345678"`,
300 `"\z"`,
301 "`",
302 "`xxx",
303 "``x\r",
304 "`\"",
305 `"\'"`,
306 `'\"'`,
307 "\"\n\"",
308 "\"\\n\n\"",
309 "'\n'",
310 `"\udead"`,
311 `"\ud83d\ude4f"`,
312 }
313
314 func TestUnquote(t *testing.T) {
315 for _, tt := range unquotetests {
316 testUnquote(t, tt.in, tt.out, nil)
317 }
318 for _, tt := range quotetests {
319 testUnquote(t, tt.out, tt.in, nil)
320 }
321 for _, s := range misquoted {
322 testUnquote(t, s, "", ErrSyntax)
323 }
324 }
325
326
327 func TestUnquoteInvalidUTF8(t *testing.T) {
328 tests := []struct {
329 in string
330
331
332 want string
333 wantErr error
334 }{
335 {in: `"foo"`, want: "foo"},
336 {in: `"foo`, wantErr: ErrSyntax},
337 {in: `"` + "\xc0" + `"`, want: "\xef\xbf\xbd"},
338 {in: `"a` + "\xc0" + `"`, want: "a\xef\xbf\xbd"},
339 {in: `"\t` + "\xc0" + `"`, want: "\t\xef\xbf\xbd"},
340 }
341 for _, tt := range tests {
342 testUnquote(t, tt.in, tt.want, tt.wantErr)
343 }
344 }
345
346 func testUnquote(t *testing.T, in, want string, wantErr error) {
347
348 got, gotErr := Unquote(in)
349 if got != want || gotErr != wantErr {
350 t.Errorf("Unquote(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr)
351 }
352
353
354
355
356 if gotErr == nil {
357 want = in
358 }
359 suffix := "\n\r\\\"`'"
360 if len(in) > 0 {
361 suffix = strings.ReplaceAll(suffix, in[:1], "")
362 }
363 in += suffix
364 got, gotErr = QuotedPrefix(in)
365 if gotErr == nil && wantErr != nil {
366 _, wantErr = Unquote(got)
367 want = got
368 }
369 if got != want || gotErr != wantErr {
370 t.Errorf("QuotedPrefix(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr)
371 }
372 }
373
374 func BenchmarkUnquoteEasy(b *testing.B) {
375 for i := 0; i < b.N; i++ {
376 Unquote(`"Give me a rock, paper and scissors and I will move the world."`)
377 }
378 }
379
380 func BenchmarkUnquoteHard(b *testing.B) {
381 for i := 0; i < b.N; i++ {
382 Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`)
383 }
384 }
385
View as plain text