...
Run Format

Source file src/strconv/quote_test.go

Documentation: 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  // Issue 23685: invalid UTF-8 should not go through the fast path.
   330  func TestUnquoteInvalidUTF8(t *testing.T) {
   331  	tests := []struct {
   332  		in string
   333  
   334  		// one of:
   335  		want    string
   336  		wantErr string
   337  	}{
   338  		{in: `"foo"`, want: "foo"},
   339  		{in: `"foo`, wantErr: "invalid syntax"},
   340  		{in: `"` + "\xc0" + `"`, want: "\xef\xbf\xbd"},
   341  		{in: `"a` + "\xc0" + `"`, want: "a\xef\xbf\xbd"},
   342  		{in: `"\t` + "\xc0" + `"`, want: "\t\xef\xbf\xbd"},
   343  	}
   344  	for i, tt := range tests {
   345  		got, err := Unquote(tt.in)
   346  		var gotErr string
   347  		if err != nil {
   348  			gotErr = err.Error()
   349  		}
   350  		if gotErr != tt.wantErr {
   351  			t.Errorf("%d. Unquote(%q) = err %v; want %q", i, tt.in, err, tt.wantErr)
   352  		}
   353  		if tt.wantErr == "" && err == nil && got != tt.want {
   354  			t.Errorf("%d. Unquote(%q) = %02x; want %02x", i, tt.in, []byte(got), []byte(tt.want))
   355  		}
   356  	}
   357  }
   358  
   359  func BenchmarkUnquoteEasy(b *testing.B) {
   360  	for i := 0; i < b.N; i++ {
   361  		Unquote(`"Give me a rock, paper and scissors and I will move the world."`)
   362  	}
   363  }
   364  
   365  func BenchmarkUnquoteHard(b *testing.B) {
   366  	for i := 0; i < b.N; i++ {
   367  		Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`)
   368  	}
   369  }
   370  

View as plain text