github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/server/mdb_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  //go:build !race
    14  // +build !race
    15  
    16  package server
    17  
    18  import (
    19  	"context"
    20  	"crypto/rand"
    21  	"crypto/rsa"
    22  	"crypto/tls"
    23  	"crypto/x509"
    24  	"crypto/x509/pkix"
    25  	"encoding/pem"
    26  	"io/ioutil"
    27  	"math/big"
    28  	"net/http"
    29  	"os"
    30  	"path/filepath"
    31  	"time"
    32  
    33  	"github.com/go-allegrosql-driver/allegrosql"
    34  	tmysql "github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    35  	. "github.com/whtcorpsinc/check"
    36  	"github.com/whtcorpsinc/errors"
    37  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    38  	"github.com/whtcorpsinc/milevadb/config"
    39  	"github.com/whtcorpsinc/milevadb/ekv"
    40  	"github.com/whtcorpsinc/milevadb/metrics"
    41  	"github.com/whtcorpsinc/milevadb/petri"
    42  	"github.com/whtcorpsinc/milevadb/soliton"
    43  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    44  	"github.com/whtcorpsinc/milevadb/stochastik"
    45  )
    46  
    47  type milevadbTestSuite struct {
    48  	*milevadbTestSuiteBase
    49  }
    50  
    51  type milevadbTestSerialSuite struct {
    52  	*milevadbTestSuiteBase
    53  }
    54  
    55  type milevadbTestSuiteBase struct {
    56  	*testServerClient
    57  	milevadbdrv *MilevaDBDriver
    58  	server      *Server
    59  	petri       *petri.Petri
    60  	causetstore ekv.CausetStorage
    61  }
    62  
    63  func newMilevaDBTestSuiteBase() *milevadbTestSuiteBase {
    64  	return &milevadbTestSuiteBase{
    65  		testServerClient: newTestServerClient(),
    66  	}
    67  }
    68  
    69  var _ = Suite(&milevadbTestSuite{newMilevaDBTestSuiteBase()})
    70  var _ = SerialSuites(&milevadbTestSerialSuite{newMilevaDBTestSuiteBase()})
    71  
    72  func (ts *milevadbTestSuite) SetUpSuite(c *C) {
    73  	metrics.RegisterMetrics()
    74  	ts.milevadbTestSuiteBase.SetUpSuite(c)
    75  }
    76  
    77  func (ts *milevadbTestSuiteBase) SetUpSuite(c *C) {
    78  	var err error
    79  	ts.causetstore, err = mockstore.NewMockStore()
    80  	stochastik.DisableStats4Test()
    81  	c.Assert(err, IsNil)
    82  	ts.petri, err = stochastik.BootstrapStochastik(ts.causetstore)
    83  	c.Assert(err, IsNil)
    84  	ts.milevadbdrv = NewMilevaDBDriver(ts.causetstore)
    85  	cfg := newTestConfig()
    86  	cfg.Port = ts.port
    87  	cfg.Status.ReportStatus = true
    88  	cfg.Status.StatusPort = ts.statusPort
    89  	cfg.Performance.TCPKeepAlive = true
    90  
    91  	server, err := NewServer(cfg, ts.milevadbdrv)
    92  	c.Assert(err, IsNil)
    93  	ts.port = getPortFromTCPAddr(server.listener.Addr())
    94  	ts.statusPort = getPortFromTCPAddr(server.statusListener.Addr())
    95  	ts.server = server
    96  	go ts.server.Run()
    97  	ts.waitUntilServerOnline()
    98  }
    99  
   100  func (ts *milevadbTestSuiteBase) TearDownSuite(c *C) {
   101  	if ts.causetstore != nil {
   102  		ts.causetstore.Close()
   103  	}
   104  	if ts.petri != nil {
   105  		ts.petri.Close()
   106  	}
   107  	if ts.server != nil {
   108  		ts.server.Close()
   109  	}
   110  }
   111  
   112  func (ts *milevadbTestSuite) TestRegression(c *C) {
   113  	if regression {
   114  		c.Parallel()
   115  		ts.runTestRegression(c, nil, "Regression")
   116  	}
   117  }
   118  
   119  func (ts *milevadbTestSuite) TestUint64(c *C) {
   120  	ts.runTestPrepareResultFieldType(c)
   121  }
   122  
   123  func (ts *milevadbTestSuite) TestSpecialType(c *C) {
   124  	c.Parallel()
   125  	ts.runTestSpecialType(c)
   126  }
   127  
   128  func (ts *milevadbTestSuite) TestPreparedString(c *C) {
   129  	c.Parallel()
   130  	ts.runTestPreparedString(c)
   131  }
   132  
   133  func (ts *milevadbTestSuite) TestPreparedTimestamp(c *C) {
   134  	c.Parallel()
   135  	ts.runTestPreparedTimestamp(c)
   136  }
   137  
   138  // this test will change `ekv.TxnTotalSizeLimit` which may affect other test suites,
   139  // so we must make it running in serial.
   140  func (ts *milevadbTestSerialSuite) TestLoadData(c *C) {
   141  	ts.runTestLoadData(c, ts.server)
   142  	ts.runTestLoadDataWithSelectIntoOutfile(c, ts.server)
   143  }
   144  
   145  func (ts *milevadbTestSerialSuite) TestStmtCount(c *C) {
   146  	ts.runTestStmtCount(c)
   147  }
   148  
   149  func (ts *milevadbTestSuite) TestConcurrentUFIDelate(c *C) {
   150  	c.Parallel()
   151  	ts.runTestConcurrentUFIDelate(c)
   152  }
   153  
   154  func (ts *milevadbTestSuite) TestErrorCode(c *C) {
   155  	c.Parallel()
   156  	ts.runTestErrorCode(c)
   157  }
   158  
   159  func (ts *milevadbTestSuite) TestAuth(c *C) {
   160  	c.Parallel()
   161  	ts.runTestAuth(c)
   162  	ts.runTestIssue3682(c)
   163  }
   164  
   165  func (ts *milevadbTestSuite) TestIssues(c *C) {
   166  	c.Parallel()
   167  	ts.runTestIssue3662(c)
   168  	ts.runTestIssue3680(c)
   169  }
   170  
   171  func (ts *milevadbTestSuite) TestDBNameEscape(c *C) {
   172  	c.Parallel()
   173  	ts.runTestDBNameEscape(c)
   174  }
   175  
   176  func (ts *milevadbTestSuite) TestResultFieldBlockIsNull(c *C) {
   177  	c.Parallel()
   178  	ts.runTestResultFieldBlockIsNull(c)
   179  }
   180  
   181  func (ts *milevadbTestSuite) TestStatusAPI(c *C) {
   182  	c.Parallel()
   183  	ts.runTestStatusAPI(c)
   184  }
   185  
   186  func (ts *milevadbTestSuite) TestStatusPort(c *C) {
   187  	var err error
   188  	ts.causetstore, err = mockstore.NewMockStore()
   189  	stochastik.DisableStats4Test()
   190  	c.Assert(err, IsNil)
   191  	ts.petri, err = stochastik.BootstrapStochastik(ts.causetstore)
   192  	c.Assert(err, IsNil)
   193  	ts.milevadbdrv = NewMilevaDBDriver(ts.causetstore)
   194  	cfg := newTestConfig()
   195  	cfg.Port = 0
   196  	cfg.Status.ReportStatus = true
   197  	cfg.Status.StatusPort = ts.statusPort
   198  	cfg.Performance.TCPKeepAlive = true
   199  
   200  	server, err := NewServer(cfg, ts.milevadbdrv)
   201  	c.Assert(err, NotNil)
   202  	c.Assert(server, IsNil)
   203  }
   204  
   205  func (ts *milevadbTestSuite) TestStatusAPIWithTLS(c *C) {
   206  	caCert, caKey, err := generateCert(0, "MilevaDB CA 2", nil, nil, "/tmp/ca-key-2.pem", "/tmp/ca-cert-2.pem")
   207  	c.Assert(err, IsNil)
   208  	_, _, err = generateCert(1, "milevadb-server-2", caCert, caKey, "/tmp/server-key-2.pem", "/tmp/server-cert-2.pem")
   209  	c.Assert(err, IsNil)
   210  
   211  	defer func() {
   212  		os.Remove("/tmp/ca-key-2.pem")
   213  		os.Remove("/tmp/ca-cert-2.pem")
   214  		os.Remove("/tmp/server-key-2.pem")
   215  		os.Remove("/tmp/server-cert-2.pem")
   216  	}()
   217  
   218  	cli := newTestServerClient()
   219  	cli.statusScheme = "https"
   220  	cfg := newTestConfig()
   221  	cfg.Port = cli.port
   222  	cfg.Status.StatusPort = cli.statusPort
   223  	cfg.Security.ClusterSSLCA = "/tmp/ca-cert-2.pem"
   224  	cfg.Security.ClusterSSLCert = "/tmp/server-cert-2.pem"
   225  	cfg.Security.ClusterSSLKey = "/tmp/server-key-2.pem"
   226  	server, err := NewServer(cfg, ts.milevadbdrv)
   227  	c.Assert(err, IsNil)
   228  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   229  	cli.statusPort = getPortFromTCPAddr(server.statusListener.Addr())
   230  	go server.Run()
   231  	time.Sleep(time.Millisecond * 100)
   232  
   233  	// https connection should work.
   234  	ts.runTestStatusAPI(c)
   235  
   236  	// but plain http connection should fail.
   237  	cli.statusScheme = "http"
   238  	_, err = cli.fetchStatus("/status")
   239  	c.Assert(err, NotNil)
   240  
   241  	server.Close()
   242  }
   243  
   244  func (ts *milevadbTestSuite) TestStatusAPIWithTLSCNCheck(c *C) {
   245  	caPath := filepath.Join(os.TemFIDelir(), "ca-cert-cn.pem")
   246  	serverKeyPath := filepath.Join(os.TemFIDelir(), "server-key-cn.pem")
   247  	serverCertPath := filepath.Join(os.TemFIDelir(), "server-cert-cn.pem")
   248  	client1KeyPath := filepath.Join(os.TemFIDelir(), "client-key-cn-check-a.pem")
   249  	client1CertPath := filepath.Join(os.TemFIDelir(), "client-cert-cn-check-a.pem")
   250  	client2KeyPath := filepath.Join(os.TemFIDelir(), "client-key-cn-check-b.pem")
   251  	client2CertPath := filepath.Join(os.TemFIDelir(), "client-cert-cn-check-b.pem")
   252  
   253  	caCert, caKey, err := generateCert(0, "MilevaDB CA CN CHECK", nil, nil, filepath.Join(os.TemFIDelir(), "ca-key-cn.pem"), caPath)
   254  	c.Assert(err, IsNil)
   255  	_, _, err = generateCert(1, "milevadb-server-cn-check", caCert, caKey, serverKeyPath, serverCertPath)
   256  	c.Assert(err, IsNil)
   257  	_, _, err = generateCert(2, "milevadb-client-cn-check-a", caCert, caKey, client1KeyPath, client1CertPath, func(c *x509.Certificate) {
   258  		c.Subject.CommonName = "milevadb-client-1"
   259  	})
   260  	c.Assert(err, IsNil)
   261  	_, _, err = generateCert(3, "milevadb-client-cn-check-b", caCert, caKey, client2KeyPath, client2CertPath, func(c *x509.Certificate) {
   262  		c.Subject.CommonName = "milevadb-client-2"
   263  	})
   264  	c.Assert(err, IsNil)
   265  
   266  	cli := newTestServerClient()
   267  	cli.statusScheme = "https"
   268  	cfg := newTestConfig()
   269  	cfg.Port = cli.port
   270  	cfg.Status.StatusPort = cli.statusPort
   271  	cfg.Security.ClusterSSLCA = caPath
   272  	cfg.Security.ClusterSSLCert = serverCertPath
   273  	cfg.Security.ClusterSSLKey = serverKeyPath
   274  	cfg.Security.ClusterVerifyCN = []string{"milevadb-client-2"}
   275  	server, err := NewServer(cfg, ts.milevadbdrv)
   276  	c.Assert(err, IsNil)
   277  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   278  	cli.statusPort = getPortFromTCPAddr(server.statusListener.Addr())
   279  	go server.Run()
   280  	time.Sleep(time.Millisecond * 100)
   281  
   282  	hc := newTLSHttpClient(c, caPath,
   283  		client1CertPath,
   284  		client1KeyPath,
   285  	)
   286  	_, err = hc.Get(cli.statusURL("/status"))
   287  	c.Assert(err, NotNil)
   288  
   289  	hc = newTLSHttpClient(c, caPath,
   290  		client2CertPath,
   291  		client2KeyPath,
   292  	)
   293  	_, err = hc.Get(cli.statusURL("/status"))
   294  	c.Assert(err, IsNil)
   295  }
   296  
   297  func newTLSHttpClient(c *C, caFile, certFile, keyFile string) *http.Client {
   298  	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
   299  	c.Assert(err, IsNil)
   300  	caCert, err := ioutil.ReadFile(caFile)
   301  	c.Assert(err, IsNil)
   302  	caCertPool := x509.NewCertPool()
   303  	caCertPool.AppendCertsFromPEM(caCert)
   304  	tlsConfig := &tls.Config{
   305  		Certificates:       []tls.Certificate{cert},
   306  		RootCAs:            caCertPool,
   307  		InsecureSkipVerify: true,
   308  	}
   309  	tlsConfig.BuildNameToCertificate()
   310  	return &http.Client{Transport: &http.Transport{TLSClientConfig: tlsConfig}}
   311  }
   312  
   313  func (ts *milevadbTestSuite) TestMultiStatements(c *C) {
   314  	c.Parallel()
   315  	ts.runTestMultiStatements(c)
   316  }
   317  
   318  func (ts *milevadbTestSuite) TestSocketForwarding(c *C) {
   319  	cli := newTestServerClient()
   320  	cfg := newTestConfig()
   321  	cfg.Socket = "/tmp/milevadbtest.sock"
   322  	cfg.Port = cli.port
   323  	os.Remove(cfg.Socket)
   324  	cfg.Status.ReportStatus = false
   325  
   326  	server, err := NewServer(cfg, ts.milevadbdrv)
   327  	c.Assert(err, IsNil)
   328  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   329  	go server.Run()
   330  	time.Sleep(time.Millisecond * 100)
   331  	defer server.Close()
   332  
   333  	cli.runTestRegression(c, func(config *allegrosql.Config) {
   334  		config.User = "root"
   335  		config.Net = "unix"
   336  		config.Addr = "/tmp/milevadbtest.sock"
   337  		config.DBName = "test"
   338  		config.Params = map[string]string{"sql_mode": "'STRICT_ALL_TABLES'"}
   339  	}, "SocketRegression")
   340  }
   341  
   342  func (ts *milevadbTestSuite) TestSocket(c *C) {
   343  	cfg := newTestConfig()
   344  	cfg.Socket = "/tmp/milevadbtest.sock"
   345  	cfg.Port = 0
   346  	os.Remove(cfg.Socket)
   347  	cfg.Host = ""
   348  	cfg.Status.ReportStatus = false
   349  
   350  	server, err := NewServer(cfg, ts.milevadbdrv)
   351  	c.Assert(err, IsNil)
   352  	go server.Run()
   353  	time.Sleep(time.Millisecond * 100)
   354  	defer server.Close()
   355  
   356  	//a fake server client, config is override, just used to run tests
   357  	cli := newTestServerClient()
   358  	cli.runTestRegression(c, func(config *allegrosql.Config) {
   359  		config.User = "root"
   360  		config.Net = "unix"
   361  		config.Addr = "/tmp/milevadbtest.sock"
   362  		config.DBName = "test"
   363  		config.Params = map[string]string{"sql_mode": "STRICT_ALL_TABLES"}
   364  	}, "SocketRegression")
   365  
   366  }
   367  
   368  // generateCert generates a private key and a certificate in PEM format based on parameters.
   369  // If parentCert and parentCertKey is specified, the new certificate will be signed by the parentCert.
   370  // Otherwise, the new certificate will be self-signed and is a CA.
   371  func generateCert(sn int, commonName string, parentCert *x509.Certificate, parentCertKey *rsa.PrivateKey, outKeyFile string, outCertFile string, opts ...func(c *x509.Certificate)) (*x509.Certificate, *rsa.PrivateKey, error) {
   372  	privateKey, err := rsa.GenerateKey(rand.Reader, 528)
   373  	if err != nil {
   374  		return nil, nil, errors.Trace(err)
   375  	}
   376  	notBefore := time.Now().Add(-10 * time.Minute).UTC()
   377  	notAfter := notBefore.Add(1 * time.Hour).UTC()
   378  
   379  	template := x509.Certificate{
   380  		SerialNumber:          big.NewInt(int64(sn)),
   381  		Subject:               pkix.Name{CommonName: commonName, Names: []pkix.AttributeTypeAndValue{soliton.MockPkixAttribute(soliton.CommonName, commonName)}},
   382  		DNSNames:              []string{commonName},
   383  		NotBefore:             notBefore,
   384  		NotAfter:              notAfter,
   385  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
   386  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
   387  		BasicConstraintsValid: true,
   388  	}
   389  	for _, opt := range opts {
   390  		opt(&template)
   391  	}
   392  
   393  	var parent *x509.Certificate
   394  	var priv *rsa.PrivateKey
   395  
   396  	if parentCert == nil || parentCertKey == nil {
   397  		template.IsCA = true
   398  		template.KeyUsage |= x509.KeyUsageCertSign
   399  		parent = &template
   400  		priv = privateKey
   401  	} else {
   402  		parent = parentCert
   403  		priv = parentCertKey
   404  	}
   405  
   406  	derBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, priv)
   407  	if err != nil {
   408  		return nil, nil, errors.Trace(err)
   409  	}
   410  
   411  	cert, err := x509.ParseCertificate(derBytes)
   412  	if err != nil {
   413  		return nil, nil, errors.Trace(err)
   414  	}
   415  
   416  	certOut, err := os.Create(outCertFile)
   417  	if err != nil {
   418  		return nil, nil, errors.Trace(err)
   419  	}
   420  	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
   421  	certOut.Close()
   422  
   423  	keyOut, err := os.OpenFile(outKeyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   424  	if err != nil {
   425  		return nil, nil, errors.Trace(err)
   426  	}
   427  	pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
   428  	keyOut.Close()
   429  
   430  	return cert, privateKey, nil
   431  }
   432  
   433  // registerTLSConfig registers a allegrosql client TLS config.
   434  // See https://godoc.org/github.com/go-allegrosql-driver/allegrosql#RegisterTLSConfig for details.
   435  func registerTLSConfig(configName string, caCertPath string, clientCertPath string, clientKeyPath string, serverName string, verifyServer bool) error {
   436  	rootCertPool := x509.NewCertPool()
   437  	data, err := ioutil.ReadFile(caCertPath)
   438  	if err != nil {
   439  		return err
   440  	}
   441  	if ok := rootCertPool.AppendCertsFromPEM(data); !ok {
   442  		return errors.New("Failed to append PEM")
   443  	}
   444  	clientCert := make([]tls.Certificate, 0, 1)
   445  	certs, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
   446  	if err != nil {
   447  		return err
   448  	}
   449  	clientCert = append(clientCert, certs)
   450  	tlsConfig := &tls.Config{
   451  		RootCAs:            rootCertPool,
   452  		Certificates:       clientCert,
   453  		ServerName:         serverName,
   454  		InsecureSkipVerify: !verifyServer,
   455  	}
   456  	allegrosql.RegisterTLSConfig(configName, tlsConfig)
   457  	return nil
   458  }
   459  
   460  func (ts *milevadbTestSuite) TestSystemTimeZone(c *C) {
   461  	tk := testkit.NewTestKit(c, ts.causetstore)
   462  	cfg := newTestConfig()
   463  	cfg.Port, cfg.Status.StatusPort = 0, 0
   464  	cfg.Status.ReportStatus = false
   465  	server, err := NewServer(cfg, ts.milevadbdrv)
   466  	c.Assert(err, IsNil)
   467  	defer server.Close()
   468  
   469  	tz1 := tk.MustQuery("select variable_value from allegrosql.milevadb where variable_name = 'system_tz'").Rows()
   470  	tk.MustQuery("select @@system_time_zone").Check(tz1)
   471  }
   472  
   473  func (ts *milevadbTestSerialSuite) TestTLS(c *C) {
   474  	// Generate valid TLS certificates.
   475  	caCert, caKey, err := generateCert(0, "MilevaDB CA", nil, nil, "/tmp/ca-key.pem", "/tmp/ca-cert.pem")
   476  	c.Assert(err, IsNil)
   477  	_, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key.pem", "/tmp/server-cert.pem")
   478  	c.Assert(err, IsNil)
   479  	_, _, err = generateCert(2, "ALLEGROALLEGROSQL Client Certificate", caCert, caKey, "/tmp/client-key.pem", "/tmp/client-cert.pem")
   480  	c.Assert(err, IsNil)
   481  	err = registerTLSConfig("client-certificate", "/tmp/ca-cert.pem", "/tmp/client-cert.pem", "/tmp/client-key.pem", "milevadb-server", true)
   482  	c.Assert(err, IsNil)
   483  
   484  	defer func() {
   485  		os.Remove("/tmp/ca-key.pem")
   486  		os.Remove("/tmp/ca-cert.pem")
   487  		os.Remove("/tmp/server-key.pem")
   488  		os.Remove("/tmp/server-cert.pem")
   489  		os.Remove("/tmp/client-key.pem")
   490  		os.Remove("/tmp/client-cert.pem")
   491  	}()
   492  
   493  	// Start the server without TLS.
   494  	connOverrider := func(config *allegrosql.Config) {
   495  		config.TLSConfig = "skip-verify"
   496  	}
   497  	cli := newTestServerClient()
   498  	cfg := newTestConfig()
   499  	cfg.Port = cli.port
   500  	cfg.Status.ReportStatus = false
   501  	server, err := NewServer(cfg, ts.milevadbdrv)
   502  	c.Assert(err, IsNil)
   503  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   504  	go server.Run()
   505  	time.Sleep(time.Millisecond * 100)
   506  	err = cli.runTestTLSConnection(c, connOverrider) // We should get ErrNoTLS.
   507  	c.Assert(err, NotNil)
   508  	c.Assert(errors.Cause(err).Error(), Equals, allegrosql.ErrNoTLS.Error())
   509  	server.Close()
   510  
   511  	// Start the server with TLS but without CA, in this case the server will not verify client's certificate.
   512  	connOverrider = func(config *allegrosql.Config) {
   513  		config.TLSConfig = "skip-verify"
   514  	}
   515  	cli = newTestServerClient()
   516  	cfg = newTestConfig()
   517  	cfg.Port = cli.port
   518  	cfg.Status.ReportStatus = false
   519  	cfg.Security = config.Security{
   520  		SSLCert: "/tmp/server-cert.pem",
   521  		SSLKey:  "/tmp/server-key.pem",
   522  	}
   523  	server, err = NewServer(cfg, ts.milevadbdrv)
   524  	c.Assert(err, IsNil)
   525  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   526  	go server.Run()
   527  	time.Sleep(time.Millisecond * 100)
   528  	err = cli.runTestTLSConnection(c, connOverrider) // We should establish connection successfully.
   529  	c.Assert(err, IsNil)
   530  	cli.runTestRegression(c, connOverrider, "TLSRegression")
   531  	// Perform server verification.
   532  	connOverrider = func(config *allegrosql.Config) {
   533  		config.TLSConfig = "client-certificate"
   534  	}
   535  	err = cli.runTestTLSConnection(c, connOverrider) // We should establish connection successfully.
   536  	c.Assert(err, IsNil, Commentf("%v", errors.ErrorStack(err)))
   537  	cli.runTestRegression(c, connOverrider, "TLSRegression")
   538  	server.Close()
   539  
   540  	// Start the server with TLS & CA, if the client presents its certificate, the certificate will be verified.
   541  	cli = newTestServerClient()
   542  	cfg = newTestConfig()
   543  	cfg.Port = cli.port
   544  	cfg.Status.ReportStatus = false
   545  	cfg.Security = config.Security{
   546  		SSLCA:   "/tmp/ca-cert.pem",
   547  		SSLCert: "/tmp/server-cert.pem",
   548  		SSLKey:  "/tmp/server-key.pem",
   549  	}
   550  	server, err = NewServer(cfg, ts.milevadbdrv)
   551  	c.Assert(err, IsNil)
   552  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   553  	go server.Run()
   554  	time.Sleep(time.Millisecond * 100)
   555  	// The client does not provide a certificate, the connection should succeed.
   556  	err = cli.runTestTLSConnection(c, nil)
   557  	c.Assert(err, IsNil)
   558  	cli.runTestRegression(c, connOverrider, "TLSRegression")
   559  	// The client provides a valid certificate.
   560  	connOverrider = func(config *allegrosql.Config) {
   561  		config.TLSConfig = "client-certificate"
   562  	}
   563  	err = cli.runTestTLSConnection(c, connOverrider)
   564  	c.Assert(err, IsNil)
   565  	cli.runTestRegression(c, connOverrider, "TLSRegression")
   566  	server.Close()
   567  
   568  	c.Assert(soliton.IsTLSExpiredError(errors.New("unknown test")), IsFalse)
   569  	c.Assert(soliton.IsTLSExpiredError(x509.CertificateInvalidError{Reason: x509.CANotAuthorizedForThisName}), IsFalse)
   570  	c.Assert(soliton.IsTLSExpiredError(x509.CertificateInvalidError{Reason: x509.Expired}), IsTrue)
   571  
   572  	_, err = soliton.LoadTLSCertificates("", "wrong key", "wrong cert")
   573  	c.Assert(err, NotNil)
   574  	_, err = soliton.LoadTLSCertificates("wrong ca", "/tmp/server-key.pem", "/tmp/server-cert.pem")
   575  	c.Assert(err, NotNil)
   576  }
   577  
   578  func (ts *milevadbTestSerialSuite) TestReloadTLS(c *C) {
   579  	// Generate valid TLS certificates.
   580  	caCert, caKey, err := generateCert(0, "MilevaDB CA", nil, nil, "/tmp/ca-key-reload.pem", "/tmp/ca-cert-reload.pem")
   581  	c.Assert(err, IsNil)
   582  	_, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-reload.pem", "/tmp/server-cert-reload.pem")
   583  	c.Assert(err, IsNil)
   584  	_, _, err = generateCert(2, "ALLEGROALLEGROSQL Client Certificate", caCert, caKey, "/tmp/client-key-reload.pem", "/tmp/client-cert-reload.pem")
   585  	c.Assert(err, IsNil)
   586  	err = registerTLSConfig("client-certificate-reload", "/tmp/ca-cert-reload.pem", "/tmp/client-cert-reload.pem", "/tmp/client-key-reload.pem", "milevadb-server", true)
   587  	c.Assert(err, IsNil)
   588  
   589  	defer func() {
   590  		os.Remove("/tmp/ca-key-reload.pem")
   591  		os.Remove("/tmp/ca-cert-reload.pem")
   592  
   593  		os.Remove("/tmp/server-key-reload.pem")
   594  		os.Remove("/tmp/server-cert-reload.pem")
   595  		os.Remove("/tmp/client-key-reload.pem")
   596  		os.Remove("/tmp/client-cert-reload.pem")
   597  	}()
   598  
   599  	// try old cert used in startup configuration.
   600  	cli := newTestServerClient()
   601  	cfg := newTestConfig()
   602  	cfg.Port = cli.port
   603  	cfg.Status.ReportStatus = false
   604  	cfg.Security = config.Security{
   605  		SSLCA:   "/tmp/ca-cert-reload.pem",
   606  		SSLCert: "/tmp/server-cert-reload.pem",
   607  		SSLKey:  "/tmp/server-key-reload.pem",
   608  	}
   609  	server, err := NewServer(cfg, ts.milevadbdrv)
   610  	c.Assert(err, IsNil)
   611  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   612  	go server.Run()
   613  	time.Sleep(time.Millisecond * 100)
   614  	// The client provides a valid certificate.
   615  	connOverrider := func(config *allegrosql.Config) {
   616  		config.TLSConfig = "client-certificate-reload"
   617  	}
   618  	err = cli.runTestTLSConnection(c, connOverrider)
   619  	c.Assert(err, IsNil)
   620  
   621  	// try reload a valid cert.
   622  	tlsCfg := server.getTLSConfig()
   623  	cert, err := x509.ParseCertificate(tlsCfg.Certificates[0].Certificate[0])
   624  	c.Assert(err, IsNil)
   625  	oldExpireTime := cert.NotAfter
   626  	_, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-reload2.pem", "/tmp/server-cert-reload2.pem", func(c *x509.Certificate) {
   627  		c.NotBefore = time.Now().Add(-24 * time.Hour).UTC()
   628  		c.NotAfter = time.Now().Add(1 * time.Hour).UTC()
   629  	})
   630  	c.Assert(err, IsNil)
   631  	os.Rename("/tmp/server-key-reload2.pem", "/tmp/server-key-reload.pem")
   632  	os.Rename("/tmp/server-cert-reload2.pem", "/tmp/server-cert-reload.pem")
   633  	connOverrider = func(config *allegrosql.Config) {
   634  		config.TLSConfig = "skip-verify"
   635  	}
   636  	err = cli.runReloadTLS(c, connOverrider, false)
   637  	c.Assert(err, IsNil)
   638  	connOverrider = func(config *allegrosql.Config) {
   639  		config.TLSConfig = "client-certificate-reload"
   640  	}
   641  	err = cli.runTestTLSConnection(c, connOverrider)
   642  	c.Assert(err, IsNil)
   643  
   644  	tlsCfg = server.getTLSConfig()
   645  	cert, err = x509.ParseCertificate(tlsCfg.Certificates[0].Certificate[0])
   646  	c.Assert(err, IsNil)
   647  	newExpireTime := cert.NotAfter
   648  	c.Assert(newExpireTime.After(oldExpireTime), IsTrue)
   649  
   650  	// try reload a expired cert.
   651  	_, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-reload3.pem", "/tmp/server-cert-reload3.pem", func(c *x509.Certificate) {
   652  		c.NotBefore = time.Now().Add(-24 * time.Hour).UTC()
   653  		c.NotAfter = c.NotBefore.Add(1 * time.Hour).UTC()
   654  	})
   655  	c.Assert(err, IsNil)
   656  	os.Rename("/tmp/server-key-reload3.pem", "/tmp/server-key-reload.pem")
   657  	os.Rename("/tmp/server-cert-reload3.pem", "/tmp/server-cert-reload.pem")
   658  	connOverrider = func(config *allegrosql.Config) {
   659  		config.TLSConfig = "skip-verify"
   660  	}
   661  	err = cli.runReloadTLS(c, connOverrider, false)
   662  	c.Assert(err, IsNil)
   663  	connOverrider = func(config *allegrosql.Config) {
   664  		config.TLSConfig = "client-certificate-reload"
   665  	}
   666  	err = cli.runTestTLSConnection(c, connOverrider)
   667  	c.Assert(err, NotNil)
   668  	c.Assert(soliton.IsTLSExpiredError(err), IsTrue, Commentf("real error is %+v", err))
   669  	server.Close()
   670  }
   671  
   672  func (ts *milevadbTestSerialSuite) TestErrorNoRollback(c *C) {
   673  	// Generate valid TLS certificates.
   674  	caCert, caKey, err := generateCert(0, "MilevaDB CA", nil, nil, "/tmp/ca-key-rollback.pem", "/tmp/ca-cert-rollback.pem")
   675  	c.Assert(err, IsNil)
   676  	_, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-rollback.pem", "/tmp/server-cert-rollback.pem")
   677  	c.Assert(err, IsNil)
   678  	_, _, err = generateCert(2, "ALLEGROALLEGROSQL Client Certificate", caCert, caKey, "/tmp/client-key-rollback.pem", "/tmp/client-cert-rollback.pem")
   679  	c.Assert(err, IsNil)
   680  	err = registerTLSConfig("client-cert-rollback-test", "/tmp/ca-cert-rollback.pem", "/tmp/client-cert-rollback.pem", "/tmp/client-key-rollback.pem", "milevadb-server", true)
   681  	c.Assert(err, IsNil)
   682  
   683  	defer func() {
   684  		os.Remove("/tmp/ca-key-rollback.pem")
   685  		os.Remove("/tmp/ca-cert-rollback.pem")
   686  
   687  		os.Remove("/tmp/server-key-rollback.pem")
   688  		os.Remove("/tmp/server-cert-rollback.pem")
   689  		os.Remove("/tmp/client-key-rollback.pem")
   690  		os.Remove("/tmp/client-cert-rollback.pem")
   691  	}()
   692  
   693  	cli := newTestServerClient()
   694  	cfg := newTestConfig()
   695  	cfg.Port = cli.port
   696  	cfg.Status.ReportStatus = false
   697  
   698  	cfg.Security = config.Security{
   699  		RequireSecureTransport: true,
   700  		SSLCA:                  "wrong path",
   701  		SSLCert:                "wrong path",
   702  		SSLKey:                 "wrong path",
   703  	}
   704  	_, err = NewServer(cfg, ts.milevadbdrv)
   705  	c.Assert(err, NotNil)
   706  
   707  	// test reload tls fail with/without "error no rollback option"
   708  	cfg.Security = config.Security{
   709  		SSLCA:   "/tmp/ca-cert-rollback.pem",
   710  		SSLCert: "/tmp/server-cert-rollback.pem",
   711  		SSLKey:  "/tmp/server-key-rollback.pem",
   712  	}
   713  	server, err := NewServer(cfg, ts.milevadbdrv)
   714  	c.Assert(err, IsNil)
   715  	cli.port = getPortFromTCPAddr(server.listener.Addr())
   716  	go server.Run()
   717  	time.Sleep(time.Millisecond * 100)
   718  	connOverrider := func(config *allegrosql.Config) {
   719  		config.TLSConfig = "client-cert-rollback-test"
   720  	}
   721  	err = cli.runTestTLSConnection(c, connOverrider)
   722  	c.Assert(err, IsNil)
   723  	os.Remove("/tmp/server-key-rollback.pem")
   724  	err = cli.runReloadTLS(c, connOverrider, false)
   725  	c.Assert(err, NotNil)
   726  	tlsCfg := server.getTLSConfig()
   727  	c.Assert(tlsCfg, NotNil)
   728  	err = cli.runReloadTLS(c, connOverrider, true)
   729  	c.Assert(err, IsNil)
   730  	tlsCfg = server.getTLSConfig()
   731  	c.Assert(tlsCfg, IsNil)
   732  }
   733  
   734  func (ts *milevadbTestSuite) TestClientWithDefCauslation(c *C) {
   735  	c.Parallel()
   736  	ts.runTestClientWithDefCauslation(c)
   737  }
   738  
   739  func (ts *milevadbTestSuite) TestCreateBlockFlen(c *C) {
   740  	// issue #4540
   741  	qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil)
   742  	c.Assert(err, IsNil)
   743  	_, err = InterDircute(context.Background(), qctx, "use test;")
   744  	c.Assert(err, IsNil)
   745  
   746  	ctx := context.Background()
   747  	testALLEGROSQL := "CREATE TABLE `t1` (" +
   748  		"`a` char(36) NOT NULL," +
   749  		"`b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," +
   750  		"`c` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," +
   751  		"`d` varchar(50) DEFAULT ''," +
   752  		"`e` char(36) NOT NULL DEFAULT ''," +
   753  		"`f` char(36) NOT NULL DEFAULT ''," +
   754  		"`g` char(1) NOT NULL DEFAULT 'N'," +
   755  		"`h` varchar(100) NOT NULL," +
   756  		"`i` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," +
   757  		"`j` varchar(10) DEFAULT ''," +
   758  		"`k` varchar(10) DEFAULT ''," +
   759  		"`l` varchar(20) DEFAULT ''," +
   760  		"`m` varchar(20) DEFAULT ''," +
   761  		"`n` varchar(30) DEFAULT ''," +
   762  		"`o` varchar(100) DEFAULT ''," +
   763  		"`p` varchar(50) DEFAULT ''," +
   764  		"`q` varchar(50) DEFAULT ''," +
   765  		"`r` varchar(100) DEFAULT ''," +
   766  		"`s` varchar(20) DEFAULT ''," +
   767  		"`t` varchar(50) DEFAULT ''," +
   768  		"`u` varchar(100) DEFAULT ''," +
   769  		"`v` varchar(50) DEFAULT ''," +
   770  		"`w` varchar(300) NOT NULL," +
   771  		"`x` varchar(250) DEFAULT ''," +
   772  		"`y` decimal(20)," +
   773  		"`z` decimal(20, 4)," +
   774  		"PRIMARY KEY (`a`)" +
   775  		") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin"
   776  	_, err = InterDircute(ctx, qctx, testALLEGROSQL)
   777  	c.Assert(err, IsNil)
   778  	rs, err := InterDircute(ctx, qctx, "show create causet t1")
   779  	c.Assert(err, IsNil)
   780  	req := rs.NewChunk()
   781  	err = rs.Next(ctx, req)
   782  	c.Assert(err, IsNil)
   783  	defcaus := rs.DeferredCausets()
   784  	c.Assert(err, IsNil)
   785  	c.Assert(len(defcaus), Equals, 2)
   786  	c.Assert(int(defcaus[0].DeferredCausetLength), Equals, 5*tmysql.MaxBytesOfCharacter)
   787  	c.Assert(int(defcaus[1].DeferredCausetLength), Equals, len(req.GetRow(0).GetString(1))*tmysql.MaxBytesOfCharacter)
   788  
   789  	// for issue#5246
   790  	rs, err = InterDircute(ctx, qctx, "select y, z from t1")
   791  	c.Assert(err, IsNil)
   792  	defcaus = rs.DeferredCausets()
   793  	c.Assert(len(defcaus), Equals, 2)
   794  	c.Assert(int(defcaus[0].DeferredCausetLength), Equals, 21)
   795  	c.Assert(int(defcaus[1].DeferredCausetLength), Equals, 22)
   796  }
   797  
   798  func InterDircute(ctx context.Context, qc *MilevaDBContext, allegrosql string) (ResultSet, error) {
   799  	stmts, err := qc.Parse(ctx, allegrosql)
   800  	if err != nil {
   801  		return nil, err
   802  	}
   803  	if len(stmts) != 1 {
   804  		panic("wrong input for InterDircute: " + allegrosql)
   805  	}
   806  	return qc.InterDircuteStmt(ctx, stmts[0])
   807  }
   808  
   809  func (ts *milevadbTestSuite) TestShowBlocksFlen(c *C) {
   810  	qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil)
   811  	c.Assert(err, IsNil)
   812  	ctx := context.Background()
   813  	_, err = InterDircute(ctx, qctx, "use test;")
   814  	c.Assert(err, IsNil)
   815  
   816  	testALLEGROSQL := "create causet abcdefghijklmnopqrstuvwxyz (i int)"
   817  	_, err = InterDircute(ctx, qctx, testALLEGROSQL)
   818  	c.Assert(err, IsNil)
   819  	rs, err := InterDircute(ctx, qctx, "show blocks")
   820  	c.Assert(err, IsNil)
   821  	req := rs.NewChunk()
   822  	err = rs.Next(ctx, req)
   823  	c.Assert(err, IsNil)
   824  	defcaus := rs.DeferredCausets()
   825  	c.Assert(err, IsNil)
   826  	c.Assert(len(defcaus), Equals, 1)
   827  	c.Assert(int(defcaus[0].DeferredCausetLength), Equals, 26*tmysql.MaxBytesOfCharacter)
   828  }
   829  
   830  func checkDefCausNames(c *C, defCausumns []*DeferredCausetInfo, names ...string) {
   831  	for i, name := range names {
   832  		c.Assert(defCausumns[i].Name, Equals, name)
   833  		c.Assert(defCausumns[i].OrgName, Equals, name)
   834  	}
   835  }
   836  
   837  func (ts *milevadbTestSuite) TestFieldList(c *C) {
   838  	qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil)
   839  	c.Assert(err, IsNil)
   840  	_, err = InterDircute(context.Background(), qctx, "use test;")
   841  	c.Assert(err, IsNil)
   842  
   843  	ctx := context.Background()
   844  	testALLEGROSQL := `create causet t (
   845  		c_bit bit(10),
   846  		c_int_d int,
   847  		c_bigint_d bigint,
   848  		c_float_d float,
   849  		c_double_d double,
   850  		c_decimal decimal(6, 3),
   851  		c_datetime datetime(2),
   852  		c_time time(3),
   853  		c_date date,
   854  		c_timestamp timestamp(4) DEFAULT CURRENT_TIMESTAMP(4),
   855  		c_char char(20),
   856  		c_varchar varchar(20),
   857  		c_text_d text,
   858  		c_binary binary(20),
   859  		c_blob_d blob,
   860  		c_set set('a', 'b', 'c'),
   861  		c_enum enum('a', 'b', 'c'),
   862  		c_json JSON,
   863  		c_year year
   864  	)`
   865  	_, err = InterDircute(ctx, qctx, testALLEGROSQL)
   866  	c.Assert(err, IsNil)
   867  	defCausInfos, err := qctx.FieldList("t")
   868  	c.Assert(err, IsNil)
   869  	c.Assert(len(defCausInfos), Equals, 19)
   870  
   871  	checkDefCausNames(c, defCausInfos, "c_bit", "c_int_d", "c_bigint_d", "c_float_d",
   872  		"c_double_d", "c_decimal", "c_datetime", "c_time", "c_date", "c_timestamp",
   873  		"c_char", "c_varchar", "c_text_d", "c_binary", "c_blob_d", "c_set", "c_enum",
   874  		"c_json", "c_year")
   875  
   876  	for _, defcaus := range defCausInfos {
   877  		c.Assert(defcaus.Schema, Equals, "test")
   878  	}
   879  
   880  	for _, defcaus := range defCausInfos {
   881  		c.Assert(defcaus.Block, Equals, "t")
   882  	}
   883  
   884  	for i, defCaus := range defCausInfos {
   885  		switch i {
   886  		case 10, 11, 12, 15, 16:
   887  			// c_char char(20), c_varchar varchar(20), c_text_d text,
   888  			// c_set set('a', 'b', 'c'), c_enum enum('a', 'b', 'c')
   889  			c.Assert(defCaus.Charset, Equals, uint16(tmysql.CharsetNameToID(tmysql.DefaultCharset)), Commentf("index %d", i))
   890  			continue
   891  		}
   892  
   893  		c.Assert(defCaus.Charset, Equals, uint16(tmysql.CharsetNameToID("binary")), Commentf("index %d", i))
   894  	}
   895  
   896  	// c_decimal decimal(6, 3)
   897  	c.Assert(defCausInfos[5].Decimal, Equals, uint8(3))
   898  
   899  	// for issue#10513
   900  	tooLongDeferredCausetAsName := "COALESCE(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)"
   901  	defCausumnAsName := tooLongDeferredCausetAsName[:tmysql.MaxAliasIdentifierLen]
   902  
   903  	rs, err := InterDircute(ctx, qctx, "select "+tooLongDeferredCausetAsName)
   904  	c.Assert(err, IsNil)
   905  	defcaus := rs.DeferredCausets()
   906  	c.Assert(defcaus[0].OrgName, Equals, tooLongDeferredCausetAsName)
   907  	c.Assert(defcaus[0].Name, Equals, defCausumnAsName)
   908  
   909  	rs, err = InterDircute(ctx, qctx, "select c_bit as '"+tooLongDeferredCausetAsName+"' from t")
   910  	c.Assert(err, IsNil)
   911  	defcaus = rs.DeferredCausets()
   912  	c.Assert(defcaus[0].OrgName, Equals, "c_bit")
   913  	c.Assert(defcaus[0].Name, Equals, defCausumnAsName)
   914  }
   915  
   916  func (ts *milevadbTestSuite) TestSumAvg(c *C) {
   917  	c.Parallel()
   918  	ts.runTestSumAvg(c)
   919  }
   920  
   921  func (ts *milevadbTestSuite) TestNullFlag(c *C) {
   922  	// issue #9689
   923  	qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil)
   924  	c.Assert(err, IsNil)
   925  
   926  	ctx := context.Background()
   927  	rs, err := InterDircute(ctx, qctx, "select 1")
   928  	c.Assert(err, IsNil)
   929  	defcaus := rs.DeferredCausets()
   930  	c.Assert(len(defcaus), Equals, 1)
   931  	expectFlag := uint16(tmysql.NotNullFlag | tmysql.BinaryFlag)
   932  	c.Assert(dumpFlag(defcaus[0].Type, defcaus[0].Flag), Equals, expectFlag)
   933  }