vitess.io/vitess@v0.16.2/go/vt/binlog/event_streamer_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 binlog
    18  
    19  import (
    20  	"testing"
    21  
    22  	"vitess.io/vitess/go/test/utils"
    23  
    24  	"github.com/stretchr/testify/require"
    25  	"google.golang.org/protobuf/proto"
    26  
    27  	binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
    28  	querypb "vitess.io/vitess/go/vt/proto/query"
    29  )
    30  
    31  var dmlErrorCases = []string{
    32  	"query",
    33  	"query /* _stream 10 (eid id `name` ) (null 1 'bmFtZQ==' ); */",
    34  	"query /* _stream _table_ eid id `name` ) (null 1 'bmFtZQ==' ); */",
    35  	"query /* _stream _table_ (10 id `name` ) (null 1 'bmFtZQ==' ); */",
    36  	"query /* _stream _table_ (eid id `name`  (null 1 'bmFtZQ==' ); */",
    37  	"query /* _stream _table_ (eid id `name`)  (null 'aaa' 'bmFtZQ==' ); */",
    38  	"query /* _stream _table_ (eid id `name`)  (null 'bmFtZQ==' ); */",
    39  	"query /* _stream _table_ (eid id `name`)  (null 1.1 'bmFtZQ==' ); */",
    40  	"query /* _stream _table_ (eid id `name`)  (null a 'bmFtZQ==' ); */",
    41  }
    42  
    43  func TestEventErrors(t *testing.T) {
    44  	var got *querypb.StreamEvent
    45  	evs := &EventStreamer{
    46  		sendEvent: func(event *querypb.StreamEvent) error {
    47  			got = event
    48  			return nil
    49  		},
    50  	}
    51  	for _, sql := range dmlErrorCases {
    52  		statements := []FullBinlogStatement{
    53  			{
    54  				Statement: &binlogdatapb.BinlogTransaction_Statement{
    55  					Category: binlogdatapb.BinlogTransaction_Statement_BL_INSERT,
    56  					Sql:      []byte(sql),
    57  				},
    58  			},
    59  		}
    60  		err := evs.transactionToEvent(nil, statements)
    61  		if err != nil {
    62  			t.Errorf("%s: %v", sql, err)
    63  			continue
    64  		}
    65  		want := &querypb.StreamEvent{
    66  			Statements: []*querypb.StreamEvent_Statement{
    67  				{
    68  					Category: querypb.StreamEvent_Statement_Error,
    69  					Sql:      []byte(sql),
    70  				},
    71  			},
    72  		}
    73  		if !proto.Equal(got, want) {
    74  			t.Errorf("error for SQL: '%v' got: %+v, want: %+v", sql, got, want)
    75  		}
    76  	}
    77  }
    78  
    79  func TestSetErrors(t *testing.T) {
    80  	evs := &EventStreamer{
    81  		sendEvent: func(event *querypb.StreamEvent) error {
    82  			return nil
    83  		},
    84  	}
    85  	statements := []FullBinlogStatement{
    86  		{
    87  			Statement: &binlogdatapb.BinlogTransaction_Statement{
    88  				Category: binlogdatapb.BinlogTransaction_Statement_BL_SET,
    89  				Sql:      []byte("SET INSERT_ID=abcd"),
    90  			},
    91  		},
    92  	}
    93  	before := binlogStreamerErrors.Counts()["EventStreamer"]
    94  	err := evs.transactionToEvent(nil, statements)
    95  	require.NoError(t, err)
    96  	got := binlogStreamerErrors.Counts()["EventStreamer"]
    97  	if got != before+1 {
    98  		t.Errorf("got: %v, want: %+v", got, before+1)
    99  	}
   100  }
   101  
   102  func TestDMLEvent(t *testing.T) {
   103  	statements := []FullBinlogStatement{
   104  		{
   105  			Statement: &binlogdatapb.BinlogTransaction_Statement{
   106  				Category: binlogdatapb.BinlogTransaction_Statement_BL_SET,
   107  				Sql:      []byte("SET TIMESTAMP=2"),
   108  			},
   109  		},
   110  		{
   111  			Statement: &binlogdatapb.BinlogTransaction_Statement{
   112  				Category: binlogdatapb.BinlogTransaction_Statement_BL_SET,
   113  				Sql:      []byte("SET INSERT_ID=10"),
   114  			},
   115  		},
   116  		{
   117  			Statement: &binlogdatapb.BinlogTransaction_Statement{
   118  				Category: binlogdatapb.BinlogTransaction_Statement_BL_INSERT,
   119  				Sql:      []byte("query /* _stream _table_ (eid id `name`)  (null 1 'bmFtZQ==' ) (null 18446744073709551615 'bmFtZQ==' ); */"),
   120  			},
   121  		},
   122  		{
   123  			Statement: &binlogdatapb.BinlogTransaction_Statement{
   124  				Category: binlogdatapb.BinlogTransaction_Statement_BL_INSERT,
   125  				Sql:      []byte("query"),
   126  			},
   127  		},
   128  	}
   129  	eventToken := &querypb.EventToken{
   130  		Timestamp: 1,
   131  		Position:  "MariaDB/0-41983-20",
   132  	}
   133  	evs := &EventStreamer{
   134  		sendEvent: func(event *querypb.StreamEvent) error {
   135  			for _, statement := range event.Statements {
   136  				switch statement.Category {
   137  				case querypb.StreamEvent_Statement_DML:
   138  					want := `category:DML table_name:"_table_" primary_key_fields:{name:"eid" type:INT64} primary_key_fields:{name:"id" type:UINT64} primary_key_fields:{name:"name" type:VARBINARY} primary_key_values:{lengths:2 lengths:1 lengths:4 values:"101name"} primary_key_values:{lengths:2 lengths:20 lengths:4 values:"1118446744073709551615name"}`
   139  					utils.MustMatchPB(t, want, statement)
   140  				case querypb.StreamEvent_Statement_Error:
   141  					want := `sql:"query"`
   142  					utils.MustMatchPB(t, want, statement)
   143  				default:
   144  					t.Errorf("unexpected: %#v", event)
   145  				}
   146  			}
   147  			// then test the position
   148  			want := `timestamp:1 position:"MariaDB/0-41983-20"`
   149  			utils.MustMatchPB(t, want, event.EventToken)
   150  			return nil
   151  		},
   152  	}
   153  	err := evs.transactionToEvent(eventToken, statements)
   154  	require.NoError(t, err)
   155  }
   156  
   157  func TestDDLEvent(t *testing.T) {
   158  	statements := []FullBinlogStatement{
   159  		{
   160  			Statement: &binlogdatapb.BinlogTransaction_Statement{
   161  				Category: binlogdatapb.BinlogTransaction_Statement_BL_SET,
   162  				Sql:      []byte("SET TIMESTAMP=2"),
   163  			},
   164  		},
   165  		{
   166  			Statement: &binlogdatapb.BinlogTransaction_Statement{
   167  				Category: binlogdatapb.BinlogTransaction_Statement_BL_DDL,
   168  				Sql:      []byte("DDL"),
   169  			},
   170  		},
   171  	}
   172  	eventToken := &querypb.EventToken{
   173  		Timestamp: 1,
   174  		Position:  "MariaDB/0-41983-20",
   175  	}
   176  	evs := &EventStreamer{
   177  		sendEvent: func(event *querypb.StreamEvent) error {
   178  			for _, statement := range event.Statements {
   179  				switch statement.Category {
   180  				case querypb.StreamEvent_Statement_DDL:
   181  					want := `category:DDL sql:"DDL"`
   182  					utils.MustMatchPB(t, want, statement)
   183  				default:
   184  					t.Errorf("unexpected: %#v", event)
   185  				}
   186  			}
   187  			// then test the position
   188  			want := `timestamp:1 position:"MariaDB/0-41983-20"`
   189  			utils.MustMatchPB(t, want, event.EventToken)
   190  			return nil
   191  		},
   192  	}
   193  	err := evs.transactionToEvent(eventToken, statements)
   194  	require.NoError(t, err)
   195  }