vitess.io/vitess@v0.16.2/go/mysql/binlog_event_json_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package mysql 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "testing" 23 24 "github.com/stretchr/testify/require" 25 ) 26 27 func TestJSONTypes(t *testing.T) { 28 // most of these test cases have been taken from open source java/python adapters 29 // like https://github.com/shyiko/mysql-binlog-connector-java/pull/119/files 30 testcases := []struct { 31 name string 32 data []byte 33 expected string 34 isMap bool 35 }{{ 36 name: "null", 37 data: []byte{}, 38 expected: `null`, 39 }, { 40 name: "map, string value", 41 data: []byte{0, 1, 0, 14, 0, 11, 0, 1, 0, 12, 12, 0, 97, 1, 98}, 42 expected: `{"a":"b"}`, 43 }, { 44 name: "map, int value", 45 data: []byte{0, 1, 0, 12, 0, 11, 0, 1, 0, 5, 2, 0, 97}, 46 expected: `{"a":2}`, 47 }, { 48 name: "map, object value", 49 data: []byte{0, 1, 0, 29, 0, 11, 0, 4, 0, 0, 15, 0, 97, 115, 100, 102, 1, 0, 14, 0, 11, 0, 3, 0, 5, 123, 0, 102, 111, 111}, 50 expected: `{"asdf":{"foo":123}}`, 51 }, { 52 name: "list of ints", 53 data: []byte{2, 2, 0, 10, 0, 5, 1, 0, 5, 2, 0}, 54 expected: `[1,2]`, 55 }, { 56 name: "list of maps", 57 data: []byte{0, 4, 0, 60, 0, 32, 0, 1, 0, 33, 0, 1, 0, 34, 0, 2, 0, 36, 0, 2, 0, 12, 38, 0, 12, 40, 0, 12, 42, 0, 2, 46, 0, 97, 99, 97, 98, 98, 99, 1, 98, 1, 100, 3, 97, 98, 99, 2, 0, 14, 0, 12, 10, 0, 12, 12, 0, 1, 120, 1, 121}, 58 expected: `{"a":"b","c":"d","ab":"abc","bc":["x","y"]}`, 59 isMap: true, 60 }, { 61 name: "list with one string", 62 data: []byte{2, 1, 0, 37, 0, 12, 8, 0, 0, 4, 104, 101, 114, 101}, 63 expected: `["here"]`, 64 }, { 65 name: "list varied", 66 data: []byte{2, 3, 0, 37, 0, 12, 13, 0, 2, 18, 0, 12, 33, 0, 4, 104, 101, 114, 101, 2, 0, 15, 0, 12, 10, 0, 12, 12, 0, 1, 73, 2, 97, 109, 3, 33, 33, 33}, 67 expected: `["here",["I","am"],"!!!"]`, 68 }, { 69 name: "string", 70 data: []byte{12, 13, 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103}, 71 expected: `"scalar string"`, 72 }, { 73 name: "map, long string value", 74 data: []byte{0, 1, 0, 149, 0, 11, 0, 6, 0, 12, 17, 0, 115, 99, 111, 112, 101, 115, 130, 1, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 69, 65, 65, 65, 65, 65, 65, 69, 65, 65, 65, 65, 65, 65, 56, 65, 65, 65, 66, 103, 65, 65, 65, 65, 65, 65, 66, 65, 65, 65, 65, 67, 65, 65, 65, 65, 65, 65, 65, 65, 65, 84, 216, 142, 184}, 75 expected: `{"scopes":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAEAAAAAAEAAAAAA8AAABgAAAAAABAAAACAAAAAAAAA"}`, 76 }, { 77 // repeat the same string 10 times, to test the case where length of string 78 // requires 2 bytes to store 79 name: "long string", 80 data: []byte{12, 130, 1, 81 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 82 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 83 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 84 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 85 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 86 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 87 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 88 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 89 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103, 90 115, 99, 97, 108, 97, 114, 32, 115, 116, 114, 105, 110, 103}, 91 expected: `"scalar stringscalar stringscalar stringscalar stringscalar stringscalar stringscalar stringscalar stringscalar stringscalar string"`, 92 }, { 93 name: "bool true", 94 data: []byte{4, 1}, 95 expected: `true`, 96 }, { 97 name: "bool false", 98 data: []byte{4, 2}, 99 expected: `false`, 100 }, { 101 name: "bool null", 102 data: []byte{4, 0}, 103 expected: `null`, 104 }, { 105 name: "uint16 max", 106 data: []byte{6, 255, 255}, 107 expected: `65535`, 108 }, { 109 name: "uint32 max", 110 data: []byte{8, 255, 255, 255, 255}, 111 expected: `4294967295`, 112 }, { 113 name: "uint64 max", 114 data: []byte{10, 255, 255, 255, 255, 255, 255, 255, 255}, 115 expected: `18446744073709551615`, 116 }, { 117 name: "int16 -1", 118 data: []byte{5, 255, 255}, 119 expected: `-1`, 120 }, { 121 name: "int32 -1", 122 data: []byte{7, 255, 255, 255, 255}, 123 expected: `-1`, 124 }, { 125 name: "int64 -1", 126 data: []byte{9, 255, 255, 255, 255, 255, 255, 255, 255}, 127 expected: `-1`, 128 }, { 129 name: "int16 max", 130 data: []byte{5, 255, 127}, 131 expected: `32767`, 132 }, { 133 name: "int32 max", 134 data: []byte{7, 255, 255, 255, 127}, 135 expected: `2147483647`, 136 }, { 137 name: "int64 max", 138 data: []byte{9, 255, 255, 255, 255, 255, 255, 255, 127}, 139 expected: `9223372036854775807`, 140 }, { 141 name: "uint16/1", 142 data: []byte{6, 1, 0}, 143 expected: `1`, 144 }, { 145 name: "int32/32768", 146 data: []byte{7, 0, 128, 0, 0}, 147 expected: `32768`, 148 }, { 149 name: "int16/neg", 150 data: []byte{5, 0, 128}, 151 expected: `-32768`, 152 }, { 153 name: "int32/neg", 154 data: []byte{7, 255, 127, 255, 255}, 155 expected: `-32769`, 156 }, { 157 name: "uint32", 158 data: []byte{8, 0, 128, 0, 0}, 159 expected: `32768`, 160 }, { 161 name: "int64", 162 data: []byte{9, 0, 0, 0, 128, 0, 0, 0, 0}, 163 expected: `2147483648`, 164 }, { 165 name: "int32/neg", 166 data: []byte{7, 0, 0, 0, 128}, 167 expected: `-2147483648`, 168 }, { 169 name: "int64/neg", 170 data: []byte{9, 255, 255, 255, 127, 255, 255, 255, 255}, 171 expected: `-2147483649`, 172 }, { 173 name: "uint64", 174 data: []byte{10, 255, 255, 255, 255, 255, 255, 255, 255}, 175 expected: `18446744073709551615`, 176 }, { 177 name: "int64/neg", 178 data: []byte{9, 0, 0, 0, 0, 0, 0, 0, 128}, 179 expected: `-9223372036854775808`, 180 }, { 181 name: "double", 182 data: []byte{11, 110, 134, 27, 240, 249, 33, 9, 64}, 183 expected: `3.14159`, 184 }, { 185 name: "empty map", 186 data: []byte{0, 0, 0, 4, 0}, 187 expected: `{}`, 188 }, { 189 name: "empty list", 190 data: []byte{2, 0, 0, 4, 0}, 191 expected: `[]`, 192 }, { 193 // opaque, datetime 194 name: "datetime", 195 data: []byte{15, 12, 8, 0, 0, 0, 25, 118, 31, 149, 25}, 196 expected: `"2015-01-15 23:24:25.000000"`, 197 }, { 198 // opaque, time 199 name: "time", 200 data: []byte{15, 11, 8, 0, 0, 0, 25, 118, 1, 0, 0}, 201 expected: `"23:24:25.000000"`, 202 }, { 203 // opaque, time 204 name: "time2", 205 data: []byte{15, 11, 8, 192, 212, 1, 25, 118, 1, 0, 0}, 206 expected: `"23:24:25.120000"`, 207 }, { 208 // opaque, date 209 name: "date", 210 data: []byte{15, 10, 8, 0, 0, 0, 0, 0, 30, 149, 25}, 211 expected: `"2015-01-15"`, 212 }, { 213 // opaque, decimal 214 name: "decimal", 215 data: []byte{15, 246, 8, 13, 4, 135, 91, 205, 21, 4, 210}, 216 expected: `1.234567891234e+08`, 217 }, { 218 // opaque, bit field. Not yet implemented. 219 name: "bitfield: unimplemented", 220 data: []byte{15, 16, 2, 202, 254}, 221 expected: `opaque type 16 is not supported yet, data [2 202 254]`, 222 }} 223 for _, tc := range testcases { 224 name := fmt.Sprintf("%s (%s)", tc.name, tc.expected) 225 t.Run(name, func(t *testing.T) { 226 val, err := getJSONValue(tc.data) 227 if err != nil { 228 require.Equal(t, tc.expected, err.Error()) 229 return 230 } 231 if tc.isMap { // map keys sorting order is not guaranteed, so we convert back to golang maps and compare 232 var gotJSON, wantJSON map[string]any 233 err = json.Unmarshal([]byte(val), &gotJSON) 234 require.NoError(t, err) 235 err = json.Unmarshal([]byte(tc.expected), &wantJSON) 236 require.NoError(t, err) 237 require.EqualValues(t, wantJSON, gotJSON) 238 return 239 } 240 require.Equal(t, tc.expected, val) 241 }) 242 } 243 }