vitess.io/vitess@v0.16.2/go/test/endtoend/mysqlctl/mysqlctl_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 mysqlctl
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"os"
    23  	"os/exec"
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/require"
    27  
    28  	"vitess.io/vitess/go/test/endtoend/cluster"
    29  )
    30  
    31  var (
    32  	clusterInstance *cluster.LocalProcessCluster
    33  	primaryTablet   cluster.Vttablet
    34  	replicaTablet   cluster.Vttablet
    35  	hostname        = "localhost"
    36  	keyspaceName    = "test_keyspace"
    37  	shardName       = "0"
    38  	cell            = "zone1"
    39  )
    40  
    41  func TestMain(m *testing.M) {
    42  	defer cluster.PanicHandler(nil)
    43  	flag.Parse()
    44  
    45  	exitCode := func() int {
    46  		clusterInstance = cluster.NewCluster(cell, hostname)
    47  		defer clusterInstance.Teardown()
    48  
    49  		// Start topo server
    50  		err := clusterInstance.StartTopo()
    51  		if err != nil {
    52  			return 1
    53  		}
    54  
    55  		if err := clusterInstance.VtctlProcess.CreateKeyspace(keyspaceName); err != nil {
    56  			return 1
    57  		}
    58  
    59  		initCluster([]string{"0"}, 2)
    60  
    61  		// Collect tablet paths and ports
    62  		tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets
    63  		for _, tablet := range tablets {
    64  			if tablet.Type == "primary" {
    65  				primaryTablet = *tablet
    66  			} else if tablet.Type != "rdonly" {
    67  				replicaTablet = *tablet
    68  			}
    69  		}
    70  
    71  		return m.Run()
    72  	}()
    73  	os.Exit(exitCode)
    74  }
    75  
    76  func initCluster(shardNames []string, totalTabletsRequired int) {
    77  	keyspace := cluster.Keyspace{
    78  		Name: keyspaceName,
    79  	}
    80  	for _, shardName := range shardNames {
    81  		shard := &cluster.Shard{
    82  			Name: shardName,
    83  		}
    84  		var mysqlCtlProcessList []*exec.Cmd
    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 Mysqlctl process
    99  			tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory)
   100  			proc, err := tablet.MysqlctlProcess.StartProcess()
   101  			if err != nil {
   102  				return
   103  			}
   104  			mysqlCtlProcessList = append(mysqlCtlProcessList, proc)
   105  
   106  			// start vttablet process
   107  			tablet.VttabletProcess = cluster.VttabletProcessInstance(
   108  				tablet.HTTPPort,
   109  				tablet.GrpcPort,
   110  				tablet.TabletUID,
   111  				clusterInstance.Cell,
   112  				shardName,
   113  				keyspaceName,
   114  				clusterInstance.VtctldProcess.Port,
   115  				tablet.Type,
   116  				clusterInstance.TopoProcess.Port,
   117  				clusterInstance.Hostname,
   118  				clusterInstance.TmpDirectory,
   119  				clusterInstance.VtTabletExtraArgs,
   120  				clusterInstance.DefaultCharset)
   121  			tablet.Alias = tablet.VttabletProcess.TabletPath
   122  
   123  			shard.Vttablets = append(shard.Vttablets, tablet)
   124  		}
   125  		for _, proc := range mysqlCtlProcessList {
   126  			if err := proc.Wait(); err != nil {
   127  				return
   128  			}
   129  		}
   130  
   131  		keyspace.Shards = append(keyspace.Shards, *shard)
   132  	}
   133  	clusterInstance.Keyspaces = append(clusterInstance.Keyspaces, keyspace)
   134  }
   135  
   136  func TestRestart(t *testing.T) {
   137  	defer cluster.PanicHandler(t)
   138  	err := primaryTablet.MysqlctlProcess.Stop()
   139  	require.Nil(t, err)
   140  	primaryTablet.MysqlctlProcess.CleanupFiles(primaryTablet.TabletUID)
   141  	err = primaryTablet.MysqlctlProcess.Start()
   142  	require.Nil(t, err)
   143  }
   144  
   145  func TestAutoDetect(t *testing.T) {
   146  	defer cluster.PanicHandler(t)
   147  
   148  	// Start up tablets with an empty MYSQL_FLAVOR, which means auto-detect
   149  	sqlFlavor := os.Getenv("MYSQL_FLAVOR")
   150  	os.Setenv("MYSQL_FLAVOR", "")
   151  
   152  	err := clusterInstance.Keyspaces[0].Shards[0].Vttablets[0].VttabletProcess.Setup()
   153  	require.Nil(t, err, "error should be nil")
   154  	err = clusterInstance.Keyspaces[0].Shards[0].Vttablets[1].VttabletProcess.Setup()
   155  	require.Nil(t, err, "error should be nil")
   156  
   157  	// Reparent tablets, which requires flavor detection
   158  	err = clusterInstance.VtctlclientProcess.InitializeShard(keyspaceName, shardName, cell, primaryTablet.TabletUID)
   159  	require.Nil(t, err, "error should be nil")
   160  
   161  	//Reset flavor
   162  	os.Setenv("MYSQL_FLAVOR", sqlFlavor)
   163  
   164  }