github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/server/conn_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 "bufio" 18 "bytes" 19 "context" 20 "encoding/binary" 21 "fmt" 22 "io" 23 24 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 25 . "github.com/whtcorpsinc/check" 26 "github.com/whtcorpsinc/failpoint" 27 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb" 28 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 29 "github.com/whtcorpsinc/milevadb/ekv" 30 "github.com/whtcorpsinc/milevadb/interlock" 31 "github.com/whtcorpsinc/milevadb/petri" 32 "github.com/whtcorpsinc/milevadb/soliton/memcam" 33 "github.com/whtcorpsinc/milevadb/soliton/testkit" 34 "github.com/whtcorpsinc/milevadb/soliton/testleak" 35 "github.com/whtcorpsinc/milevadb/stochastik" 36 ) 37 38 type ConnTestSuite struct { 39 dom *petri.Petri 40 causetstore ekv.CausetStorage 41 } 42 43 var _ = SerialSuites(&ConnTestSuite{}) 44 45 func (ts *ConnTestSuite) SetUpSuite(c *C) { 46 testleak.BeforeTest() 47 var err error 48 ts.causetstore, err = mockstore.NewMockStore() 49 c.Assert(err, IsNil) 50 ts.dom, err = stochastik.BootstrapStochastik(ts.causetstore) 51 c.Assert(err, IsNil) 52 } 53 54 func (ts *ConnTestSuite) TearDownSuite(c *C) { 55 ts.dom.Close() 56 ts.causetstore.Close() 57 testleak.AfterTest(c)() 58 } 59 60 func (ts *ConnTestSuite) TestMalformHandshakeHeader(c *C) { 61 c.Parallel() 62 data := []byte{0x00} 63 var p handshakeResponse41 64 _, err := parseHandshakeResponseHeader(context.Background(), &p, data) 65 c.Assert(err, NotNil) 66 } 67 68 func (ts *ConnTestSuite) TestParseHandshakeResponse(c *C) { 69 c.Parallel() 70 // test data from http://dev.allegrosql.com/doc/internals/en/connection-phase-packets.html#packet-ProtodefCaus::HandshakeResponse41 71 data := []byte{ 72 0x85, 0xa2, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6f, 0x74, 0x00, 0x14, 0x22, 0x50, 0x79, 0xa2, 0x12, 0xd4, 75 0xe8, 0x82, 0xe5, 0xb3, 0xf4, 0x1a, 0x97, 0x75, 0x6b, 0xc8, 0xbe, 0xdb, 0x9f, 0x80, 0x6d, 0x79, 76 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 77 0x6f, 0x72, 0x64, 0x00, 0x61, 0x03, 0x5f, 0x6f, 0x73, 0x09, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6e, 78 0x36, 0x2e, 0x30, 0x0c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 79 0x08, 0x6c, 0x69, 0x62, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x04, 0x5f, 0x70, 0x69, 0x64, 0x05, 0x32, 80 0x32, 0x33, 0x34, 0x34, 0x0f, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 81 0x73, 0x69, 0x6f, 0x6e, 0x08, 0x35, 0x2e, 0x36, 0x2e, 0x36, 0x2d, 0x6d, 0x39, 0x09, 0x5f, 0x70, 82 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x06, 0x78, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x03, 0x66, 83 0x6f, 0x6f, 0x03, 0x62, 0x61, 0x72, 84 } 85 var p handshakeResponse41 86 offset, err := parseHandshakeResponseHeader(context.Background(), &p, data) 87 c.Assert(err, IsNil) 88 c.Assert(p.Capability&allegrosql.ClientConnectAtts, Equals, allegrosql.ClientConnectAtts) 89 err = parseHandshakeResponseBody(context.Background(), &p, data, offset) 90 c.Assert(err, IsNil) 91 eq := mapIdentical(p.Attrs, map[string]string{ 92 "_client_version": "5.6.6-m9", 93 "_platform": "x86_64", 94 "foo": "bar", 95 "_os": "debian6.0", 96 "_client_name": "libmysql", 97 "_pid": "22344"}) 98 c.Assert(eq, IsTrue) 99 100 data = []byte{ 101 0x8d, 0xa6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 103 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x6d, 0x00, 0x14, 0xab, 0x09, 0xee, 0xf6, 0xbc, 0xb1, 0x32, 104 0x3e, 0x61, 0x14, 0x38, 0x65, 0xc0, 0x99, 0x1d, 0x95, 0x7d, 0x75, 0xd4, 0x47, 0x74, 0x65, 0x73, 105 0x74, 0x00, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 106 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00, 107 } 108 p = handshakeResponse41{} 109 offset, err = parseHandshakeResponseHeader(context.Background(), &p, data) 110 c.Assert(err, IsNil) 111 capability := allegrosql.ClientProtodefCaus41 | 112 allegrosql.ClientPluginAuth | 113 allegrosql.ClientSecureConnection | 114 allegrosql.ClientConnectWithDB 115 c.Assert(p.Capability&capability, Equals, capability) 116 err = parseHandshakeResponseBody(context.Background(), &p, data, offset) 117 c.Assert(err, IsNil) 118 c.Assert(p.User, Equals, "pam") 119 c.Assert(p.DBName, Equals, "test") 120 121 // Test for compatibility of ProtodefCaus::HandshakeResponse320 122 data = []byte{ 123 0x00, 0x80, 0x00, 0x00, 0x01, 0x72, 0x6f, 0x6f, 0x74, 0x00, 0x00, 124 } 125 p = handshakeResponse41{} 126 offset, err = parseOldHandshakeResponseHeader(context.Background(), &p, data) 127 c.Assert(err, IsNil) 128 capability = allegrosql.ClientProtodefCaus41 | 129 allegrosql.ClientSecureConnection 130 c.Assert(p.Capability&capability, Equals, capability) 131 err = parseOldHandshakeResponseBody(context.Background(), &p, data, offset) 132 c.Assert(err, IsNil) 133 c.Assert(p.User, Equals, "root") 134 } 135 136 func (ts *ConnTestSuite) TestIssue1768(c *C) { 137 c.Parallel() 138 // this data is from captured handshake packet, using allegrosql client. 139 // MilevaDB should handle authorization correctly, even allegrosql client set 140 // the ClientPluginAuthLenencClientData capability. 141 data := []byte{ 142 0x85, 0xa6, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 144 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x00, 0x14, 0xe9, 0x7a, 0x2b, 0xec, 0x4a, 0xa8, 145 0xea, 0x67, 0x8a, 0xc2, 0x46, 0x4d, 0x32, 0xa4, 0xda, 0x39, 0x77, 0xe5, 0x61, 0x1a, 0x65, 0x03, 146 0x5f, 0x6f, 0x73, 0x05, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x0c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 147 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x08, 0x6c, 0x69, 0x62, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x04, 148 0x5f, 0x70, 0x69, 0x64, 0x04, 0x39, 0x30, 0x33, 0x30, 0x0f, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 149 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x06, 0x35, 0x2e, 0x37, 0x2e, 0x31, 0x34, 150 0x09, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x06, 0x78, 0x38, 0x36, 0x5f, 0x36, 151 0x34, 0x0c, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x05, 0x6d, 152 0x79, 0x73, 0x71, 0x6c, 153 } 154 p := handshakeResponse41{} 155 offset, err := parseHandshakeResponseHeader(context.Background(), &p, data) 156 c.Assert(err, IsNil) 157 c.Assert(p.Capability&allegrosql.ClientPluginAuthLenencClientData, Equals, allegrosql.ClientPluginAuthLenencClientData) 158 err = parseHandshakeResponseBody(context.Background(), &p, data, offset) 159 c.Assert(err, IsNil) 160 c.Assert(len(p.Auth) > 0, IsTrue) 161 } 162 163 func (ts *ConnTestSuite) TestAuthSwitchRequest(c *C) { 164 c.Parallel() 165 // this data is from a MyALLEGROSQL 8.0 client 166 data := []byte{ 167 0x85, 0xa6, 0xff, 0x1, 0x0, 0x0, 0x0, 0x1, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 168 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x72, 0x6f, 169 0x6f, 0x74, 0x0, 0x0, 0x63, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x68, 0x61, 170 0x32, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x0, 0x79, 0x4, 0x5f, 0x70, 171 0x69, 0x64, 0x5, 0x37, 0x37, 0x30, 0x38, 0x36, 0x9, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 172 0x6f, 0x72, 0x6d, 0x6, 0x78, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x3, 0x5f, 0x6f, 0x73, 0x5, 173 0x4c, 0x69, 0x6e, 0x75, 0x78, 0xc, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 174 0x61, 0x6d, 0x65, 0x8, 0x6c, 0x69, 0x62, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x7, 0x6f, 0x73, 175 0x5f, 0x75, 0x73, 0x65, 0x72, 0xa, 0x6e, 0x75, 0x6c, 0x6c, 0x6e, 0x6f, 0x74, 0x6e, 0x69, 176 0x6c, 0xf, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 177 0x6f, 0x6e, 0x6, 0x38, 0x2e, 0x30, 0x2e, 0x32, 0x31, 0xc, 0x70, 0x72, 0x6f, 0x67, 0x72, 178 0x61, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5, 0x6d, 0x79, 0x73, 0x71, 0x6c, 179 } 180 181 var resp handshakeResponse41 182 pos, err := parseHandshakeResponseHeader(context.Background(), &resp, data) 183 c.Assert(err, IsNil) 184 err = parseHandshakeResponseBody(context.Background(), &resp, data, pos) 185 c.Assert(err, IsNil) 186 c.Assert(resp.AuthPlugin == "caching_sha2_password", IsTrue) 187 } 188 189 func (ts *ConnTestSuite) TestInitialHandshake(c *C) { 190 c.Parallel() 191 var outBuffer bytes.Buffer 192 cc := &clientConn{ 193 connectionID: 1, 194 salt: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}, 195 server: &Server{ 196 capability: defaultCapability, 197 }, 198 pkt: &packetIO{ 199 bufWriter: bufio.NewWriter(&outBuffer), 200 }, 201 } 202 err := cc.writeInitialHandshake(context.TODO()) 203 c.Assert(err, IsNil) 204 205 expected := new(bytes.Buffer) 206 expected.WriteByte(0x0a) // ProtodefCaus 207 expected.WriteString(allegrosql.ServerVersion) // Version 208 expected.WriteByte(0x00) // NULL 209 binary.Write(expected, binary.LittleEndian, uint32(1)) // Connection ID 210 expected.Write([]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00}) // Salt 211 binary.Write(expected, binary.LittleEndian, uint16(defaultCapability&0xFFFF)) // Server Capability 212 expected.WriteByte(uint8(allegrosql.DefaultDefCauslationID)) // Server Language 213 binary.Write(expected, binary.LittleEndian, allegrosql.ServerStatusAutocommit) // Server Status 214 binary.Write(expected, binary.LittleEndian, uint16((defaultCapability>>16)&0xFFFF)) // Extended Server Capability 215 expected.WriteByte(0x15) // Authentication Plugin Length 216 expected.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) // Unused 217 expected.Write([]byte{0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x00}) // Salt 218 expected.WriteString("mysql_native_password") // Authentication Plugin 219 expected.WriteByte(0x00) // NULL 220 c.Assert(outBuffer.Bytes()[4:], DeepEquals, expected.Bytes()) 221 } 222 223 type dispatchInput struct { 224 com byte 225 in []byte 226 err error 227 out []byte 228 } 229 230 func (ts *ConnTestSuite) TestDispatch(c *C) { 231 userData := append([]byte("root"), 0x0, 0x0) 232 userData = append(userData, []byte("test")...) 233 userData = append(userData, 0x0) 234 235 inputs := []dispatchInput{ 236 { 237 com: allegrosql.ComSleep, 238 in: nil, 239 err: nil, 240 out: nil, 241 }, 242 { 243 com: allegrosql.ComQuit, 244 in: nil, 245 err: io.EOF, 246 out: nil, 247 }, 248 { 249 com: allegrosql.ComQuery, 250 in: []byte("do 1"), 251 err: nil, 252 out: []byte{0x3, 0x0, 0x0, 0x0, 0x0, 0x00, 0x0}, 253 }, 254 { 255 com: allegrosql.ComInitDB, 256 in: []byte("test"), 257 err: nil, 258 out: []byte{0x3, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0}, 259 }, 260 { 261 com: allegrosql.ComPing, 262 in: nil, 263 err: nil, 264 out: []byte{0x3, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 265 }, 266 { 267 com: allegrosql.ComStmtPrepare, 268 in: []byte("select 1"), 269 err: nil, 270 out: []byte{ 271 0xc, 0x0, 0x0, 0x3, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 272 0x0, 0x0, 0x4, 0x3, 0x64, 0x65, 0x66, 0x0, 0x0, 0x0, 0x1, 0x31, 0x1, 0x31, 0xc, 0x3f, 273 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x81, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x5, 0xfe, 274 }, 275 }, 276 { 277 com: allegrosql.ComStmtInterDircute, 278 in: []byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0}, 279 err: nil, 280 out: []byte{ 281 0x1, 0x0, 0x0, 0x6, 0x1, 0x18, 0x0, 0x0, 0x7, 0x3, 0x64, 0x65, 0x66, 0x0, 0x0, 0x0, 282 0x1, 0x31, 0x1, 0x31, 0xc, 0x3f, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x81, 0x0, 0x0, 0x0, 283 0x0, 0x1, 0x0, 0x0, 0x8, 0xfe, 284 }, 285 }, 286 { 287 com: allegrosql.ComStmtFetch, 288 in: []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 289 err: nil, 290 out: []byte{0x1, 0x0, 0x0, 0x9, 0xfe}, 291 }, 292 { 293 com: allegrosql.ComStmtReset, 294 in: []byte{0x1, 0x0, 0x0, 0x0}, 295 err: nil, 296 out: []byte{0x3, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0}, 297 }, 298 { 299 com: allegrosql.ComSetOption, 300 in: []byte{0x1, 0x0, 0x0, 0x0}, 301 err: nil, 302 out: []byte{0x1, 0x0, 0x0, 0xb, 0xfe}, 303 }, 304 { 305 com: allegrosql.ComStmtClose, 306 in: []byte{0x1, 0x0, 0x0, 0x0}, 307 err: nil, 308 out: []byte{}, 309 }, 310 { 311 com: allegrosql.ComFieldList, 312 in: []byte("t"), 313 err: nil, 314 out: []byte{ 315 0x26, 0x0, 0x0, 0xc, 0x3, 0x64, 0x65, 0x66, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1, 0x74, 316 0x1, 0x74, 0x1, 0x61, 0x1, 0x61, 0xc, 0x3f, 0x0, 0xb, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 317 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0xd, 0xfe, 318 }, 319 }, 320 { 321 com: allegrosql.ComChangeUser, 322 in: userData, 323 err: nil, 324 out: []byte{0x3, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0}, 325 }, 326 { 327 com: allegrosql.ComRefresh, // flush privileges 328 in: []byte{0x01}, 329 err: nil, 330 out: []byte{0x3, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0}, 331 }, 332 { 333 com: allegrosql.ComRefresh, // flush logs etc 334 in: []byte{0x02}, 335 err: nil, 336 out: []byte{0x3, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0}, 337 }, 338 { 339 com: allegrosql.ComResetConnection, 340 in: nil, 341 err: nil, 342 out: []byte{0x3, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0}, 343 }, 344 } 345 346 ts.testDispatch(c, inputs, 0) 347 } 348 349 func (ts *ConnTestSuite) TestDispatchClientProtodefCaus41(c *C) { 350 userData := append([]byte("root"), 0x0, 0x0) 351 userData = append(userData, []byte("test")...) 352 userData = append(userData, 0x0) 353 354 inputs := []dispatchInput{ 355 { 356 com: allegrosql.ComSleep, 357 in: nil, 358 err: nil, 359 out: nil, 360 }, 361 { 362 com: allegrosql.ComQuit, 363 in: nil, 364 err: io.EOF, 365 out: nil, 366 }, 367 { 368 com: allegrosql.ComQuery, 369 in: []byte("do 1"), 370 err: nil, 371 out: []byte{0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 372 }, 373 { 374 com: allegrosql.ComInitDB, 375 in: []byte("test"), 376 err: nil, 377 out: []byte{0x7, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 378 }, 379 { 380 com: allegrosql.ComPing, 381 in: nil, 382 err: nil, 383 out: []byte{0x7, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 384 }, 385 { 386 com: allegrosql.ComStmtPrepare, 387 in: []byte("select 1"), 388 err: nil, 389 out: []byte{ 390 0xc, 0x0, 0x0, 0x3, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 391 0x0, 0x0, 0x4, 0x3, 0x64, 0x65, 0x66, 0x0, 0x0, 0x0, 0x1, 0x31, 0x1, 0x31, 0xc, 0x3f, 392 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x81, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x5, 0xfe, 393 0x0, 0x0, 0x2, 0x0, 394 }, 395 }, 396 { 397 com: allegrosql.ComStmtInterDircute, 398 in: []byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0}, 399 err: nil, 400 out: []byte{ 401 0x1, 0x0, 0x0, 0x6, 0x1, 0x18, 0x0, 0x0, 0x7, 0x3, 0x64, 0x65, 0x66, 0x0, 0x0, 0x0, 402 0x1, 0x31, 0x1, 0x31, 0xc, 0x3f, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x81, 0x0, 0x0, 0x0, 403 0x0, 0x5, 0x0, 0x0, 0x8, 0xfe, 0x0, 0x0, 0x42, 0x0, 404 }, 405 }, 406 { 407 com: allegrosql.ComStmtFetch, 408 in: []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 409 err: nil, 410 out: []byte{0x5, 0x0, 0x0, 0x9, 0xfe, 0x0, 0x0, 0x82, 0x0}, 411 }, 412 { 413 com: allegrosql.ComStmtReset, 414 in: []byte{0x1, 0x0, 0x0, 0x0}, 415 err: nil, 416 out: []byte{0x7, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 417 }, 418 { 419 com: allegrosql.ComSetOption, 420 in: []byte{0x1, 0x0, 0x0, 0x0}, 421 err: nil, 422 out: []byte{0x5, 0x0, 0x0, 0xb, 0xfe, 0x0, 0x0, 0x2, 0x0}, 423 }, 424 { 425 com: allegrosql.ComStmtClose, 426 in: []byte{0x1, 0x0, 0x0, 0x0}, 427 err: nil, 428 out: []byte{}, 429 }, 430 { 431 com: allegrosql.ComFieldList, 432 in: []byte("t"), 433 err: nil, 434 out: []byte{ 435 0x26, 0x0, 0x0, 0xc, 0x3, 0x64, 0x65, 0x66, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1, 0x74, 436 0x1, 0x74, 0x1, 0x61, 0x1, 0x61, 0xc, 0x3f, 0x0, 0xb, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 437 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0xd, 0xfe, 438 0x0, 0x0, 0x2, 0x0, 439 }, 440 }, 441 { 442 com: allegrosql.ComChangeUser, 443 in: userData, 444 err: nil, 445 out: []byte{0x7, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 446 }, 447 { 448 com: allegrosql.ComRefresh, // flush privileges 449 in: []byte{0x01}, 450 err: nil, 451 out: []byte{0x7, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 452 }, 453 { 454 com: allegrosql.ComRefresh, // flush logs etc 455 in: []byte{0x02}, 456 err: nil, 457 out: []byte{0x7, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 458 }, 459 { 460 com: allegrosql.ComResetConnection, 461 in: nil, 462 err: nil, 463 out: []byte{0x7, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, 464 }, 465 } 466 467 ts.testDispatch(c, inputs, allegrosql.ClientProtodefCaus41) 468 } 469 470 func (ts *ConnTestSuite) testDispatch(c *C, inputs []dispatchInput, capability uint32) { 471 causetstore, err := mockstore.NewMockStore() 472 c.Assert(err, IsNil) 473 defer causetstore.Close() 474 dom, err := stochastik.BootstrapStochastik(causetstore) 475 c.Assert(err, IsNil) 476 defer dom.Close() 477 478 se, err := stochastik.CreateStochastik4Test(causetstore) 479 c.Assert(err, IsNil) 480 tc := &MilevaDBContext{ 481 Stochastik: se, 482 stmts: make(map[int]*MilevaDBStatement), 483 } 484 _, err = se.InterDircute(context.Background(), "create causet test.t(a int)") 485 c.Assert(err, IsNil) 486 _, err = se.InterDircute(context.Background(), "insert into test.t values (1)") 487 c.Assert(err, IsNil) 488 489 var outBuffer bytes.Buffer 490 milevadbdrv := NewMilevaDBDriver(ts.causetstore) 491 cfg := newTestConfig() 492 cfg.Port, cfg.Status.StatusPort = 0, 0 493 cfg.Status.ReportStatus = false 494 server, err := NewServer(cfg, milevadbdrv) 495 496 c.Assert(err, IsNil) 497 defer server.Close() 498 499 cc := &clientConn{ 500 connectionID: 1, 501 salt: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}, 502 server: server, 503 pkt: &packetIO{ 504 bufWriter: bufio.NewWriter(&outBuffer), 505 }, 506 defCauslation: allegrosql.DefaultDefCauslationID, 507 peerHost: "localhost", 508 alloc: memcam.NewSlabPredictor(512), 509 ctx: tc, 510 capability: capability, 511 } 512 for _, cs := range inputs { 513 inBytes := append([]byte{cs.com}, cs.in...) 514 err := cc.dispatch(context.Background(), inBytes) 515 c.Assert(err, Equals, cs.err) 516 if err == nil { 517 err = cc.flush(context.TODO()) 518 c.Assert(err, IsNil) 519 c.Assert(outBuffer.Bytes(), DeepEquals, cs.out) 520 } else { 521 _ = cc.flush(context.TODO()) 522 } 523 outBuffer.Reset() 524 } 525 } 526 527 func (ts *ConnTestSuite) TestGetStochastikVarsWaitTimeout(c *C) { 528 c.Parallel() 529 se, err := stochastik.CreateStochastik4Test(ts.causetstore) 530 c.Assert(err, IsNil) 531 tc := &MilevaDBContext{ 532 Stochastik: se, 533 stmts: make(map[int]*MilevaDBStatement), 534 } 535 cc := &clientConn{ 536 connectionID: 1, 537 server: &Server{ 538 capability: defaultCapability, 539 }, 540 ctx: tc, 541 } 542 c.Assert(cc.getStochastikVarsWaitTimeout(context.Background()), Equals, uint64(0)) 543 } 544 545 func mapIdentical(m1, m2 map[string]string) bool { 546 return mapBelong(m1, m2) && mapBelong(m2, m1) 547 } 548 549 func mapBelong(m1, m2 map[string]string) bool { 550 for k1, v1 := range m1 { 551 v2, ok := m2[k1] 552 if !ok && v1 != v2 { 553 return false 554 } 555 } 556 return true 557 } 558 559 func (ts *ConnTestSuite) TestConnInterDircutionTimeout(c *C) { 560 //There is no underlying netCon, use failpoint to avoid panic 561 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/server/FakeClientConn", "return(1)"), IsNil) 562 563 c.Parallel() 564 se, err := stochastik.CreateStochastik4Test(ts.causetstore) 565 c.Assert(err, IsNil) 566 567 connID := 1 568 se.SetConnectionID(uint64(connID)) 569 tc := &MilevaDBContext{ 570 Stochastik: se, 571 stmts: make(map[int]*MilevaDBStatement), 572 } 573 cc := &clientConn{ 574 connectionID: uint32(connID), 575 server: &Server{ 576 capability: defaultCapability, 577 }, 578 ctx: tc, 579 alloc: memcam.NewSlabPredictor(32 * 1024), 580 } 581 srv := &Server{ 582 clients: map[uint32]*clientConn{ 583 uint32(connID): cc, 584 }, 585 } 586 handle := ts.dom.ExpensiveQueryHandle().SetStochastikManager(srv) 587 go handle.Run() 588 589 _, err = se.InterDircute(context.Background(), "use test;") 590 c.Assert(err, IsNil) 591 _, err = se.InterDircute(context.Background(), "CREATE TABLE testBlock2 (id bigint PRIMARY KEY, age int)") 592 c.Assert(err, IsNil) 593 for i := 0; i < 10; i++ { 594 str := fmt.Sprintf("insert into testBlock2 values(%d, %d)", i, i%80) 595 _, err = se.InterDircute(context.Background(), str) 596 c.Assert(err, IsNil) 597 } 598 599 _, err = se.InterDircute(context.Background(), "select SLEEP(1);") 600 c.Assert(err, IsNil) 601 602 _, err = se.InterDircute(context.Background(), "set @@max_execution_time = 500;") 603 c.Assert(err, IsNil) 604 605 err = cc.handleQuery(context.Background(), "select * FROM testBlock2 WHERE SLEEP(1);") 606 c.Assert(err, IsNil) 607 608 _, err = se.InterDircute(context.Background(), "set @@max_execution_time = 1500;") 609 c.Assert(err, IsNil) 610 611 _, err = se.InterDircute(context.Background(), "set @@milevadb_expensive_query_time_threshold = 1;") 612 c.Assert(err, IsNil) 613 614 records, err := se.InterDircute(context.Background(), "select SLEEP(2);") 615 c.Assert(err, IsNil) 616 tk := testkit.NewTestKit(c, ts.causetstore) 617 tk.ResultSetToResult(records[0], Commentf("%v", records[0])).Check(testkit.Rows("1")) 618 619 _, err = se.InterDircute(context.Background(), "set @@max_execution_time = 0;") 620 c.Assert(err, IsNil) 621 622 err = cc.handleQuery(context.Background(), "select * FROM testBlock2 WHERE SLEEP(1);") 623 c.Assert(err, IsNil) 624 625 err = cc.handleQuery(context.Background(), "select /*+ MAX_EXECUTION_TIME(100)*/ * FROM testBlock2 WHERE SLEEP(1);") 626 c.Assert(err, IsNil) 627 628 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/server/FakeClientConn"), IsNil) 629 } 630 631 func (ts *ConnTestSuite) TestShutDown(c *C) { 632 cc := &clientConn{} 633 se, err := stochastik.CreateStochastik4Test(ts.causetstore) 634 c.Assert(err, IsNil) 635 cc.ctx = &MilevaDBContext{Stochastik: se} 636 // set killed flag 637 cc.status = connStatusShutdown 638 // assert ErrQueryInterrupted 639 err = cc.handleQuery(context.Background(), "select 1") 640 c.Assert(err, Equals, interlock.ErrQueryInterrupted) 641 } 642 643 func (ts *ConnTestSuite) TestShutdownOrNotify(c *C) { 644 c.Parallel() 645 se, err := stochastik.CreateStochastik4Test(ts.causetstore) 646 c.Assert(err, IsNil) 647 tc := &MilevaDBContext{ 648 Stochastik: se, 649 stmts: make(map[int]*MilevaDBStatement), 650 } 651 cc := &clientConn{ 652 connectionID: 1, 653 server: &Server{ 654 capability: defaultCapability, 655 }, 656 status: connStatusWaitShutdown, 657 ctx: tc, 658 } 659 c.Assert(cc.ShutdownOrNotify(), IsFalse) 660 cc.status = connStatusReading 661 c.Assert(cc.ShutdownOrNotify(), IsTrue) 662 c.Assert(cc.status, Equals, connStatusShutdown) 663 cc.status = connStatusDispatching 664 c.Assert(cc.ShutdownOrNotify(), IsFalse) 665 c.Assert(cc.status, Equals, connStatusWaitShutdown) 666 } 667 668 func (ts *ConnTestSuite) TestPrefetchPointKeys(c *C) { 669 cc := &clientConn{ 670 alloc: memcam.NewSlabPredictor(1024), 671 pkt: &packetIO{ 672 bufWriter: bufio.NewWriter(bytes.NewBuffer(nil)), 673 }, 674 } 675 tk := testkit.NewTestKitWithInit(c, ts.causetstore) 676 cc.ctx = &MilevaDBContext{Stochastik: tk.Se} 677 ctx := context.Background() 678 tk.MustInterDirc("set @@milevadb_enable_clustered_index=0") 679 tk.MustInterDirc("create causet prefetch (a int, b int, c int, primary key (a, b))") 680 tk.MustInterDirc("insert prefetch values (1, 1, 1), (2, 2, 2), (3, 3, 3)") 681 tk.MustInterDirc("begin optimistic") 682 tk.MustInterDirc("uFIDelate prefetch set c = c + 1 where a = 2 and b = 2") 683 query := "uFIDelate prefetch set c = c + 1 where a = 1 and b = 1;" + 684 "uFIDelate prefetch set c = c + 1 where a = 2 and b = 2;" + 685 "uFIDelate prefetch set c = c + 1 where a = 3 and b = 3;" 686 err := cc.handleQuery(ctx, query) 687 c.Assert(err, IsNil) 688 txn, err := tk.Se.Txn(false) 689 c.Assert(err, IsNil) 690 c.Assert(txn.Valid(), IsTrue) 691 snap := txn.GetSnapshot() 692 c.Assert(einsteindb.SnapCacheHitCount(snap), Equals, 4) 693 tk.MustInterDirc("commit") 694 tk.MustQuery("select * from prefetch").Check(testkit.Rows("1 1 2", "2 2 4", "3 3 4")) 695 696 tk.MustInterDirc("begin pessimistic") 697 tk.MustInterDirc("uFIDelate prefetch set c = c + 1 where a = 2 and b = 2") 698 c.Assert(tk.Se.GetStochastikVars().TxnCtx.PessimisticCacheHit, Equals, 1) 699 err = cc.handleQuery(ctx, query) 700 c.Assert(err, IsNil) 701 txn, err = tk.Se.Txn(false) 702 c.Assert(err, IsNil) 703 c.Assert(txn.Valid(), IsTrue) 704 c.Assert(tk.Se.GetStochastikVars().TxnCtx.PessimisticCacheHit, Equals, 5) 705 tk.MustInterDirc("commit") 706 tk.MustQuery("select * from prefetch").Check(testkit.Rows("1 1 3", "2 2 6", "3 3 5")) 707 }