github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/server/util_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "time" 18 19 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 20 . "github.com/whtcorpsinc/check" 21 "github.com/whtcorpsinc/errors" 22 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 23 "github.com/whtcorpsinc/milevadb/config" 24 "github.com/whtcorpsinc/milevadb/ekv" 25 "github.com/whtcorpsinc/milevadb/petri" 26 "github.com/whtcorpsinc/milevadb/soliton/chunk" 27 "github.com/whtcorpsinc/milevadb/soliton/mock" 28 "github.com/whtcorpsinc/milevadb/soliton/testleak" 29 "github.com/whtcorpsinc/milevadb/stochastik" 30 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 31 "github.com/whtcorpsinc/milevadb/types" 32 "github.com/whtcorpsinc/milevadb/types/json" 33 ) 34 35 var _ = Suite(&testUtilSuite{}) 36 37 func newStoreWithBootstrap() (ekv.CausetStorage, *petri.Petri, error) { 38 causetstore, err := mockstore.NewMockStore() 39 if err != nil { 40 return nil, nil, errors.Trace(err) 41 } 42 stochastik.SetSchemaLease(0) 43 dom, err := stochastik.BootstrapStochastik(causetstore) 44 return causetstore, dom, errors.Trace(err) 45 } 46 47 type testUtilSuite struct { 48 causetstore ekv.CausetStorage 49 dom *petri.Petri 50 } 51 52 func (s *testUtilSuite) SetUpSuite(c *C) { 53 testleak.BeforeTest() 54 55 var err error 56 s.causetstore, s.dom, err = newStoreWithBootstrap() 57 c.Assert(err, IsNil) 58 } 59 60 func (s *testUtilSuite) TearDownSuite(c *C) { 61 s.dom.Close() 62 s.causetstore.Close() 63 64 testleak.AfterTest(c)() 65 } 66 67 func (s *testUtilSuite) TestDumpBinaryTime(c *C) { 68 t, err := types.ParseTimestamp(nil, "0000-00-00 00:00:00.000000") 69 c.Assert(err, IsNil) 70 d := dumpBinaryDateTime(nil, t) 71 c.Assert(d, DeepEquals, []byte{0}) 72 73 t, err = types.ParseTimestamp(&stmtctx.StatementContext{TimeZone: time.Local}, "1991-05-01 01:01:01.100001") 74 c.Assert(err, IsNil) 75 d = dumpBinaryDateTime(nil, t) 76 // 199 & 7 composed to uint16 1991 (litter-endian) 77 // 160 & 134 & 1 & 0 composed to uint32 1000001 (litter-endian) 78 c.Assert(d, DeepEquals, []byte{11, 199, 7, 5, 1, 1, 1, 1, 161, 134, 1, 0}) 79 80 t, err = types.ParseDatetime(nil, "0000-00-00 00:00:00.000000") 81 c.Assert(err, IsNil) 82 d = dumpBinaryDateTime(nil, t) 83 c.Assert(d, DeepEquals, []byte{0}) 84 t, err = types.ParseDatetime(nil, "1993-07-13 01:01:01.000000") 85 c.Assert(err, IsNil) 86 d = dumpBinaryDateTime(nil, t) 87 // 201 & 7 composed to uint16 1993 (litter-endian) 88 c.Assert(d, DeepEquals, []byte{11, 201, 7, 7, 13, 1, 1, 1, 0, 0, 0, 0}) 89 90 t, err = types.ParseDate(nil, "0000-00-00") 91 c.Assert(err, IsNil) 92 d = dumpBinaryDateTime(nil, t) 93 c.Assert(d, DeepEquals, []byte{0}) 94 t, err = types.ParseDate(nil, "1992-06-01") 95 c.Assert(err, IsNil) 96 d = dumpBinaryDateTime(nil, t) 97 // 200 & 7 composed to uint16 1992 (litter-endian) 98 c.Assert(d, DeepEquals, []byte{4, 200, 7, 6, 1}) 99 100 t, err = types.ParseDate(nil, "0000-00-00") 101 c.Assert(err, IsNil) 102 d = dumpBinaryDateTime(nil, t) 103 c.Assert(d, DeepEquals, []byte{0}) 104 105 myDuration, err := types.ParseDuration(nil, "0000-00-00 00:00:00.000000", 6) 106 c.Assert(err, IsNil) 107 d = dumpBinaryTime(myDuration.Duration) 108 c.Assert(d, DeepEquals, []byte{0}) 109 110 d = dumpBinaryTime(0) 111 c.Assert(d, DeepEquals, []byte{0}) 112 113 d = dumpBinaryTime(-1) 114 c.Assert(d, DeepEquals, []byte{12, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) 115 116 d = dumpBinaryTime(time.Nanosecond + 86400*1000*time.Microsecond) 117 c.Assert(d, DeepEquals, []byte{12, 0, 0, 0, 0, 0, 0, 1, 26, 128, 26, 6, 0}) 118 } 119 120 func (s *testUtilSuite) TestDumpTextValue(c *C) { 121 defCausumns := []*DeferredCausetInfo{{ 122 Type: allegrosql.TypeLonglong, 123 Decimal: allegrosql.NotFixedDec, 124 }} 125 126 null := types.NewIntCauset(0) 127 null.SetNull() 128 bs, err := dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{null}).ToRow()) 129 c.Assert(err, IsNil) 130 _, isNull, _, err := parseLengthEncodedBytes(bs) 131 c.Assert(err, IsNil) 132 c.Assert(isNull, IsTrue) 133 134 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{types.NewIntCauset(10)}).ToRow()) 135 c.Assert(err, IsNil) 136 c.Assert(mustDecodeStr(c, bs), Equals, "10") 137 138 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{types.NewUintCauset(11)}).ToRow()) 139 c.Assert(err, IsNil) 140 c.Assert(mustDecodeStr(c, bs), Equals, "11") 141 142 defCausumns[0].Flag = defCausumns[0].Flag | uint16(allegrosql.UnsignedFlag) 143 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{types.NewUintCauset(11)}).ToRow()) 144 c.Assert(err, IsNil) 145 c.Assert(mustDecodeStr(c, bs), Equals, "11") 146 147 defCausumns[0].Type = allegrosql.TypeFloat 148 defCausumns[0].Decimal = 1 149 f32 := types.NewFloat32Causet(1.2) 150 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{f32}).ToRow()) 151 c.Assert(err, IsNil) 152 c.Assert(mustDecodeStr(c, bs), Equals, "1.2") 153 154 defCausumns[0].Decimal = 2 155 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{f32}).ToRow()) 156 c.Assert(err, IsNil) 157 c.Assert(mustDecodeStr(c, bs), Equals, "1.20") 158 159 f64 := types.NewFloat64Causet(2.2) 160 defCausumns[0].Type = allegrosql.TypeDouble 161 defCausumns[0].Decimal = 1 162 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{f64}).ToRow()) 163 c.Assert(err, IsNil) 164 c.Assert(mustDecodeStr(c, bs), Equals, "2.2") 165 166 defCausumns[0].Decimal = 2 167 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{f64}).ToRow()) 168 c.Assert(err, IsNil) 169 c.Assert(mustDecodeStr(c, bs), Equals, "2.20") 170 171 defCausumns[0].Type = allegrosql.TypeBlob 172 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{types.NewBytesCauset([]byte("foo"))}).ToRow()) 173 c.Assert(err, IsNil) 174 c.Assert(mustDecodeStr(c, bs), Equals, "foo") 175 176 defCausumns[0].Type = allegrosql.TypeVarchar 177 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{types.NewStringCauset("bar")}).ToRow()) 178 c.Assert(err, IsNil) 179 c.Assert(mustDecodeStr(c, bs), Equals, "bar") 180 181 var d types.Causet 182 183 sc := mock.NewContext().GetStochastikVars().StmtCtx 184 sc.IgnoreZeroInDate = true 185 losAngelesTz, err := time.LoadLocation("America/Los_Angeles") 186 c.Assert(err, IsNil) 187 sc.TimeZone = losAngelesTz 188 189 time, err := types.ParseTime(sc, "2020-01-05 23:59:59.575601", allegrosql.TypeDatetime, 0) 190 c.Assert(err, IsNil) 191 d.SetMysqlTime(time) 192 defCausumns[0].Type = allegrosql.TypeDatetime 193 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{d}).ToRow()) 194 c.Assert(err, IsNil) 195 c.Assert(mustDecodeStr(c, bs), Equals, "2020-01-06 00:00:00") 196 197 duration, err := types.ParseDuration(sc, "11:30:45", 0) 198 c.Assert(err, IsNil) 199 d.SetMysqlDuration(duration) 200 defCausumns[0].Type = allegrosql.TypeDuration 201 defCausumns[0].Decimal = 0 202 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{d}).ToRow()) 203 c.Assert(err, IsNil) 204 c.Assert(mustDecodeStr(c, bs), Equals, "11:30:45") 205 206 d.SetMysqlDecimal(types.NewDecFromStringForTest("1.23")) 207 defCausumns[0].Type = allegrosql.TypeNewDecimal 208 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{d}).ToRow()) 209 c.Assert(err, IsNil) 210 c.Assert(mustDecodeStr(c, bs), Equals, "1.23") 211 212 year := types.NewIntCauset(0) 213 defCausumns[0].Type = allegrosql.TypeYear 214 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{year}).ToRow()) 215 c.Assert(err, IsNil) 216 c.Assert(mustDecodeStr(c, bs), Equals, "0000") 217 218 year.SetInt64(1984) 219 defCausumns[0].Type = allegrosql.TypeYear 220 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{year}).ToRow()) 221 c.Assert(err, IsNil) 222 c.Assert(mustDecodeStr(c, bs), Equals, "1984") 223 224 enum := types.NewMysqlEnumCauset(types.Enum{Name: "ename", Value: 0}) 225 defCausumns[0].Type = allegrosql.TypeEnum 226 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{enum}).ToRow()) 227 c.Assert(err, IsNil) 228 c.Assert(mustDecodeStr(c, bs), Equals, "ename") 229 230 set := types.Causet{} 231 set.SetMysqlSet(types.Set{Name: "sname", Value: 0}, allegrosql.DefaultDefCauslationName) 232 defCausumns[0].Type = allegrosql.TypeSet 233 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{set}).ToRow()) 234 c.Assert(err, IsNil) 235 c.Assert(mustDecodeStr(c, bs), Equals, "sname") 236 237 js := types.Causet{} 238 binaryJSON, err := json.ParseBinaryFromString(`{"a": 1, "b": 2}`) 239 c.Assert(err, IsNil) 240 js.SetMysqlJSON(binaryJSON) 241 defCausumns[0].Type = allegrosql.TypeJSON 242 bs, err = dumpTextRow(nil, defCausumns, chunk.MutRowFromCausets([]types.Causet{js}).ToRow()) 243 c.Assert(err, IsNil) 244 c.Assert(mustDecodeStr(c, bs), Equals, `{"a": 1, "b": 2}`) 245 } 246 247 func mustDecodeStr(c *C, b []byte) string { 248 str, _, _, err := parseLengthEncodedBytes(b) 249 c.Assert(err, IsNil) 250 return string(str) 251 } 252 253 func (s *testUtilSuite) TestAppendFormatFloat(c *C) { 254 tests := []struct { 255 fVal float64 256 out string 257 prec int 258 bitSize int 259 }{ 260 { 261 99999999999999999999, 262 "1e20", 263 -1, 264 64, 265 }, 266 { 267 1e15, 268 "1e15", 269 -1, 270 64, 271 }, 272 { 273 9e14, 274 "900000000000000", 275 -1, 276 64, 277 }, 278 { 279 -9999999999999999, 280 "-1e16", 281 -1, 282 64, 283 }, 284 { 285 999999999999999, 286 "999999999999999", 287 -1, 288 64, 289 }, 290 { 291 0.000000000000001, 292 "0.000000000000001", 293 -1, 294 64, 295 }, 296 { 297 0.0000000000000009, 298 "9e-16", 299 -1, 300 64, 301 }, 302 { 303 -0.0000000000000009, 304 "-9e-16", 305 -1, 306 64, 307 }, 308 { 309 0.11111, 310 "0.111", 311 3, 312 64, 313 }, 314 { 315 0.11111, 316 "0.111", 317 3, 318 64, 319 }, 320 { 321 0.1111111111111111111, 322 "0.11111111", 323 -1, 324 32, 325 }, 326 { 327 0.1111111111111111111, 328 "0.1111111111111111", 329 -1, 330 64, 331 }, 332 { 333 0.0000000000000009, 334 "0.000", 335 3, 336 64, 337 }, 338 { 339 0, 340 "0", 341 -1, 342 64, 343 }, 344 } 345 for _, t := range tests { 346 c.Assert(string(appendFormatFloat(nil, t.fVal, t.prec, t.bitSize)), Equals, t.out) 347 } 348 } 349 350 func (s *testUtilSuite) TestDumpLengthEncodedInt(c *C) { 351 testCases := []struct { 352 num uint64 353 buffer []byte 354 }{ 355 { 356 uint64(0), 357 []byte{0x00}, 358 }, 359 { 360 uint64(513), 361 []byte{'\xfc', '\x01', '\x02'}, 362 }, 363 { 364 uint64(197121), 365 []byte{'\xfd', '\x01', '\x02', '\x03'}, 366 }, 367 { 368 uint64(578437695752307201), 369 []byte{'\xfe', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08'}, 370 }, 371 } 372 for _, tc := range testCases { 373 b := dumpLengthEncodedInt(nil, tc.num) 374 c.Assert(b, DeepEquals, tc.buffer) 375 } 376 } 377 378 func (s *testUtilSuite) TestParseLengthEncodedInt(c *C) { 379 testCases := []struct { 380 buffer []byte 381 num uint64 382 isNull bool 383 n int 384 }{ 385 { 386 []byte{'\xfb'}, 387 uint64(0), 388 true, 389 1, 390 }, 391 { 392 []byte{'\x00'}, 393 uint64(0), 394 false, 395 1, 396 }, 397 { 398 []byte{'\xfc', '\x01', '\x02'}, 399 uint64(513), 400 false, 401 3, 402 }, 403 { 404 []byte{'\xfd', '\x01', '\x02', '\x03'}, 405 uint64(197121), 406 false, 407 4, 408 }, 409 { 410 []byte{'\xfe', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08'}, 411 uint64(578437695752307201), 412 false, 413 9, 414 }, 415 } 416 417 for _, tc := range testCases { 418 num, isNull, n := parseLengthEncodedInt(tc.buffer) 419 c.Assert(num, Equals, tc.num) 420 c.Assert(isNull, Equals, tc.isNull) 421 c.Assert(n, Equals, tc.n) 422 423 c.Assert(lengthEncodedIntSize(tc.num), Equals, tc.n) 424 } 425 } 426 427 func (s *testUtilSuite) TestDumpUint(c *C) { 428 testCases := []uint64{ 429 0, 430 1, 431 1<<64 - 1, 432 } 433 parseUint64 := func(b []byte) uint64 { 434 return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | 435 uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | 436 uint64(b[6])<<48 | uint64(b[7])<<56 437 } 438 for _, tc := range testCases { 439 b := dumpUint64(nil, tc) 440 c.Assert(len(b), Equals, 8) 441 c.Assert(parseUint64(b), Equals, tc) 442 } 443 } 444 445 func (s *testUtilSuite) TestParseLengthEncodedBytes(c *C) { 446 buffer := []byte{'\xfb'} 447 b, isNull, n, err := parseLengthEncodedBytes(buffer) 448 c.Assert(b, IsNil) 449 c.Assert(isNull, IsTrue) 450 c.Assert(n, Equals, 1) 451 c.Assert(err, IsNil) 452 453 buffer = []byte{0} 454 b, isNull, n, err = parseLengthEncodedBytes(buffer) 455 c.Assert(b, IsNil) 456 c.Assert(isNull, IsFalse) 457 c.Assert(n, Equals, 1) 458 c.Assert(err, IsNil) 459 460 buffer = []byte{'\x01'} 461 b, isNull, n, err = parseLengthEncodedBytes(buffer) 462 c.Assert(b, IsNil) 463 c.Assert(isNull, IsFalse) 464 c.Assert(n, Equals, 2) 465 c.Assert(err.Error(), Equals, "EOF") 466 } 467 468 func (s *testUtilSuite) TestParseNullTermString(c *C) { 469 for _, t := range []struct { 470 input string 471 str string 472 remain string 473 }{ 474 { 475 "abc\x00def", 476 "abc", 477 "def", 478 }, 479 { 480 "\x00def", 481 "", 482 "def", 483 }, 484 { 485 "def\x00hig\x00k", 486 "def", 487 "hig\x00k", 488 }, 489 { 490 "abcdef", 491 "", 492 "abcdef", 493 }, 494 } { 495 str, remain := parseNullTermString([]byte(t.input)) 496 c.Assert(string(str), Equals, t.str) 497 c.Assert(string(remain), Equals, t.remain) 498 } 499 } 500 501 func newTestConfig() *config.Config { 502 cfg := config.NewConfig() 503 cfg.Host = "127.0.0.1" 504 cfg.Status.StatusHost = "127.0.0.1" 505 return cfg 506 }