vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletmanager/vreplication/external_connector_test.go (about)

     1  /*
     2  Copyright 2020 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 vreplication
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  
    25  	"vitess.io/vitess/go/vt/binlog/binlogplayer"
    26  	binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
    27  	qh "vitess.io/vitess/go/vt/vttablet/tabletmanager/vreplication/queryhistory"
    28  )
    29  
    30  func TestExternalConnectorCopy(t *testing.T) {
    31  	execStatements(t, []string{
    32  		"create table tab1(id int, val varbinary(128), primary key(id))",
    33  		fmt.Sprintf("create table %s.tab1(id int, val varbinary(128), primary key(id))", vrepldb),
    34  		"insert into tab1 values(1, 'a'), (2, 'b')",
    35  
    36  		"create table tab2(id int, val varbinary(128), primary key(id))",
    37  		fmt.Sprintf("create table %s.tab2(id int, val varbinary(128), primary key(id))", vrepldb),
    38  		"insert into tab2 values(1, 'a'), (2, 'b')",
    39  
    40  		"create table tab3(id int, val varbinary(128), primary key(id))",
    41  		fmt.Sprintf("create table %s.tab3(id int, val varbinary(128), primary key(id))", vrepldb),
    42  		"insert into tab3 values(1, 'a'), (2, 'b')",
    43  	})
    44  	defer execStatements(t, []string{
    45  		"drop table tab1",
    46  		fmt.Sprintf("drop table %s.tab1", vrepldb),
    47  		"drop table tab2",
    48  		fmt.Sprintf("drop table %s.tab2", vrepldb),
    49  		"drop table tab3",
    50  		fmt.Sprintf("drop table %s.tab3", vrepldb),
    51  	})
    52  
    53  	filter1 := &binlogdatapb.Filter{
    54  		Rules: []*binlogdatapb.Rule{{
    55  			Match:  "tab1",
    56  			Filter: "",
    57  		}},
    58  	}
    59  	bls1 := &binlogdatapb.BinlogSource{
    60  		ExternalMysql: "exta",
    61  		Filter:        filter1,
    62  	}
    63  	cancel1 := startExternalVReplication(t, bls1, "")
    64  
    65  	expectDBClientAndVreplicationQueries(t, []string{
    66  		"begin",
    67  		"insert into tab1(id,val) values (1,'a'), (2,'b')",
    68  		"/insert into _vt.copy_state",
    69  		"commit",
    70  		"/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name",
    71  		"/update _vt.vreplication set state='Running'",
    72  	}, "")
    73  	execStatements(t, []string{"insert into tab1 values(3, 'c')"})
    74  	expectDBClientQueries(t, qh.Expect(
    75  		"begin",
    76  		"insert into tab1(id,val) values (3,'c')",
    77  		"/update _vt.vreplication set pos=",
    78  		"commit",
    79  	))
    80  	// Cancel immediately so we don't deal with spurious updates.
    81  	cancel1()
    82  
    83  	// Check that only one connector was created.
    84  	assert.Equal(t, 1, len(playerEngine.ec.connectors))
    85  	filter2 := &binlogdatapb.Filter{
    86  		Rules: []*binlogdatapb.Rule{{
    87  			Match:  "tab2",
    88  			Filter: "",
    89  		}},
    90  	}
    91  	bls2 := &binlogdatapb.BinlogSource{
    92  		ExternalMysql: "exta",
    93  		Filter:        filter2,
    94  	}
    95  	cancel2 := startExternalVReplication(t, bls2, "")
    96  
    97  	expectDBClientAndVreplicationQueries(t, []string{
    98  		"begin",
    99  		"insert into tab2(id,val) values (1,'a'), (2,'b')",
   100  		"/insert into _vt.copy_state",
   101  		"commit",
   102  		"/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name",
   103  		"/update _vt.vreplication set state='Running'",
   104  	}, "")
   105  	cancel2()
   106  
   107  	// Check that only one connector was created.
   108  	assert.Equal(t, 1, len(playerEngine.ec.connectors))
   109  
   110  	filter3 := &binlogdatapb.Filter{
   111  		Rules: []*binlogdatapb.Rule{{
   112  			Match:  "tab3",
   113  			Filter: "",
   114  		}},
   115  	}
   116  	bls3 := &binlogdatapb.BinlogSource{
   117  		ExternalMysql: "extb",
   118  		Filter:        filter3,
   119  	}
   120  	cancel3 := startExternalVReplication(t, bls3, "")
   121  
   122  	expectDBClientAndVreplicationQueries(t, []string{
   123  		"begin",
   124  		"insert into tab3(id,val) values (1,'a'), (2,'b')",
   125  		"/insert into _vt.copy_state",
   126  		"commit",
   127  		"/delete cs, pca from _vt.copy_state as cs left join _vt.post_copy_action as pca on cs.vrepl_id=pca.vrepl_id and cs.table_name=pca.table_name",
   128  		"/update _vt.vreplication set state='Running'",
   129  	}, "")
   130  	cancel3()
   131  
   132  	// Check that there now two connectors.
   133  	assert.Equal(t, 2, len(playerEngine.ec.connectors))
   134  }
   135  
   136  func TestExternalConnectorPlay(t *testing.T) {
   137  	execStatements(t, []string{
   138  		"create table tab1(id int, val varbinary(128), primary key(id))",
   139  		fmt.Sprintf("create table %s.tab1(id int, val varbinary(128), primary key(id))", vrepldb),
   140  	})
   141  	defer execStatements(t, []string{
   142  		"drop table tab1",
   143  		fmt.Sprintf("drop table %s.tab1", vrepldb),
   144  	})
   145  
   146  	filter1 := &binlogdatapb.Filter{
   147  		Rules: []*binlogdatapb.Rule{{
   148  			Match:  "tab1",
   149  			Filter: "",
   150  		}},
   151  	}
   152  	bls1 := &binlogdatapb.BinlogSource{
   153  		ExternalMysql: "exta",
   154  		Filter:        filter1,
   155  	}
   156  	pos := primaryPosition(t)
   157  	cancel1 := startExternalVReplication(t, bls1, pos)
   158  	defer cancel1()
   159  
   160  	execStatements(t, []string{
   161  		"insert into tab1 values(1, 'a'), (2, 'b')",
   162  	})
   163  
   164  	expectDBClientAndVreplicationQueries(t, []string{
   165  		"begin",
   166  		"insert into tab1(id,val) values (1,'a')",
   167  		"insert into tab1(id,val) values (2,'b')",
   168  		"/update _vt.vreplication set pos=",
   169  		"commit",
   170  	}, pos)
   171  }
   172  
   173  func expectDBClientAndVreplicationQueries(t *testing.T, queries []string, pos string) {
   174  	t.Helper()
   175  	vrepQueries := getExpectedVreplicationQueries(t, pos)
   176  	expectedQueries := append(vrepQueries, queries...)
   177  	expectDBClientQueries(t, qh.Expect(expectedQueries[0], expectedQueries[1:]...))
   178  }
   179  
   180  func getExpectedVreplicationQueries(t *testing.T, pos string) []string {
   181  	if pos == "" {
   182  		return []string{
   183  			"/insert into _vt.vreplication",
   184  			"begin",
   185  			"/insert into _vt.copy_state",
   186  			"/update _vt.vreplication set state='Copying'",
   187  			"commit",
   188  			"/update _vt.vreplication set pos=",
   189  		}
   190  	}
   191  	return []string{
   192  		"/insert into _vt.vreplication",
   193  		"/update _vt.vreplication set state='Running'",
   194  	}
   195  }
   196  
   197  func startExternalVReplication(t *testing.T, bls *binlogdatapb.BinlogSource, pos string) (cancelr func()) {
   198  	query := binlogplayer.CreateVReplication("test", bls, pos, 9223372036854775807, 9223372036854775807, 0, vrepldb, 0, 0, false)
   199  	qr, err := playerEngine.Exec(query)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	return func() {
   204  		t.Helper()
   205  		query := fmt.Sprintf("delete from _vt.vreplication where id = %d", qr.InsertID)
   206  		if _, err := playerEngine.Exec(query); err != nil {
   207  			t.Fatal(err)
   208  		}
   209  		expectDeleteQueries(t)
   210  	}
   211  }