Home | History | Annotate | Download | only in strconv
      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 
      5 package strconv_test
      6 
      7 import (
      8 	. "strconv"
      9 	"testing"
     10 	"unicode"
     11 )
     12 
     13 // Verify that our IsPrint agrees with unicode.IsPrint.
     14 func 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.
     28 func 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 
     41 type quoteTest struct {
     42 	in      string
     43 	out     string
     44 	ascii   string
     45 	graphic string
     46 }
     47 
     48 var 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 
     59 func 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 
     70 func 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 
     81 func 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 
     92 func BenchmarkQuote(b *testing.B) {
     93 	for i := 0; i < b.N; i++ {
     94 		Quote("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v")
     95 	}
     96 }
     97 
     98 func BenchmarkQuoteRune(b *testing.B) {
     99 	for i := 0; i < b.N; i++ {
    100 		QuoteRune('\a')
    101 	}
    102 }
    103 
    104 var benchQuoteBuf []byte
    105 
    106 func BenchmarkAppendQuote(b *testing.B) {
    107 	for i := 0; i < b.N; i++ {
    108 		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")
    109 	}
    110 }
    111 
    112 var benchQuoteRuneBuf []byte
    113 
    114 func BenchmarkAppendQuoteRune(b *testing.B) {
    115 	for i := 0; i < b.N; i++ {
    116 		benchQuoteRuneBuf = AppendQuoteRune(benchQuoteRuneBuf[:0], '\a')
    117 	}
    118 }
    119 
    120 type quoteRuneTest struct {
    121 	in      rune
    122 	out     string
    123 	ascii   string
    124 	graphic string
    125 }
    126 
    127 var quoterunetests = []quoteRuneTest{
    128 	{'a', `'a'`, `'a'`, `'a'`},
    129 	{'\a', `'\a'`, `'\a'`, `'\a'`},
    130 	{'\\', `'\\'`, `'\\'`, `'\\'`},
    131 	{0xFF, `''`, `'\u00ff'`, `''`},
    132 	{0x263a, `''`, `'\u263a'`, `''`},
    133 	{0xfffd, `''`, `'\ufffd'`, `''`},
    134 	{0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`},
    135 	{0x0010ffff + 1, `''`, `'\ufffd'`, `''`},
    136 	{0x04, `'\x04'`, `'\x04'`, `'\x04'`},
    137 	// Some differences between graphic and printable. Note the last column is double-quoted.
    138 	{'\u00a0', `'\u00a0'`, `'\u00a0'`, "'\u00a0'"},
    139 	{'\u2000', `'\u2000'`, `'\u2000'`, "'\u2000'"},
    140 	{'\u3000', `'\u3000'`, `'\u3000'`, "'\u3000'"},
    141 }
    142 
    143 func TestQuoteRune(t *testing.T) {
    144 	for _, tt := range quoterunetests {
    145 		if out := QuoteRune(tt.in); out != tt.out {
    146 			t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
    147 		}
    148 		if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
    149 			t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
    150 		}
    151 	}
    152 }
    153 
    154 func TestQuoteRuneToASCII(t *testing.T) {
    155 	for _, tt := range quoterunetests {
    156 		if out := QuoteRuneToASCII(tt.in); out != tt.ascii {
    157 			t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii)
    158 		}
    159 		if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
    160 			t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
    161 		}
    162 	}
    163 }
    164 
    165 func TestQuoteRuneToGraphic(t *testing.T) {
    166 	for _, tt := range quoterunetests {
    167 		if out := QuoteRuneToGraphic(tt.in); out != tt.graphic {
    168 			t.Errorf("QuoteRuneToGraphic(%U) = %s, want %s", tt.in, out, tt.graphic)
    169 		}
    170 		if out := AppendQuoteRuneToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic {
    171 			t.Errorf("AppendQuoteRuneToGraphic(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic)
    172 		}
    173 	}
    174 }
    175 
    176 type canBackquoteTest struct {
    177 	in  string
    178 	out bool
    179 }
    180 
    181 var canbackquotetests = []canBackquoteTest{
    182 	{"`", false},
    183 	{string(0), false},
    184 	{string(1), false},
    185 	{string(2), false},
    186 	{string(3), false},
    187 	{string(4), false},
    188 	{string(5), false},
    189 	{string(6), false},
    190 	{string(7), false},
    191 	{string(8), false},
    192 	{string(9), true}, // \t
    193 	{string(10), false},
    194 	{string(11), false},
    195 	{string(12), false},
    196 	{string(13), false},
    197 	{string(14), false},
    198 	{string(15), false},
    199 	{string(16), false},
    200 	{string(17), false},
    201 	{string(18), false},
    202 	{string(19), false},
    203 	{string(20), false},
    204 	{string(21), false},
    205 	{string(22), false},
    206 	{string(23), false},
    207 	{string(24), false},
    208 	{string(25), false},
    209 	{string(26), false},
    210 	{string(27), false},
    211 	{string(28), false},
    212 	{string(29), false},
    213 	{string(30), false},
    214 	{string(31), false},
    215 	{string(0x7F), false},
    216 	{`' !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, true},
    217 	{`0123456789`, true},
    218 	{`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true},
    219 	{`abcdefghijklmnopqrstuvwxyz`, true},
    220 	{``, true},
    221 	{"\x80", false},
    222 	{"a\xe0\xa0z", false},
    223 	{"\ufeffabc", false},
    224 	{"a\ufeffz", false},
    225 }
    226 
    227 func TestCanBackquote(t *testing.T) {
    228 	for _, tt := range canbackquotetests {
    229 		if out := CanBackquote(tt.in); out != tt.out {
    230 			t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
    231 		}
    232 	}
    233 }
    234 
    235 type unQuoteTest struct {
    236 	in  string
    237 	out string
    238 }
    239 
    240 var unquotetests = []unQuoteTest{
    241 	{`""`, ""},
    242 	{`"a"`, "a"},
    243 	{`"abc"`, "abc"},
    244 	{`""`, ""},
    245 	{`"hello world"`, "hello world"},
    246 	{`"\xFF"`, "\xFF"},
    247 	{`"\377"`, "\377"},
    248 	{`"\u1234"`, "\u1234"},
    249 	{`"\U00010111"`, "\U00010111"},
    250 	{`"\U0001011111"`, "\U0001011111"},
    251 	{`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""},
    252 	{`"'"`, "'"},
    253 
    254 	{`'a'`, "a"},
    255 	{`''`, ""},
    256 	{`'\a'`, "\a"},
    257 	{`'\x10'`, "\x10"},
    258 	{`'\377'`, "\377"},
    259 	{`'\u1234'`, "\u1234"},
    260 	{`'\U00010111'`, "\U00010111"},
    261 	{`'\t'`, "\t"},
    262 	{`' '`, " "},
    263 	{`'\''`, "'"},
    264 	{`'"'`, "\""},
    265 
    266 	{"``", ``},
    267 	{"`a`", `a`},
    268 	{"`abc`", `abc`},
    269 	{"``", ``},
    270 	{"`hello world`", `hello world`},
    271 	{"`\\xFF`", `\xFF`},
    272 	{"`\\377`", `\377`},
    273 	{"`\\`", `\`},
    274 	{"`\n`", "\n"},
    275 	{"`	`", `	`},
    276 	{"` `", ` `},
    277 	{"`a\rb`", "ab"},
    278 }
    279 
    280 var misquoted = []string{
    281 	``,
    282 	`"`,
    283 	`"a`,
    284 	`"'`,
    285 	`b"`,
    286 	`"\"`,
    287 	`"\9"`,
    288 	`"\19"`,
    289 	`"\129"`,
    290 	`'\'`,
    291 	`'\9'`,
    292 	`'\19'`,
    293 	`'\129'`,
    294 	`'ab'`,
    295 	`"\x1!"`,
    296 	`"\U12345678"`,
    297 	`"\z"`,
    298 	"`",
    299 	"`xxx",
    300 	"`\"",
    301 	`"\'"`,
    302 	`'\"'`,
    303 	"\"\n\"",
    304 	"\"\\n\n\"",
    305 	"'\n'",
    306 }
    307 
    308 func TestUnquote(t *testing.T) {
    309 	for _, tt := range unquotetests {
    310 		if out, err := Unquote(tt.in); err != nil || out != tt.out {
    311 			t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
    312 		}
    313 	}
    314 
    315 	// run the quote tests too, backward
    316 	for _, tt := range quotetests {
    317 		if in, err := Unquote(tt.out); in != tt.in {
    318 			t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
    319 		}
    320 	}
    321 
    322 	for _, s := range misquoted {
    323 		if out, err := Unquote(s); out != "" || err != ErrSyntax {
    324 			t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax)
    325 		}
    326 	}
    327 }
    328 
    329 func BenchmarkUnquoteEasy(b *testing.B) {
    330 	for i := 0; i < b.N; i++ {
    331 		Unquote(`"Give me a rock, paper and scissors and I will move the world."`)
    332 	}
    333 }
    334 
    335 func BenchmarkUnquoteHard(b *testing.B) {
    336 	for i := 0; i < b.N; i++ {
    337 		Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`)
    338 	}
    339 }
    340