github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/mysql_protocol_test.go (about) 1 // Copyright 2021 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "bytes" 19 "context" 20 "database/sql" 21 "encoding/binary" 22 "fmt" 23 "math" 24 "sync" 25 "testing" 26 "time" 27 28 "github.com/stretchr/testify/assert" 29 "go.uber.org/zap" 30 31 // mysqlDriver "github.com/go-sql-driver/mysql" 32 "github.com/BurntSushi/toml" 33 "github.com/fagongzi/goetty/v2" 34 goetty_buf "github.com/fagongzi/goetty/v2/buf" 35 "github.com/golang/mock/gomock" 36 fuzz "github.com/google/gofuzz" 37 "github.com/prashantv/gostub" 38 "github.com/smartystreets/goconvey/convey" 39 "github.com/stretchr/testify/require" 40 41 "github.com/matrixorigin/matrixone/pkg/common/moerr" 42 "github.com/matrixorigin/matrixone/pkg/config" 43 "github.com/matrixorigin/matrixone/pkg/container/types" 44 "github.com/matrixorigin/matrixone/pkg/container/vector" 45 "github.com/matrixorigin/matrixone/pkg/defines" 46 mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" 47 "github.com/matrixorigin/matrixone/pkg/logutil" 48 "github.com/matrixorigin/matrixone/pkg/pb/txn" 49 "github.com/matrixorigin/matrixone/pkg/sql/parsers" 50 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 51 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" 52 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 53 "github.com/matrixorigin/matrixone/pkg/sql/plan" 54 "github.com/matrixorigin/matrixone/pkg/testutil" 55 "github.com/matrixorigin/matrixone/pkg/vm/engine" 56 "github.com/matrixorigin/matrixone/pkg/vm/process" 57 ) 58 59 type TestRoutineManager struct { 60 rwlock sync.Mutex 61 clients map[goetty.IOSession]*Routine 62 63 pu *config.ParameterUnit 64 } 65 66 func (tRM *TestRoutineManager) Created(rs goetty.IOSession) { 67 pro := NewMysqlClientProtocol(nextConnectionID(), rs, 1024, tRM.pu.SV) 68 routine := NewRoutine(context.TODO(), pro, tRM.pu.SV, rs) 69 70 hsV10pkt := pro.makeHandshakeV10Payload() 71 err := pro.writePackets(hsV10pkt, true) 72 if err != nil { 73 panic(err) 74 } 75 76 tRM.rwlock.Lock() 77 defer tRM.rwlock.Unlock() 78 tRM.clients[rs] = routine 79 } 80 81 func (tRM *TestRoutineManager) Closed(rs goetty.IOSession) { 82 tRM.rwlock.Lock() 83 defer tRM.rwlock.Unlock() 84 delete(tRM.clients, rs) 85 } 86 87 func NewTestRoutineManager(pu *config.ParameterUnit) *TestRoutineManager { 88 rm := &TestRoutineManager{ 89 clients: make(map[goetty.IOSession]*Routine), 90 pu: pu, 91 } 92 return rm 93 } 94 95 func TestMysqlClientProtocol_Handshake(t *testing.T) { 96 //client connection method: mysql -h 127.0.0.1 -P 6001 --default-auth=mysql_native_password -uroot -p 97 //client connect 98 //ion method: mysql -h 127.0.0.1 -P 6001 -udump -p 99 100 var db *sql.DB 101 var err error 102 //before anything using the configuration 103 pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil) 104 _, err = toml.DecodeFile("test/system_vars_config.toml", pu.SV) 105 require.NoError(t, err) 106 pu.SV.SkipCheckUser = true 107 setGlobalPu(pu) 108 109 ctx := context.WithValue(context.TODO(), config.ParameterUnitKey, pu) 110 111 // A mock autoincrcache manager. 112 setGlobalAicm(&defines.AutoIncrCacheManager{}) 113 rm, _ := NewRoutineManager(ctx) 114 setGlobalRtMgr(rm) 115 116 wg := sync.WaitGroup{} 117 wg.Add(1) 118 119 //running server 120 go func() { 121 defer wg.Done() 122 echoServer(getGlobalRtMgr().Handler, getGlobalRtMgr(), NewSqlCodec()) 123 }() 124 125 time.Sleep(time.Second * 2) 126 db, err = openDbConn(t, 6001) 127 require.NoError(t, err) 128 129 time.Sleep(time.Millisecond * 10) 130 //close server 131 setServer(1) 132 wg.Wait() 133 134 closeDbConn(t, db) 135 } 136 137 func newMrsForConnectionId(rows [][]interface{}) *MysqlResultSet { 138 mrs := &MysqlResultSet{} 139 140 col1 := &MysqlColumn{} 141 col1.SetName("connection_id") 142 col1.SetColumnType(defines.MYSQL_TYPE_LONGLONG) 143 144 mrs.AddColumn(col1) 145 146 for _, row := range rows { 147 mrs.AddRow(row) 148 } 149 150 return mrs 151 } 152 153 func newMrsForSleep(rows [][]interface{}) *MysqlResultSet { 154 mrs := &MysqlResultSet{} 155 156 col1 := &MysqlColumn{} 157 col1.SetName("sleep") 158 col1.SetColumnType(defines.MYSQL_TYPE_TINY) 159 160 mrs.AddColumn(col1) 161 162 for _, row := range rows { 163 mrs.AddRow(row) 164 } 165 166 return mrs 167 } 168 169 func TestKill(t *testing.T) { 170 //client connection method: mysql -h 127.0.0.1 -P 6001 --default-auth=mysql_native_password -uroot -p 171 //client connect 172 //ion method: mysql -h 127.0.0.1 -P 6001 -udump -p 173 ctrl := gomock.NewController(t) 174 defer ctrl.Finish() 175 var conn1, conn2 *sql.DB 176 var err error 177 var connIdRow *sql.Row 178 179 //before anything using the configuration 180 eng := mock_frontend.NewMockEngine(ctrl) 181 eng.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 182 eng.EXPECT().Hints().Return(engine.Hints{CommitOrRollbackTimeout: time.Second * 10}).AnyTimes() 183 wp := newTestWorkspace() 184 185 txnOp := mock_frontend.NewMockTxnOperator(ctrl) 186 txnOp.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() 187 txnOp.EXPECT().GetWorkspace().Return(wp).AnyTimes() 188 txnOp.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() 189 txnOp.EXPECT().Rollback(gomock.Any()).Return(nil).AnyTimes() 190 txnClient := mock_frontend.NewMockTxnClient(ctrl) 191 txnClient.EXPECT().New(gomock.Any(), gomock.Any(), gomock.Any()).Return(txnOp, nil).AnyTimes() 192 pu, err := getParameterUnit("test/system_vars_config.toml", eng, txnClient) 193 require.NoError(t, err) 194 pu.SV.SkipCheckUser = true 195 setGlobalPu(pu) 196 sql1 := "select connection_id();" 197 var sql2, sql3, sql4 string 198 199 noResultSet := make(map[string]bool) 200 resultSet := make(map[string]*result) 201 resultSet[sql1] = &result{ 202 gen: func(ses *Session) *MysqlResultSet { 203 mrs := newMrsForConnectionId([][]interface{}{ 204 {ses.GetConnectionID()}, 205 }) 206 return mrs 207 }, 208 isSleepSql: false, 209 } 210 211 sql5 := "select sleep(30);" 212 resultSet[sql5] = &result{ 213 gen: func(ses *Session) *MysqlResultSet { 214 return newMrsForSleep([][]interface{}{ 215 {uint8(0)}, 216 }) 217 }, 218 isSleepSql: true, 219 seconds: 30, 220 } 221 222 sql6 := "select sleep(30);" 223 resultSet[sql6] = &result{ 224 gen: func(ses *Session) *MysqlResultSet { 225 return newMrsForSleep([][]interface{}{ 226 {uint8(0)}, 227 }) 228 }, 229 isSleepSql: true, 230 seconds: 30, 231 } 232 233 var wrapperStubFunc = func(execCtx *ExecCtx, db string, user string, eng engine.Engine, proc *process.Process, ses *Session) ([]ComputationWrapper, error) { 234 var cw []ComputationWrapper = nil 235 var stmts []tree.Statement = nil 236 var cmdFieldStmt *InternalCmdFieldList 237 var err error 238 if isCmdFieldListSql(execCtx.input.getSql()) { 239 cmdFieldStmt, err = parseCmdFieldList(execCtx.reqCtx, execCtx.input.getSql()) 240 if err != nil { 241 return nil, err 242 } 243 stmts = append(stmts, cmdFieldStmt) 244 } else { 245 stmts, err = parsers.Parse(execCtx.reqCtx, dialect.MYSQL, execCtx.input.getSql(), 1, 0) 246 if err != nil { 247 return nil, err 248 } 249 } 250 251 for _, stmt := range stmts { 252 cw = append(cw, newMockWrapper(ctrl, ses, resultSet, noResultSet, execCtx.input.getSql(), stmt, proc)) 253 } 254 return cw, nil 255 } 256 257 bhStub := gostub.Stub(&GetComputationWrapper, wrapperStubFunc) 258 defer bhStub.Reset() 259 260 ctx := context.WithValue(context.TODO(), config.ParameterUnitKey, pu) 261 // A mock autoincrcache manager. 262 setGlobalAicm(&defines.AutoIncrCacheManager{}) 263 temp, _ := NewRoutineManager(ctx) 264 setGlobalRtMgr(temp) 265 266 wg := sync.WaitGroup{} 267 wg.Add(1) 268 269 //running server 270 go func() { 271 defer wg.Done() 272 echoServer(getGlobalRtMgr().Handler, getGlobalRtMgr(), NewSqlCodec()) 273 }() 274 275 logutil.Infof("open conn1") 276 time.Sleep(time.Second * 2) 277 conn1, err = openDbConn(t, 6001) 278 require.NoError(t, err) 279 logutil.Infof("open conn1 done") 280 281 logutil.Infof("open conn2") 282 time.Sleep(time.Second * 2) 283 conn2, err = openDbConn(t, 6001) 284 require.NoError(t, err) 285 logutil.Infof("open conn2 done") 286 287 logutil.Infof("get the connection id of conn1") 288 //get the connection id of conn1 289 var conn1Id uint64 290 connIdRow = conn1.QueryRow(sql1) 291 err = connIdRow.Scan(&conn1Id) 292 require.NoError(t, err) 293 logutil.Infof("get the connection id of conn1 done") 294 295 logutil.Infof("get the connection id of conn2") 296 //get the connection id of conn2 297 var conn2Id uint64 298 connIdRow = conn2.QueryRow(sql1) 299 err = connIdRow.Scan(&conn2Id) 300 require.NoError(t, err) 301 logutil.Infof("get the connection id of conn2 done") 302 logutil.Infof("conn==>%v %v", conn1Id, conn2Id) 303 304 wgSleep := sync.WaitGroup{} 305 wgSleep.Add(1) 306 307 //=================================== 308 //connection 1 exec : select sleep(30); 309 go func() { 310 defer wgSleep.Done() 311 var resultId int 312 logutil.Infof("conn1 sleep(30)") 313 connIdRow = conn1.QueryRow(sql5) 314 //find race on err here 315 err := connIdRow.Scan(&resultId) 316 require.NoError(t, err) 317 logutil.Infof("conn1 sleep(30) done") 318 }() 319 320 //sleep before cancel 321 time.Sleep(time.Second * 2) 322 323 logutil.Infof("conn2 kill query on conn1") 324 //conn2 kills the query 325 sql3 = fmt.Sprintf("kill query %d;", conn1Id) 326 noResultSet[sql3] = true 327 _, err = conn2.Exec(sql3) 328 require.NoError(t, err) 329 logutil.Infof("conn2 kill query on conn1: KILL query done") 330 331 //check killed result 332 wgSleep.Wait() 333 res := resultSet[sql5] 334 require.Equal(t, res.resultX.Load(), contextCancel) 335 logutil.Infof("conn2 kill query on conn1 done") 336 337 //================================ 338 339 //connection 1 exec : select sleep(30); 340 wgSleep2 := sync.WaitGroup{} 341 wgSleep2.Add(1) 342 go func() { 343 defer wgSleep2.Done() 344 var resultId int 345 logutil.Infof("conn1 sleep(30) 2") 346 connIdRow = conn1.QueryRow(sql6) 347 err = connIdRow.Scan(&resultId) 348 require.NoError(t, err) 349 logutil.Infof("conn1 sleep(30) 2 done") 350 }() 351 352 //sleep before cancel 353 time.Sleep(time.Second * 2) 354 355 logutil.Infof("conn2 kill conn1") 356 //conn2 kills the connection 1 357 sql2 = fmt.Sprintf("kill %d;", conn1Id) 358 noResultSet[sql2] = true 359 _, err = conn2.Exec(sql2) 360 require.NoError(t, err) 361 logutil.Infof("conn2 kill conn1 : KILL connection done") 362 363 //check killed result 364 wgSleep2.Wait() 365 res = resultSet[sql6] 366 require.Equal(t, res.resultX.Load(), contextCancel) 367 logutil.Infof("conn2 kill conn1 done") 368 369 logutil.Infof("conn1 test itself after being killed") 370 //============================== 371 //conn 1 is killed by conn2 372 //check conn1 is disconnected or not 373 err = conn1.Ping() 374 require.Error(t, err) 375 logutil.Infof("conn1 test itself after being killed done") 376 377 //============================== 378 379 logutil.Infof("conn2 kill itself") 380 //conn2 kills itself 381 sql4 = fmt.Sprintf("kill %d;", conn2Id) 382 noResultSet[sql4] = true 383 _, err = conn2.Exec(sql4) 384 require.NoError(t, err) 385 logutil.Infof("conn2 kill itself done") 386 387 time.Sleep(time.Millisecond * 10) 388 //close server 389 setServer(1) 390 wg.Wait() 391 392 logutil.Infof("close conn1,conn2") 393 //close the connection 394 closeDbConn(t, conn1) 395 closeDbConn(t, conn2) 396 logutil.Infof("close conn1,conn2 done") 397 } 398 399 func TestReadIntLenEnc(t *testing.T) { 400 var intEnc MysqlProtocolImpl 401 var data = make([]byte, 24) 402 var cases = [][]uint64{ 403 {0, 123, 250}, 404 {251, 10000, 1<<16 - 1}, 405 {1 << 16, 1<<16 + 10000, 1<<24 - 1}, 406 {1 << 24, 1<<24 + 10000, 1<<64 - 1}, 407 } 408 var caseLens = []int{1, 3, 4, 9} 409 for j := 0; j < len(cases); j++ { 410 for i := 0; i < len(cases[j]); i++ { 411 value := cases[j][i] 412 p1 := intEnc.writeIntLenEnc(data, 0, value) 413 val, p2, ok := intEnc.readIntLenEnc(data, 0) 414 if !ok || p1 != caseLens[j] || p1 != p2 || val != value { 415 t.Errorf("IntLenEnc %d failed.", value) 416 break 417 } 418 _, _, ok = intEnc.readIntLenEnc(data[0:caseLens[j]-1], 0) 419 if ok { 420 t.Errorf("read IntLenEnc failed.") 421 break 422 } 423 } 424 } 425 } 426 427 func TestReadCountOfBytes(t *testing.T) { 428 var client MysqlProtocolImpl 429 var data = make([]byte, 24) 430 var length = 10 431 for i := 0; i < length; i++ { 432 data[i] = byte(length - i) 433 } 434 435 r, pos, ok := client.readCountOfBytes(data, 0, length) 436 if !ok || pos != length { 437 t.Error("read bytes failed.") 438 return 439 } 440 441 for i := 0; i < length; i++ { 442 if r[i] != data[i] { 443 t.Error("read != write") 444 break 445 } 446 } 447 448 _, _, ok = client.readCountOfBytes(data, 0, 100) 449 if ok { 450 t.Error("read bytes failed.") 451 return 452 } 453 454 _, pos, ok = client.readCountOfBytes(data, 0, 0) 455 if !ok || pos != 0 { 456 t.Error("read bytes failed.") 457 return 458 } 459 } 460 461 func TestReadStringFix(t *testing.T) { 462 var client MysqlProtocolImpl 463 var data = make([]byte, 24) 464 var length = 10 465 var s = "haha, test read string fix function" 466 pos := client.writeStringFix(data, 0, s, length) 467 if pos != length { 468 t.Error("write string fix failed.") 469 return 470 } 471 var x string 472 var ok bool 473 474 x, pos, ok = client.readStringFix(data, 0, length) 475 if !ok || pos != length || x != s[0:length] { 476 t.Error("read string fix failed.") 477 return 478 } 479 var sLen = []int{ 480 length + 10, 481 length + 20, 482 length + 30, 483 } 484 for i := 0; i < len(sLen); i++ { 485 x, pos, ok = client.readStringFix(data, 0, sLen[i]) 486 if ok && pos == sLen[i] && x == s[0:sLen[i]] { 487 t.Error("read string fix failed.") 488 return 489 } 490 } 491 492 //empty string 493 pos = client.writeStringFix(data, 0, s, 0) 494 if pos != 0 { 495 t.Error("write string fix failed.") 496 return 497 } 498 499 x, pos, ok = client.readStringFix(data, 0, 0) 500 if !ok || pos != 0 || x != "" { 501 t.Error("read string fix failed.") 502 return 503 } 504 } 505 506 func TestReadStringNUL(t *testing.T) { 507 var client MysqlProtocolImpl 508 var data = make([]byte, 24) 509 var length = 10 510 var s = "haha, test read string fix function" 511 pos := client.writeStringNUL(data, 0, s[0:length]) 512 if pos != length+1 { 513 t.Error("write string NUL failed.") 514 return 515 } 516 var x string 517 var ok bool 518 519 x, pos, ok = client.readStringNUL(data, 0) 520 if !ok || pos != length+1 || x != s[0:length] { 521 t.Error("read string NUL failed.") 522 return 523 } 524 var sLen = []int{ 525 length + 10, 526 length + 20, 527 length + 30, 528 } 529 for i := 0; i < len(sLen); i++ { 530 x, pos, ok = client.readStringNUL(data, 0) 531 if ok && pos == sLen[i]+1 && x == s[0:sLen[i]] { 532 t.Error("read string NUL failed.") 533 return 534 } 535 } 536 } 537 538 func TestReadStringLenEnc(t *testing.T) { 539 var client MysqlProtocolImpl 540 var data = make([]byte, 24) 541 var length = 10 542 var s = "haha, test read string fix function" 543 pos := client.writeStringLenEnc(data, 0, s[0:length]) 544 if pos != length+1 { 545 t.Error("write string lenenc failed.") 546 return 547 } 548 var x string 549 var ok bool 550 551 x, pos, ok = client.readStringLenEnc(data, 0) 552 if !ok || pos != length+1 || x != s[0:length] { 553 t.Error("read string lenenc failed.") 554 return 555 } 556 557 //empty string 558 pos = client.writeStringLenEnc(data, 0, s[0:0]) 559 if pos != 1 { 560 t.Error("write string lenenc failed.") 561 return 562 } 563 564 x, pos, ok = client.readStringLenEnc(data, 0) 565 if !ok || pos != 1 || x != s[0:0] { 566 t.Error("read string lenenc failed.") 567 return 568 } 569 } 570 571 // can not run this test case in ubuntu+golang1.9, let's add an issue(#4656) for that, I will fixed in someday. 572 // func TestMysqlClientProtocol_TlsHandshake(t *testing.T) { 573 // //before anything using the configuration 574 // pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil) 575 // _, err := toml.DecodeFile("test/system_vars_config.toml", pu.SV) 576 // if err != nil { 577 // panic(err) 578 // } 579 // pu.SV.EnableTls = true 580 // ctx := context.WithValue(context.TODO(), config.ParameterUnitKey, pu) 581 // rm, _ := NewRoutineManager(ctx, pu) 582 // rm.SetSkipCheckUser(true) 583 584 // wg := sync.WaitGroup{} 585 // wg.Add(1) 586 587 // // //running server 588 // go func() { 589 // defer wg.Done() 590 // echoServer(rm.Handler, rm, NewSqlCodec()) 591 // }() 592 593 // // to := NewTimeout(1*time.Minute, false) 594 // // for isClosed() && !to.isTimeout() { 595 // // } 596 597 // time.Sleep(time.Second * 2) 598 // db := open_tls_db(t, 6001) 599 // closeDbConn(t, db) 600 601 // time.Sleep(time.Millisecond * 10) 602 // //close server 603 // setServer(1) 604 // wg.Wait() 605 // } 606 607 // func makeMysqlTinyIntResultSet(unsigned bool) *MysqlResultSet { 608 // var rs = &MysqlResultSet{} 609 // 610 // name := "Tiny" 611 // if unsigned { 612 // name = name + "Uint" 613 // } else { 614 // name = name + "Int" 615 // } 616 // 617 // mysqlCol := new(MysqlColumn) 618 // mysqlCol.SetName(name) 619 // mysqlCol.SetOrgName(name + "OrgName") 620 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_TINY) 621 // mysqlCol.SetSchema(name + "Schema") 622 // mysqlCol.SetTable(name + "Table") 623 // mysqlCol.SetOrgTable(name + "Table") 624 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 625 // mysqlCol.SetSigned(!unsigned) 626 // 627 // rs.AddColumn(mysqlCol) 628 // if unsigned { 629 // var cases = []uint8{0, 1, 254, 255} 630 // for _, v := range cases { 631 // var data = make([]interface{}, 1) 632 // data[0] = v 633 // rs.AddRow(data) 634 // } 635 // } else { 636 // var cases = []int8{-128, -127, 127} 637 // for _, v := range cases { 638 // var data = make([]interface{}, 1) 639 // data[0] = v 640 // rs.AddRow(data) 641 // } 642 // } 643 // 644 // return rs 645 // } 646 // 647 // func makeMysqlTinyResult(unsigned bool) *MysqlExecutionResult { 648 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlTinyIntResultSet(unsigned)) 649 // } 650 // 651 // func makeMysqlShortResultSet(unsigned bool) *MysqlResultSet { 652 // var rs = &MysqlResultSet{} 653 // 654 // name := "Short" 655 // if unsigned { 656 // name = name + "Uint" 657 // } else { 658 // name = name + "Int" 659 // } 660 // mysqlCol := new(MysqlColumn) 661 // mysqlCol.SetName(name) 662 // mysqlCol.SetOrgName(name + "OrgName") 663 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_SHORT) 664 // mysqlCol.SetSchema(name + "Schema") 665 // mysqlCol.SetTable(name + "Table") 666 // mysqlCol.SetOrgTable(name + "Table") 667 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 668 // mysqlCol.SetSigned(!unsigned) 669 // 670 // rs.AddColumn(mysqlCol) 671 // if unsigned { 672 // var cases = []uint16{0, 1, 254, 255, 65535} 673 // for _, v := range cases { 674 // var data = make([]interface{}, 1) 675 // data[0] = v 676 // rs.AddRow(data) 677 // } 678 // } else { 679 // var cases = []int16{-32768, 0, 32767} 680 // for _, v := range cases { 681 // var data = make([]interface{}, 1) 682 // data[0] = v 683 // rs.AddRow(data) 684 // } 685 // } 686 // 687 // return rs 688 // } 689 // 690 // func makeMysqlShortResult(unsigned bool) *MysqlExecutionResult { 691 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlShortResultSet(unsigned)) 692 // } 693 // 694 // func makeMysqlLongResultSet(unsigned bool) *MysqlResultSet { 695 // var rs = &MysqlResultSet{} 696 // 697 // name := "Long" 698 // if unsigned { 699 // name = name + "Uint" 700 // } else { 701 // name = name + "Int" 702 // } 703 // mysqlCol := new(MysqlColumn) 704 // mysqlCol.SetName(name) 705 // mysqlCol.SetOrgName(name + "OrgName") 706 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_LONG) 707 // mysqlCol.SetSchema(name + "Schema") 708 // mysqlCol.SetTable(name + "Table") 709 // mysqlCol.SetOrgTable(name + "Table") 710 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 711 // mysqlCol.SetSigned(!unsigned) 712 // 713 // rs.AddColumn(mysqlCol) 714 // if unsigned { 715 // var cases = []uint32{0, 4294967295} 716 // for _, v := range cases { 717 // var data = make([]interface{}, 1) 718 // data[0] = v 719 // rs.AddRow(data) 720 // } 721 // } else { 722 // var cases = []int32{-2147483648, 0, 2147483647} 723 // for _, v := range cases { 724 // var data = make([]interface{}, 1) 725 // data[0] = v 726 // rs.AddRow(data) 727 // } 728 // } 729 // 730 // return rs 731 // } 732 // 733 // func makeMysqlLongResult(unsigned bool) *MysqlExecutionResult { 734 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlLongResultSet(unsigned)) 735 // } 736 // 737 // func makeMysqlLongLongResultSet(unsigned bool) *MysqlResultSet { 738 // var rs = &MysqlResultSet{} 739 // 740 // name := "LongLong" 741 // if unsigned { 742 // name = name + "Uint" 743 // } else { 744 // name = name + "Int" 745 // } 746 // mysqlCol := new(MysqlColumn) 747 // mysqlCol.SetName(name) 748 // mysqlCol.SetOrgName(name + "OrgName") 749 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_LONGLONG) 750 // mysqlCol.SetSchema(name + "Schema") 751 // mysqlCol.SetTable(name + "Table") 752 // mysqlCol.SetOrgTable(name + "Table") 753 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 754 // mysqlCol.SetSigned(!unsigned) 755 // 756 // rs.AddColumn(mysqlCol) 757 // if unsigned { 758 // var cases = []uint64{0, 4294967295, 18446744073709551615} 759 // for _, v := range cases { 760 // var data = make([]interface{}, 1) 761 // data[0] = v 762 // rs.AddRow(data) 763 // } 764 // } else { 765 // var cases = []int64{-9223372036854775808, 0, 9223372036854775807} 766 // for _, v := range cases { 767 // var data = make([]interface{}, 1) 768 // data[0] = v 769 // rs.AddRow(data) 770 // } 771 // } 772 // 773 // return rs 774 // } 775 // 776 // func makeMysqlLongLongResult(unsigned bool) *MysqlExecutionResult { 777 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlLongLongResultSet(unsigned)) 778 // } 779 // 780 // func makeMysqlInt24ResultSet(unsigned bool) *MysqlResultSet { 781 // var rs = &MysqlResultSet{} 782 // 783 // name := "Int24" 784 // if unsigned { 785 // name = name + "Uint" 786 // } else { 787 // name = name + "Int" 788 // } 789 // mysqlCol := new(MysqlColumn) 790 // mysqlCol.SetName(name) 791 // mysqlCol.SetOrgName(name + "OrgName") 792 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_INT24) 793 // mysqlCol.SetSchema(name + "Schema") 794 // mysqlCol.SetTable(name + "Table") 795 // mysqlCol.SetOrgTable(name + "Table") 796 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 797 // mysqlCol.SetSigned(!unsigned) 798 // 799 // rs.AddColumn(mysqlCol) 800 // if unsigned { 801 // //[0,16777215] 802 // var cases = []uint32{0, 16777215, 4294967295} 803 // for _, v := range cases { 804 // var data = make([]interface{}, 1) 805 // data[0] = v 806 // rs.AddRow(data) 807 // } 808 // } else { 809 // //[-8388608,8388607] 810 // var cases = []int32{-2147483648, -8388608, 0, 8388607, 2147483647} 811 // for _, v := range cases { 812 // var data = make([]interface{}, 1) 813 // data[0] = v 814 // rs.AddRow(data) 815 // } 816 // } 817 // 818 // return rs 819 // } 820 // 821 // func makeMysqlInt24Result(unsigned bool) *MysqlExecutionResult { 822 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlInt24ResultSet(unsigned)) 823 // } 824 // 825 // func makeMysqlYearResultSet(unsigned bool) *MysqlResultSet { 826 // var rs = &MysqlResultSet{} 827 // 828 // name := "Year" 829 // if unsigned { 830 // name = name + "Uint" 831 // } else { 832 // name = name + "Int" 833 // } 834 // mysqlCol := new(MysqlColumn) 835 // mysqlCol.SetName(name) 836 // mysqlCol.SetOrgName(name + "OrgName") 837 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_YEAR) 838 // mysqlCol.SetSchema(name + "Schema") 839 // mysqlCol.SetTable(name + "Table") 840 // mysqlCol.SetOrgTable(name + "Table") 841 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 842 // mysqlCol.SetSigned(!unsigned) 843 // 844 // rs.AddColumn(mysqlCol) 845 // if unsigned { 846 // var cases = []uint16{0, 1, 254, 255, 65535} 847 // for _, v := range cases { 848 // var data = make([]interface{}, 1) 849 // data[0] = v 850 // rs.AddRow(data) 851 // } 852 // } else { 853 // var cases = []int16{-32768, 0, 32767} 854 // for _, v := range cases { 855 // var data = make([]interface{}, 1) 856 // data[0] = v 857 // rs.AddRow(data) 858 // } 859 // } 860 // 861 // return rs 862 // } 863 // 864 // func makeMysqlYearResult(unsigned bool) *MysqlExecutionResult { 865 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlYearResultSet(unsigned)) 866 // } 867 // 868 // func makeMysqlVarcharResultSet() *MysqlResultSet { 869 // var rs = &MysqlResultSet{} 870 // 871 // name := "Varchar" 872 // 873 // mysqlCol := new(MysqlColumn) 874 // mysqlCol.SetName(name) 875 // mysqlCol.SetOrgName(name + "OrgName") 876 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_VARCHAR) 877 // mysqlCol.SetSchema(name + "Schema") 878 // mysqlCol.SetTable(name + "Table") 879 // mysqlCol.SetOrgTable(name + "Table") 880 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 881 // 882 // rs.AddColumn(mysqlCol) 883 // 884 // var cases = []string{"abc", "abcde", "", "x-", "xx"} 885 // for _, v := range cases { 886 // var data = make([]interface{}, 1) 887 // data[0] = v 888 // rs.AddRow(data) 889 // } 890 // 891 // return rs 892 // } 893 // 894 // func makeMysqlVarcharResult() *MysqlExecutionResult { 895 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlVarcharResultSet()) 896 // } 897 // 898 // func makeMysqlVarStringResultSet() *MysqlResultSet { 899 // var rs = &MysqlResultSet{} 900 // 901 // name := "Varstring" 902 // 903 // mysqlCol := new(MysqlColumn) 904 // mysqlCol.SetName(name) 905 // mysqlCol.SetOrgName(name + "OrgName") 906 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) 907 // mysqlCol.SetSchema(name + "Schema") 908 // mysqlCol.SetTable(name + "Table") 909 // mysqlCol.SetOrgTable(name + "Table") 910 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 911 // 912 // rs.AddColumn(mysqlCol) 913 // 914 // var cases = []string{"abc", "abcde", "", "x-", "xx"} 915 // for _, v := range cases { 916 // var data = make([]interface{}, 1) 917 // data[0] = v 918 // rs.AddRow(data) 919 // } 920 // 921 // return rs 922 // } 923 // 924 // func makeMysqlVarStringResult() *MysqlExecutionResult { 925 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlVarStringResultSet()) 926 // } 927 // 928 // func makeMysqlStringResultSet() *MysqlResultSet { 929 // var rs = &MysqlResultSet{} 930 // 931 // name := "String" 932 // 933 // mysqlCol := new(MysqlColumn) 934 // mysqlCol.SetName(name) 935 // mysqlCol.SetOrgName(name + "OrgName") 936 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_STRING) 937 // mysqlCol.SetSchema(name + "Schema") 938 // mysqlCol.SetTable(name + "Table") 939 // mysqlCol.SetOrgTable(name + "Table") 940 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 941 // 942 // rs.AddColumn(mysqlCol) 943 // 944 // var cases = []string{"abc", "abcde", "", "x-", "xx"} 945 // for _, v := range cases { 946 // var data = make([]interface{}, 1) 947 // data[0] = v 948 // rs.AddRow(data) 949 // } 950 // 951 // return rs 952 // } 953 // 954 // func makeMysqlStringResult() *MysqlExecutionResult { 955 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlStringResultSet()) 956 // } 957 // 958 // func makeMysqlFloatResultSet() *MysqlResultSet { 959 // var rs = &MysqlResultSet{} 960 // 961 // name := "Float" 962 // 963 // mysqlCol := new(MysqlColumn) 964 // mysqlCol.SetName(name) 965 // mysqlCol.SetOrgName(name + "OrgName") 966 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_FLOAT) 967 // mysqlCol.SetSchema(name + "Schema") 968 // mysqlCol.SetTable(name + "Table") 969 // mysqlCol.SetOrgTable(name + "Table") 970 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 971 // 972 // rs.AddColumn(mysqlCol) 973 // 974 // var cases = []float32{math.MaxFloat32, math.SmallestNonzeroFloat32, -math.MaxFloat32, -math.SmallestNonzeroFloat32} 975 // for _, v := range cases { 976 // var data = make([]interface{}, 1) 977 // data[0] = v 978 // rs.AddRow(data) 979 // } 980 // 981 // return rs 982 // } 983 // 984 // func makeMysqlFloatResult() *MysqlExecutionResult { 985 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlFloatResultSet()) 986 // } 987 // 988 // func makeMysqlDoubleResultSet() *MysqlResultSet { 989 // var rs = &MysqlResultSet{} 990 // 991 // name := "Double" 992 // 993 // mysqlCol := new(MysqlColumn) 994 // mysqlCol.SetName(name) 995 // mysqlCol.SetOrgName(name + "OrgName") 996 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_DOUBLE) 997 // mysqlCol.SetSchema(name + "Schema") 998 // mysqlCol.SetTable(name + "Table") 999 // mysqlCol.SetOrgTable(name + "Table") 1000 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1001 // 1002 // rs.AddColumn(mysqlCol) 1003 // 1004 // var cases = []float64{math.MaxFloat64, math.SmallestNonzeroFloat64, -math.MaxFloat64, -math.SmallestNonzeroFloat64} 1005 // for _, v := range cases { 1006 // var data = make([]interface{}, 1) 1007 // data[0] = v 1008 // rs.AddRow(data) 1009 // } 1010 // 1011 // return rs 1012 // } 1013 // 1014 // func makeMysqlDoubleResult() *MysqlExecutionResult { 1015 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlDoubleResultSet()) 1016 // } 1017 // 1018 // func makeMysqlDateResultSet() *MysqlResultSet { 1019 // var rs = &MysqlResultSet{} 1020 // 1021 // name := "Date" 1022 // 1023 // mysqlCol := new(MysqlColumn) 1024 // mysqlCol.SetName(name) 1025 // mysqlCol.SetOrgName(name + "OrgName") 1026 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_DATE) 1027 // mysqlCol.SetSchema(name + "Schema") 1028 // mysqlCol.SetTable(name + "Table") 1029 // mysqlCol.SetOrgTable(name + "Table") 1030 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1031 // 1032 // rs.AddColumn(mysqlCol) 1033 // 1034 // d1, _ := types.ParseDateCast("1997-01-01") 1035 // d2, _ := types.ParseDateCast("2008-02-02") 1036 // var cases = []types.Date{ 1037 // d1, 1038 // d2, 1039 // } 1040 // for _, v := range cases { 1041 // var data = make([]interface{}, 1) 1042 // data[0] = v 1043 // rs.AddRow(data) 1044 // } 1045 // 1046 // return rs 1047 // } 1048 // 1049 // func makeMysqlDateResult() *MysqlExecutionResult { 1050 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlDateResultSet()) 1051 // } 1052 // 1053 // func makeMysqlTimeResultSet() *MysqlResultSet { 1054 // var rs = &MysqlResultSet{} 1055 // 1056 // name := "Time" 1057 // 1058 // mysqlCol := new(MysqlColumn) 1059 // mysqlCol.SetName(name) 1060 // mysqlCol.SetOrgName(name + "OrgName") 1061 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_TIME) 1062 // mysqlCol.SetSchema(name + "Schema") 1063 // mysqlCol.SetTable(name + "Table") 1064 // mysqlCol.SetOrgTable(name + "Table") 1065 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1066 // 1067 // rs.AddColumn(mysqlCol) 1068 // 1069 // t1, _ := types.ParseTime("110:21:15", 0) 1070 // t2, _ := types.ParseTime("2018-04-28 10:21:15.123", 0) 1071 // t3, _ := types.ParseTime("-112:12:12", 0) 1072 // var cases = []types.Time{ 1073 // t1, 1074 // t2, 1075 // t3, 1076 // } 1077 // for _, v := range cases { 1078 // var data = make([]interface{}, 1) 1079 // data[0] = v 1080 // rs.AddRow(data) 1081 // } 1082 // 1083 // return rs 1084 // } 1085 // 1086 // func makeMysqlTimeResult() *MysqlExecutionResult { 1087 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlTimeResultSet()) 1088 // } 1089 // 1090 // func makeMysqlDatetimeResultSet() *MysqlResultSet { 1091 // var rs = &MysqlResultSet{} 1092 // 1093 // name := "Date" 1094 // 1095 // mysqlCol := new(MysqlColumn) 1096 // mysqlCol.SetName(name) 1097 // mysqlCol.SetOrgName(name + "OrgName") 1098 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_DATETIME) 1099 // mysqlCol.SetSchema(name + "Schema") 1100 // mysqlCol.SetTable(name + "Table") 1101 // mysqlCol.SetOrgTable(name + "Table") 1102 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1103 // 1104 // rs.AddColumn(mysqlCol) 1105 // 1106 // d1, _ := types.ParseDatetime("2018-04-28 10:21:15", 0) 1107 // d2, _ := types.ParseDatetime("2018-04-28 10:21:15.123", 0) 1108 // d3, _ := types.ParseDatetime("2015-03-03 12:12:12", 0) 1109 // var cases = []types.Datetime{ 1110 // d1, 1111 // d2, 1112 // d3, 1113 // } 1114 // for _, v := range cases { 1115 // var data = make([]interface{}, 1) 1116 // data[0] = v 1117 // rs.AddRow(data) 1118 // } 1119 // 1120 // return rs 1121 // } 1122 // 1123 // func makeMysqlDatetimeResult() *MysqlExecutionResult { 1124 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMysqlDatetimeResultSet()) 1125 // } 1126 func make9ColumnsResultSet() *MysqlResultSet { 1127 var rs = &MysqlResultSet{} 1128 1129 var columnTypes = []defines.MysqlType{ 1130 defines.MYSQL_TYPE_TINY, 1131 defines.MYSQL_TYPE_SHORT, 1132 defines.MYSQL_TYPE_LONG, 1133 defines.MYSQL_TYPE_LONGLONG, 1134 defines.MYSQL_TYPE_VARCHAR, 1135 defines.MYSQL_TYPE_FLOAT, 1136 defines.MYSQL_TYPE_DATE, 1137 defines.MYSQL_TYPE_TIME, 1138 defines.MYSQL_TYPE_DATETIME, 1139 defines.MYSQL_TYPE_DOUBLE, 1140 } 1141 1142 var names = []string{ 1143 "Tiny", 1144 "Short", 1145 "Long", 1146 "Longlong", 1147 "Varchar", 1148 "Float", 1149 "Date", 1150 "Time", 1151 "Datetime", 1152 "Double", 1153 } 1154 1155 d1, _ := types.ParseDateCast("1997-01-01") 1156 d2, _ := types.ParseDateCast("2008-02-02") 1157 1158 dt1, _ := types.ParseDatetime("2018-04-28 10:21:15", 0) 1159 dt2, _ := types.ParseDatetime("2018-04-28 10:21:15.123", 0) 1160 dt3, _ := types.ParseDatetime("2015-03-03 12:12:12", 0) 1161 1162 t1, _ := types.ParseTime("2018-04-28 10:21:15", 0) 1163 t2, _ := types.ParseTime("2018-04-28 10:21:15.123", 0) 1164 t3, _ := types.ParseTime("2015-03-03 12:12:12", 0) 1165 1166 var cases = [][]interface{}{ 1167 {int8(-128), int16(-32768), int32(-2147483648), int64(-9223372036854775808), "abc", float32(math.MaxFloat32), d1, t1, dt1, float64(0.01)}, 1168 {int8(-127), int16(0), int32(0), int64(0), "abcde", float32(math.SmallestNonzeroFloat32), d2, t2, dt2, float64(0.01)}, 1169 {int8(127), int16(32767), int32(2147483647), int64(9223372036854775807), "", float32(-math.MaxFloat32), d1, t3, dt3, float64(0.01)}, 1170 {int8(126), int16(32766), int32(2147483646), int64(9223372036854775806), "x-", float32(-math.SmallestNonzeroFloat32), d2, t1, dt1, float64(0.01)}, 1171 } 1172 1173 for i, ct := range columnTypes { 1174 name := names[i] 1175 mysqlCol := new(MysqlColumn) 1176 mysqlCol.SetName(name) 1177 mysqlCol.SetOrgName(name + "OrgName") 1178 mysqlCol.SetColumnType(ct) 1179 mysqlCol.SetSchema(name + "Schema") 1180 mysqlCol.SetTable(name + "Table") 1181 mysqlCol.SetOrgTable(name + "Table") 1182 mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1183 1184 rs.AddColumn(mysqlCol) 1185 } 1186 1187 for _, v := range cases { 1188 rs.AddRow(v) 1189 } 1190 1191 return rs 1192 } 1193 1194 //func makeMysql9ColumnsResult() *MysqlExecutionResult { 1195 // return NewMysqlExecutionResult(0, 0, 0, 0, make9ColumnsResultSet()) 1196 //} 1197 1198 //func makeMoreThan16MBResultSet() *MysqlResultSet { 1199 // var rs = &MysqlResultSet{} 1200 // 1201 // var columnTypes = []defines.MysqlType{ 1202 // defines.MYSQL_TYPE_LONGLONG, 1203 // defines.MYSQL_TYPE_DOUBLE, 1204 // defines.MYSQL_TYPE_VARCHAR, 1205 // } 1206 // 1207 // var names = []string{ 1208 // "Longlong", 1209 // "Double", 1210 // "Varchar", 1211 // } 1212 // 1213 // var rowCase = []interface{}{int64(9223372036854775807), math.MaxFloat64, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"} 1214 // 1215 // for i, ct := range columnTypes { 1216 // name := names[i] 1217 // mysqlCol := new(MysqlColumn) 1218 // mysqlCol.SetName(name) 1219 // mysqlCol.SetOrgName(name + "OrgName") 1220 // mysqlCol.SetColumnType(ct) 1221 // mysqlCol.SetSchema(name + "Schema") 1222 // mysqlCol.SetTable(name + "Table") 1223 // mysqlCol.SetOrgTable(name + "Table") 1224 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1225 // 1226 // rs.AddColumn(mysqlCol) 1227 // } 1228 // 1229 // //the size of the total result set will be more than 16MB 1230 // for i := 0; i < 40000; i++ { 1231 // rs.AddRow(rowCase) 1232 // } 1233 // 1234 // return rs 1235 //} 1236 // 1237 //// the size of resultset will be morethan 16MB 1238 //func makeMoreThan16MBResult() *MysqlExecutionResult { 1239 // return NewMysqlExecutionResult(0, 0, 0, 0, makeMoreThan16MBResultSet()) 1240 //} 1241 // 1242 //func make16MBRowResultSet() *MysqlResultSet { 1243 // var rs = &MysqlResultSet{} 1244 // 1245 // name := "Varstring" 1246 // 1247 // mysqlCol := new(MysqlColumn) 1248 // mysqlCol.SetName(name) 1249 // mysqlCol.SetOrgName(name + "OrgName") 1250 // mysqlCol.SetColumnType(defines.MYSQL_TYPE_VAR_STRING) 1251 // mysqlCol.SetSchema(name + "Schema") 1252 // mysqlCol.SetTable(name + "Table") 1253 // mysqlCol.SetOrgTable(name + "Table") 1254 // mysqlCol.SetCharset(uint16(Utf8mb4CollationID)) 1255 // 1256 // rs.AddColumn(mysqlCol) 1257 // 1258 // /* 1259 // How to test the max size of the data in one packet that the client can received ? 1260 // Environment: Mysql Version 8.0.23 1261 // 1. shell: mysql --help | grep allowed-packet 1262 // something like: 1263 // " 1264 // --max-allowed-packet=# 1265 // max-allowed-packet 16777216 1266 // " 1267 // so, we get: 1268 // max-allowed-packet means : The maximum packet length to send to or receive from server. 1269 // default value : 16777216 (16MB) 1270 // 2. shell execution: mysql -uroot -e "select repeat('a',16*1024*1024-4);" > 16MB-mysql.txt 1271 // we get: ERROR 2020 (HY000) at line 1: Got packet bigger than 'max_allowed_packet' bytes 1272 // 3. shell execution: mysql -uroot -e "select repeat('a',16*1024*1024-5);" > 16MB-mysql.txt 1273 // execution succeeded 1274 // 4. so, the max size of the data in one packet is (max-allowed-packet - 5). 1275 // 5. To change max-allowed-packet. 1276 // shell execution: mysql max-allowed-packet=xxxxx .... 1277 // */ 1278 // 1279 // //test in shell : mysql -h 127.0.0.1 -P 6001 -udump -p111 -e "16mbrow" > 16mbrow.txt 1280 // //max data size : 16 * 1024 * 1024 - 5 1281 // var stuff = make([]byte, 16*1024*1024-5) 1282 // for i := range stuff { 1283 // stuff[i] = 'a' 1284 // } 1285 // 1286 // var rowCase = []interface{}{string(stuff)} 1287 // for i := 0; i < 1; i++ { 1288 // rs.AddRow(rowCase) 1289 // } 1290 // 1291 // return rs 1292 //} 1293 // 1294 //// the size of resultset row will be more than 16MB 1295 //func make16MBRowResult() *MysqlExecutionResult { 1296 // return NewMysqlExecutionResult(0, 0, 0, 0, make16MBRowResultSet()) 1297 //} 1298 // 1299 //func (tRM *TestRoutineManager) resultsetHandler(rs goetty.IOSession, msg interface{}, _ uint64) error { 1300 // tRM.rwlock.Lock() 1301 // routine := tRM.clients[rs] 1302 // tRM.rwlock.Unlock() 1303 // ctx := context.TODO() 1304 // 1305 // pu, err := getParameterUnit("test/system_vars_config.toml", nil, nil) 1306 // if err != nil { 1307 // return err 1308 // } 1309 // pu.SV.SkipCheckUser = true 1310 // pro := routine.getProtocol().(*MysqlProtocolImpl) 1311 // packet, ok := msg.(*Packet) 1312 // pro.SetSequenceID(uint8(packet.SequenceID + 1)) 1313 // if !ok { 1314 // return moerr.NewInternalError(ctx, "message is not Packet") 1315 // } 1316 // setGlobalPu(pu) 1317 // ses := NewSession(pro, nil, nil, false, nil) 1318 // ses.SetRequestContext(ctx) 1319 // pro.SetSession(ses) 1320 // 1321 // length := packet.Length 1322 // payload := packet.Payload 1323 // for uint32(length) == MaxPayloadSize { 1324 // var err error 1325 // msg, err = pro.GetTcpConnection().Read(goetty.ReadOptions{}) 1326 // if err != nil { 1327 // return moerr.NewInternalError(ctx, "read msg error") 1328 // } 1329 // 1330 // packet, ok = msg.(*Packet) 1331 // if !ok { 1332 // return moerr.NewInternalError(ctx, "message is not Packet") 1333 // } 1334 // 1335 // pro.SetSequenceID(uint8(packet.SequenceID + 1)) 1336 // payload = append(payload, packet.Payload...) 1337 // length = packet.Length 1338 // } 1339 // 1340 // // finish handshake process 1341 // if !pro.IsEstablished() { 1342 // _, err := pro.HandleHandshake(ctx, payload) 1343 // if err != nil { 1344 // return err 1345 // } 1346 // if err = pro.Authenticate(ctx); err != nil { 1347 // return err 1348 // } 1349 // pro.SetEstablished() 1350 // return nil 1351 // } 1352 // 1353 // var req *Request 1354 // var resp *Response 1355 // req = pro.GetRequest(payload) 1356 // switch req.GetCmd() { 1357 // case COM_QUIT: 1358 // resp = &Response{ 1359 // category: OkResponse, 1360 // status: 0, 1361 // data: nil, 1362 // } 1363 // if err := pro.SendResponse(ctx, resp); err != nil { 1364 // fmt.Printf("send response failed. error:%v", err) 1365 // break 1366 // } 1367 // case COM_QUERY: 1368 // var query = string(req.GetData().([]byte)) 1369 // 1370 // switch query { 1371 // case "tiny": 1372 // resp = &Response{ 1373 // category: ResultResponse, 1374 // status: 0, 1375 // cmd: 0, 1376 // data: makeMysqlTinyResult(false), 1377 // } 1378 // case "tinyu": 1379 // resp = &Response{ 1380 // category: ResultResponse, 1381 // status: 0, 1382 // data: makeMysqlTinyResult(true), 1383 // } 1384 // case "short": 1385 // resp = &Response{ 1386 // category: ResultResponse, 1387 // status: 0, 1388 // data: makeMysqlShortResult(false), 1389 // } 1390 // case "shortu": 1391 // resp = &Response{ 1392 // category: ResultResponse, 1393 // status: 0, 1394 // data: makeMysqlShortResult(true), 1395 // } 1396 // case "long": 1397 // resp = &Response{ 1398 // category: ResultResponse, 1399 // status: 0, 1400 // data: makeMysqlLongResult(false), 1401 // } 1402 // case "longu": 1403 // resp = &Response{ 1404 // category: ResultResponse, 1405 // status: 0, 1406 // data: makeMysqlLongResult(true), 1407 // } 1408 // case "longlong": 1409 // resp = &Response{ 1410 // category: ResultResponse, 1411 // status: 0, 1412 // data: makeMysqlLongLongResult(false), 1413 // } 1414 // case "longlongu": 1415 // resp = &Response{ 1416 // category: ResultResponse, 1417 // status: 0, 1418 // data: makeMysqlLongLongResult(true), 1419 // } 1420 // case "int24": 1421 // resp = &Response{ 1422 // category: ResultResponse, 1423 // status: 0, 1424 // data: makeMysqlInt24Result(false), 1425 // } 1426 // case "int24u": 1427 // resp = &Response{ 1428 // category: ResultResponse, 1429 // status: 0, 1430 // data: makeMysqlInt24Result(true), 1431 // } 1432 // case "year": 1433 // resp = &Response{ 1434 // category: ResultResponse, 1435 // status: 0, 1436 // data: makeMysqlYearResult(false), 1437 // } 1438 // case "yearu": 1439 // resp = &Response{ 1440 // category: ResultResponse, 1441 // status: 0, 1442 // data: makeMysqlYearResult(true), 1443 // } 1444 // case "varchar": 1445 // resp = &Response{ 1446 // category: ResultResponse, 1447 // status: 0, 1448 // data: makeMysqlVarcharResult(), 1449 // } 1450 // case "varstring": 1451 // resp = &Response{ 1452 // category: ResultResponse, 1453 // status: 0, 1454 // data: makeMysqlVarStringResult(), 1455 // } 1456 // case "string": 1457 // resp = &Response{ 1458 // category: ResultResponse, 1459 // status: 0, 1460 // data: makeMysqlStringResult(), 1461 // } 1462 // case "float": 1463 // resp = &Response{ 1464 // category: ResultResponse, 1465 // status: 0, 1466 // data: makeMysqlFloatResult(), 1467 // } 1468 // case "double": 1469 // resp = &Response{ 1470 // category: ResultResponse, 1471 // status: 0, 1472 // data: makeMysqlDoubleResult(), 1473 // } 1474 // case "date": 1475 // resp = &Response{ 1476 // category: ResultResponse, 1477 // status: 0, 1478 // data: makeMysqlDateResult(), 1479 // } 1480 // case "time": 1481 // resp = &Response{ 1482 // category: ResultResponse, 1483 // status: 0, 1484 // data: makeMysqlTimeResult(), 1485 // } 1486 // case "datetime": 1487 // resp = &Response{ 1488 // category: ResultResponse, 1489 // status: 0, 1490 // data: makeMysqlDatetimeResult(), 1491 // } 1492 // case "9columns": 1493 // resp = &Response{ 1494 // category: ResultResponse, 1495 // status: 0, 1496 // data: makeMysql9ColumnsResult(), 1497 // } 1498 // case "16mb": 1499 // resp = &Response{ 1500 // category: ResultResponse, 1501 // status: 0, 1502 // data: makeMoreThan16MBResult(), 1503 // } 1504 // case "16mbrow": 1505 // resp = &Response{ 1506 // category: ResultResponse, 1507 // status: 0, 1508 // data: make16MBRowResult(), 1509 // } 1510 // default: 1511 // resp = &Response{ 1512 // category: OkResponse, 1513 // status: 0, 1514 // data: nil, 1515 // } 1516 // } 1517 // 1518 // if err := pro.SendResponse(ctx, resp); err != nil { 1519 // fmt.Printf("send response failed. error:%v", err) 1520 // break 1521 // } 1522 // case COM_PING: 1523 // resp = NewResponse( 1524 // OkResponse, 1525 // 0, 0, 0, 1526 // 0, 1527 // int(COM_PING), 1528 // nil, 1529 // ) 1530 // if err := pro.SendResponse(ctx, resp); err != nil { 1531 // fmt.Printf("send response failed. error:%v", err) 1532 // break 1533 // } 1534 // 1535 // default: 1536 // fmt.Printf("unsupported command. 0x%x \n", req.cmd) 1537 // } 1538 // if req.cmd == COM_QUIT { 1539 // return nil 1540 // } 1541 // return nil 1542 //} 1543 1544 //TODO:replace by the dedicated table functions. 1545 //func TestMysqlResultSet(t *testing.T) { 1546 // //client connection method: mysql -h 127.0.0.1 -P 6001 -udump -p 1547 // //pwd: mysql-server-mysql-8.0.23/mysql-test 1548 // //with mysqltest: mysqltest --test-file=t/1st.test --result-file=r/1st.result --user=dump -p111 -P 6001 --host=127.0.0.1 1549 // 1550 // //test: 1551 // //./mysql-test-run 1st --extern user=root --extern port=3306 --extern host=127.0.0.1 1552 // // mysql5.7 failed 1553 // // mysql-8.0.23 success 1554 // //./mysql-test-run 1st --extern user=root --extern port=6001 --extern host=127.0.0.1 1555 // // matrixone failed: mysql-test-run: *** ERROR: Could not connect to extern server using command: '/Users/pengzhen/Documents/mysql-server-mysql-8.0.23/bld/runtime_output_directory//mysql --no-defaults --user=root --user=root --port=6001 --host=127.0.0.1 --silent --database=mysql --execute="SHOW GLOBAL VARIABLES"' 1556 // pu := config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil) 1557 // _, err := toml.DecodeFile("test/system_vars_config.toml", pu.SV) 1558 // if err != nil { 1559 // panic(err) 1560 // } 1561 // pu.SV.SkipCheckUser = true 1562 // 1563 // trm := NewTestRoutineManager(pu) 1564 // var atomTrm atomic.Value 1565 // atomTrm.Store(trm) 1566 // 1567 // wg := sync.WaitGroup{} 1568 // wg.Add(1) 1569 // 1570 // go func() { 1571 // defer wg.Done() 1572 // 1573 // temTrm := atomTrm.Load().(*TestRoutineManager) 1574 // echoServer(temTrm.resultsetHandler, temTrm, NewSqlCodec()) 1575 // }() 1576 // 1577 // // to := NewTimeout(1*time.Minute, false) 1578 // // for isClosed() && !to.isTimeout() { 1579 // // } 1580 // 1581 // time.Sleep(time.Second * 2) 1582 // db, err := openDbConn(t, 6001) 1583 // require.NoError(t, err) 1584 // 1585 // do_query_resp_resultset(t, db, false, false, "tiny", makeMysqlTinyIntResultSet(false)) 1586 // do_query_resp_resultset(t, db, false, false, "tinyu", makeMysqlTinyIntResultSet(true)) 1587 // do_query_resp_resultset(t, db, false, false, "short", makeMysqlShortResultSet(false)) 1588 // do_query_resp_resultset(t, db, false, false, "shortu", makeMysqlShortResultSet(true)) 1589 // do_query_resp_resultset(t, db, false, false, "long", makeMysqlLongResultSet(false)) 1590 // do_query_resp_resultset(t, db, false, false, "longu", makeMysqlLongResultSet(true)) 1591 // do_query_resp_resultset(t, db, false, false, "longlong", makeMysqlLongLongResultSet(false)) 1592 // do_query_resp_resultset(t, db, false, false, "longlongu", makeMysqlLongLongResultSet(true)) 1593 // do_query_resp_resultset(t, db, false, false, "int24", makeMysqlInt24ResultSet(false)) 1594 // do_query_resp_resultset(t, db, false, false, "int24u", makeMysqlInt24ResultSet(true)) 1595 // do_query_resp_resultset(t, db, false, false, "year", makeMysqlYearResultSet(false)) 1596 // do_query_resp_resultset(t, db, false, false, "yearu", makeMysqlYearResultSet(true)) 1597 // do_query_resp_resultset(t, db, false, false, "varchar", makeMysqlVarcharResultSet()) 1598 // do_query_resp_resultset(t, db, false, false, "varstring", makeMysqlVarStringResultSet()) 1599 // do_query_resp_resultset(t, db, false, false, "string", makeMysqlStringResultSet()) 1600 // do_query_resp_resultset(t, db, false, false, "float", makeMysqlFloatResultSet()) 1601 // do_query_resp_resultset(t, db, false, false, "double", makeMysqlDoubleResultSet()) 1602 // do_query_resp_resultset(t, db, false, false, "date", makeMysqlDateResultSet()) 1603 // do_query_resp_resultset(t, db, false, false, "time", makeMysqlTimeResultSet()) 1604 // do_query_resp_resultset(t, db, false, false, "datetime", makeMysqlDatetimeResultSet()) 1605 // do_query_resp_resultset(t, db, false, false, "9columns", make9ColumnsResultSet()) 1606 // do_query_resp_resultset(t, db, false, false, "16mbrow", make16MBRowResultSet()) 1607 // do_query_resp_resultset(t, db, false, false, "16mb", makeMoreThan16MBResultSet()) 1608 // 1609 // time.Sleep(time.Millisecond * 10) 1610 // //close server 1611 // setServer(1) 1612 // wg.Wait() 1613 // 1614 // closeDbConn(t, db) 1615 //} 1616 1617 // func open_tls_db(t *testing.T, port int) *sql.DB { 1618 // tlsName := "custom" 1619 // rootCertPool := x509.NewCertPool() 1620 // pem, err := os.ReadFile("test/ca.pem") 1621 // if err != nil { 1622 // setServer(1) 1623 // require.NoError(t, err) 1624 // } 1625 // if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { 1626 // log.Fatal("Failed to append PEM.") 1627 // } 1628 // clientCert := make([]tls.Certificate, 0, 1) 1629 // certs, err := tls.LoadX509KeyPair("test/client-cert2.pem", "test/client-key2.pem") 1630 // if err != nil { 1631 // setServer(1) 1632 // require.NoError(t, err) 1633 // } 1634 // clientCert = append(clientCert, certs) 1635 // err = mysqlDriver.RegisterTLSConfig(tlsName, &tls.Config{ 1636 // RootCAs: rootCertPool, 1637 // Certificates: clientCert, 1638 // MinVersion: tls.VersionTLS12, 1639 // InsecureSkipVerify: true, 1640 // }) 1641 // if err != nil { 1642 // setServer(1) 1643 // require.NoError(t, err) 1644 // } 1645 1646 // dsn := fmt.Sprintf("dump:111@tcp(127.0.0.1:%d)/?readTimeout=5s&timeout=5s&writeTimeout=5s&tls=%s", port, tlsName) 1647 // db, err := sql.Open("mysql", dsn) 1648 // if err != nil { 1649 // require.NoError(t, err) 1650 // } else { 1651 // db.SetConnMaxLifetime(time.Minute * 3) 1652 // db.SetMaxOpenConns(1) 1653 // db.SetMaxIdleConns(1) 1654 // time.Sleep(time.Millisecond * 100) 1655 1656 // // ping opens the connection 1657 // logutil.Info("start ping") 1658 // err = db.Ping() 1659 // if err != nil { 1660 // setServer(1) 1661 // require.NoError(t, err) 1662 // } 1663 // } 1664 // return db 1665 // } 1666 1667 func openDbConn(t *testing.T, port int) (db *sql.DB, err error) { 1668 dsn := fmt.Sprintf("dump:111@tcp(127.0.0.1:%d)/?readTimeout=30s&timeout=30s&writeTimeout=30s", port) 1669 for i := 0; i < 3; i++ { 1670 db, err = tryConn(dsn) 1671 if err != nil { 1672 logger.Error("open conn failed.", zap.Error(err)) 1673 time.Sleep(time.Second) 1674 continue 1675 } 1676 break 1677 } 1678 return 1679 } 1680 1681 func tryConn(dsn string) (*sql.DB, error) { 1682 db, err := sql.Open("mysql", dsn) 1683 if err != nil { 1684 return nil, err 1685 } else { 1686 db.SetConnMaxLifetime(time.Minute * 3) 1687 db.SetMaxOpenConns(1) 1688 db.SetMaxIdleConns(1) 1689 time.Sleep(time.Millisecond * 100) 1690 1691 //ping opens the connection 1692 err = db.Ping() 1693 if err != nil { 1694 return nil, err 1695 } 1696 } 1697 return db, err 1698 } 1699 1700 func closeDbConn(t *testing.T, db *sql.DB) { 1701 err := db.Close() 1702 assert.NoError(t, err) 1703 } 1704 1705 //func do_query_resp_resultset(t *testing.T, db *sql.DB, wantErr bool, skipResultsetCheck bool, query string, mrs *MysqlResultSet) { 1706 // logutil.Infof("query: %v", query) 1707 // rows, err := db.Query(query) 1708 // if wantErr { 1709 // require.Error(t, err) 1710 // require.True(t, rows == nil) 1711 // return 1712 // } 1713 // require.NoError(t, err) 1714 // defer func() { 1715 // err = rows.Close() 1716 // require.NoError(t, err) 1717 // err = rows.Err() 1718 // require.NoError(t, err) 1719 // }() 1720 // 1721 // //column check 1722 // columns, err := rows.Columns() 1723 // require.NoError(t, err) 1724 // require.True(t, len(columns) == len(mrs.Columns)) 1725 // 1726 // //colType, err := rows.ColumnTypes() 1727 // //require.NoError(t, err) 1728 // //for i, ct := range colType { 1729 // // fmt.Printf("column %d\n",i) 1730 // // fmt.Printf("name %v \n",ct.Name()) 1731 // // l,o := ct.RowCount() 1732 // // fmt.Printf("length %v %v \n",l,o) 1733 // // p,s,o := ct.DecimalSize() 1734 // // fmt.Printf("decimalsize %v %v %v \n",p,s,o) 1735 // // fmt.Printf("scantype %v \n",ct.ScanType()) 1736 // // n,o := ct.Nullable() 1737 // // fmt.Printf("nullable %v %v \n",n,o) 1738 // // fmt.Printf("databaseTypeName %s \n",ct.DatabaseTypeName()) 1739 // //} 1740 // 1741 // values := make([][]byte, len(columns)) 1742 // 1743 // // rows.Scan wants '[]interface{}' as an argument, so we must copy the 1744 // // references into such a slice 1745 // // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details 1746 // scanArgs := make([]interface{}, len(columns)) 1747 // for i := uint64(0); i < mrs.GetColumnCount(); i++ { 1748 // scanArgs[i] = &values[i] 1749 // } 1750 // 1751 // rowIdx := uint64(0) 1752 // for rows.Next() { 1753 // err = rows.Scan(scanArgs...) 1754 // require.NoError(t, err) 1755 // 1756 // //fmt.Println(rowIdx) 1757 // //fmt.Println(mrs.GetRow(rowIdx)) 1758 // // 1759 // //for i := uint64(0); i < mrs.GetColumnCount(); i++ { 1760 // // arg := scanArgs[i] 1761 // // val := *(arg.(*[]byte)) 1762 // // fmt.Printf("%v ",val) 1763 // //} 1764 // //fmt.Println() 1765 // 1766 // if !skipResultsetCheck { 1767 // for i := uint64(0); i < mrs.GetColumnCount(); i++ { 1768 // arg := scanArgs[i] 1769 // val := *(arg.(*[]byte)) 1770 // 1771 // column, err := mrs.GetColumn(context.TODO(), i) 1772 // require.NoError(t, err) 1773 // 1774 // col, ok := column.(*MysqlColumn) 1775 // require.True(t, ok) 1776 // 1777 // isNUll, err := mrs.ColumnIsNull(context.TODO(), rowIdx, i) 1778 // require.NoError(t, err) 1779 // 1780 // if isNUll { 1781 // require.True(t, val == nil) 1782 // } else { 1783 // var data []byte = nil 1784 // switch col.ColumnType() { 1785 // case defines.MYSQL_TYPE_TINY, defines.MYSQL_TYPE_SHORT, defines.MYSQL_TYPE_INT24, defines.MYSQL_TYPE_LONG, defines.MYSQL_TYPE_YEAR: 1786 // value, err := mrs.GetInt64(context.TODO(), rowIdx, i) 1787 // require.NoError(t, err) 1788 // if col.ColumnType() == defines.MYSQL_TYPE_YEAR { 1789 // if value == 0 { 1790 // data = append(data, []byte("0000")...) 1791 // } else { 1792 // data = strconv.AppendInt(data, value, 10) 1793 // } 1794 // } else { 1795 // data = strconv.AppendInt(data, value, 10) 1796 // } 1797 // 1798 // case defines.MYSQL_TYPE_LONGLONG: 1799 // if uint32(col.Flag())&defines.UNSIGNED_FLAG != 0 { 1800 // value, err := mrs.GetUint64(context.TODO(), rowIdx, i) 1801 // require.NoError(t, err) 1802 // data = strconv.AppendUint(data, value, 10) 1803 // } else { 1804 // value, err := mrs.GetInt64(context.TODO(), rowIdx, i) 1805 // require.NoError(t, err) 1806 // data = strconv.AppendInt(data, value, 10) 1807 // } 1808 // case defines.MYSQL_TYPE_VARCHAR, defines.MYSQL_TYPE_VAR_STRING, defines.MYSQL_TYPE_STRING: 1809 // value, err := mrs.GetString(context.TODO(), rowIdx, i) 1810 // require.NoError(t, err) 1811 // data = []byte(value) 1812 // case defines.MYSQL_TYPE_FLOAT: 1813 // value, err := mrs.GetFloat64(context.TODO(), rowIdx, i) 1814 // require.NoError(t, err) 1815 // data = strconv.AppendFloat(data, value, 'f', -1, 32) 1816 // case defines.MYSQL_TYPE_DOUBLE: 1817 // value, err := mrs.GetFloat64(context.TODO(), rowIdx, i) 1818 // require.NoError(t, err) 1819 // data = strconv.AppendFloat(data, value, 'f', -1, 64) 1820 // case defines.MYSQL_TYPE_DATE: 1821 // value, err := mrs.GetValue(context.TODO(), rowIdx, i) 1822 // require.NoError(t, err) 1823 // x := value.(types.Date).String() 1824 // data = []byte(x) 1825 // case defines.MYSQL_TYPE_TIME: 1826 // value, err := mrs.GetValue(context.TODO(), rowIdx, i) 1827 // require.NoError(t, err) 1828 // x := value.(types.Time).String() 1829 // data = []byte(x) 1830 // case defines.MYSQL_TYPE_DATETIME: 1831 // value, err := mrs.GetValue(context.TODO(), rowIdx, i) 1832 // require.NoError(t, err) 1833 // x := value.(types.Datetime).String() 1834 // data = []byte(x) 1835 // default: 1836 // require.NoError(t, moerr.NewInternalError(context.TODO(), "unsupported type %v", col.ColumnType())) 1837 // } 1838 // //check 1839 // ret := reflect.DeepEqual(data, val) 1840 // //fmt.Println(i) 1841 // //fmt.Println(data) 1842 // //fmt.Println(val) 1843 // require.True(t, ret) 1844 // } 1845 // } 1846 // } 1847 // 1848 // rowIdx++ 1849 // } 1850 // 1851 // require.True(t, rowIdx == mrs.GetRowCount()) 1852 // 1853 //} 1854 1855 func Test_writePackets(t *testing.T) { 1856 ctx := context.TODO() 1857 convey.Convey("writepackets 16MB succ", t, func() { 1858 ctrl := gomock.NewController(t) 1859 defer ctrl.Finish() 1860 ioses := mock_frontend.NewMockIOSession(ctrl) 1861 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 1862 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 1863 ioses.EXPECT().Ref().AnyTimes() 1864 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 1865 sv, err := getSystemVariables("test/system_vars_config.toml") 1866 if err != nil { 1867 t.Error(err) 1868 } 1869 1870 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 1871 err = proto.writePackets(make([]byte, MaxPayloadSize), true) 1872 convey.So(err, convey.ShouldBeNil) 1873 }) 1874 convey.Convey("writepackets 16MB failed", t, func() { 1875 ctrl := gomock.NewController(t) 1876 defer ctrl.Finish() 1877 ioses := mock_frontend.NewMockIOSession(ctrl) 1878 1879 cnt := 0 1880 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).DoAndReturn(func(msg interface{}, opts goetty.WriteOptions) error { 1881 if cnt == 0 { 1882 cnt++ 1883 return nil 1884 } else { 1885 cnt++ 1886 return moerr.NewInternalError(ctx, "write and flush failed.") 1887 } 1888 }).AnyTimes() 1889 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 1890 ioses.EXPECT().Ref().AnyTimes() 1891 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 1892 sv, err := getSystemVariables("test/system_vars_config.toml") 1893 if err != nil { 1894 t.Error(err) 1895 } 1896 1897 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 1898 err = proto.writePackets(make([]byte, MaxPayloadSize), true) 1899 convey.So(err, convey.ShouldBeError) 1900 }) 1901 1902 convey.Convey("writepackets 16MB failed 2", t, func() { 1903 ctrl := gomock.NewController(t) 1904 defer ctrl.Finish() 1905 ioses := mock_frontend.NewMockIOSession(ctrl) 1906 1907 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).DoAndReturn(func(msg interface{}, opts goetty.WriteOptions) error { 1908 return moerr.NewInternalError(ctx, "write and flush failed.") 1909 }).AnyTimes() 1910 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 1911 ioses.EXPECT().Ref().AnyTimes() 1912 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 1913 sv, err := getSystemVariables("test/system_vars_config.toml") 1914 if err != nil { 1915 t.Error(err) 1916 } 1917 1918 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 1919 err = proto.writePackets(make([]byte, MaxPayloadSize), true) 1920 convey.So(err, convey.ShouldBeError) 1921 }) 1922 } 1923 1924 func Test_openpacket(t *testing.T) { 1925 convey.Convey("openpacket succ", t, func() { 1926 ctrl := gomock.NewController(t) 1927 defer ctrl.Finish() 1928 ioses := mock_frontend.NewMockIOSession(ctrl) 1929 1930 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 1931 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 1932 ioses.EXPECT().Ref().AnyTimes() 1933 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 1934 sv, err := getSystemVariables("test/system_vars_config.toml") 1935 if err != nil { 1936 t.Error(err) 1937 } 1938 1939 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 1940 1941 err = proto.openPacket() 1942 convey.So(err, convey.ShouldBeNil) 1943 outBuf := proto.tcpConn.OutBuf() 1944 headLen := outBuf.GetWriteIndex() - beginWriteIndex(outBuf, proto.beginOffset) 1945 convey.So(headLen, convey.ShouldEqual, HeaderLengthOfTheProtocol) 1946 }) 1947 1948 convey.Convey("fillpacket succ", t, func() { 1949 ctrl := gomock.NewController(t) 1950 defer ctrl.Finish() 1951 ioses := mock_frontend.NewMockIOSession(ctrl) 1952 1953 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 1954 ioses.EXPECT().Flush(gomock.Any()).Return(nil).AnyTimes() 1955 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 1956 ioses.EXPECT().Ref().AnyTimes() 1957 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 1958 pu, err := getParameterUnit("test/system_vars_config.toml", nil, nil) 1959 if err != nil { 1960 t.Error(err) 1961 } 1962 setGlobalPu(pu) 1963 1964 proto := NewMysqlClientProtocol(0, ioses, 1024, pu.SV) 1965 // fill proto.ses 1966 ses := NewSession(context.TODO(), proto, nil, nil, false, nil) 1967 proto.ses = ses 1968 1969 err = proto.fillPacket(make([]byte, MaxPayloadSize)...) 1970 convey.So(err, convey.ShouldBeNil) 1971 1972 err = proto.closePacket(true) 1973 convey.So(err, convey.ShouldBeNil) 1974 1975 proto.append(nil, make([]byte, 1024)...) 1976 }) 1977 1978 convey.Convey("closepacket falied.", t, func() { 1979 ctrl := gomock.NewController(t) 1980 defer ctrl.Finish() 1981 ioses := mock_frontend.NewMockIOSession(ctrl) 1982 1983 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 1984 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 1985 ioses.EXPECT().Ref().AnyTimes() 1986 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 1987 pu, err := getParameterUnit("test/system_vars_config.toml", nil, nil) 1988 if err != nil { 1989 t.Error(err) 1990 } 1991 setGlobalPu(pu) 1992 1993 proto := NewMysqlClientProtocol(0, ioses, 1024, pu.SV) 1994 // fill proto.ses 1995 ses := NewSession(context.TODO(), proto, nil, nil, false, nil) 1996 proto.ses = ses 1997 1998 err = proto.openPacket() 1999 convey.So(err, convey.ShouldBeNil) 2000 2001 proto.beginOffset = proto.tcpConn.OutBuf().GetWriteIndex() - proto.tcpConn.OutBuf().GetReadIndex() 2002 err = proto.closePacket(true) 2003 convey.So(err, convey.ShouldBeError) 2004 }) 2005 2006 convey.Convey("append -- data checks", t, func() { 2007 ctrl := gomock.NewController(t) 2008 defer ctrl.Finish() 2009 ioses := mock_frontend.NewMockIOSession(ctrl) 2010 2011 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2012 ioses.EXPECT().Flush(gomock.Any()).Return(nil).AnyTimes() 2013 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2014 ioses.EXPECT().Ref().AnyTimes() 2015 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2016 sv, err := getSystemVariables("test/system_vars_config.toml") 2017 if err != nil { 2018 t.Error(err) 2019 } 2020 2021 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2022 2023 mysqlPack := func(payload []byte) []byte { 2024 n := len(payload) 2025 var curLen int 2026 var header [4]byte 2027 var data []byte = nil 2028 var sequenceId byte = 0 2029 for i := 0; i < n; i += curLen { 2030 curLen = Min(int(MaxPayloadSize), n-i) 2031 binary.LittleEndian.PutUint32(header[:], uint32(curLen)) 2032 header[3] = sequenceId 2033 sequenceId++ 2034 data = append(data, header[:]...) 2035 data = append(data, payload[i:i+curLen]...) 2036 if i+curLen == n && curLen == int(MaxPayloadSize) { 2037 binary.LittleEndian.PutUint32(header[:], uint32(0)) 2038 header[3] = sequenceId 2039 sequenceId++ 2040 data = append(data, header[:]...) 2041 } 2042 } 2043 return data 2044 } 2045 2046 data16MB := func(cnt int) []byte { 2047 data := make([]byte, cnt*int(MaxPayloadSize)) 2048 return data 2049 } 2050 2051 type kase struct { 2052 data []byte 2053 len int 2054 } 2055 2056 kases := []kase{ 2057 { 2058 data: []byte{1, 2, 3, 4}, 2059 len: HeaderLengthOfTheProtocol + 4, 2060 }, 2061 { 2062 data: data16MB(1), 2063 len: HeaderLengthOfTheProtocol + int(MaxPayloadSize) + HeaderLengthOfTheProtocol, 2064 }, 2065 { 2066 data: data16MB(2), 2067 len: HeaderLengthOfTheProtocol + int(MaxPayloadSize) + HeaderLengthOfTheProtocol + int(MaxPayloadSize) + HeaderLengthOfTheProtocol, 2068 }, 2069 { 2070 data: data16MB(3), 2071 len: HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2072 HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2073 HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2074 HeaderLengthOfTheProtocol, 2075 }, 2076 { 2077 data: data16MB(4), 2078 len: HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2079 HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2080 HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2081 HeaderLengthOfTheProtocol + int(MaxPayloadSize) + 2082 HeaderLengthOfTheProtocol, 2083 }, 2084 } 2085 2086 for _, c := range kases { 2087 proto.SetSequenceID(0) 2088 2089 err = proto.openRow(nil) 2090 convey.So(err, convey.ShouldBeNil) 2091 2092 outBuf := proto.tcpConn.OutBuf() 2093 beginOffset := proto.beginOffset 2094 2095 rawBuf := proto.append(nil, c.data...) 2096 2097 err = proto.closeRow(nil) 2098 convey.So(err, convey.ShouldBeNil) 2099 2100 want := mysqlPack(c.data) 2101 2102 convey.So(c.len, convey.ShouldEqual, len(want)) 2103 2104 widx := outBuf.GetWriteIndex() 2105 beginIdx := beginWriteIndex(outBuf, beginOffset) 2106 res := rawBuf[beginIdx:widx] 2107 2108 convey.So(bytes.Equal(res, want), convey.ShouldBeTrue) 2109 } 2110 }) 2111 2112 } 2113 2114 func TestSendPrepareResponse(t *testing.T) { 2115 ctx := context.TODO() 2116 convey.Convey("send Prepare response succ", t, func() { 2117 ctrl := gomock.NewController(t) 2118 defer ctrl.Finish() 2119 ioses := mock_frontend.NewMockIOSession(ctrl) 2120 2121 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2122 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2123 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2124 ioses.EXPECT().Ref().AnyTimes() 2125 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2126 sv, err := getSystemVariables("test/system_vars_config.toml") 2127 if err != nil { 2128 t.Error(err) 2129 } 2130 2131 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2132 proto.SetSession(&Session{ 2133 feSessionImpl: feSessionImpl{ 2134 txnHandler: &TxnHandler{}, 2135 }, 2136 }) 2137 2138 st := tree.NewPrepareString(tree.Identifier(getPrepareStmtName(1)), "select ?, 1") 2139 stmts, err := mysql.Parse(ctx, st.Sql, 1, 0) 2140 if err != nil { 2141 t.Error(err) 2142 } 2143 compCtx := plan.NewEmptyCompilerContext() 2144 preparePlan, err := buildPlan(context.TODO(), nil, compCtx, st) 2145 if err != nil { 2146 t.Error(err) 2147 } 2148 prepareStmt := &PrepareStmt{ 2149 Name: preparePlan.GetDcl().GetPrepare().GetName(), 2150 PreparePlan: preparePlan, 2151 PrepareStmt: stmts[0], 2152 } 2153 err = proto.SendPrepareResponse(ctx, prepareStmt) 2154 2155 convey.So(err, convey.ShouldBeNil) 2156 }) 2157 2158 convey.Convey("send Prepare response error", t, func() { 2159 ctrl := gomock.NewController(t) 2160 defer ctrl.Finish() 2161 ioses := mock_frontend.NewMockIOSession(ctrl) 2162 2163 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2164 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2165 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2166 ioses.EXPECT().Ref().AnyTimes() 2167 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2168 sv, err := getSystemVariables("test/system_vars_config.toml") 2169 if err != nil { 2170 t.Error(err) 2171 } 2172 2173 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2174 2175 st := tree.NewPrepareString("stmt1", "select ?, 1") 2176 stmts, err := mysql.Parse(ctx, st.Sql, 1, 0) 2177 if err != nil { 2178 t.Error(err) 2179 } 2180 compCtx := plan.NewEmptyCompilerContext() 2181 preparePlan, err := buildPlan(context.TODO(), nil, compCtx, st) 2182 if err != nil { 2183 t.Error(err) 2184 } 2185 prepareStmt := &PrepareStmt{ 2186 Name: preparePlan.GetDcl().GetPrepare().GetName(), 2187 PreparePlan: preparePlan, 2188 PrepareStmt: stmts[0], 2189 } 2190 err = proto.SendPrepareResponse(ctx, prepareStmt) 2191 2192 convey.So(err, convey.ShouldBeError) 2193 }) 2194 } 2195 2196 func FuzzParseExecuteData(f *testing.F) { 2197 ctx := context.TODO() 2198 2199 ctrl := gomock.NewController(f) 2200 defer ctrl.Finish() 2201 ioses := mock_frontend.NewMockIOSession(ctrl) 2202 proc := testutil.NewProcess() 2203 2204 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2205 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2206 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2207 ioses.EXPECT().Ref().AnyTimes() 2208 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2209 sv, err := getSystemVariables("test/system_vars_config.toml") 2210 if err != nil { 2211 f.Error(err) 2212 } 2213 2214 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2215 2216 st := tree.NewPrepareString(tree.Identifier(getPrepareStmtName(1)), "select ?, 1") 2217 stmts, err := mysql.Parse(ctx, st.Sql, 1, 0) 2218 if err != nil { 2219 f.Error(err) 2220 } 2221 compCtx := plan.NewEmptyCompilerContext() 2222 preparePlan, err := buildPlan(context.TODO(), nil, compCtx, st) 2223 if err != nil { 2224 f.Error(err) 2225 } 2226 prepareStmt := &PrepareStmt{ 2227 Name: preparePlan.GetDcl().GetPrepare().GetName(), 2228 PreparePlan: preparePlan, 2229 PrepareStmt: stmts[0], 2230 params: vector.NewVec(types.T_varchar.ToType()), 2231 } 2232 2233 var testData []byte 2234 testData = append(testData, 0) //flag 2235 testData = append(testData, 0, 0, 0, 0) // skip iteration-count 2236 nullBitmapLen := (1 + 7) >> 3 2237 //nullBitmapLen 2238 for i := 0; i < nullBitmapLen; i++ { 2239 testData = append(testData, 0) 2240 } 2241 testData = append(testData, 1) // new param bound flag 2242 testData = append(testData, uint8(defines.MYSQL_TYPE_TINY)) // type 2243 testData = append(testData, 0) //is unsigned 2244 testData = append(testData, 10) //tiny value 2245 2246 f.Add(testData) 2247 2248 testData = []byte{} 2249 testData = append(testData, 0) //flag 2250 testData = append(testData, 0, 0, 0, 0) // skip iteration-count 2251 nullBitmapLen = (1 + 7) >> 3 2252 //nullBitmapLen 2253 for i := 0; i < nullBitmapLen; i++ { 2254 testData = append(testData, 0) 2255 } 2256 testData = append(testData, 1) // new param bound flag 2257 testData = append(testData, uint8(defines.MYSQL_TYPE_TINY)) // type 2258 testData = append(testData, 0) //is unsigned 2259 testData = append(testData, 4) //tiny value 2260 f.Add(testData) 2261 2262 f.Fuzz(func(t *testing.T, data []byte) { 2263 proto.ParseExecuteData(ctx, proc, prepareStmt, data, 0) 2264 }) 2265 } 2266 2267 /* FIXME The prepare process has undergone some modifications, 2268 so the unit tests for prepare need to be refactored, and the subsequent pr I will resubmit a reasonable ut 2269 func TestParseExecuteData(t *testing.T) { 2270 ctx := context.TODO() 2271 convey.Convey("parseExecuteData succ", t, func() { 2272 ctrl := gomock.NewController(t) 2273 defer ctrl.Finish() 2274 ioses := mock_frontend.NewMockIOSession(ctrl) 2275 2276 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2277 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2278 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2279 ioses.EXPECT().Ref().AnyTimes() 2280 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2281 sv, err := getSystemVariables("test/system_vars_config.toml") 2282 if err != nil { 2283 t.Error(err) 2284 } 2285 2286 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2287 proc := testutil.NewProcess() 2288 2289 st := tree.NewPrepareString(tree.Identifier(getPrepareStmtName(1)), "select ?, 1") 2290 stmts, err := mysql.Parse(ctx, st.Sql, 1) 2291 if err != nil { 2292 t.Error(err) 2293 } 2294 compCtx := plan.NewEmptyCompilerContext() 2295 preparePlan, err := buildPlan(context.TODO(), nil, compCtx, st) 2296 if err != nil { 2297 t.Error(err) 2298 } 2299 prepareStmt := &PrepareStmt{ 2300 Name: preparePlan.GetDcl().GetPrepare().GetName(), 2301 PreparePlan: preparePlan, 2302 PrepareStmt: stmts[0], 2303 params: vector.NewVec(types.T_varchar.ToType()), 2304 } 2305 2306 var testData []byte 2307 testData = append(testData, 0) //flag 2308 testData = append(testData, 0, 0, 0, 0) // skip iteration-count 2309 nullBitmapLen := (1 + 7) >> 3 2310 //nullBitmapLen 2311 for i := 0; i < nullBitmapLen; i++ { 2312 testData = append(testData, 0) 2313 } 2314 testData = append(testData, 1) // new param bound flag 2315 testData = append(testData, uint8(defines.MYSQL_TYPE_TINY)) // type 2316 testData = append(testData, 0) //is unsigned 2317 testData = append(testData, 10) //tiny value 2318 2319 err = proto.ParseExecuteData(ctx, proc, prepareStmt, testData, 0) 2320 convey.So(err, convey.ShouldBeNil) 2321 }) 2322 2323 } 2324 */ 2325 2326 func Test_resultset(t *testing.T) { 2327 ctx := context.TODO() 2328 convey.Convey("send result set batch row succ", t, func() { 2329 ctrl := gomock.NewController(t) 2330 defer ctrl.Finish() 2331 ioses := mock_frontend.NewMockIOSession(ctrl) 2332 2333 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2334 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2335 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2336 ioses.EXPECT().Ref().AnyTimes() 2337 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2338 sv, err := getSystemVariables("test/system_vars_config.toml") 2339 if err != nil { 2340 t.Error(err) 2341 } 2342 2343 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2344 eng := mock_frontend.NewMockEngine(ctrl) 2345 txnClient := mock_frontend.NewMockTxnClient(ctrl) 2346 pu, err := getParameterUnit("test/system_vars_config.toml", eng, txnClient) 2347 if err != nil { 2348 t.Error(err) 2349 } 2350 setGlobalPu(pu) 2351 var gSys GlobalSystemVariables 2352 InitGlobalSystemVariables(&gSys) 2353 ses := NewSession(ctx, proto, nil, &gSys, true, nil) 2354 proto.ses = ses 2355 2356 res := make9ColumnsResultSet() 2357 2358 err = proto.SendResultSetTextBatchRow(res, uint64(len(res.Data))) 2359 convey.So(err, convey.ShouldBeNil) 2360 }) 2361 2362 convey.Convey("send result set batch row speedup succ", t, func() { 2363 ctrl := gomock.NewController(t) 2364 defer ctrl.Finish() 2365 ioses := mock_frontend.NewMockIOSession(ctrl) 2366 2367 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2368 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2369 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2370 ioses.EXPECT().Ref().AnyTimes() 2371 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2372 sv, err := getSystemVariables("test/system_vars_config.toml") 2373 if err != nil { 2374 t.Error(err) 2375 } 2376 2377 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2378 eng := mock_frontend.NewMockEngine(ctrl) 2379 txnClient := mock_frontend.NewMockTxnClient(ctrl) 2380 pu, err := getParameterUnit("test/system_vars_config.toml", eng, txnClient) 2381 if err != nil { 2382 t.Error(err) 2383 } 2384 setGlobalPu(pu) 2385 var gSys GlobalSystemVariables 2386 InitGlobalSystemVariables(&gSys) 2387 ses := NewSession(ctx, proto, nil, &gSys, true, nil) 2388 proto.ses = ses 2389 2390 res := make9ColumnsResultSet() 2391 2392 err = proto.SendResultSetTextBatchRowSpeedup(res, uint64(len(res.Data))) 2393 convey.So(err, convey.ShouldBeNil) 2394 }) 2395 2396 convey.Convey("send result set succ", t, func() { 2397 ctrl := gomock.NewController(t) 2398 defer ctrl.Finish() 2399 ioses := mock_frontend.NewMockIOSession(ctrl) 2400 2401 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2402 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2403 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2404 ioses.EXPECT().Ref().AnyTimes() 2405 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2406 sv, err := getSystemVariables("test/system_vars_config.toml") 2407 if err != nil { 2408 t.Error(err) 2409 } 2410 2411 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2412 eng := mock_frontend.NewMockEngine(ctrl) 2413 txnClient := mock_frontend.NewMockTxnClient(ctrl) 2414 pu, err := getParameterUnit("test/system_vars_config.toml", eng, txnClient) 2415 if err != nil { 2416 t.Error(err) 2417 } 2418 setGlobalPu(pu) 2419 var gSys GlobalSystemVariables 2420 InitGlobalSystemVariables(&gSys) 2421 ses := NewSession(ctx, proto, nil, &gSys, true, nil) 2422 proto.ses = ses 2423 2424 res := make9ColumnsResultSet() 2425 2426 err = proto.sendResultSet(ctx, res, int(COM_QUERY), 0, 0) 2427 convey.So(err, convey.ShouldBeNil) 2428 2429 err = proto.SendResultSetTextRow(res, 0) 2430 convey.So(err, convey.ShouldBeNil) 2431 }) 2432 2433 convey.Convey("send binary result set succ", t, func() { 2434 ctrl := gomock.NewController(t) 2435 defer ctrl.Finish() 2436 ioses := mock_frontend.NewMockIOSession(ctrl) 2437 2438 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2439 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2440 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2441 ioses.EXPECT().Ref().AnyTimes() 2442 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2443 sv, err := getSystemVariables("test/system_vars_config.toml") 2444 if err != nil { 2445 t.Error(err) 2446 } 2447 2448 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2449 eng := mock_frontend.NewMockEngine(ctrl) 2450 txnClient := mock_frontend.NewMockTxnClient(ctrl) 2451 pu, err := getParameterUnit("test/system_vars_config.toml", eng, txnClient) 2452 if err != nil { 2453 t.Error(err) 2454 } 2455 setGlobalPu(pu) 2456 var gSys GlobalSystemVariables 2457 InitGlobalSystemVariables(&gSys) 2458 ses := NewSession(ctx, proto, nil, &gSys, true, nil) 2459 ses.cmd = COM_STMT_EXECUTE 2460 proto.ses = ses 2461 2462 res := make9ColumnsResultSet() 2463 2464 err = proto.SendResultSetTextBatchRowSpeedup(res, 0) 2465 convey.So(err, convey.ShouldBeNil) 2466 }) 2467 } 2468 2469 func Test_send_packet(t *testing.T) { 2470 convey.Convey("send err packet", t, func() { 2471 ctrl := gomock.NewController(t) 2472 defer ctrl.Finish() 2473 ioses := mock_frontend.NewMockIOSession(ctrl) 2474 2475 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2476 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2477 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2478 ioses.EXPECT().Ref().AnyTimes() 2479 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2480 sv, err := getSystemVariables("test/system_vars_config.toml") 2481 if err != nil { 2482 t.Error(err) 2483 } 2484 2485 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2486 2487 err = proto.sendErrPacket(1, "fake state", "fake error") 2488 convey.So(err, convey.ShouldBeNil) 2489 }) 2490 convey.Convey("send eof packet", t, func() { 2491 ctrl := gomock.NewController(t) 2492 defer ctrl.Finish() 2493 ioses := mock_frontend.NewMockIOSession(ctrl) 2494 2495 ioses.EXPECT().OutBuf().Return(goetty_buf.NewByteBuf(1024)).AnyTimes() 2496 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2497 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2498 ioses.EXPECT().Ref().AnyTimes() 2499 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2500 sv, err := getSystemVariables("test/system_vars_config.toml") 2501 if err != nil { 2502 t.Error(err) 2503 } 2504 2505 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2506 2507 err = proto.sendEOFPacket(1, 0) 2508 convey.So(err, convey.ShouldBeNil) 2509 2510 err = proto.SendEOFPacketIf(1, 0) 2511 convey.So(err, convey.ShouldBeNil) 2512 2513 err = proto.sendEOFOrOkPacket(1, 0) 2514 convey.So(err, convey.ShouldBeNil) 2515 }) 2516 } 2517 2518 func Test_analyse320resp(t *testing.T) { 2519 convey.Convey("analyse 320 resp succ", t, func() { 2520 ctrl := gomock.NewController(t) 2521 defer ctrl.Finish() 2522 ioses := mock_frontend.NewMockIOSession(ctrl) 2523 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2524 ioses.EXPECT().Ref().AnyTimes() 2525 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2526 sv, err := getSystemVariables("test/system_vars_config.toml") 2527 if err != nil { 2528 t.Error(err) 2529 } 2530 2531 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2532 2533 var data []byte = nil 2534 var cap uint16 = 0 2535 cap |= uint16(CLIENT_CONNECT_WITH_DB) 2536 var header [2]byte 2537 proto.io.WriteUint16(header[:], 0, cap) 2538 //int<2> capabilities flags, CLIENT_PROTOCOL_41 never set 2539 data = append(data, header[:]...) 2540 //int<3> max-packet size 2541 data = append(data, 0xff, 0xff, 0xff) 2542 //string[NUL] username 2543 username := "abc" 2544 data = append(data, []byte(username)...) 2545 data = append(data, 0x0) 2546 //auth response 2547 authResp := []byte{0x1, 0x2, 0x3, 0x4} 2548 data = append(data, authResp...) 2549 data = append(data, 0x0) 2550 //database 2551 dbName := "T" 2552 data = append(data, []byte(dbName)...) 2553 data = append(data, 0x0) 2554 2555 ok, resp320, err := proto.analyseHandshakeResponse320(context.TODO(), data) 2556 convey.So(err, convey.ShouldBeNil) 2557 convey.So(ok, convey.ShouldBeTrue) 2558 2559 convey.So(resp320.username, convey.ShouldEqual, username) 2560 convey.So(bytes.Equal(resp320.authResponse, authResp), convey.ShouldBeTrue) 2561 convey.So(resp320.database, convey.ShouldEqual, dbName) 2562 }) 2563 2564 convey.Convey("analyse 320 resp failed", t, func() { 2565 ctrl := gomock.NewController(t) 2566 defer ctrl.Finish() 2567 ioses := mock_frontend.NewMockIOSession(ctrl) 2568 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2569 ioses.EXPECT().Ref().AnyTimes() 2570 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2571 sv, err := getSystemVariables("test/system_vars_config.toml") 2572 if err != nil { 2573 t.Error(err) 2574 } 2575 2576 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2577 2578 type kase struct { 2579 data []byte 2580 res bool 2581 } 2582 2583 kases := []kase{ 2584 {data: []byte{0}, res: false}, 2585 {data: []byte{0, 0, 0, 0}, res: false}, 2586 {data: []byte{0, 0, 1, 2, 3}, res: false}, 2587 {data: []byte{0, 0, 1, 2, 3, 'a', 0}, res: true}, 2588 {data: []byte{0, 0, 1, 2, 3, 'a', 0, 1, 2, 3}, res: true}, 2589 {data: []byte{uint8(CLIENT_CONNECT_WITH_DB), 0, 1, 2, 3, 'a', 0}, res: false}, 2590 {data: []byte{uint8(CLIENT_CONNECT_WITH_DB), 0, 1, 2, 3, 'a', 0, 'b', 'c'}, res: false}, 2591 {data: []byte{uint8(CLIENT_CONNECT_WITH_DB), 0, 1, 2, 3, 'a', 0, 'b', 'c', 0}, res: false}, 2592 {data: []byte{uint8(CLIENT_CONNECT_WITH_DB), 0, 1, 2, 3, 'a', 0, 'b', 'c', 0, 'd', 'e'}, res: false}, 2593 {data: []byte{uint8(CLIENT_CONNECT_WITH_DB), 0, 1, 2, 3, 'a', 0, 'b', 'c', 0, 'd', 'e', 0}, res: true}, 2594 } 2595 2596 for _, c := range kases { 2597 ok, _, _ := proto.analyseHandshakeResponse320(context.TODO(), c.data) 2598 convey.So(ok, convey.ShouldEqual, c.res) 2599 } 2600 }) 2601 } 2602 2603 func Test_analyse41resp(t *testing.T) { 2604 convey.Convey("analyse 41 resp succ", t, func() { 2605 ctrl := gomock.NewController(t) 2606 defer ctrl.Finish() 2607 ioses := mock_frontend.NewMockIOSession(ctrl) 2608 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2609 ioses.EXPECT().Ref().AnyTimes() 2610 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2611 sv, err := getSystemVariables("test/system_vars_config.toml") 2612 if err != nil { 2613 t.Error(err) 2614 } 2615 2616 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2617 2618 var data []byte = nil 2619 var cap uint32 = 0 2620 cap |= CLIENT_PROTOCOL_41 | CLIENT_CONNECT_WITH_DB 2621 var header [4]byte 2622 proto.io.WriteUint32(header[:], 0, cap) 2623 //int<4> capabilities flags of the client, CLIENT_PROTOCOL_41 always set 2624 data = append(data, header[:]...) 2625 //int<4> max-packet size 2626 data = append(data, 0xff, 0xff, 0xff, 0xff) 2627 //int<1> character set 2628 data = append(data, 0x1) 2629 //string[23] reserved (all [0]) 2630 data = append(data, make([]byte, 23)...) 2631 //string[NUL] username 2632 username := "abc" 2633 data = append(data, []byte(username)...) 2634 data = append(data, 0x0) 2635 //auth response 2636 authResp := []byte{0x1, 0x2, 0x3, 0x4} 2637 data = append(data, authResp...) 2638 data = append(data, 0x0) 2639 //database 2640 dbName := "T" 2641 data = append(data, []byte(dbName)...) 2642 data = append(data, 0x0) 2643 2644 ok, resp41, err := proto.analyseHandshakeResponse41(context.TODO(), data) 2645 convey.So(err, convey.ShouldBeNil) 2646 convey.So(ok, convey.ShouldBeTrue) 2647 2648 convey.So(resp41.username, convey.ShouldEqual, username) 2649 convey.So(bytes.Equal(resp41.authResponse, authResp), convey.ShouldBeTrue) 2650 convey.So(resp41.database, convey.ShouldEqual, dbName) 2651 }) 2652 2653 convey.Convey("analyse 41 resp failed", t, func() { 2654 ctrl := gomock.NewController(t) 2655 defer ctrl.Finish() 2656 ioses := mock_frontend.NewMockIOSession(ctrl) 2657 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2658 ioses.EXPECT().Read(gomock.Any()).Return(new(Packet), nil).AnyTimes() 2659 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2660 ioses.EXPECT().Ref().AnyTimes() 2661 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2662 sv, err := getSystemVariables("test/system_vars_config.toml") 2663 if err != nil { 2664 t.Error(err) 2665 } 2666 2667 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2668 2669 type kase struct { 2670 data []byte 2671 res bool 2672 } 2673 2674 var cap uint32 = 0 2675 cap |= CLIENT_PROTOCOL_41 | CLIENT_CONNECT_WITH_DB | CLIENT_PLUGIN_AUTH 2676 var header [4]byte 2677 proto.io.WriteUint32(header[:], 0, cap) 2678 2679 kases := []kase{ 2680 {data: []byte{0}, res: false}, 2681 {data: []byte{0, 0, 0, 0}, res: false}, 2682 {data: append(header[:], []byte{ 2683 0, 0, 0, 2684 }...), res: false}, 2685 {data: append(header[:], []byte{ 2686 0, 0, 0, 0, 2687 }...), res: false}, 2688 {data: append(header[:], []byte{ 2689 0, 0, 0, 0, 2690 0, 2691 0, 0, 0, 2692 }...), res: false}, 2693 {data: append(header[:], []byte{ 2694 0, 0, 0, 0, 2695 0, 2696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2697 }...), res: false}, 2698 {data: append(header[:], []byte{ 2699 0, 0, 0, 0, 2700 0, 2701 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2702 'a', 'b', 'c', 2703 }...), res: false}, 2704 {data: append(header[:], []byte{ 2705 0, 0, 0, 0, 2706 0, 2707 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2708 'a', 'b', 'c', 0, 2709 'd', 'e', 'f', 2710 }...), res: false}, 2711 {data: append(header[:], []byte{ 2712 0, 0, 0, 0, 2713 0, 2714 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2715 'a', 'b', 'c', 0, 2716 'd', 'e', 'f', 0, 2717 'T', 2718 }...), res: false}, 2719 {data: append(header[:], []byte{ 2720 0, 0, 0, 0, 2721 0, 2722 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2723 'a', 'b', 'c', 0, 2724 'd', 'e', 'f', 0, 2725 'T', 0, 2726 'm', 'y', 's', 2727 }...), res: false}, 2728 {data: append(header[:], []byte{ 2729 0, 0, 0, 0, 2730 0, 2731 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2732 'a', 'b', 'c', 0, 2733 'd', 'e', 'f', 0, 2734 'T', 0, 2735 'm', 'y', 's', 'q', 'l', '_', 'n', 'a', 't', 'i', 'v', 'e', '_', 'p', 'a', 's', 's', 'w', 'o', 'r', 'x', 0, 2736 }...), res: true}, 2737 {data: append(header[:], []byte{ 2738 0, 0, 0, 0, 2739 0, 2740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2741 'a', 'b', 'c', 0, 2742 'd', 'e', 'f', 0, 2743 'T', 0, 2744 'm', 'y', 's', 'q', 'l', '_', 'n', 'a', 't', 'i', 'v', 'e', '_', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', 0, 2745 }...), res: true}, 2746 } 2747 2748 for _, c := range kases { 2749 ok, _, _ := proto.analyseHandshakeResponse41(context.TODO(), c.data) 2750 convey.So(ok, convey.ShouldEqual, c.res) 2751 } 2752 }) 2753 } 2754 2755 func Test_handleHandshake(t *testing.T) { 2756 ctx := context.TODO() 2757 convey.Convey("handleHandshake succ", t, func() { 2758 ctrl := gomock.NewController(t) 2759 defer ctrl.Finish() 2760 ioses := mock_frontend.NewMockIOSession(ctrl) 2761 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2762 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2763 ioses.EXPECT().Ref().AnyTimes() 2764 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2765 var IO IOPackageImpl 2766 var SV = &config.FrontendParameters{} 2767 SV.SkipCheckUser = true 2768 mp := &MysqlProtocolImpl{SV: SV} 2769 mp.io = &IO 2770 mp.tcpConn = ioses 2771 payload := []byte{'a'} 2772 _, err := mp.HandleHandshake(ctx, payload) 2773 convey.So(err, convey.ShouldNotBeNil) 2774 2775 payload = append(payload, []byte{'b', 'c'}...) 2776 _, err = mp.HandleHandshake(ctx, payload) 2777 convey.So(err, convey.ShouldNotBeNil) 2778 2779 payload = append(payload, []byte{'c', 'd', 0}...) 2780 _, err = mp.HandleHandshake(ctx, payload) 2781 convey.So(err, convey.ShouldBeNil) 2782 }) 2783 } 2784 2785 func Test_handleHandshake_Recover(t *testing.T) { 2786 f := fuzz.New() 2787 count := 10000 2788 maxLen := 0 2789 2790 ctx := context.TODO() 2791 ctrl := gomock.NewController(t) 2792 defer ctrl.Finish() 2793 ioses := mock_frontend.NewMockIOSession(ctrl) 2794 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2795 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2796 ioses.EXPECT().Ref().AnyTimes() 2797 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2798 convey.Convey("handleHandshake succ", t, func() { 2799 var IO IOPackageImpl 2800 var SV = &config.FrontendParameters{} 2801 SV.SkipCheckUser = true 2802 mp := &MysqlProtocolImpl{SV: SV} 2803 mp.io = &IO 2804 mp.tcpConn = ioses 2805 var payload []byte 2806 for i := 0; i < count; i++ { 2807 f.Fuzz(&payload) 2808 _, _ = mp.HandleHandshake(ctx, payload) 2809 maxLen = Max(maxLen, len(payload)) 2810 } 2811 maxLen = 0 2812 var payload2 string 2813 for i := 0; i < count; i++ { 2814 f.Fuzz(&payload2) 2815 _, _ = mp.HandleHandshake(ctx, []byte(payload2)) 2816 maxLen = Max(maxLen, len(payload2)) 2817 } 2818 }) 2819 } 2820 2821 func TestMysqlProtocolImpl_Close(t *testing.T) { 2822 ctrl := gomock.NewController(t) 2823 defer ctrl.Finish() 2824 ioses := mock_frontend.NewMockIOSession(ctrl) 2825 ioses.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 2826 ioses.EXPECT().Read(gomock.Any()).Return(new(Packet), nil).AnyTimes() 2827 ioses.EXPECT().RemoteAddress().Return("").AnyTimes() 2828 ioses.EXPECT().Ref().AnyTimes() 2829 ioses.EXPECT().Flush(gomock.Any()).AnyTimes() 2830 ioses.EXPECT().Disconnect().AnyTimes() 2831 sv, err := getSystemVariables("test/system_vars_config.toml") 2832 if err != nil { 2833 t.Error(err) 2834 } 2835 2836 proto := NewMysqlClientProtocol(0, ioses, 1024, sv) 2837 proto.Quit() 2838 assert.Nil(t, proto.GetSalt()) 2839 assert.Nil(t, proto.strconvBuffer) 2840 assert.Nil(t, proto.lenEncBuffer) 2841 assert.Nil(t, proto.binaryNullBuffer) 2842 }