github.com/m3db/m3@v1.5.0/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 }