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  }