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