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  }