vitess.io/vitess@v0.16.2/go/test/endtoend/mysqlctld/mysqlctld_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mysqlctld
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"os"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"vitess.io/vitess/go/test/endtoend/cluster"
    28  )
    29  
    30  var (
    31  	clusterInstance *cluster.LocalProcessCluster
    32  	primaryTablet   *cluster.Vttablet
    33  	replicaTablet   *cluster.Vttablet
    34  	hostname        = "localhost"
    35  	keyspaceName    = "test_keyspace"
    36  	shardName       = "0"
    37  	cell            = "zone1"
    38  )
    39  
    40  func TestMain(m *testing.M) {
    41  	defer cluster.PanicHandler(nil)
    42  	flag.Parse()
    43  
    44  	exitCode := func() int {
    45  		clusterInstance = cluster.NewCluster(cell, hostname)
    46  		defer clusterInstance.Teardown()
    47  
    48  		// Start topo server
    49  		err := clusterInstance.StartTopo()
    50  		if err != nil {
    51  			return 1
    52  		}
    53  
    54  		if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName); err != nil {
    55  			return 1
    56  		}
    57  
    58  		if err := initCluster([]string{"0"}, 2); err != nil {
    59  			return 1
    60  		}
    61  
    62  		// Collect tablet paths and ports
    63  		tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
    64  		for _, tablet := range tablets {
    65  			if tablet.Type == "primary" {
    66  				primaryTablet = tablet
    67  			} else if tablet.Type != "rdonly" {
    68  				replicaTablet = tablet
    69  			}
    70  		}
    71  
    72  		return m.Run()
    73  	}()
    74  	os.Exit(exitCode)
    75  }
    76  
    77  func initCluster(shardNames []string, totalTabletsRequired int) error {
    78  	keyspace := cluster.Keyspace{
    79  		Name: keyspaceName,
    80  	}
    81  	for _, shardName := range shardNames {
    82  		shard := &cluster.Shard{
    83  			Name: shardName,
    84  		}
    85  		for i := 0; i < totalTabletsRequired; i++ {
    86  			// instantiate vttablet object with reserved ports
    87  			tabletUID := clusterInstance.GetAndReserveTabletUID()
    88  			tablet := &cluster.Vttablet{
    89  				TabletUID: tabletUID,
    90  				HTTPPort:  clusterInstance.GetAndReservePort(),
    91  				GrpcPort:  clusterInstance.GetAndReservePort(),
    92  				MySQLPort: clusterInstance.GetAndReservePort(),
    93  				Alias:     fmt.Sprintf("%s-%010d", clusterInstance.Cell, tabletUID),
    94  			}
    95  			if i == 0 { // Make the first one as primary
    96  				tablet.Type = "primary"
    97  			}
    98  			// Start Mysqlctld process
    99  			tablet.MysqlctldProcess = *cluster.MysqlCtldProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory)
   100  			err := tablet.MysqlctldProcess.Start()
   101  			if err != nil {
   102  				return err
   103  			}
   104  
   105  			// start vttablet process
   106  			tablet.VttabletProcess = cluster.VttabletProcessInstance(
   107  				tablet.HTTPPort,
   108  				tablet.GrpcPort,
   109  				tablet.TabletUID,
   110  				clusterInstance.Cell,
   111  				shardName,
   112  				keyspaceName,
   113  				clusterInstance.VtctldProcess.Port,
   114  				tablet.Type,
   115  				clusterInstance.TopoProcess.Port,
   116  				clusterInstance.Hostname,
   117  				clusterInstance.TmpDirectory,
   118  				clusterInstance.VtTabletExtraArgs,
   119  				clusterInstance.DefaultCharset)
   120  			tablet.Alias = tablet.VttabletProcess.TabletPath
   121  
   122  			shard.Vttablets = append(shard.Vttablets, tablet)
   123  		}
   124  
   125  		keyspace.Shards = append(keyspace.Shards, *shard)
   126  	}
   127  	clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace)
   128  
   129  	return nil
   130  }
   131  
   132  func TestRestart(t *testing.T) {
   133  	defer cluster.PanicHandler(t)
   134  	err := primaryTablet.MysqlctldProcess.Stop()
   135  	require.Nil(t, err)
   136  	primaryTablet.MysqlctldProcess.CleanupFiles(primaryTablet.TabletUID)
   137  	err = primaryTablet.MysqlctldProcess.Start()
   138  	require.Nil(t, err)
   139  }
   140  
   141  func TestAutoDetect(t *testing.T) {
   142  	defer cluster.PanicHandler(t)
   143  
   144  	// Start up tablets with an empty MYSQL_FLAVOR, which means auto-detect
   145  	sqlFlavor := os.Getenv("MYSQL_FLAVOR")
   146  	os.Setenv("MYSQL_FLAVOR", "")
   147  
   148  	err := clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.Setup()
   149  	require.Nil(t, err, "error should be nil")
   150  	err = clusterInstance.Keyspaces[0].Shards[0].Vttablets[1].VttabletProcess.Setup()
   151  	require.Nil(t, err, "error should be nil")
   152  
   153  	// Reparent tablets, which requires flavor detection
   154  	err = clusterInstance.VtctlclientProcess.InitializeShard(keyspaceName, shardName, cell, primaryTablet.TabletUID)
   155  	require.Nil(t, err, "error should be nil")
   156  
   157  	//Reset flavor
   158  	os.Setenv("MYSQL_FLAVOR", sqlFlavor)
   159  
   160  }