vitess.io/vitess@v0.16.2/go/test/endtoend/topotest/consul/main_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 package consul 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "os" 24 "testing" 25 "time" 26 27 "vitess.io/vitess/go/vt/log" 28 29 "github.com/google/go-cmp/cmp" 30 "github.com/stretchr/testify/require" 31 32 "vitess.io/vitess/go/mysql" 33 "vitess.io/vitess/go/sqltypes" 34 "vitess.io/vitess/go/test/endtoend/cluster" 35 ) 36 37 var ( 38 clusterInstance *cluster.LocalProcessCluster 39 cell = "zone1" 40 hostname = "localhost" 41 KeyspaceName = "customer" 42 SchemaSQL = ` 43 CREATE TABLE t1 ( 44 c1 BIGINT NOT NULL, 45 c2 BIGINT NOT NULL, 46 c3 BIGINT, 47 c4 varchar(100), 48 PRIMARY KEY (c1), 49 UNIQUE KEY (c2), 50 UNIQUE KEY (c3), 51 UNIQUE KEY (c4) 52 ) ENGINE=Innodb;` 53 VSchema = ` 54 { 55 "sharded": false, 56 "tables": { 57 "t1": {} 58 } 59 } 60 ` 61 ) 62 63 func TestMain(m *testing.M) { 64 defer cluster.PanicHandler(nil) 65 flag.Parse() 66 67 exitCode := func() int { 68 clusterInstance = cluster.NewCluster(cell, hostname) 69 defer clusterInstance.Teardown() 70 71 // Start topo server 72 clusterInstance.TopoFlavor = "consul" 73 if err := clusterInstance.StartTopo(); err != nil { 74 return 1 75 } 76 77 // Start keyspace 78 Keyspace := &cluster.Keyspace{ 79 Name: KeyspaceName, 80 SchemaSQL: SchemaSQL, 81 VSchema: VSchema, 82 } 83 if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { 84 log.Fatal(err.Error()) 85 return 1 86 } 87 88 // Start vtgate 89 if err := clusterInstance.StartVtgate(); err != nil { 90 log.Fatal(err.Error()) 91 return 1 92 } 93 94 return m.Run() 95 }() 96 os.Exit(exitCode) 97 } 98 99 func TestTopoRestart(t *testing.T) { 100 defer cluster.PanicHandler(t) 101 ctx := context.Background() 102 vtParams := mysql.ConnParams{ 103 Host: "localhost", 104 Port: clusterInstance.VtgateMySQLPort, 105 } 106 conn, err := mysql.Connect(ctx, &vtParams) 107 require.Nil(t, err) 108 defer conn.Close() 109 110 execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`) 111 assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) 112 113 defer execute(t, conn, `delete from t1`) 114 115 ch := make(chan any) 116 117 go func() { 118 clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, *clusterInstance.TopoFlavorString()) 119 120 // Some sleep to server few queries when topo is down. 121 time.Sleep(400 * time.Millisecond) 122 123 clusterInstance.TopoProcess.Setup(*clusterInstance.TopoFlavorString(), clusterInstance) 124 125 // topo is up now. 126 ch <- 1 127 }() 128 129 timeOut := time.After(15 * time.Second) 130 131 for { 132 select { 133 case <-ch: 134 return 135 case <-timeOut: 136 require.Fail(t, "timed out - topo process did not come up") 137 case <-time.After(100 * time.Millisecond): 138 assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) 139 } 140 } 141 } 142 143 func execute(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { 144 t.Helper() 145 qr, err := conn.ExecuteFetch(query, 1000, true) 146 require.NoError(t, err) 147 return qr 148 } 149 150 func execMulti(t *testing.T, conn *mysql.Conn, query string) []*sqltypes.Result { 151 t.Helper() 152 var res []*sqltypes.Result 153 qr, more, err := conn.ExecuteFetchMulti(query, 1000, true) 154 res = append(res, qr) 155 require.NoError(t, err) 156 for more == true { 157 qr, more, _, err = conn.ReadQueryResult(1000, true) 158 require.NoError(t, err) 159 res = append(res, qr) 160 } 161 return res 162 } 163 164 func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { 165 t.Helper() 166 qr := execute(t, conn, query) 167 got := fmt.Sprintf("%v", qr.Rows) 168 diff := cmp.Diff(expected, got) 169 if diff != "" { 170 t.Errorf("Query: %s (-want +got):\n%s", query, diff) 171 } 172 }