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  }