go.uber.org/yarpc@v1.72.1/peer/abstractpeer/peer_test.go (about) 1 // Copyright (c) 2022 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package abstractpeer 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/golang/mock/gomock" 28 "github.com/stretchr/testify/assert" 29 "go.uber.org/yarpc/api/peer" 30 . "go.uber.org/yarpc/api/peer/peertest" 31 ) 32 33 func TestPeerIdentifier(t *testing.T) { 34 tests := []struct { 35 hostport string 36 expectedIdentifier string 37 }{ 38 { 39 "localhost:12345", 40 "localhost:12345", 41 }, 42 { 43 "123.123.123.123:12345", 44 "123.123.123.123:12345", 45 }, 46 } 47 48 for _, tt := range tests { 49 pi := PeerIdentifier(tt.hostport) 50 51 assert.Equal(t, tt.expectedIdentifier, pi.Identifier()) 52 } 53 } 54 55 func TestPeer(t *testing.T) { 56 type testStruct struct { 57 msg string 58 59 // PeerID for all the hostport.Peer initialization 60 inputPeerID string 61 62 // List of "Subscribers" that we can define beforehand and reference in our PeerActions 63 // using the "ID" field in the subscriber definition, the "ExpectedNotifyCount" is the 64 // expected number of times the subscriber will be notified 65 SubDefinitions []SubscriberDefinition 66 67 // List of actions to be applied to the peer 68 actions []PeerAction 69 70 // Expected result from running Identifier() on the peer after the actions have been applied 71 expectedIdentifier string 72 73 // Expected result from running HostPort() on the peer after the actions have been applied 74 expectedHostPort string 75 76 // Expected result from running Status() on the peer after the actions have been applied 77 expectedStatus peer.Status 78 79 // Expected subscribers in the Peer's "subscribers" map after the actions have been applied 80 expectedSubscribers []string 81 } 82 tests := []testStruct{ 83 { 84 msg: "create", 85 inputPeerID: "localhost:12345", 86 expectedIdentifier: "localhost:12345", 87 expectedHostPort: "localhost:12345", 88 expectedStatus: peer.Status{ 89 PendingRequestCount: 0, 90 ConnectionStatus: peer.Unavailable, 91 }, 92 }, 93 { 94 msg: "start request", 95 SubDefinitions: []SubscriberDefinition{{ID: "1", ExpectedNotifyCount: 1}}, 96 actions: []PeerAction{ 97 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 98 StartStopReqAction{Stop: false}, 99 }, 100 expectedSubscribers: []string{"1"}, 101 expectedStatus: peer.Status{ 102 PendingRequestCount: 1, 103 ConnectionStatus: peer.Unavailable, 104 }, 105 }, 106 { 107 msg: "start request stop request", 108 SubDefinitions: []SubscriberDefinition{{ID: "1", ExpectedNotifyCount: 2}}, 109 actions: []PeerAction{ 110 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 111 StartStopReqAction{Stop: true}, 112 }, 113 expectedSubscribers: []string{"1"}, 114 expectedStatus: peer.Status{ 115 PendingRequestCount: 0, 116 ConnectionStatus: peer.Unavailable, 117 }, 118 }, 119 { 120 msg: "start 5 stop 2", 121 SubDefinitions: []SubscriberDefinition{{ID: "1", ExpectedNotifyCount: 7}}, 122 actions: []PeerAction{ 123 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 124 StartStopReqAction{Stop: true}, 125 StartStopReqAction{Stop: false}, 126 StartStopReqAction{Stop: false}, 127 StartStopReqAction{Stop: true}, 128 StartStopReqAction{Stop: false}, 129 }, 130 expectedSubscribers: []string{"1"}, 131 expectedStatus: peer.Status{ 132 PendingRequestCount: 3, 133 ConnectionStatus: peer.Unavailable, 134 }, 135 }, 136 { 137 msg: "start 5 stop 5", 138 SubDefinitions: []SubscriberDefinition{{ID: "1", ExpectedNotifyCount: 10}}, 139 actions: []PeerAction{ 140 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 141 StartStopReqAction{Stop: true}, 142 StartStopReqAction{Stop: true}, 143 StartStopReqAction{Stop: true}, 144 StartStopReqAction{Stop: true}, 145 StartStopReqAction{Stop: true}, 146 }, 147 expectedSubscribers: []string{"1"}, 148 expectedStatus: peer.Status{ 149 150 ConnectionStatus: peer.Unavailable, 151 }, 152 }, 153 { 154 msg: "set status", 155 SubDefinitions: []SubscriberDefinition{ 156 {ID: "1", ExpectedNotifyCount: 1}, 157 {ID: "2", ExpectedNotifyCount: 1}, 158 {ID: "3", ExpectedNotifyCount: 1}, 159 }, 160 actions: []PeerAction{ 161 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 162 SubscribeAction{SubscriberID: "2", ExpectedSubCount: 2}, 163 SubscribeAction{SubscriberID: "3", ExpectedSubCount: 3}, 164 SetStatusAction{InputStatus: peer.Available}, 165 }, 166 expectedSubscribers: []string{"1", "2", "3"}, 167 expectedStatus: peer.Status{ 168 PendingRequestCount: 0, 169 ConnectionStatus: peer.Available, 170 }, 171 }, 172 { 173 msg: "incremental subscribe", 174 SubDefinitions: []SubscriberDefinition{ 175 {ID: "1", ExpectedNotifyCount: 3}, 176 {ID: "2", ExpectedNotifyCount: 2}, 177 {ID: "3", ExpectedNotifyCount: 1}, 178 }, 179 actions: []PeerAction{ 180 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 181 SetStatusAction{InputStatus: peer.Available}, 182 SubscribeAction{SubscriberID: "2", ExpectedSubCount: 2}, 183 SetStatusAction{InputStatus: peer.Available}, 184 SubscribeAction{SubscriberID: "3", ExpectedSubCount: 3}, 185 SetStatusAction{InputStatus: peer.Available}, 186 }, 187 expectedSubscribers: []string{"1", "2", "3"}, 188 expectedStatus: peer.Status{ 189 PendingRequestCount: 0, 190 ConnectionStatus: peer.Available, 191 }, 192 }, 193 { 194 msg: "subscribe unsubscribe", 195 SubDefinitions: []SubscriberDefinition{ 196 {ID: "1", ExpectedNotifyCount: 1}, 197 }, 198 actions: []PeerAction{ 199 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 200 SetStatusAction{InputStatus: peer.Available}, 201 UnsubscribeAction{SubscriberID: "1", ExpectedSubCount: 0}, 202 SetStatusAction{InputStatus: peer.Available}, 203 }, 204 expectedStatus: peer.Status{ 205 PendingRequestCount: 0, 206 ConnectionStatus: peer.Available, 207 }, 208 }, 209 { 210 msg: "incremental subscribe unsubscribe", 211 SubDefinitions: []SubscriberDefinition{ 212 {ID: "1", ExpectedNotifyCount: 5}, 213 {ID: "2", ExpectedNotifyCount: 3}, 214 {ID: "3", ExpectedNotifyCount: 1}, 215 }, 216 actions: []PeerAction{ 217 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 218 SetStatusAction{InputStatus: peer.Available}, 219 SubscribeAction{SubscriberID: "2", ExpectedSubCount: 2}, 220 SetStatusAction{InputStatus: peer.Available}, 221 SubscribeAction{SubscriberID: "3", ExpectedSubCount: 3}, 222 SetStatusAction{InputStatus: peer.Available}, 223 UnsubscribeAction{SubscriberID: "3", ExpectedSubCount: 2}, 224 SetStatusAction{InputStatus: peer.Available}, 225 UnsubscribeAction{SubscriberID: "2", ExpectedSubCount: 1}, 226 SetStatusAction{InputStatus: peer.Available}, 227 UnsubscribeAction{SubscriberID: "1", ExpectedSubCount: 0}, 228 SetStatusAction{InputStatus: peer.Available}, 229 }, 230 expectedStatus: peer.Status{ 231 PendingRequestCount: 0, 232 ConnectionStatus: peer.Available, 233 }, 234 }, 235 { 236 msg: "unsubscribe error", 237 SubDefinitions: []SubscriberDefinition{ 238 {ID: "1", ExpectedNotifyCount: 0}, 239 }, 240 actions: []PeerAction{ 241 UnsubscribeAction{ 242 SubscriberID: "1", 243 ExpectedErrType: peer.ErrPeerHasNoReferenceToSubscriber{}, 244 ExpectedSubCount: 0, 245 }, 246 }, 247 expectedStatus: peer.Status{ 248 PendingRequestCount: 0, 249 ConnectionStatus: peer.Unavailable, 250 }, 251 }, 252 { 253 msg: "concurrent update and subscribe", 254 SubDefinitions: []SubscriberDefinition{ 255 {ID: "1", ExpectedNotifyCount: 2}, 256 }, 257 actions: []PeerAction{ 258 PeerConcurrentAction{ 259 Actions: []PeerAction{ 260 SubscribeAction{SubscriberID: "1", ExpectedSubCount: 1}, 261 SetStatusAction{InputStatus: peer.Available}, 262 SetStatusAction{InputStatus: peer.Available}, 263 }, 264 Wait: time.Millisecond * 70, 265 }, 266 }, 267 expectedSubscribers: []string{"1"}, 268 expectedStatus: peer.Status{ 269 PendingRequestCount: 0, 270 ConnectionStatus: peer.Available, 271 }, 272 }, 273 } 274 275 for _, tt := range tests { 276 t.Run(tt.msg, func(t *testing.T) { 277 mockCtrl := gomock.NewController(t) 278 defer mockCtrl.Finish() 279 280 if tt.inputPeerID == "" { 281 tt.inputPeerID = "localhost:12345" 282 tt.expectedIdentifier = "localhost:12345" 283 tt.expectedHostPort = "localhost:12345" 284 } 285 286 transport := NewMockTransport(mockCtrl) 287 288 peer := NewPeer(PeerIdentifier(tt.inputPeerID), transport) 289 290 deps := &Dependencies{ 291 Subscribers: CreateSubscriberMap(mockCtrl, tt.SubDefinitions), 292 } 293 294 ApplyPeerActions(t, peer, tt.actions, deps) 295 296 assert.Equal(t, tt.expectedIdentifier, peer.Identifier()) 297 assert.Equal(t, tt.expectedHostPort, peer.HostPort()) 298 assert.Equal(t, transport, peer.Transport()) 299 assert.Equal(t, tt.expectedStatus, peer.Status()) 300 301 assert.Len(t, peer.subscribers, len(tt.expectedSubscribers)) 302 for _, subID := range tt.expectedSubscribers { 303 sub, ok := deps.Subscribers[subID] 304 assert.True(t, ok, "referenced subscriber id that does not exist %s", sub) 305 306 _, ok = peer.subscribers[sub] 307 assert.True(t, ok, "peer did not have reference to subscriber %v", sub) 308 } 309 }) 310 } 311 }