go.uber.org/yarpc@v1.72.1/internal/request/validator_outbound_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 request
    22  
    23  import (
    24  	"context"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/golang/mock/gomock"
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  	"go.uber.org/yarpc/api/transport"
    32  	"go.uber.org/yarpc/api/transport/transporttest"
    33  	"go.uber.org/yarpc/api/x/introspection"
    34  )
    35  
    36  func TestCall(t *testing.T) {
    37  	ctrl := gomock.NewController(t)
    38  	defer ctrl.Finish()
    39  
    40  	ctx := context.Background()
    41  	req := newValidTestRequest()
    42  
    43  	t.Run("unary", func(t *testing.T) {
    44  		out := transporttest.NewMockUnaryOutbound(ctrl)
    45  		validatorOut := UnaryValidatorOutbound{UnaryOutbound: out}
    46  
    47  		ctx, cancel := context.WithTimeout(ctx, time.Second)
    48  		defer cancel()
    49  		out.EXPECT().Call(ctx, req).Return(nil, nil)
    50  
    51  		_, err := validatorOut.Call(ctx, req)
    52  		require.NoError(t, err)
    53  	})
    54  
    55  	t.Run("oneway", func(t *testing.T) {
    56  		out := transporttest.NewMockOnewayOutbound(ctrl)
    57  		validatorOut := OnewayValidatorOutbound{OnewayOutbound: out}
    58  
    59  		ctx, cancel := context.WithTimeout(ctx, time.Second)
    60  		defer cancel()
    61  		out.EXPECT().CallOneway(ctx, req).Return(nil, nil)
    62  
    63  		_, err := validatorOut.CallOneway(ctx, req)
    64  		require.NoError(t, err)
    65  	})
    66  }
    67  
    68  func TestCallErrors(t *testing.T) {
    69  	ctrl := gomock.NewController(t)
    70  	validatorOut := UnaryValidatorOutbound{UnaryOutbound: transporttest.NewMockUnaryOutbound(ctrl)}
    71  	validatorOutOneway := OnewayValidatorOutbound{OnewayOutbound: transporttest.NewMockOnewayOutbound(ctrl)}
    72  
    73  	tests := []struct {
    74  		name string
    75  		ctx  context.Context
    76  		req  *transport.Request
    77  	}{
    78  		{
    79  			name: "invalid context",
    80  			ctx:  context.Background(), // no deadline
    81  			req:  newValidTestRequest(),
    82  		},
    83  		{
    84  			name: "invalid request",
    85  			req:  &transport.Request{},
    86  		},
    87  	}
    88  
    89  	for _, tt := range tests {
    90  		t.Run("unary: "+tt.name, func(t *testing.T) {
    91  			res, err := validatorOut.Call(tt.ctx, tt.req)
    92  			assert.Nil(t, res)
    93  			assert.Error(t, err, "expected error from invalid request")
    94  		})
    95  
    96  		t.Run("oneway: "+tt.name, func(t *testing.T) {
    97  			ack, err := validatorOutOneway.CallOneway(tt.ctx, tt.req)
    98  			assert.Nil(t, ack)
    99  			assert.Error(t, err, "expected error from invalid request")
   100  		})
   101  
   102  		// Streaming requests without deadlines are valid, so this this test
   103  		// table does not apply.
   104  	}
   105  }
   106  
   107  func TestIntrospect(t *testing.T) {
   108  	ctrl := gomock.NewController(t)
   109  
   110  	t.Run("unary", func(t *testing.T) {
   111  		validatorOut := UnaryValidatorOutbound{UnaryOutbound: transporttest.NewMockUnaryOutbound(ctrl)}
   112  		assert.Equal(t, introspection.OutboundStatusNotSupported, validatorOut.Introspect())
   113  	})
   114  
   115  	t.Run("oneway", func(t *testing.T) {
   116  		validatorOut := OnewayValidatorOutbound{OnewayOutbound: transporttest.NewMockOnewayOutbound(ctrl)}
   117  		assert.Equal(t, introspection.OutboundStatusNotSupported, validatorOut.Introspect())
   118  	})
   119  
   120  	t.Run("stream", func(t *testing.T) {
   121  		validatorOut := StreamValidatorOutbound{StreamOutbound: transporttest.NewMockStreamOutbound(ctrl)}
   122  		assert.Equal(t, introspection.OutboundStatusNotSupported, validatorOut.Introspect())
   123  	})
   124  }
   125  
   126  func newValidTestRequest() *transport.Request {
   127  	return &transport.Request{
   128  		Service:   "service",
   129  		Procedure: "procedure",
   130  		Caller:    "caller",
   131  		Encoding:  "encoding",
   132  	}
   133  }
   134  
   135  func TestStreamValidate(t *testing.T) {
   136  	mockCtrl := gomock.NewController(t)
   137  	defer mockCtrl.Finish()
   138  
   139  	ctx := context.Background()
   140  	req := &transport.StreamRequest{
   141  		Meta: &transport.RequestMeta{
   142  			Service:   "service",
   143  			Procedure: "proc",
   144  			Caller:    "caller",
   145  			Encoding:  "raw",
   146  		},
   147  	}
   148  	stream, err := transport.NewClientStream(transporttest.NewMockStreamCloser(mockCtrl))
   149  	require.NoError(t, err)
   150  
   151  	out := transporttest.NewMockStreamOutbound(mockCtrl)
   152  	out.EXPECT().CallStream(ctx, req).Times(1).Return(stream, nil)
   153  
   154  	validator := StreamValidatorOutbound{StreamOutbound: out}
   155  
   156  	gotStream, gotErr := validator.CallStream(ctx, req)
   157  
   158  	assert.NoError(t, gotErr)
   159  	assert.Equal(t, stream, gotStream)
   160  }
   161  
   162  func TestStreamValidateError(t *testing.T) {
   163  	mockCtrl := gomock.NewController(t)
   164  	defer mockCtrl.Finish()
   165  
   166  	ctx := context.Background()
   167  	req := &transport.StreamRequest{
   168  		Meta: &transport.RequestMeta{
   169  			Service:  "service",
   170  			Caller:   "caller",
   171  			Encoding: "raw",
   172  		},
   173  	}
   174  
   175  	out := transporttest.NewMockStreamOutbound(mockCtrl)
   176  
   177  	validator := StreamValidatorOutbound{StreamOutbound: out}
   178  
   179  	_, gotErr := validator.CallStream(ctx, req)
   180  
   181  	assert.Error(t, gotErr)
   182  }