go.uber.org/yarpc@v1.72.1/api/peer/peertest/peers.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 peertest 22 23 import ( 24 "fmt" 25 "sync" 26 27 "github.com/golang/mock/gomock" 28 "go.uber.org/yarpc/api/peer" 29 ) 30 31 // MockPeerIdentifier is a small wrapper around the PeerIdentifier interfaces for a string 32 // unfortunately gomock + assert.Equal has difficulty seeing between mock objects of the same type. 33 type MockPeerIdentifier string 34 35 // Identifier returns a unique identifier for MockPeerIDs 36 func (pid MockPeerIdentifier) Identifier() string { 37 return string(pid) 38 } 39 40 // NewLightMockPeer returns a new MockPeer 41 func NewLightMockPeer(pid MockPeerIdentifier, conStatus peer.ConnectionStatus) *LightMockPeer { 42 return &LightMockPeer{ 43 MockPeerIdentifier: pid, 44 PeerStatus: peer.Status{ 45 ConnectionStatus: conStatus, 46 PendingRequestCount: 0, 47 }, 48 } 49 } 50 51 // LightMockPeer is a small simple wrapper around the Peer interface for mocking and changing 52 // a peer's attributes 53 // MockPeer is NOT thread safe 54 type LightMockPeer struct { 55 sync.Mutex 56 57 MockPeerIdentifier 58 59 PeerStatus peer.Status 60 } 61 62 // Status returns the Status Object of the MockPeer 63 func (p *LightMockPeer) Status() peer.Status { 64 return p.PeerStatus 65 } 66 67 // StartRequest is run when a Request starts 68 func (p *LightMockPeer) StartRequest() { 69 p.Lock() 70 p.PeerStatus.PendingRequestCount++ 71 p.Unlock() 72 } 73 74 // EndRequest should be run after a MockPeer request has finished 75 func (p *LightMockPeer) EndRequest() { 76 p.Lock() 77 p.PeerStatus.PendingRequestCount-- 78 p.Unlock() 79 } 80 81 // PeerIdentifierMatcher is used to match a Peer/PeerIdentifier by comparing 82 // The peer's .Identifier function with the Matcher string 83 type PeerIdentifierMatcher string 84 85 // Matches returns true of got is equivalent to the PeerIdentifier Matching string 86 func (pim PeerIdentifierMatcher) Matches(got interface{}) bool { 87 gotPID, ok := got.(peer.Identifier) 88 if !ok { 89 return false 90 } 91 return gotPID.Identifier() == string(pim) 92 } 93 94 // String returns a description of the matcher 95 func (pim PeerIdentifierMatcher) String() string { 96 return fmt.Sprintf("PeerIdentifierMatcher(%s)", string(pim)) 97 } 98 99 // CreatePeerIDs takes a slice of peerID strings and returns a slice of PeerIdentifiers 100 func CreatePeerIDs(peerIDStrs []string) []peer.Identifier { 101 pids := make([]peer.Identifier, 0, len(peerIDStrs)) 102 for _, id := range peerIDStrs { 103 pids = append(pids, MockPeerIdentifier(id)) 104 } 105 return pids 106 } 107 108 // ExpectPeerRetains registers expectations on a MockTransport to generate peers on the RetainPeer function 109 func ExpectPeerRetains( 110 transport *MockTransport, 111 availablePeerStrs []string, 112 unavailablePeerStrs []string, 113 ) map[string]*LightMockPeer { 114 peers := make(map[string]*LightMockPeer, len(availablePeerStrs)+len(unavailablePeerStrs)) 115 for _, peerStr := range availablePeerStrs { 116 p := NewLightMockPeer(MockPeerIdentifier(peerStr), peer.Available) 117 transport.EXPECT().RetainPeer(PeerIdentifierMatcher(peerStr), gomock.Any()).Return(p, nil) 118 peers[p.Identifier()] = p 119 } 120 for _, peerStr := range unavailablePeerStrs { 121 p := NewLightMockPeer(MockPeerIdentifier(peerStr), peer.Unavailable) 122 transport.EXPECT().RetainPeer(PeerIdentifierMatcher(peerStr), gomock.Any()).Return(p, nil) 123 peers[p.Identifier()] = p 124 } 125 return peers 126 } 127 128 // ExpectPeerRetainsWithError registers expectations on a MockTransport return errors 129 func ExpectPeerRetainsWithError( 130 transport *MockTransport, 131 peerStrs []string, 132 err error, // Will be returned from the MockTransport on the Retains of these Peers 133 ) { 134 for _, peerStr := range peerStrs { 135 transport.EXPECT().RetainPeer(PeerIdentifierMatcher(peerStr), gomock.Any()).Return(nil, err) 136 } 137 } 138 139 // ExpectPeerReleases registers expectations on a MockTransport to release peers through the ReleasePeer function 140 func ExpectPeerReleases( 141 transport *MockTransport, 142 peerStrs []string, 143 err error, 144 ) { 145 for _, peerStr := range peerStrs { 146 transport.EXPECT().ReleasePeer(PeerIdentifierMatcher(peerStr), gomock.Any()).Return(err) 147 } 148 }