// Copyright 2015 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. // +build !race package server import ( "crypto/rand" "crypto/rsa" "crypto/tls" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "io/ioutil" "math/big" "os" "time" "github.com/go-sql-driver/mysql" "github.com/hanchuanchuan/goInception/config" "github.com/hanchuanchuan/goInception/domain" "github.com/hanchuanchuan/goInception/kv" "github.com/hanchuanchuan/goInception/session" "github.com/hanchuanchuan/goInception/store/mockstore" . "github.com/pingcap/check" "github.com/pingcap/errors" ) type TidbTestSuite struct { tidbdrv *TiDBDriver server *Server domain *domain.Domain store kv.Storage } var suite = new(TidbTestSuite) var _ = Suite(suite) func (ts *TidbTestSuite) SetUpSuite(c *C) { var err error ts.store, err = mockstore.NewMockTikvStore() session.SetStatsLease(0) c.Assert(err, IsNil) ts.domain, err = session.BootstrapSession(ts.store) c.Assert(err, IsNil) ts.tidbdrv = NewTiDBDriver(ts.store) cfg := config.NewConfig() cfg.Port = 4001 cfg.Status.ReportStatus = true cfg.Status.StatusPort = 10090 cfg.Performance.TCPKeepAlive = true server, err := NewServer(cfg, ts.tidbdrv) c.Assert(err, IsNil) ts.server = server go ts.server.Run() waitUntilServerOnline(cfg.Status.StatusPort) // Run this test here because parallel would affect the result of it. // runTestStmtCount(c) defaultLoadDataBatchCnt = 3 } func (ts *TidbTestSuite) TearDownSuite(c *C) { if ts.store != nil { ts.store.Close() } if ts.domain != nil { ts.domain.Close() } if ts.server != nil { ts.server.Close() } } // generateCert generates a private key and a certificate in PEM format based on parameters. // If parentCert and parentCertKey is specified, the new certificate will be signed by the parentCert. // Otherwise, the new certificate will be self-signed and is a CA. func generateCert(sn int, commonName string, parentCert *x509.Certificate, parentCertKey *rsa.PrivateKey, outKeyFile string, outCertFile string) (*x509.Certificate, *rsa.PrivateKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, 512) if err != nil { return nil, nil, errors.Trace(err) } notBefore := time.Now().Add(-10 * time.Minute).UTC() notAfter := notBefore.Add(1 * time.Hour).UTC() template := x509.Certificate{ SerialNumber: big.NewInt(int64(sn)), Subject: pkix.Name{CommonName: commonName}, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } var parent *x509.Certificate var priv *rsa.PrivateKey if parentCert == nil || parentCertKey == nil { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign parent = &template priv = privateKey } else { parent = parentCert priv = parentCertKey } derBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, priv) if err != nil { return nil, nil, errors.Trace(err) } cert, err := x509.ParseCertificate(derBytes) if err != nil { return nil, nil, errors.Trace(err) } certOut, err := os.Create(outCertFile) if err != nil { return nil, nil, errors.Trace(err) } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() keyOut, err := os.OpenFile(outKeyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return nil, nil, errors.Trace(err) } pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) keyOut.Close() return cert, privateKey, nil } // registerTLSConfig registers a mysql client TLS config. // See https://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig for details. func registerTLSConfig(configName string, caCertPath string, clientCertPath string, clientKeyPath string, serverName string, verifyServer bool) error { rootCertPool := x509.NewCertPool() data, err := ioutil.ReadFile(caCertPath) if err != nil { return err } if ok := rootCertPool.AppendCertsFromPEM(data); !ok { return errors.New("Failed to append PEM") } clientCert := make([]tls.Certificate, 0, 1) certs, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath) if err != nil { return err } clientCert = append(clientCert, certs) tlsConfig := &tls.Config{ RootCAs: rootCertPool, Certificates: clientCert, ServerName: serverName, InsecureSkipVerify: !verifyServer, } mysql.RegisterTLSConfig(configName, tlsConfig) return nil } func checkColNames(c *C, columns []*ColumnInfo, names ...string) { for i, name := range names { c.Assert(columns[i].Name, Equals, name) c.Assert(columns[i].OrgName, Equals, name) } }