github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/p2p/mock_message_handler_manager.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 "sync" 19 "testing" 20 "time" 21 22 "github.com/pingcap/tiflow/pkg/errors" 23 "github.com/stretchr/testify/require" 24 ) 25 26 // MockMessageHandlerManager is used in unit-test only, it simulates a message 27 // handler manager 28 type MockMessageHandlerManager struct { 29 mu sync.RWMutex 30 handlers map[Topic]HandlerFunc 31 tpi map[Topic]TypeInformation 32 33 injectedError chan error 34 } 35 36 // NewMockMessageHandlerManager creates a new MockMessageHandlerManager instance 37 func NewMockMessageHandlerManager() *MockMessageHandlerManager { 38 return &MockMessageHandlerManager{ 39 handlers: make(map[Topic]HandlerFunc), 40 tpi: make(map[Topic]TypeInformation), 41 injectedError: make(chan error, 1), 42 } 43 } 44 45 // AssertHasHandler checks the given topic is registered 46 func (m *MockMessageHandlerManager) AssertHasHandler(t *testing.T, topic Topic, tpi TypeInformation) { 47 m.mu.Lock() 48 defer m.mu.Unlock() 49 50 require.Contains(t, m.handlers, topic) 51 require.Contains(t, m.tpi, topic) 52 require.Equal(t, tpi, m.tpi[topic]) 53 } 54 55 // AssertNoHandler checks the given topic is not registered 56 func (m *MockMessageHandlerManager) AssertNoHandler(t *testing.T, topic Topic) { 57 m.mu.Lock() 58 defer m.mu.Unlock() 59 60 require.NotContains(t, m.handlers, topic) 61 require.NotContains(t, m.tpi, topic) 62 } 63 64 // InvokeHandler gets the handler of given topic and invoke the handler to 65 // simulate to send message from given sender 66 func (m *MockMessageHandlerManager) InvokeHandler(t *testing.T, topic Topic, senderID NodeID, message interface{}) error { 67 m.mu.RLock() 68 defer m.mu.RUnlock() 69 70 require.Containsf(t, m.handlers, topic, 71 "trying to invoke a non-existent handler for topic %s", topic) 72 73 var err error 74 require.NotPanicsf(t, func() { 75 err = m.handlers[topic](senderID, message) 76 }, "message handler panicked for topic %s", topic) 77 return errors.Trace(err) 78 } 79 80 // InjectError injects an error into the mock message handler 81 func (m *MockMessageHandlerManager) InjectError(err error) { 82 m.injectedError <- err 83 } 84 85 // RegisterHandler implements MessageHandlerManager.RegisterHandler 86 func (m *MockMessageHandlerManager) RegisterHandler( 87 ctx context.Context, 88 topic Topic, 89 tpi TypeInformation, 90 fn HandlerFunc, 91 ) (bool, error) { 92 m.mu.Lock() 93 defer m.mu.Unlock() 94 95 if _, ok := m.handlers[topic]; ok { 96 // If the handler already exists, we return false. 97 return false, nil 98 } 99 100 m.handlers[topic] = fn 101 m.tpi[topic] = tpi 102 return true, nil 103 } 104 105 // UnregisterHandler implements MessageHandlerManager.UnregisterHandler 106 func (m *MockMessageHandlerManager) UnregisterHandler(ctx context.Context, topic Topic) (bool, error) { 107 m.mu.Lock() 108 defer m.mu.Unlock() 109 110 if _, ok := m.handlers[topic]; !ok { 111 return false, nil 112 } 113 114 delete(m.handlers, topic) 115 delete(m.tpi, topic) 116 return true, nil 117 } 118 119 // CheckError implements MessageHandlerManager.CheckError 120 func (m *MockMessageHandlerManager) CheckError(ctx context.Context) error { 121 select { 122 case <-ctx.Done(): 123 return errors.Trace(ctx.Err()) 124 case err := <-m.injectedError: 125 return err 126 default: 127 } 128 return nil 129 } 130 131 // Clean implements MessageHandlerManager.Clean 132 func (m *MockMessageHandlerManager) Clean(ctx context.Context) error { 133 m.mu.Lock() 134 defer m.mu.Unlock() 135 136 for topic := range m.handlers { 137 delete(m.handlers, topic) 138 delete(m.tpi, topic) 139 } 140 141 return nil 142 } 143 144 // SetTimeout implements MessageHandlerManager.SetTimeout 145 func (m *MockMessageHandlerManager) SetTimeout(timeout time.Duration) { 146 // This function is a dummy 147 }