github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/sink/codec/canal/canal_encoder_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package canal 15 16 import ( 17 "context" 18 "testing" 19 20 "github.com/golang/protobuf/proto" 21 "github.com/pingcap/tiflow/cdc/entry" 22 "github.com/pingcap/tiflow/cdc/model" 23 "github.com/pingcap/tiflow/pkg/config" 24 "github.com/pingcap/tiflow/pkg/sink/codec/common" 25 canal "github.com/pingcap/tiflow/proto/canal" 26 "github.com/stretchr/testify/require" 27 ) 28 29 func TestCanalBatchEncoder(t *testing.T) { 30 helper := entry.NewSchemaTestHelper(t) 31 defer helper.Close() 32 33 sql := `create table test.t(a varchar(10) primary key)` 34 _ = helper.DDL2Event(sql) 35 36 event1 := helper.DML2Event(`insert into test.t values("aa")`, "test", "t") 37 event2 := helper.DML2Event(`insert into test.t values("bb")`, "test", "t") 38 39 rowCases := [][]*model.RowChangedEvent{ 40 {event1}, 41 {event1, event2}, 42 } 43 44 ctx := context.Background() 45 encoder := newBatchEncoder(common.NewConfig(config.ProtocolCanal)) 46 for _, cs := range rowCases { 47 for _, event := range cs { 48 err := encoder.AppendRowChangedEvent(ctx, "", event, nil) 49 require.NoError(t, err) 50 } 51 res := encoder.Build() 52 require.Len(t, res, 1) 53 require.Nil(t, res[0].Key) 54 require.Equal(t, len(cs), res[0].GetRowsCount()) 55 56 packet := &canal.Packet{} 57 err := proto.Unmarshal(res[0].Value, packet) 58 require.Nil(t, err) 59 require.Equal(t, canal.PacketType_MESSAGES, packet.GetType()) 60 messages := &canal.Messages{} 61 err = proto.Unmarshal(packet.GetBody(), messages) 62 require.Nil(t, err) 63 require.Equal(t, len(cs), len(messages.GetMessages())) 64 } 65 66 createTableA := helper.DDL2Event(`create table test.a(a varchar(10) primary key)`) 67 createTableB := helper.DDL2Event(`create table test.b(a varchar(10) primary key)`) 68 69 ddlCases := [][]*model.DDLEvent{ 70 {createTableA}, 71 {createTableA, createTableB}, 72 } 73 for _, cs := range ddlCases { 74 encoder := newBatchEncoder(common.NewConfig(config.ProtocolCanal)) 75 for _, ddl := range cs { 76 msg, err := encoder.EncodeDDLEvent(ddl) 77 require.NoError(t, err) 78 require.NotNil(t, msg) 79 require.Nil(t, msg.Key) 80 81 packet := &canal.Packet{} 82 err = proto.Unmarshal(msg.Value, packet) 83 require.NoError(t, err) 84 require.Equal(t, canal.PacketType_MESSAGES, packet.GetType()) 85 messages := &canal.Messages{} 86 err = proto.Unmarshal(packet.GetBody(), messages) 87 require.NoError(t, err) 88 require.Equal(t, 1, len(messages.GetMessages())) 89 require.NoError(t, err) 90 } 91 } 92 } 93 94 func TestCanalAppendRowChangedEventWithCallback(t *testing.T) { 95 helper := entry.NewSchemaTestHelper(t) 96 defer helper.Close() 97 98 sql := `create table test.t(a varchar(10) primary key)` 99 _ = helper.DDL2Event(sql) 100 101 row := helper.DML2Event(`insert into test.t values("aa")`, "test", "t") 102 encoder := newBatchEncoder(common.NewConfig(config.ProtocolCanal)) 103 require.NotNil(t, encoder) 104 105 count := 0 106 107 tests := []struct { 108 row *model.RowChangedEvent 109 callback func() 110 }{ 111 { 112 row: row, 113 callback: func() { 114 count += 1 115 }, 116 }, 117 { 118 row: row, 119 callback: func() { 120 count += 2 121 }, 122 }, 123 { 124 row: row, 125 callback: func() { 126 count += 3 127 }, 128 }, 129 { 130 row: row, 131 callback: func() { 132 count += 4 133 }, 134 }, 135 { 136 row: row, 137 callback: func() { 138 count += 5 139 }, 140 }, 141 } 142 143 // Empty build makes sure that the callback build logic not broken. 144 msgs := encoder.Build() 145 require.Len(t, msgs, 0, "no message should be built and no panic") 146 147 // Append the events. 148 for _, test := range tests { 149 err := encoder.AppendRowChangedEvent(context.Background(), "", test.row, test.callback) 150 require.Nil(t, err) 151 } 152 require.Equal(t, 0, count, "nothing should be called") 153 154 msgs = encoder.Build() 155 require.Len(t, msgs, 1, "expected one message") 156 msgs[0].Callback() 157 require.Equal(t, 15, count, "expected all callbacks to be called") 158 }