vitess.io/vitess@v0.16.2/go/test/endtoend/reparent/prscomplex/main_test.go (about) 1 /* 2 Copyright 2022 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 misc 18 19 import ( 20 "context" 21 _ "embed" 22 "flag" 23 "os" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 30 "vitess.io/vitess/go/mysql" 31 "vitess.io/vitess/go/test/endtoend/cluster" 32 rutils "vitess.io/vitess/go/test/endtoend/reparent/utils" 33 "vitess.io/vitess/go/test/endtoend/utils" 34 ) 35 36 var ( 37 clusterInstance *cluster.LocalProcessCluster 38 vtParams mysql.ConnParams 39 keyspaceName = "ks" 40 cell = "test" 41 42 //go:embed schema.sql 43 schemaSQL string 44 ) 45 46 func TestMain(m *testing.M) { 47 defer cluster.PanicHandler(nil) 48 flag.Parse() 49 50 exitCode := func() int { 51 clusterInstance = cluster.NewCluster(cell, "localhost") 52 defer clusterInstance.Teardown() 53 54 // Start topo server 55 err := clusterInstance.StartTopo() 56 if err != nil { 57 return 1 58 } 59 60 // Start keyspace 61 keyspace := &cluster.Keyspace{ 62 Name: keyspaceName, 63 SchemaSQL: schemaSQL, 64 } 65 clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, 66 "--queryserver-config-query-timeout=9000", 67 "--queryserver-config-pool-size=3", 68 "--queryserver-config-stream-pool-size=3", 69 "--queryserver-config-transaction-cap=2", 70 "--queryserver-config-transaction-timeout=20", 71 "--shutdown_grace_period=3", 72 "--queryserver-config-schema-change-signal=false") 73 err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false) 74 if err != nil { 75 return 1 76 } 77 78 // Start vtgate 79 clusterInstance.VtGateExtraArgs = append(clusterInstance.VtGateExtraArgs, 80 "--planner-version=gen4", 81 "--mysql_default_workload=olap", 82 "--schema_change_signal=false") 83 err = clusterInstance.StartVtgate() 84 if err != nil { 85 return 1 86 } 87 88 vtParams = mysql.ConnParams{ 89 Host: clusterInstance.Hostname, 90 Port: clusterInstance.VtgateMySQLPort, 91 } 92 return m.Run() 93 }() 94 os.Exit(exitCode) 95 } 96 97 /* 98 TestAcquireSameConnID tests that a query started on a connection gets reconnected with a new connection. 99 Another query acquires the old connection ID and does not override the query list maintained by the vttablet process. 100 PRS should not fail as the query list is maintained appropriately. 101 */ 102 func TestAcquireSameConnID(t *testing.T) { 103 defer func() { 104 err := recover() 105 if err != nil { 106 require.Equal(t, "Fail in goroutine after TestAcquireSameConnID has completed", err) 107 } 108 }() 109 ctx := context.Background() 110 conn, err := mysql.Connect(ctx, &vtParams) 111 require.NoError(t, err) 112 defer conn.Close() 113 114 // start a reserved connection 115 utils.Exec(t, conn, "set sql_mode=''") 116 _ = utils.Exec(t, conn, "select connection_id()") 117 118 // restart the mysql to trigger reconnect on next query. 119 primTablet := clusterInstance.Keyspaces[0].Shards[0].PrimaryTablet() 120 err = primTablet.MysqlctlProcess.Stop() 121 require.NoError(t, err) 122 err = primTablet.MysqlctlProcess.StartProvideInit(false) 123 require.NoError(t, err) 124 125 go func() { 126 // this will trigger reconnect with a new connection id, which will be lower than the origin connection id. 127 _, _ = utils.ExecAllowError(t, conn, "select connection_id(), sleep(4000)") 128 }() 129 time.Sleep(5 * time.Second) 130 131 totalErrCount := 0 132 // run through 100 times to acquire new connection, this might override the original connection id. 133 var conn2 *mysql.Conn 134 for i := 0; i < 100; i++ { 135 conn2, err = mysql.Connect(ctx, &vtParams) 136 require.NoError(t, err) 137 138 utils.Exec(t, conn2, "set sql_mode=''") 139 // ReserveExecute 140 _, err = utils.ExecAllowError(t, conn2, "select connection_id()") 141 if err != nil { 142 totalErrCount++ 143 } 144 // Execute 145 _, err = utils.ExecAllowError(t, conn2, "select connection_id()") 146 if err != nil { 147 totalErrCount++ 148 } 149 } 150 151 // We run the above loop 100 times so we execute 200 queries, of which only some should fail due to MySQL restart. 152 assert.Less(t, totalErrCount, 10, "MySQL restart can cause some errors, but not too many.") 153 154 // prs should happen without any error. 155 text, err := rutils.Prs(t, clusterInstance, clusterInstance.Keyspaces[0].Shards[0].Replica()) 156 require.NoError(t, err, text) 157 }