go.uber.org/yarpc@v1.72.1/peer/hostport/hostport_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  	"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  }