vitess.io/vitess@v0.16.2/go/vt/schemamanager/local_controller_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 schemamanager 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "path" 24 "reflect" 25 "strings" 26 "testing" 27 28 querypb "vitess.io/vitess/go/vt/proto/query" 29 ) 30 31 func TestLocalControllerNoSchemaChanges(t *testing.T) { 32 schemaChangeDir := t.TempDir() 33 controller := NewLocalController(schemaChangeDir) 34 ctx := context.Background() 35 if err := controller.Open(ctx); err != nil { 36 t.Fatalf("Open should succeed, but got error: %v", err) 37 } 38 defer controller.Close() 39 data, err := controller.Read(ctx) 40 if err != nil { 41 t.Fatalf("Read should succeed, but got error: %v", err) 42 } 43 if len(data) != 0 { 44 t.Fatalf("there is no schema change, Read should return empty data") 45 } 46 } 47 48 func TestLocalControllerOpen(t *testing.T) { 49 controller := NewLocalController("") 50 ctx := context.Background() 51 52 if err := controller.Open(ctx); err == nil || !strings.Contains(err.Error(), "no such file or directory") { 53 t.Fatalf("Open should fail, no such dir, but got: %v", err) 54 } 55 56 schemaChangeDir := t.TempDir() 57 58 // create a file under schema change dir 59 _, err := os.Create(path.Join(schemaChangeDir, "create_test_table.sql")) 60 if err != nil { 61 t.Fatalf("failed to create sql file, error: %v", err) 62 } 63 64 controller = NewLocalController(schemaChangeDir) 65 if err := controller.Open(ctx); err != nil { 66 t.Fatalf("Open should succeed") 67 } 68 data, err := controller.Read(ctx) 69 if err != nil { 70 t.Fatalf("Read should succeed, but got error: %v", err) 71 } 72 if len(data) != 0 { 73 t.Fatalf("there is no schema change, Read should return empty data") 74 } 75 controller.Close() 76 77 testKeyspaceDir := path.Join(schemaChangeDir, "test_keyspace") 78 if err := os.MkdirAll(testKeyspaceDir, os.ModePerm); err != nil { 79 t.Fatalf("failed to create test_keyspace dir, error: %v", err) 80 } 81 82 controller = NewLocalController(schemaChangeDir) 83 if err := controller.Open(ctx); err != nil { 84 t.Fatalf("Open should succeed") 85 } 86 data, err = controller.Read(ctx) 87 if err != nil { 88 t.Fatalf("Read should succeed, but got error: %v", err) 89 } 90 if len(data) != 0 { 91 t.Fatalf("there is no schema change, Read should return empty data") 92 } 93 controller.Close() 94 } 95 96 func TestLocalControllerSchemaChange(t *testing.T) { 97 schemaChangeDir := t.TempDir() 98 99 testKeyspaceInputDir := path.Join(schemaChangeDir, "test_keyspace/input") 100 if err := os.MkdirAll(testKeyspaceInputDir, os.ModePerm); err != nil { 101 t.Fatalf("failed to create test_keyspace dir, error: %v", err) 102 } 103 104 file, err := os.Create(path.Join(testKeyspaceInputDir, "create_test_table.sql")) 105 if err != nil { 106 t.Fatalf("failed to create sql file, error: %v", err) 107 } 108 109 sqls := []string{ 110 "create table test_table_01 (id int)", 111 "create table test_table_02 (id string)", 112 } 113 114 file.WriteString(strings.Join(sqls, ";")) 115 file.Close() 116 117 controller := NewLocalController(schemaChangeDir) 118 ctx := context.Background() 119 120 if err := controller.Open(ctx); err != nil { 121 t.Fatalf("Open should succeed, but got error: %v", err) 122 } 123 124 defer controller.Close() 125 126 data, err := controller.Read(ctx) 127 if err != nil { 128 t.Fatalf("Read should succeed, but got error: %v", err) 129 } 130 131 if !reflect.DeepEqual(sqls, data) { 132 t.Fatalf("expect to get sqls: %v, but got: %v", sqls, data) 133 } 134 135 if controller.Keyspace() != "test_keyspace" { 136 t.Fatalf("expect to get keyspace: 'test_keyspace', but got: '%s'", 137 controller.Keyspace()) 138 } 139 140 // test various callbacks 141 if err := controller.OnReadSuccess(ctx); err != nil { 142 t.Fatalf("OnReadSuccess should succeed, but got error: %v", err) 143 } 144 145 if err := controller.OnReadFail(ctx, fmt.Errorf("read fail")); err != nil { 146 t.Fatalf("OnReadFail should succeed, but got error: %v", err) 147 } 148 149 errorPath := path.Join(controller.errorDir, controller.sqlFilename) 150 151 if err := controller.OnValidationSuccess(ctx); err != nil { 152 t.Fatalf("OnReadSuccess should succeed, but got error: %v", err) 153 } 154 155 // move sql file from error dir to input dir for OnValidationFail test 156 os.Rename(errorPath, controller.sqlPath) 157 158 if err := controller.OnValidationFail(ctx, fmt.Errorf("validation fail")); err != nil { 159 t.Fatalf("OnValidationFail should succeed, but got error: %v", err) 160 } 161 162 if _, err := os.Stat(errorPath); os.IsNotExist(err) { 163 t.Fatalf("sql file should be moved to error dir, error: %v", err) 164 } 165 166 // move sql file from error dir to input dir for OnExecutorComplete test 167 os.Rename(errorPath, controller.sqlPath) 168 169 result := &ExecuteResult{ 170 Sqls: []string{"create table test_table (id int)"}, 171 SuccessShards: []ShardResult{{ 172 Shard: "0", 173 Result: &querypb.QueryResult{}, 174 }}, 175 } 176 logPath := path.Join(controller.logDir, controller.sqlFilename) 177 completePath := path.Join(controller.completeDir, controller.sqlFilename) 178 if err := controller.OnExecutorComplete(ctx, result); err != nil { 179 t.Fatalf("OnExecutorComplete should succeed, but got error: %v", err) 180 } 181 if _, err := os.Stat(completePath); os.IsNotExist(err) { 182 t.Fatalf("sql file should be moved to complete dir, error: %v", err) 183 } 184 185 if _, err := os.Stat(logPath); os.IsNotExist(err) { 186 t.Fatalf("sql file should be moved to log dir, error: %v", err) 187 } 188 189 // move sql file from error dir to input dir for OnExecutorComplete test 190 os.Rename(completePath, controller.sqlPath) 191 192 result = &ExecuteResult{ 193 Sqls: []string{"create table test_table (id int)"}, 194 FailedShards: []ShardWithError{{ 195 Shard: "0", 196 Err: "execute error", 197 }}, 198 } 199 200 if err := controller.OnExecutorComplete(ctx, result); err != nil { 201 t.Fatalf("OnExecutorComplete should succeed, but got error: %v", err) 202 } 203 204 if _, err := os.Stat(errorPath); os.IsNotExist(err) { 205 t.Fatalf("sql file should be moved to error dir, error: %v", err) 206 } 207 }