github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/p2p/message_handler_manager_test.go (about) 1 // Copyright 2022 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 p2p 15 16 import ( 17 "context" 18 "testing" 19 "time" 20 21 "github.com/pingcap/tiflow/pkg/errors" 22 p2pImpl "github.com/pingcap/tiflow/pkg/p2p" 23 "github.com/stretchr/testify/mock" 24 "github.com/stretchr/testify/require" 25 ) 26 27 // handlerRegistrar must be implemented by MessageServer 28 var _ handlerRegistrar = (*p2pImpl.MessageServer)(nil) 29 30 type mockHandlerRegistrar struct { 31 mock.Mock 32 } 33 34 func (r *mockHandlerRegistrar) SyncAddHandler( 35 ctx context.Context, 36 topic Topic, 37 information TypeInformation, 38 handlerFunc HandlerFunc, 39 ) (<-chan error, error) { 40 args := r.Called(ctx, topic, information, handlerFunc) 41 return args.Get(0).(<-chan error), args.Error(1) 42 } 43 44 func (r *mockHandlerRegistrar) SyncRemoveHandler(ctx context.Context, topic Topic) error { 45 args := r.Called(ctx, topic) 46 return args.Error(0) 47 } 48 49 type msgContent struct{} 50 51 func TestMessageHandlerManagerBasics(t *testing.T) { 52 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 53 defer cancel() 54 55 registrar := &mockHandlerRegistrar{} 56 manager := newMessageHandlerManager(registrar) 57 58 errCh1 := make(chan error, 1) 59 registrar.On("SyncAddHandler", mock.Anything, "test-topic-1", &msgContent{}, mock.Anything). 60 Return((<-chan error)(errCh1), nil) 61 ok, err := manager.RegisterHandler(ctx, "test-topic-1", &msgContent{}, func(NodeID, MessageValue) error { 62 // This function does not matter here 63 return nil 64 }) 65 require.NoError(t, err) 66 require.True(t, ok) 67 registrar.AssertExpectations(t) 68 69 // Test duplicate handler 70 ok, err = manager.RegisterHandler(ctx, "test-topic-1", &msgContent{}, func(NodeID, MessageValue) error { 71 // This function does not matter here 72 return nil 73 }) 74 require.NoError(t, err) 75 require.False(t, ok) 76 77 errCh2 := make(chan error, 1) 78 registrar.ExpectedCalls = nil 79 registrar.On("SyncAddHandler", mock.Anything, "test-topic-2", &msgContent{}, mock.Anything). 80 Return((<-chan error)(errCh2), nil) 81 ok, err = manager.RegisterHandler(ctx, "test-topic-2", &msgContent{}, func(NodeID, MessageValue) error { 82 // This function does not matter here 83 return nil 84 }) 85 require.NoError(t, err) 86 require.True(t, ok) 87 registrar.AssertExpectations(t) 88 89 err = manager.CheckError(ctx) 90 require.NoError(t, err) 91 92 errCh1 <- errors.New("fake error") 93 err = manager.CheckError(ctx) 94 require.Error(t, err) 95 96 registrar.ExpectedCalls = nil 97 registrar.On("SyncRemoveHandler", mock.Anything, "test-topic-1").Return(nil) 98 ok, err = manager.UnregisterHandler(ctx, "test-topic-1") 99 require.NoError(t, err) 100 require.True(t, ok) 101 registrar.AssertExpectations(t) 102 103 // duplicate unregister 104 ok, err = manager.UnregisterHandler(ctx, "test-topic-1") 105 require.NoError(t, err) 106 require.False(t, ok) 107 108 registrar.ExpectedCalls = nil 109 registrar.On("SyncRemoveHandler", mock.Anything, "test-topic-2").Return(nil) 110 err = manager.Clean(ctx) 111 require.NoError(t, err) 112 } 113 114 func TestMessageHandlerManagerTimeout(t *testing.T) { 115 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 116 defer cancel() 117 118 registrar := &mockHandlerRegistrar{} 119 manager := newMessageHandlerManager(registrar) 120 manager.SetTimeout(time.Duration(0)) 121 122 registrar.On("SyncAddHandler", mock.Anything, "test-topic-1", &msgContent{}, mock.Anything). 123 Return((<-chan error)(nil), errors.New("fake error")). 124 Run(func(args mock.Arguments) { 125 ctx := args.Get(0).(context.Context) 126 select { 127 case <-ctx.Done(): 128 default: 129 require.Fail(t, "context should have been canceled") 130 } 131 }) 132 133 _, err := manager.RegisterHandler(ctx, "test-topic-1", &msgContent{}, func(NodeID, MessageValue) error { 134 // This function does not matter here 135 return nil 136 }) 137 require.Error(t, err) 138 }