vitess.io/vitess@v0.16.2/go/vt/wrangler/testlib/apply_schema_flaky_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 testlib 18 19 import ( 20 "strings" 21 "testing" 22 "time" 23 24 "vitess.io/vitess/go/vt/discovery" 25 26 "context" 27 28 "vitess.io/vitess/go/mysql/fakesqldb" 29 "vitess.io/vitess/go/sqltypes" 30 "vitess.io/vitess/go/vt/logutil" 31 "vitess.io/vitess/go/vt/mysqlctl/tmutils" 32 "vitess.io/vitess/go/vt/topo/memorytopo" 33 "vitess.io/vitess/go/vt/vttablet/tmclient" 34 "vitess.io/vitess/go/vt/wrangler" 35 36 tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" 37 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 38 ) 39 40 // TestApplySchema_AllowLongUnavailability is an integration test for the 41 // --allow_long_unavailability flag of vtctl ApplySchema. 42 // Only if the flag is specified, potentially long running schema changes are 43 // allowed. 44 func TestApplySchema_AllowLongUnavailability(t *testing.T) { 45 delay := discovery.GetTabletPickerRetryDelay() 46 defer func() { 47 discovery.SetTabletPickerRetryDelay(delay) 48 }() 49 discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) 50 51 cell := "cell1" 52 db := fakesqldb.New(t) 53 defer db.Close() 54 ts := memorytopo.NewServer(cell) 55 wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) 56 vp := NewVtctlPipe(t, ts) 57 defer vp.Close() 58 59 if err := ts.CreateKeyspace(context.Background(), "ks", &topodatapb.Keyspace{}); err != nil { 60 t.Fatalf("CreateKeyspace failed: %v", err) 61 } 62 63 beforeSchema := &tabletmanagerdatapb.SchemaDefinition{ 64 DatabaseSchema: "CREATE DATABASE `{{.DatabaseName}}` /*!40100 DEFAULT CHARACTER SET utf8 */", 65 TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ 66 { 67 Name: "table1", 68 Schema: "CREATE TABLE `table1` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `msg` varchar(64) DEFAULT NULL,\n `keyspace_id` bigint(20) unsigned NOT NULL,\n PRIMARY KEY (`id`),\n KEY `by_msg` (`msg`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8", 69 Type: tmutils.TableBaseTable, 70 RowCount: 3000000, 71 }, 72 }, 73 } 74 afterSchema := &tabletmanagerdatapb.SchemaDefinition{ 75 DatabaseSchema: "CREATE DATABASE `{{.DatabaseName}}` /*!40100 DEFAULT CHARACTER SET utf8 */", 76 TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ 77 { 78 Name: "table1", 79 Schema: "CREATE TABLE `table1` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `msg` varchar(64) DEFAULT NULL,\n `keyspace_id` bigint(20) unsigned NOT NULL,\n `id` bigint(20),\n PRIMARY KEY (`id`),\n KEY `by_msg` (`msg`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8", 80 Type: tmutils.TableBaseTable, 81 RowCount: 3000000, 82 }, 83 }, 84 } 85 preflightSchemaChanges := []*tabletmanagerdatapb.SchemaChangeResult{ 86 { 87 BeforeSchema: beforeSchema, 88 AfterSchema: afterSchema, 89 }, 90 } 91 92 tShard1 := NewFakeTablet(t, wr, cell, 0, 93 topodatapb.TabletType_PRIMARY, db, TabletKeyspaceShard(t, "ks", "-80")) 94 tShard2 := NewFakeTablet(t, wr, cell, 1, 95 topodatapb.TabletType_PRIMARY, db, TabletKeyspaceShard(t, "ks", "80-")) 96 for _, ft := range []*FakeTablet{tShard1, tShard2} { 97 ft.StartActionLoop(t, wr) 98 defer ft.StopActionLoop(t) 99 100 ft.FakeMysqlDaemon.Schema = beforeSchema 101 ft.FakeMysqlDaemon.PreflightSchemaChangeResult = preflightSchemaChanges 102 } 103 104 changeToDb := "USE `vt_ks`" 105 addColumn := "ALTER TABLE table1 ADD COLUMN new_id bigint(20)" 106 db.AddQuery(changeToDb, &sqltypes.Result{}) 107 db.AddQuery(addColumn, &sqltypes.Result{}) 108 109 // First ApplySchema fails because the table is very big and -allow_long_unavailability is missing. 110 if err := vp.Run([]string{"ApplySchema", "--sql", addColumn, "ks"}); err == nil { 111 t.Fatal("ApplySchema should have failed but did not.") 112 } else if !strings.Contains(err.Error(), "big schema change detected") || 113 !strings.Contains(strings.ToLower(err.Error()), "alter table table1") { 114 t.Fatalf("ApplySchema failed with wrong error. got: %v", err) 115 } 116 117 // Second ApplySchema succeeds because -allow_long_unavailability is set. 118 if err := vp.Run([]string{"ApplySchema", "--allow_long_unavailability", "--sql", addColumn, "ks"}); err != nil { 119 t.Fatalf("ApplySchema failed: %v", err) 120 } 121 if count := db.GetQueryCalledNum(changeToDb); count != 2 { 122 t.Fatalf("ApplySchema: unexpected call count. Query: %v got: %v want: %v", changeToDb, count, 2) 123 } 124 if count := db.GetQueryCalledNum(addColumn); count != 2 { 125 t.Fatalf("ApplySchema: unexpected call count. Query: %v got: %v want: %v", addColumn, count, 2) 126 } 127 }