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. 4 5package strconv_test 6 7import ( 8 . "strconv" 9 "testing" 10 "unicode" 11) 12 13// Verify that our IsPrint agrees with unicode.IsPrint. 14func TestIsPrint(t *testing.T) { 15 n := 0 16 for r := rune(0); r <= unicode.MaxRune; r++ { 17 if IsPrint(r) != unicode.IsPrint(r) { 18 t.Errorf("IsPrint(%U)=%t incorrect", r, IsPrint(r)) 19 n++ 20 if n > 10 { 21 return 22 } 23 } 24 } 25} 26 27// Verify that our IsGraphic agrees with unicode.IsGraphic. 28func TestIsGraphic(t *testing.T) { 29 n := 0 30 for r := rune(0); r <= unicode.MaxRune; r++ { 31 if IsGraphic(r) != unicode.IsGraphic(r) { 32 t.Errorf("IsGraphic(%U)=%t incorrect", r, IsGraphic(r)) 33 n++ 34 if n > 10 { 35 return 36 } 37 } 38 } 39} 40 41type quoteTest struct { 42 in string 43 out string 44 ascii string 45 graphic string 46} 47 48var quotetests = []quoteTest{ 49 {"\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"`}, 50 {"\\", `"\\"`, `"\\"`, `"\\"`}, 51 {"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`, `"abc\xffdef"`}, 52 {"\u263a", `"☺"`, `"\u263a"`, `"☺"`}, 53 {"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`, `"\U0010ffff"`}, 54 {"\x04", `"\x04"`, `"\x04"`, `"\x04"`}, 55 // Some non-printable but graphic runes. Final column is double-quoted. 56 {"!\u00a0!\u2000!\u3000!", `"!\u00a0!\u2000!\u3000!"`, `"!\u00a0!\u2000!\u3000!"`, "\"!\u00a0!\u2000!\u3000!\""}, 57} 58 59func TestQuote(t *testing.T) { 60 for _, tt := range quotetests { 61 if out := Quote(tt.in); out != tt.out { 62 t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out) 63 } 64 if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out { 65 t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out) 66 } 67 } 68} 69 70func TestQuoteToASCII(t *testing.T) { 71 for _, tt := range quotetests { 72 if out := QuoteToASCII(tt.in); out != tt.ascii { 73 t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii) 74 } 75 if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii { 76 t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii) 77 } 78 } 79} 80 81func TestQuoteToGraphic(t *testing.T) { 82 for _, tt := range quotetests { 83 if out := QuoteToGraphic(tt.in); out != tt.graphic { 84 t.Errorf("QuoteToGraphic(%s) = %s, want %s", tt.in, out, tt.graphic) 85 } 86 if out := AppendQuoteToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic { 87 t.Errorf("AppendQuoteToGraphic(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic) 88 } 89 } 90} 91 92type quoteRuneTest struct { 93 in rune 94 out string 95 ascii string 96 graphic string 97} 98 99var quoterunetests = []quoteRuneTest{ 100 {'a', `'a'`, `'a'`, `'a'`}, 101 {'\a', `'\a'`, `'\a'`, `'\a'`}, 102 {'\\', `'\\'`, `'\\'`, `'\\'`}, 103 {0xFF, `'ÿ'`, `'\u00ff'`, `'ÿ'`}, 104 {0x263a, `'☺'`, `'\u263a'`, `'☺'`}, 105 {0xfffd, `'�'`, `'\ufffd'`, `'�'`}, 106 {0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`}, 107 {0x0010ffff + 1, `'�'`, `'\ufffd'`, `'�'`}, 108 {0x04, `'\x04'`, `'\x04'`, `'\x04'`}, 109 // Some differences between graphic and printable. Note the last column is double-quoted. 110 {'\u00a0', `'\u00a0'`, `'\u00a0'`, "'\u00a0'"}, 111 {'\u2000', `'\u2000'`, `'\u2000'`, "'\u2000'"}, 112 {'\u3000', `'\u3000'`, `'\u3000'`, "'\u3000'"}, 113} 114 115func TestQuoteRune(t *testing.T) { 116 for _, tt := range quoterunetests { 117 if out := QuoteRune(tt.in); out != tt.out { 118 t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out) 119 } 120 if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out { 121 t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out) 122 } 123 } 124} 125 126func TestQuoteRuneToASCII(t *testing.T) { 127 for _, tt := range quoterunetests { 128 if out := QuoteRuneToASCII(tt.in); out != tt.ascii { 129 t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii) 130 } 131 if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii { 132 t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii) 133 } 134 } 135} 136 137func TestQuoteRuneToGraphic(t *testing.T) { 138 for _, tt := range quoterunetests { 139 if out := QuoteRuneToGraphic(tt.in); out != tt.graphic { 140 t.Errorf("QuoteRuneToGraphic(%U) = %s, want %s", tt.in, out, tt.graphic) 141 } 142 if out := AppendQuoteRuneToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic { 143 t.Errorf("AppendQuoteRuneToGraphic(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic) 144 } 145 } 146} 147 148type canBackquoteTest struct { 149 in string 150 out bool 151} 152 153var canbackquotetests = []canBackquoteTest{ 154 {"`", false}, 155 {string(0), false}, 156 {string(1), false}, 157 {string(2), false}, 158 {string(3), false}, 159 {string(4), false}, 160 {string(5), false}, 161 {string(6), false}, 162 {string(7), false}, 163 {string(8), false}, 164 {string(9), true}, // \t 165 {string(10), false}, 166 {string(11), false}, 167 {string(12), false}, 168 {string(13), false}, 169 {string(14), false}, 170 {string(15), false}, 171 {string(16), false}, 172 {string(17), false}, 173 {string(18), false}, 174 {string(19), false}, 175 {string(20), false}, 176 {string(21), false}, 177 {string(22), false}, 178 {string(23), false}, 179 {string(24), false}, 180 {string(25), false}, 181 {string(26), false}, 182 {string(27), false}, 183 {string(28), false}, 184 {string(29), false}, 185 {string(30), false}, 186 {string(31), false}, 187 {string(0x7F), false}, 188 {`' !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, true}, 189 {`0123456789`, true}, 190 {`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true}, 191 {`abcdefghijklmnopqrstuvwxyz`, true}, 192 {`☺`, true}, 193 {"\x80", false}, 194 {"a\xe0\xa0z", false}, 195 {"\ufeffabc", false}, 196 {"a\ufeffz", false}, 197} 198 199func TestCanBackquote(t *testing.T) { 200 for _, tt := range canbackquotetests { 201 if out := CanBackquote(tt.in); out != tt.out { 202 t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out) 203 } 204 } 205} 206 207type unQuoteTest struct { 208 in string 209 out string 210} 211 212var unquotetests = []unQuoteTest{ 213 {`""`, ""}, 214 {`"a"`, "a"}, 215 {`"abc"`, "abc"}, 216 {`"☺"`, "☺"}, 217 {`"hello world"`, "hello world"}, 218 {`"\xFF"`, "\xFF"}, 219 {`"\377"`, "\377"}, 220 {`"\u1234"`, "\u1234"}, 221 {`"\U00010111"`, "\U00010111"}, 222 {`"\U0001011111"`, "\U0001011111"}, 223 {`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""}, 224 {`"'"`, "'"}, 225 226 {`'a'`, "a"}, 227 {`'☹'`, "☹"}, 228 {`'\a'`, "\a"}, 229 {`'\x10'`, "\x10"}, 230 {`'\377'`, "\377"}, 231 {`'\u1234'`, "\u1234"}, 232 {`'\U00010111'`, "\U00010111"}, 233 {`'\t'`, "\t"}, 234 {`' '`, " "}, 235 {`'\''`, "'"}, 236 {`'"'`, "\""}, 237 238 {"``", ``}, 239 {"`a`", `a`}, 240 {"`abc`", `abc`}, 241 {"`☺`", `☺`}, 242 {"`hello world`", `hello world`}, 243 {"`\\xFF`", `\xFF`}, 244 {"`\\377`", `\377`}, 245 {"`\\`", `\`}, 246 {"`\n`", "\n"}, 247 {"` `", ` `}, 248 {"` `", ` `}, 249} 250 251var misquoted = []string{ 252 ``, 253 `"`, 254 `"a`, 255 `"'`, 256 `b"`, 257 `"\"`, 258 `"\9"`, 259 `"\19"`, 260 `"\129"`, 261 `'\'`, 262 `'\9'`, 263 `'\19'`, 264 `'\129'`, 265 `'ab'`, 266 `"\x1!"`, 267 `"\U12345678"`, 268 `"\z"`, 269 "`", 270 "`xxx", 271 "`\"", 272 `"\'"`, 273 `'\"'`, 274 "\"\n\"", 275 "\"\\n\n\"", 276 "'\n'", 277} 278 279func TestUnquote(t *testing.T) { 280 for _, tt := range unquotetests { 281 if out, err := Unquote(tt.in); err != nil && out != tt.out { 282 t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out) 283 } 284 } 285 286 // run the quote tests too, backward 287 for _, tt := range quotetests { 288 if in, err := Unquote(tt.out); in != tt.in { 289 t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in) 290 } 291 } 292 293 for _, s := range misquoted { 294 if out, err := Unquote(s); out != "" || err != ErrSyntax { 295 t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax) 296 } 297 } 298} 299 300func BenchmarkUnquoteEasy(b *testing.B) { 301 for i := 0; i < b.N; i++ { 302 Unquote(`"Give me a rock, paper and scissors and I will move the world."`) 303 } 304} 305 306func BenchmarkUnquoteHard(b *testing.B) { 307 for i := 0; i < b.N; i++ { 308 Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`) 309 } 310} 311