go.uber.org/yarpc@v1.72.1/peer/hostport/peeraction_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 hostport 22 23 import ( 24 "fmt" 25 "sync" 26 "testing" 27 "time" 28 29 "github.com/stretchr/testify/assert" 30 "go.uber.org/yarpc/api/peer" 31 "go.uber.org/yarpc/internal/testtime" 32 ) 33 34 // There are no actual tests in this file, it contains a series of helper methods 35 // for testing hostport.Peers 36 37 // Dependences are passed through all the PeerActions in order to pass certain 38 // state in between Actions 39 type Dependencies struct { 40 Subscribers map[string]peer.Subscriber 41 } 42 43 // PeerAction defines actions that can be applied on a hostport.Peer 44 type PeerAction interface { 45 Apply(*testing.T, *Peer, *Dependencies) 46 } 47 48 // StartStopReqAction will run a StartRequest and (optionally) EndRequest 49 type StartStopReqAction struct { 50 Stop bool 51 } 52 53 // Apply will run StartRequest and (optionally) EndRequest 54 func (sa StartStopReqAction) Apply(t *testing.T, p *Peer, d *Dependencies) { 55 p.StartRequest() 56 if sa.Stop { 57 p.EndRequest() 58 } 59 } 60 61 // SetStatusAction will run a SetStatus on a Peer 62 type SetStatusAction struct { 63 InputStatus peer.ConnectionStatus 64 } 65 66 // Apply will run SetStatus on the Peer 67 func (sa SetStatusAction) Apply(t *testing.T, p *Peer, d *Dependencies) { 68 p.SetStatus(sa.InputStatus) 69 70 assert.Equal(t, sa.InputStatus, p.Status().ConnectionStatus) 71 } 72 73 // SubscribeAction will run an Subscribe on a Peer 74 type SubscribeAction struct { 75 // SubscriberID is a unique identifier for a subscriber that is 76 // contained in the Dependencies object passed in Apply 77 SubscriberID string 78 79 // ExpectedSubCount is the number of subscribers on the Peer after 80 // the subscription 81 ExpectedSubCount int 82 } 83 84 // Apply will run Subscribe on a Peer 85 func (sa SubscribeAction) Apply(t *testing.T, p *Peer, d *Dependencies) { 86 sub, ok := d.Subscribers[sa.SubscriberID] 87 assert.True(t, ok, "referenced a subscriberID that does not exist %s", sa.SubscriberID) 88 89 p.Subscribe(sub) 90 91 assert.Equal(t, sa.ExpectedSubCount, p.NumSubscribers()) 92 } 93 94 // UnsubscribeAction will run Unsubscribe on a Peer 95 type UnsubscribeAction struct { 96 // SubscriberID is a unique identifier for a subscriber that is 97 // contained in the Dependencies object passed in Apply 98 SubscriberID string 99 100 // ExpectedErrType is the type of error that is expected to be returned 101 // from Unsubscribe 102 ExpectedErrType error 103 104 // ExpectedSubCount is the number of subscribers on the Peer after 105 // the subscription 106 ExpectedSubCount int 107 } 108 109 // Apply will run Unsubscribe from the Peer and assert on the result 110 func (ua UnsubscribeAction) Apply(t *testing.T, p *Peer, d *Dependencies) { 111 sub, ok := d.Subscribers[ua.SubscriberID] 112 assert.True(t, ok, "referenced a subscriberID that does not exist %s", ua.SubscriberID) 113 114 err := p.Unsubscribe(sub) 115 116 assert.Equal(t, ua.ExpectedSubCount, p.NumSubscribers()) 117 if err != nil { 118 assert.IsType(t, ua.ExpectedErrType, err) 119 } else { 120 assert.Nil(t, ua.ExpectedErrType) 121 } 122 } 123 124 // PeerConcurrentAction will run a series of actions in parallel 125 type PeerConcurrentAction struct { 126 Actions []PeerAction 127 Wait time.Duration 128 } 129 130 // Apply runs all the ConcurrentAction's actions in goroutines with a delay of `Wait` 131 // between each action. Returns when all actions have finished executing 132 func (a PeerConcurrentAction) Apply(t *testing.T, p *Peer, d *Dependencies) { 133 var wg sync.WaitGroup 134 135 wg.Add(len(a.Actions)) 136 for _, action := range a.Actions { 137 go func(ac PeerAction) { 138 defer wg.Done() 139 ac.Apply(t, p, d) 140 }(action) 141 142 if a.Wait > 0 { 143 testtime.Sleep(a.Wait) 144 } 145 } 146 147 wg.Wait() 148 } 149 150 // ApplyPeerActions runs all the PeerActions on the Peer 151 func ApplyPeerActions(t *testing.T, p *Peer, actions []PeerAction, d *Dependencies) { 152 for i, action := range actions { 153 t.Run(fmt.Sprintf("action #%d: %T", i, action), func(t *testing.T) { 154 action.Apply(t, p, d) 155 }) 156 } 157 }