vitess.io/vitess@v0.16.2/go/test/endtoend/vtgate/transaction/rollback/txn_rollback_shutdown_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 rollback 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "os" 24 "testing" 25 26 "vitess.io/vitess/go/test/endtoend/utils" 27 28 "github.com/stretchr/testify/require" 29 30 "github.com/stretchr/testify/assert" 31 32 "vitess.io/vitess/go/mysql" 33 "vitess.io/vitess/go/test/endtoend/cluster" 34 ) 35 36 var ( 37 clusterInstance *cluster.LocalProcessCluster 38 vtParams mysql.ConnParams 39 keyspaceName = "ks" 40 cell = "zone1" 41 hostname = "localhost" 42 sqlSchema = ` 43 create table buffer( 44 id BIGINT NOT NULL, 45 msg VARCHAR(64) NOT NULL, 46 PRIMARY KEY (id) 47 ) Engine=InnoDB;` 48 ) 49 50 func TestMain(m *testing.M) { 51 defer cluster.PanicHandler(nil) 52 flag.Parse() 53 54 exitCode := func() int { 55 clusterInstance = cluster.NewCluster(cell, hostname) 56 defer clusterInstance.Teardown() 57 58 // Reserve vtGate port in order to pass it to vtTablet 59 clusterInstance.VtgateGrpcPort = clusterInstance.GetAndReservePort() 60 61 // Start topo server 62 err := clusterInstance.StartTopo() 63 if err != nil { 64 panic(err) 65 } 66 67 // Start keyspace 68 keyspace := &cluster.Keyspace{ 69 Name: keyspaceName, 70 SchemaSQL: sqlSchema, 71 } 72 err = clusterInstance.StartUnshardedKeyspace(*keyspace, 1, false) 73 if err != nil { 74 panic(err) 75 } 76 77 // Set a short onterm timeout so the test goes faster. 78 clusterInstance.VtGateExtraArgs = []string{"--onterm_timeout", "1s"} 79 err = clusterInstance.StartVtgate() 80 if err != nil { 81 panic(err) 82 } 83 vtParams = clusterInstance.GetVTParams(keyspaceName) 84 return m.Run() 85 }() 86 os.Exit(exitCode) 87 } 88 89 func TestTransactionRollBackWhenShutDown(t *testing.T) { 90 defer cluster.PanicHandler(t) 91 ctx := context.Background() 92 conn, err := mysql.Connect(ctx, &vtParams) 93 require.NoError(t, err) 94 defer conn.Close() 95 96 utils.Exec(t, conn, "insert into buffer(id, msg) values(3,'mark')") 97 utils.Exec(t, conn, "insert into buffer(id, msg) values(4,'doug')") 98 99 // start an incomplete transaction 100 utils.Exec(t, conn, "begin") 101 utils.Exec(t, conn, "insert into buffer(id, msg) values(33,'mark')") 102 103 // Enforce a restart to enforce rollback 104 if err = clusterInstance.RestartVtgate(); err != nil { 105 t.Errorf("Fail to re-start vtgate: %v", err) 106 } 107 108 want := "" 109 110 // Make a new mysql connection to vtGate 111 vtParams = clusterInstance.GetVTParams(keyspaceName) 112 conn2, err := mysql.Connect(ctx, &vtParams) 113 require.NoError(t, err) 114 defer conn2.Close() 115 116 vtParams = clusterInstance.GetVTParams(keyspaceName) 117 // Verify that rollback worked 118 qr := utils.Exec(t, conn2, "select id from buffer where msg='mark'") 119 got := fmt.Sprintf("%v", qr.Rows) 120 want = `[[INT64(3)]]` 121 assert.Equal(t, want, got) 122 } 123 124 func TestErrorInAutocommitSession(t *testing.T) { 125 defer cluster.PanicHandler(t) 126 ctx := context.Background() 127 conn, err := mysql.Connect(ctx, &vtParams) 128 require.NoError(t, err) 129 defer conn.Close() 130 131 utils.Exec(t, conn, "set autocommit=true") 132 utils.Exec(t, conn, "insert into buffer(id, msg) values(1,'foo')") 133 _, err = conn.ExecuteFetch("insert into buffer(id, msg) values(1,'bar')", 1, true) 134 require.Error(t, err) // this should fail with duplicate error 135 utils.Exec(t, conn, "insert into buffer(id, msg) values(2,'baz')") 136 137 conn2, err := mysql.Connect(ctx, &vtParams) 138 require.NoError(t, err) 139 defer conn2.Close() 140 result := utils.Exec(t, conn2, "select * from buffer order by id") 141 142 // if we have properly working autocommit code, both the successful inserts should be visible to a second 143 // connection, even if we have not done an explicit commit 144 assert.Equal(t, `[[INT64(1) VARCHAR("foo")] [INT64(2) VARCHAR("baz")] [INT64(3) VARCHAR("mark")] [INT64(4) VARCHAR("doug")]]`, fmt.Sprintf("%v", result.Rows)) 145 }