github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/models/strconv/quote_test.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package strconv
    22  
    23  import (
    24  	"bytes"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  type quoteTest struct {
    31  	in  string
    32  	out string
    33  }
    34  
    35  var quotetests = []quoteTest{
    36  	// NB: original strconv tests
    37  	{"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`},
    38  	{"\\", `"\\"`},
    39  	{"abc\xffdef", `"abc\xffdef"`},
    40  	{"\u263a", `"☺"`},
    41  	{"\U0010ffff", `"\U0010ffff"`},
    42  	{"\x04", `"\x04"`},
    43  	// Some non-printable but graphic runes. Final column is double-quoted.
    44  	{"!\u00a0!\u2000!\u3000!", `"!\u00a0!\u2000!\u3000!"`},
    45  
    46  	// NB: Additional tests
    47  	{`"tag"`, `"\"tag\""`},
    48  	{`"t"a"g"`, `"\"t\"a\"g\""`},
    49  }
    50  
    51  func TestEscape(t *testing.T) {
    52  	for _, tt := range quotetests {
    53  		in := []byte(tt.in)
    54  		bufferLen := EscapedLength(in)
    55  		bb := make([]byte, bufferLen)
    56  		idx := Escape(bb, in, 0)
    57  		assert.Equal(t, idx, bufferLen)
    58  		expected := []byte(tt.out)
    59  		assert.Equal(t, expected[1:len(expected)-1], bb)
    60  	}
    61  }
    62  
    63  func TestQuote(t *testing.T) {
    64  	for _, tt := range quotetests {
    65  		in := []byte(tt.in)
    66  		bufferLen := QuotedLength(in)
    67  		bb := make([]byte, bufferLen)
    68  		idx := Quote(bb, in, 0)
    69  		assert.Equal(t, idx, bufferLen)
    70  		assert.Equal(t, []byte(tt.out), bb)
    71  	}
    72  }
    73  
    74  func TestQuoteWithOffset(t *testing.T) {
    75  	for _, tt := range quotetests {
    76  		in := []byte(tt.in)
    77  		bufferLen := QuotedLength(in)
    78  		bb := make([]byte, bufferLen+2)
    79  		bb[0] = '!'
    80  		bb[bufferLen+1] = '!'
    81  		idx := Quote(bb, in, 1)
    82  		assert.Equal(t, idx, bufferLen+1)
    83  		assert.Equal(t, []byte("!"+tt.out+"!"), bb)
    84  	}
    85  }
    86  
    87  func TestSimpleQuote(t *testing.T) {
    88  	for _, tt := range quotetests {
    89  		in := []byte(tt.in)
    90  		// accounts for buffer and 2 quotation characters
    91  		bufferLen := len(in) + 2
    92  		bb := make([]byte, bufferLen)
    93  		idx := QuoteSimple(bb, in, 0)
    94  		assert.Equal(t, idx, bufferLen)
    95  		expected := []byte("\"" + tt.in + "\"")
    96  		assert.Equal(t, expected, bb)
    97  	}
    98  }
    99  
   100  func TestSimpleQuoteWithOffset(t *testing.T) {
   101  	for _, tt := range quotetests {
   102  		in := []byte(tt.in)
   103  		// accounts for buffer, additional characters, and 2 quotation characters
   104  		bufferLen := len(in) + 4
   105  		bb := make([]byte, bufferLen)
   106  		bb[0] = '!'
   107  		bb[bufferLen-1] = '!'
   108  		idx := QuoteSimple(bb, in, 1)
   109  		assert.Equal(t, idx, bufferLen-1)
   110  		expected := []byte("!\"" + tt.in + "\"!")
   111  		assert.Equal(t, expected, bb)
   112  	}
   113  }
   114  
   115  func TestLongQuoteWithOffset(t *testing.T) {
   116  	for _, tt := range quotetests {
   117  		repeat := 100
   118  		in := []byte(tt.in)
   119  		bufferLen := QuotedLength(in)
   120  		bb := make([]byte, bufferLen*repeat)
   121  		for i := 0; i < repeat; i++ {
   122  			idx := Quote(bb, in, bufferLen*i)
   123  			assert.Equal(t, idx, bufferLen*(i+1))
   124  			expected := ""
   125  			for j := 0; j <= i; j++ {
   126  				expected += tt.out
   127  			}
   128  
   129  			assert.Equal(t, []byte(expected), bb[0:idx])
   130  		}
   131  	}
   132  }
   133  
   134  func BenchmarkQuoteSimple(b *testing.B) {
   135  	src := []byte("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v")
   136  	dst := make([]byte, len(src)+2)
   137  	for i := 0; i < b.N; i++ {
   138  		QuoteSimple(dst, src, 0)
   139  	}
   140  }
   141  
   142  func BenchmarkQuote(b *testing.B) {
   143  	src := []byte("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v")
   144  	dst := make([]byte, QuotedLength(src))
   145  	for i := 0; i < b.N; i++ {
   146  		Quote(dst, src, 0)
   147  	}
   148  }
   149  
   150  func BenchmarkQuoteWithOffset(b *testing.B) {
   151  	src := []byte("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v")
   152  	l := QuotedLength(src)
   153  	dst := make([]byte, l*100)
   154  	for i := 0; i < b.N; i++ {
   155  		Quote(dst, src, l*(i%100))
   156  	}
   157  }
   158  
   159  // NB: original utf8.EncodeRune tests
   160  var utf8map = []struct {
   161  	r   rune
   162  	str string
   163  }{
   164  	{0x0000, "\x00"},
   165  	{0x0001, "\x01"},
   166  	{0x007e, "\x7e"},
   167  	{0x007f, "\x7f"},
   168  	{0x0080, "\xc2\x80"},
   169  	{0x0081, "\xc2\x81"},
   170  	{0x00bf, "\xc2\xbf"},
   171  	{0x00c0, "\xc3\x80"},
   172  	{0x00c1, "\xc3\x81"},
   173  	{0x00c8, "\xc3\x88"},
   174  	{0x00d0, "\xc3\x90"},
   175  	{0x00e0, "\xc3\xa0"},
   176  	{0x00f0, "\xc3\xb0"},
   177  	{0x00f8, "\xc3\xb8"},
   178  	{0x00ff, "\xc3\xbf"},
   179  	{0x0100, "\xc4\x80"},
   180  	{0x07ff, "\xdf\xbf"},
   181  	{0x0400, "\xd0\x80"},
   182  	{0x0800, "\xe0\xa0\x80"},
   183  	{0x0801, "\xe0\xa0\x81"},
   184  	{0x1000, "\xe1\x80\x80"},
   185  	{0xd000, "\xed\x80\x80"},
   186  	{0xd7ff, "\xed\x9f\xbf"}, // last code point before surrogate half.
   187  	{0xe000, "\xee\x80\x80"}, // first code point after surrogate half.
   188  	{0xfffe, "\xef\xbf\xbe"},
   189  	{0xffff, "\xef\xbf\xbf"},
   190  	{0x10000, "\xf0\x90\x80\x80"},
   191  	{0x10001, "\xf0\x90\x80\x81"},
   192  	{0x40000, "\xf1\x80\x80\x80"},
   193  	{0x10fffe, "\xf4\x8f\xbf\xbe"},
   194  	{0x10ffff, "\xf4\x8f\xbf\xbf"},
   195  	{0xFFFD, "\xef\xbf\xbd"},
   196  }
   197  
   198  func TestEncodeRune(t *testing.T) {
   199  	for _, m := range utf8map {
   200  		b := []byte(m.str)
   201  		var bb [10]byte
   202  		n := encodeRune(bb[:], m.r, 0)
   203  		b1 := bb[0:n]
   204  		if !bytes.Equal(b, b1) {
   205  			t.Errorf("EncodeRune(%#04x) = %q want %q", m.r, b1, b)
   206  		}
   207  	}
   208  }
   209  
   210  func TestEncodeRuneWithOffset(t *testing.T) {
   211  	for _, m := range utf8map {
   212  		b := []byte("!" + m.str)
   213  		var bb [10]byte
   214  		bb[0] = '!'
   215  		n := encodeRune(bb[:], m.r, 1)
   216  		b1 := bb[0:n]
   217  		if !bytes.Equal(b, b1) {
   218  			t.Errorf("EncodeRune(%#04x) = %q want %q", m.r, b1, b)
   219  		}
   220  	}
   221  }