github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/connection/stubs_test.go (about) 1 /* 2 * Copyright (C) 2018 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package connection 19 20 import ( 21 "context" 22 "sync" 23 24 "github.com/mysteriumnetwork/node/core/connection/connectionstate" 25 ) 26 27 type fakeState string 28 29 const ( 30 processStarted fakeState = "processStarted" 31 connectingState fakeState = "connectingState" 32 reconnectingState fakeState = "reconnectingState" 33 waitState fakeState = "waitState" 34 authenticatingState fakeState = "authenticatingState" 35 getConfigState fakeState = "getConfigState" 36 assignIPState fakeState = "assignIPState" 37 connectedState fakeState = "connectedState" 38 exitingState fakeState = "exitingState" 39 processExited fakeState = "processExited" 40 ) 41 42 type connectionFactoryFake struct { 43 mockError error 44 mockConnection *connectionMock 45 } 46 47 func (c *connectionFactoryFake) CreateConnection(serviceType string) (Connection, error) { 48 // each test can set this value to simulate connection creation error, this flag is reset BEFORE each test 49 if c.mockError != nil { 50 return nil, c.mockError 51 } 52 53 c.mockConnection.stateChannel = make(chan connectionstate.State, 100) 54 55 stateCallback := func(state fakeState) { 56 if state == connectedState { 57 c.mockConnection.stateChannel <- connectionstate.Connected 58 } 59 if state == exitingState { 60 c.mockConnection.stateChannel <- connectionstate.Disconnecting 61 } 62 if state == reconnectingState { 63 c.mockConnection.stateChannel <- connectionstate.Reconnecting 64 } 65 // this is the last state - close channel (according to best practices of go - channel writer controls channel) 66 if state == processExited { 67 close(c.mockConnection.stateChannel) 68 } 69 } 70 c.mockConnection.StateCallback(stateCallback) 71 72 // we copy the values over, so that the factory always returns a new instance of connection 73 copy := connectionMock{ 74 stateChannel: c.mockConnection.stateChannel, 75 onStartReportStates: c.mockConnection.onStartReportStates, 76 onStartReturnError: c.mockConnection.onStartReturnError, 77 onStopReportStates: c.mockConnection.onStopReportStates, 78 stateCallback: c.mockConnection.stateCallback, 79 onStartReportStats: c.mockConnection.onStartReportStats, 80 fakeProcess: sync.WaitGroup{}, 81 stopBlock: c.mockConnection.stopBlock, 82 } 83 84 return ©, nil 85 } 86 87 type connectionMock struct { 88 stateChannel chan connectionstate.State 89 onStartReturnError error 90 onStartReportStates []fakeState 91 onStopReportStates []fakeState 92 stateCallback func(state fakeState) 93 onStartReportStats connectionstate.Statistics 94 fakeProcess sync.WaitGroup 95 stopBlock chan struct{} 96 sync.RWMutex 97 } 98 99 func (c *connectionMock) State() <-chan connectionstate.State { 100 return c.stateChannel 101 } 102 103 func (c *connectionMock) Statistics() (connectionstate.Statistics, error) { 104 return c.onStartReportStats, nil 105 } 106 107 func (c *connectionMock) GetConfig() (ConsumerConfig, error) { 108 return nil, nil 109 } 110 111 func (c *connectionMock) Reconnect(ctx context.Context, connectionParams ConnectOptions) error { 112 return c.Start(ctx, connectionParams) 113 } 114 115 func (c *connectionMock) Start(ctx context.Context, connectionParams ConnectOptions) error { 116 c.RLock() 117 defer c.RUnlock() 118 119 if c.onStartReturnError != nil { 120 return c.onStartReturnError 121 } 122 123 c.fakeProcess.Add(1) 124 for _, fakeState := range c.onStartReportStates { 125 c.reportState(fakeState) 126 } 127 return nil 128 } 129 130 func (c *connectionMock) Stop() { 131 for _, fakeState := range c.onStopReportStates { 132 c.reportState(fakeState) 133 } 134 if c.stopBlock != nil { 135 <-c.stopBlock 136 } 137 c.fakeProcess.Done() 138 } 139 140 func (c *connectionMock) reportState(state fakeState) { 141 c.RLock() 142 defer c.RUnlock() 143 144 c.stateCallback(state) 145 } 146 147 func (c *connectionMock) StateCallback(callback func(state fakeState)) { 148 c.Lock() 149 defer c.Unlock() 150 151 c.stateCallback = callback 152 }