vitess.io/vitess@v0.16.2/go/sqltypes/value_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 sqltypes 18 19 import ( 20 "bytes" 21 "reflect" 22 "strings" 23 "testing" 24 25 "github.com/stretchr/testify/assert" 26 27 "github.com/stretchr/testify/require" 28 29 querypb "vitess.io/vitess/go/vt/proto/query" 30 ) 31 32 const ( 33 InvalidNeg = "-9223372036854775809" 34 MinNeg = "-9223372036854775808" 35 MinPos = "18446744073709551615" 36 InvalidPos = "18446744073709551616" 37 ) 38 39 func TestNewValue(t *testing.T) { 40 testcases := []struct { 41 inType querypb.Type 42 inVal string 43 outVal Value 44 outErr string 45 }{{ 46 inType: Null, 47 inVal: "", 48 outVal: NULL, 49 }, { 50 inType: Int8, 51 inVal: "1", 52 outVal: TestValue(Int8, "1"), 53 }, { 54 inType: Int16, 55 inVal: "1", 56 outVal: TestValue(Int16, "1"), 57 }, { 58 inType: Int24, 59 inVal: "1", 60 outVal: TestValue(Int24, "1"), 61 }, { 62 inType: Int32, 63 inVal: "1", 64 outVal: TestValue(Int32, "1"), 65 }, { 66 inType: Int64, 67 inVal: "1", 68 outVal: TestValue(Int64, "1"), 69 }, { 70 inType: Uint8, 71 inVal: "1", 72 outVal: TestValue(Uint8, "1"), 73 }, { 74 inType: Uint16, 75 inVal: "1", 76 outVal: TestValue(Uint16, "1"), 77 }, { 78 inType: Uint24, 79 inVal: "1", 80 outVal: TestValue(Uint24, "1"), 81 }, { 82 inType: Uint32, 83 inVal: "1", 84 outVal: TestValue(Uint32, "1"), 85 }, { 86 inType: Uint64, 87 inVal: "1", 88 outVal: TestValue(Uint64, "1"), 89 }, { 90 inType: Uint64, 91 inVal: "01", 92 outVal: TestValue(Uint64, "01"), 93 }, { 94 inType: Int64, 95 inVal: "01", 96 outVal: TestValue(Int64, "01"), 97 }, { 98 inType: Float32, 99 inVal: "1.00", 100 outVal: TestValue(Float32, "1.00"), 101 }, { 102 inType: Float64, 103 inVal: "1.00", 104 outVal: TestValue(Float64, "1.00"), 105 }, { 106 inType: Decimal, 107 inVal: "1.00", 108 outVal: TestValue(Decimal, "1.00"), 109 }, { 110 inType: Timestamp, 111 inVal: "2012-02-24 23:19:43", 112 outVal: TestValue(Timestamp, "2012-02-24 23:19:43"), 113 }, { 114 inType: Date, 115 inVal: "2012-02-24", 116 outVal: TestValue(Date, "2012-02-24"), 117 }, { 118 inType: Time, 119 inVal: "23:19:43", 120 outVal: TestValue(Time, "23:19:43"), 121 }, { 122 inType: Datetime, 123 inVal: "2012-02-24 23:19:43", 124 outVal: TestValue(Datetime, "2012-02-24 23:19:43"), 125 }, { 126 inType: Year, 127 inVal: "1", 128 outVal: TestValue(Year, "1"), 129 }, { 130 inType: Text, 131 inVal: "a", 132 outVal: TestValue(Text, "a"), 133 }, { 134 inType: Blob, 135 inVal: "a", 136 outVal: TestValue(Blob, "a"), 137 }, { 138 inType: VarChar, 139 inVal: "a", 140 outVal: TestValue(VarChar, "a"), 141 }, { 142 inType: Binary, 143 inVal: "a", 144 outVal: TestValue(Binary, "a"), 145 }, { 146 inType: Char, 147 inVal: "a", 148 outVal: TestValue(Char, "a"), 149 }, { 150 inType: Bit, 151 inVal: "1", 152 outVal: TestValue(Bit, "1"), 153 }, { 154 inType: Enum, 155 inVal: "a", 156 outVal: TestValue(Enum, "a"), 157 }, { 158 inType: Set, 159 inVal: "a", 160 outVal: TestValue(Set, "a"), 161 }, { 162 inType: VarBinary, 163 inVal: "a", 164 outVal: TestValue(VarBinary, "a"), 165 }, { 166 inType: Int64, 167 inVal: InvalidNeg, 168 outErr: "out of range", 169 }, { 170 inType: Int64, 171 inVal: InvalidPos, 172 outErr: "out of range", 173 }, { 174 inType: Uint64, 175 inVal: "-1", 176 outErr: "invalid syntax", 177 }, { 178 inType: Uint64, 179 inVal: InvalidPos, 180 outErr: "out of range", 181 }, { 182 inType: Float64, 183 inVal: "a", 184 outErr: "invalid syntax", 185 }, { 186 inType: Expression, 187 inVal: "a", 188 outErr: "invalid type specified for MakeValue: EXPRESSION", 189 }} 190 for _, tcase := range testcases { 191 v, err := NewValue(tcase.inType, []byte(tcase.inVal)) 192 if tcase.outErr != "" { 193 if err == nil || !strings.Contains(err.Error(), tcase.outErr) { 194 t.Errorf("ValueFromBytes(%v, %v) error: %v, must contain %v", tcase.inType, tcase.inVal, err, tcase.outErr) 195 } 196 continue 197 } 198 if err != nil { 199 t.Errorf("ValueFromBytes(%v, %v) error: %v", tcase.inType, tcase.inVal, err) 200 continue 201 } 202 if !reflect.DeepEqual(v, tcase.outVal) { 203 t.Errorf("ValueFromBytes(%v, %v) = %v, want %v", tcase.inType, tcase.inVal, v, tcase.outVal) 204 } 205 } 206 } 207 208 // TestNew tests 'New' functions that are not tested 209 // through other code paths. 210 func TestNew(t *testing.T) { 211 got := NewInt32(1) 212 want := MakeTrusted(Int32, []byte("1")) 213 if !reflect.DeepEqual(got, want) { 214 t.Errorf("NewInt32(aa): %v, want %v", got, want) 215 } 216 217 got = NewVarBinary("aa") 218 want = MakeTrusted(VarBinary, []byte("aa")) 219 if !reflect.DeepEqual(got, want) { 220 t.Errorf("NewVarBinary(aa): %v, want %v", got, want) 221 } 222 } 223 224 func TestMakeTrusted(t *testing.T) { 225 v := MakeTrusted(Null, []byte("abcd")) 226 if !reflect.DeepEqual(v, NULL) { 227 t.Errorf("MakeTrusted(Null...) = %v, want null", v) 228 } 229 v = MakeTrusted(Int64, []byte("1")) 230 want := TestValue(Int64, "1") 231 if !reflect.DeepEqual(v, want) { 232 t.Errorf("MakeTrusted(Int64, \"1\") = %v, want %v", v, want) 233 } 234 } 235 236 func TestIntegralValue(t *testing.T) { 237 testcases := []struct { 238 in string 239 outVal Value 240 outErr string 241 }{{ 242 in: MinNeg, 243 outVal: TestValue(Int64, MinNeg), 244 }, { 245 in: "1", 246 outVal: TestValue(Int64, "1"), 247 }, { 248 in: MinPos, 249 outVal: TestValue(Uint64, MinPos), 250 }, { 251 in: InvalidPos, 252 outErr: "out of range", 253 }} 254 for _, tcase := range testcases { 255 v, err := NewIntegral(tcase.in) 256 if tcase.outErr != "" { 257 if err == nil || !strings.Contains(err.Error(), tcase.outErr) { 258 t.Errorf("BuildIntegral(%v) error: %v, must contain %v", tcase.in, err, tcase.outErr) 259 } 260 continue 261 } 262 if err != nil { 263 t.Errorf("BuildIntegral(%v) error: %v", tcase.in, err) 264 continue 265 } 266 if !reflect.DeepEqual(v, tcase.outVal) { 267 t.Errorf("BuildIntegral(%v) = %v, want %v", tcase.in, v, tcase.outVal) 268 } 269 } 270 } 271 272 func TestInterfaceValue(t *testing.T) { 273 testcases := []struct { 274 in any 275 out Value 276 }{{ 277 in: nil, 278 out: NULL, 279 }, { 280 in: []byte("a"), 281 out: TestValue(VarBinary, "a"), 282 }, { 283 in: int64(1), 284 out: TestValue(Int64, "1"), 285 }, { 286 in: uint64(1), 287 out: TestValue(Uint64, "1"), 288 }, { 289 in: float64(1.2), 290 out: TestValue(Float64, "1.2"), 291 }, { 292 in: "a", 293 out: TestValue(VarChar, "a"), 294 }} 295 for _, tcase := range testcases { 296 v, err := InterfaceToValue(tcase.in) 297 if err != nil { 298 t.Errorf("BuildValue(%#v) error: %v", tcase.in, err) 299 continue 300 } 301 if !reflect.DeepEqual(v, tcase.out) { 302 t.Errorf("BuildValue(%#v) = %v, want %v", tcase.in, v, tcase.out) 303 } 304 } 305 306 _, err := InterfaceToValue(make(chan bool)) 307 want := "unexpected" 308 if err == nil || !strings.Contains(err.Error(), want) { 309 t.Errorf("BuildValue(chan): %v, want %v", err, want) 310 } 311 } 312 313 func TestAccessors(t *testing.T) { 314 v := TestValue(Int64, "1") 315 if v.Type() != Int64 { 316 t.Errorf("v.Type=%v, want Int64", v.Type()) 317 } 318 if !bytes.Equal(v.Raw(), []byte("1")) { 319 t.Errorf("v.Raw=%s, want 1", v.Raw()) 320 } 321 if v.Len() != 1 { 322 t.Errorf("v.Len=%d, want 1", v.Len()) 323 } 324 if v.ToString() != "1" { 325 t.Errorf("v.String=%s, want 1", v.ToString()) 326 } 327 if v.IsNull() { 328 t.Error("v.IsNull: true, want false") 329 } 330 if !v.IsIntegral() { 331 t.Error("v.IsIntegral: false, want true") 332 } 333 if !v.IsSigned() { 334 t.Error("v.IsSigned: false, want true") 335 } 336 if v.IsUnsigned() { 337 t.Error("v.IsUnsigned: true, want false") 338 } 339 if v.IsFloat() { 340 t.Error("v.IsFloat: true, want false") 341 } 342 if v.IsQuoted() { 343 t.Error("v.IsQuoted: true, want false") 344 } 345 if v.IsText() { 346 t.Error("v.IsText: true, want false") 347 } 348 if v.IsBinary() { 349 t.Error("v.IsBinary: true, want false") 350 } 351 { 352 i, err := v.ToInt64() 353 if err != nil { 354 t.Errorf("v.ToInt64: got error: %+v, want no error", err) 355 } 356 if i != 1 { 357 t.Errorf("v.ToInt64=%+v, want 1", i) 358 } 359 } 360 { 361 i, err := v.ToUint64() 362 if err != nil { 363 t.Errorf("v.ToUint64: got error: %+v, want no error", err) 364 } 365 if i != 1 { 366 t.Errorf("v.ToUint64=%+v, want 1", i) 367 } 368 } 369 { 370 b, err := v.ToBool() 371 if err != nil { 372 t.Errorf("v.ToBool: got error: %+v, want no error", err) 373 } 374 if !b { 375 t.Errorf("v.ToBool=%+v, want true", b) 376 } 377 } 378 } 379 380 func TestAccessorsNegative(t *testing.T) { 381 v := TestValue(Int64, "-1") 382 if v.ToString() != "-1" { 383 t.Errorf("v.String=%s, want -1", v.ToString()) 384 } 385 if v.IsNull() { 386 t.Error("v.IsNull: true, want false") 387 } 388 if !v.IsIntegral() { 389 t.Error("v.IsIntegral: false, want true") 390 } 391 { 392 i, err := v.ToInt64() 393 if err != nil { 394 t.Errorf("v.ToInt64: got error: %+v, want no error", err) 395 } 396 if i != -1 { 397 t.Errorf("v.ToInt64=%+v, want -1", i) 398 } 399 } 400 { 401 if _, err := v.ToUint64(); err == nil { 402 t.Error("v.ToUint64: got no error, want error") 403 } 404 } 405 { 406 if _, err := v.ToBool(); err == nil { 407 t.Error("v.ToUint64: got no error, want error") 408 } 409 } 410 } 411 412 func TestToBytesAndString(t *testing.T) { 413 for _, v := range []Value{ 414 NULL, 415 TestValue(Int64, "1"), 416 TestValue(Int64, "12"), 417 } { 418 vBytes, err := v.ToBytes() 419 require.NoError(t, err) 420 if b := vBytes; !bytes.Equal(b, v.Raw()) { 421 t.Errorf("%v.ToBytes: %s, want %s", v, b, v.Raw()) 422 } 423 if s := v.ToString(); s != string(v.Raw()) { 424 t.Errorf("%v.ToString: %s, want %s", v, s, v.Raw()) 425 } 426 } 427 428 tv := TestValue(Expression, "aa") 429 tvBytes, err := tv.ToBytes() 430 require.EqualError(t, err, "expression cannot be converted to bytes") 431 if b := tvBytes; b != nil { 432 t.Errorf("%v.ToBytes: %s, want nil", tv, b) 433 } 434 if s := tv.ToString(); s != "" { 435 t.Errorf("%v.ToString: %s, want \"\"", tv, s) 436 } 437 } 438 439 func TestEncode(t *testing.T) { 440 testcases := []struct { 441 in Value 442 outSQL string 443 outASCII string 444 }{{ 445 in: NULL, 446 outSQL: "null", 447 outASCII: "null", 448 }, { 449 in: TestValue(Int64, "1"), 450 outSQL: "1", 451 outASCII: "1", 452 }, { 453 in: TestValue(VarChar, "foo"), 454 outSQL: "'foo'", 455 outASCII: "'Zm9v'", 456 }, { 457 in: TestValue(VarChar, "\x00'\"\b\n\r\t\x1A\\"), 458 outSQL: "'\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\'", 459 outASCII: "'ACciCAoNCRpc'", 460 }, { 461 in: TestValue(Bit, "a"), 462 outSQL: "b'01100001'", 463 outASCII: "'YQ=='", 464 }} 465 for _, tcase := range testcases { 466 buf := &bytes.Buffer{} 467 tcase.in.EncodeSQL(buf) 468 if tcase.outSQL != buf.String() { 469 t.Errorf("%v.EncodeSQL = %q, want %q", tcase.in, buf.String(), tcase.outSQL) 470 } 471 buf = &bytes.Buffer{} 472 tcase.in.EncodeASCII(buf) 473 if tcase.outASCII != buf.String() { 474 t.Errorf("%v.EncodeASCII = %q, want %q", tcase.in, buf.String(), tcase.outASCII) 475 } 476 } 477 } 478 479 // TestEncodeMap ensures DontEscape is not escaped 480 func TestEncodeMap(t *testing.T) { 481 if SQLEncodeMap[DontEscape] != DontEscape { 482 t.Errorf("SQLEncodeMap[DontEscape] = %v, want %v", SQLEncodeMap[DontEscape], DontEscape) 483 } 484 if SQLDecodeMap[DontEscape] != DontEscape { 485 t.Errorf("SQLDecodeMap[DontEscape] = %v, want %v", SQLEncodeMap[DontEscape], DontEscape) 486 } 487 } 488 489 func TestHexAndBitToBytes(t *testing.T) { 490 tcases := []struct { 491 in Value 492 out []byte 493 }{{ 494 in: MakeTrusted(HexNum, []byte("0x1234")), 495 out: []byte{0x12, 0x34}, 496 }, { 497 in: MakeTrusted(HexVal, []byte("X'1234'")), 498 out: []byte{0x12, 0x34}, 499 }, { 500 in: MakeTrusted(BitNum, []byte("0b1001000110100")), 501 out: []byte{0x12, 0x34}, 502 }, { 503 in: MakeTrusted(BitNum, []byte("0b11101010100101010010101010101010101010101000100100100100100101001101010101010101000001")), 504 out: []byte{0x3a, 0xa5, 0x4a, 0xaa, 0xaa, 0xa2, 0x49, 0x25, 0x35, 0x55, 0x41}, 505 }} 506 507 for _, tcase := range tcases { 508 t.Run(tcase.in.String(), func(t *testing.T) { 509 out, err := tcase.in.ToBytes() 510 require.NoError(t, err) 511 assert.Equal(t, tcase.out, out) 512 }) 513 } 514 }