github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/relay/upstream_reader_test.go (about) 1 // Copyright 2019 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 relay 15 16 import ( 17 "context" 18 "time" 19 20 "github.com/go-mysql-org/go-mysql/replication" 21 "github.com/pingcap/check" 22 "github.com/pingcap/errors" 23 "github.com/pingcap/tiflow/dm/pkg/binlog/reader" 24 ) 25 26 var _ = check.Suite(&testRemoteReaderSuite{}) 27 28 type testRemoteReaderSuite struct{} 29 30 func (t *testRemoteReaderSuite) TestInterface(c *check.C) { 31 cases := []*replication.BinlogEvent{ 32 {RawData: []byte{1}}, 33 {RawData: []byte{2}}, 34 {RawData: []byte{3}}, 35 } 36 37 cfg := &RConfig{ 38 SyncConfig: replication.BinlogSyncerConfig{ 39 ServerID: 101, 40 }, 41 MasterID: "test-master", 42 } 43 44 // test with position 45 r := NewUpstreamReader(cfg) 46 t.testInterfaceWithReader(c, r, cases) 47 48 // test with GTID 49 cfg.EnableGTID = true 50 r = NewUpstreamReader(cfg) 51 t.testInterfaceWithReader(c, r, cases) 52 } 53 54 func (t *testRemoteReaderSuite) testInterfaceWithReader(c *check.C, r Reader, cases []*replication.BinlogEvent) { 55 // replace underlying reader with a mock reader for testing 56 concreteR := r.(*upstreamReader) 57 c.Assert(concreteR, check.NotNil) 58 mockR := reader.NewMockReader() 59 concreteR.in = mockR 60 61 // start reader 62 err := r.Start() 63 c.Assert(err, check.IsNil) 64 err = r.Start() // call multi times 65 c.Assert(err, check.NotNil) 66 67 // getEvent by pushing event to mock reader 68 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 69 defer cancel() 70 concreteMR := mockR.(*reader.MockReader) 71 go func() { 72 for _, cs := range cases { 73 c.Assert(concreteMR.PushEvent(ctx, cs), check.IsNil) 74 } 75 }() 76 obtained := make([]*replication.BinlogEvent, 0, len(cases)) 77 for { 78 result, err2 := r.GetEvent(ctx) 79 c.Assert(err2, check.IsNil) 80 obtained = append(obtained, result.Event) 81 if len(obtained) == len(cases) { 82 break 83 } 84 } 85 c.Assert(obtained, check.DeepEquals, cases) 86 87 // close reader 88 err = r.Close() 89 c.Assert(err, check.IsNil) 90 err = r.Close() 91 c.Assert(err, check.NotNil) // call multi times 92 93 // getEvent from a closed reader 94 result, err := r.GetEvent(ctx) 95 c.Assert(err, check.NotNil) 96 c.Assert(result.Event, check.IsNil) 97 } 98 99 func (t *testRemoteReaderSuite) TestGetEventWithError(c *check.C) { 100 cfg := &RConfig{ 101 SyncConfig: replication.BinlogSyncerConfig{ 102 ServerID: 101, 103 }, 104 MasterID: "test-master", 105 } 106 107 r := NewUpstreamReader(cfg) 108 // replace underlying reader with a mock reader for testing 109 concreteR := r.(*upstreamReader) 110 c.Assert(concreteR, check.NotNil) 111 mockR := reader.NewMockReader() 112 concreteR.in = mockR 113 114 errOther := errors.New("other error") 115 in := []error{ 116 context.Canceled, 117 errOther, 118 } 119 expected := []error{ 120 context.Canceled, 121 errOther, 122 } 123 124 err := r.Start() 125 c.Assert(err, check.IsNil) 126 127 // getEvent by pushing event to mock reader 128 ctx, cancel := context.WithCancel(context.Background()) 129 defer cancel() 130 concreteMR := mockR.(*reader.MockReader) 131 go func() { 132 for _, cs := range in { 133 c.Assert(concreteMR.PushError(ctx, cs), check.IsNil) 134 } 135 }() 136 137 results := make([]error, 0, len(expected)) 138 for { 139 _, err2 := r.GetEvent(ctx) 140 c.Assert(err2, check.NotNil) 141 results = append(results, errors.Cause(err2)) 142 if err2 == errOther { 143 break // all received 144 } 145 } 146 c.Assert(results, check.DeepEquals, expected) 147 }