vitess.io/vitess@v0.16.2/go/test/endtoend/versionupgrade/upgrade_test.go (about) 1 /* 2 Copyright 2021 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 /* 18 19 ABOUT THIS TEST 20 =============== 21 22 This test plays part in testing an upgrade path from a previous version/tag. It takes a GitHub workflow file to complete the functionality. 23 What's in this file is the setting up of a cluster, sharded and unsharded keyspace, creating and populating some tables, then testing retrieval of data. 24 The twist here is that you can run this test over pre-existing vtdataroot, which means this test can reuse existing etcd, existing tables, existing mysql, 25 in which case it will not attempt to create keyspaces/schemas/tables, nor will it populate table data. Instead, it will only check for retrieval of data. 26 27 The game is to setup the cluster with a stable version (say `v8.0.0`), take it down (and preserve data), then setup a new cluster with a new version (namely the branch/PR head) and attempt to read the data. 28 29 Both executions must force some settings so that both reuse same directories, ports, etc. An invocation will look like: 30 go test ./go/test/endtoend/versionupgrade80/upgrade_test.go --keep-data --force-vtdataroot /tmp/vtdataroot/vtroot_10901 --force-port-start 11900 --force-base-tablet-uid 1190 31 32 */ 33 34 package versionupgrade 35 36 import ( 37 "flag" 38 "fmt" 39 "os" 40 "path" 41 "testing" 42 43 "github.com/stretchr/testify/assert" 44 "github.com/stretchr/testify/require" 45 46 "vitess.io/vitess/go/mysql" 47 "vitess.io/vitess/go/test/endtoend/cluster" 48 ) 49 50 var ( 51 clusterInstance *cluster.LocalProcessCluster 52 vtParams mysql.ConnParams 53 hostname = "localhost" 54 keyspaceName = "ks" 55 cell = "zone1" 56 schemaChangeDirectory = "" 57 totalTableCount = 4 58 createTable = ` 59 CREATE TABLE %s ( 60 id bigint(20) NOT NULL, 61 msg varchar(64), 62 PRIMARY KEY (id) 63 ) ENGINE=InnoDB; 64 ` 65 insertIntoTable = ` 66 INSERT INTO %s (id, msg) VALUES (17, 'abc'); 67 ` 68 selectFromTable = ` 69 SELECT id, msg FROM %s LIMIT 1; 70 ` 71 ) 72 73 // TestMain is the main entry point 74 func TestMain(m *testing.M) { 75 defer cluster.PanicHandler(nil) 76 flag.Parse() 77 78 exitcode, err := func() (int, error) { 79 clusterInstance = cluster.NewCluster(cell, hostname) 80 schemaChangeDirectory = path.Join("/tmp", fmt.Sprintf("schema_change_dir_%d", clusterInstance.GetAndReserveTabletUID())) 81 defer os.RemoveAll(schemaChangeDirectory) 82 defer clusterInstance.Teardown() 83 84 if _, err := os.Stat(schemaChangeDirectory); os.IsNotExist(err) { 85 _ = os.Mkdir(schemaChangeDirectory, 0700) 86 } 87 88 clusterInstance.VtctldExtraArgs = []string{ 89 "--schema_change_dir", schemaChangeDirectory, 90 "--schema_change_controller", "local", 91 "--schema_change_check_interval", "1"} 92 93 if err := clusterInstance.StartTopo(); err != nil { 94 return 1, err 95 } 96 97 // Start keyspace 98 keyspace := &cluster.Keyspace{ 99 Name: keyspaceName, 100 } 101 102 if err := clusterInstance.StartUnshardedKeyspaceLegacy(*keyspace, 2, true); err != nil { 103 return 1, err 104 } 105 if err := clusterInstance.StartKeyspaceLegacy(*keyspace, []string{"1"}, 1, false); err != nil { 106 return 1, err 107 } 108 109 // TODO: remove this once we upgrade to v12 110 // setting the planner version to 0, so the vtgate binary's default is used 111 clusterInstance.VtGatePlannerVersion = 0 112 vtgateInstance := clusterInstance.NewVtgateInstance() 113 // Start vtgate 114 if err := vtgateInstance.Setup(); err != nil { 115 return 1, err 116 } 117 // ensure it is torn down during cluster TearDown 118 clusterInstance.VtgateProcess = *vtgateInstance 119 vtParams = mysql.ConnParams{ 120 Host: clusterInstance.Hostname, 121 Port: clusterInstance.VtgateMySQLPort, 122 } 123 124 return m.Run(), nil 125 }() 126 if err != nil { 127 fmt.Printf("%v\n", err) 128 os.Exit(1) 129 } else { 130 os.Exit(exitcode) 131 } 132 133 } 134 135 func TestShards(t *testing.T) { 136 defer cluster.PanicHandler(t) 137 assert.Equal(t, 2, len(clusterInstance.Keyspaces[0].Shards)) 138 } 139 140 func TestDeploySchema(t *testing.T) { 141 defer cluster.PanicHandler(t) 142 143 if clusterInstance.ReusingVTDATAROOT { 144 // we assume data is already deployed 145 return 146 } 147 // Create n tables, populate 148 for i := 0; i < totalTableCount; i++ { 149 tableName := fmt.Sprintf("vt_upgrade_test_%02d", i) 150 151 { 152 sqlQuery := fmt.Sprintf(createTable, tableName) 153 result, err := clusterInstance.VtctlclientProcess.ApplySchemaWithOutput(keyspaceName, sqlQuery, cluster.VtctlClientParams{DDLStrategy: ""}) 154 require.Nil(t, err, result) 155 } 156 for i := range clusterInstance.Keyspaces[0].Shards { 157 sqlQuery := fmt.Sprintf(insertIntoTable, tableName) 158 tablet := clusterInstance.Keyspaces[0].Shards[i].Vttablets[0] 159 _, err := tablet.VttabletProcess.QueryTablet(sqlQuery, keyspaceName, true) 160 require.Nil(t, err) 161 } 162 } 163 164 checkTables(t, "", totalTableCount) 165 } 166 167 func TestTablesExist(t *testing.T) { 168 defer cluster.PanicHandler(t) 169 170 checkTables(t, "", totalTableCount) 171 } 172 173 // checkTables checks the number of tables in the first two shards. 174 func checkTables(t *testing.T, showTableName string, expectCount int) { 175 for i := range clusterInstance.Keyspaces[0].Shards { 176 checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[i].Vttablets[0], showTableName, expectCount) 177 } 178 } 179 180 // checkTablesCount checks the number of tables in the given tablet 181 func checkTablesCount(t *testing.T, tablet *cluster.Vttablet, showTableName string, expectCount int) { 182 query := fmt.Sprintf(`show tables like '%%%s%%';`, showTableName) 183 queryResult, err := tablet.VttabletProcess.QueryTablet(query, keyspaceName, true) 184 require.Nil(t, err) 185 assert.Equal(t, expectCount, len(queryResult.Rows)) 186 } 187 188 // TestTablesData checks the data in tables 189 func TestTablesData(t *testing.T) { 190 // Create n tables, populate 191 for i := 0; i < totalTableCount; i++ { 192 tableName := fmt.Sprintf("vt_upgrade_test_%02d", i) 193 194 for i := range clusterInstance.Keyspaces[0].Shards { 195 sqlQuery := fmt.Sprintf(selectFromTable, tableName) 196 tablet := clusterInstance.Keyspaces[0].Shards[i].Vttablets[0] 197 queryResult, err := tablet.VttabletProcess.QueryTablet(sqlQuery, keyspaceName, true) 198 require.Nil(t, err) 199 require.NotNil(t, queryResult) 200 row := queryResult.Named().Row() 201 require.NotNil(t, row) 202 require.Equal(t, int64(17), row.AsInt64("id", 0)) 203 require.Equal(t, "abc", row.AsString("msg", "")) 204 } 205 } 206 }