go.uber.org/yarpc@v1.72.1/api/middleware/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 middleware_test
    22  
    23  import (
    24  	"bytes"
    25  	"context"
    26  	"io/ioutil"
    27  	"testing"
    28  
    29  	"go.uber.org/yarpc/api/middleware"
    30  	"go.uber.org/yarpc/api/middleware/middlewaretest"
    31  	"go.uber.org/yarpc/api/transport"
    32  	"go.uber.org/yarpc/api/transport/transporttest"
    33  	"go.uber.org/yarpc/encoding/raw"
    34  	"go.uber.org/yarpc/internal/testtime"
    35  
    36  	"github.com/golang/mock/gomock"
    37  	"github.com/stretchr/testify/assert"
    38  	"github.com/stretchr/testify/require"
    39  )
    40  
    41  func TestUnaryNopOutboundMiddleware(t *testing.T) {
    42  	mockCtrl := gomock.NewController(t)
    43  	defer mockCtrl.Finish()
    44  
    45  	o := transporttest.NewMockUnaryOutbound(mockCtrl)
    46  	wrappedO := middleware.ApplyUnaryOutbound(o, middleware.NopUnaryOutbound)
    47  
    48  	ctx, cancel := context.WithTimeout(context.Background(), testtime.Second)
    49  	defer cancel()
    50  	req := &transport.Request{
    51  		Caller:    "somecaller",
    52  		Service:   "someservice",
    53  		Encoding:  raw.Encoding,
    54  		Procedure: "hello",
    55  		Body:      bytes.NewReader([]byte{1, 2, 3}),
    56  	}
    57  
    58  	res := &transport.Response{Body: ioutil.NopCloser(bytes.NewReader([]byte{4, 5, 6}))}
    59  	o.EXPECT().Call(ctx, req).Return(res, nil)
    60  
    61  	got, err := wrappedO.Call(ctx, req)
    62  	if assert.NoError(t, err) {
    63  		assert.Equal(t, res, got)
    64  	}
    65  }
    66  
    67  func TestOnewayNopOutboundMiddleware(t *testing.T) {
    68  	mockCtrl := gomock.NewController(t)
    69  	defer mockCtrl.Finish()
    70  
    71  	o := transporttest.NewMockOnewayOutbound(mockCtrl)
    72  	wrappedO := middleware.ApplyOnewayOutbound(o, middleware.NopOnewayOutbound)
    73  
    74  	ctx, cancel := context.WithTimeout(context.Background(), testtime.Second)
    75  	defer cancel()
    76  	req := &transport.Request{
    77  		Caller:    "somecaller",
    78  		Service:   "someservice",
    79  		Encoding:  raw.Encoding,
    80  		Procedure: "hello",
    81  		Body:      bytes.NewReader([]byte{1, 2, 3}),
    82  	}
    83  
    84  	o.EXPECT().CallOneway(ctx, req).Return(nil, nil)
    85  
    86  	got, err := wrappedO.CallOneway(ctx, req)
    87  	if assert.NoError(t, err) {
    88  		assert.Equal(t, nil, got)
    89  	}
    90  }
    91  
    92  func TestNilOutboundMiddleware(t *testing.T) {
    93  	ctrl := gomock.NewController(t)
    94  	defer ctrl.Finish()
    95  
    96  	t.Run("unary", func(t *testing.T) {
    97  		out := transporttest.NewMockUnaryOutbound(ctrl)
    98  		out.EXPECT().Start()
    99  
   100  		mw := middleware.ApplyUnaryOutbound(out, nil)
   101  		require.NoError(t, mw.Start())
   102  	})
   103  
   104  	t.Run("oneway", func(t *testing.T) {
   105  		out := transporttest.NewMockOnewayOutbound(ctrl)
   106  		out.EXPECT().Start()
   107  
   108  		mw := middleware.ApplyOnewayOutbound(out, nil)
   109  		require.NoError(t, mw.Start())
   110  	})
   111  }
   112  
   113  func TestOutboundMiddleware(t *testing.T) {
   114  	ctrl := gomock.NewController(t)
   115  	defer ctrl.Finish()
   116  
   117  	t.Run("unary", func(t *testing.T) {
   118  		out := transporttest.NewMockUnaryOutbound(ctrl)
   119  		mw := middlewaretest.NewMockUnaryOutbound(ctrl)
   120  		outWithMW := middleware.ApplyUnaryOutbound(out, mw)
   121  
   122  		// start
   123  		out.EXPECT().Start().Return(nil)
   124  		assert.NoError(t, outWithMW.Start(), "could not start outbound")
   125  
   126  		// transports
   127  		out.EXPECT().Transports()
   128  		outWithMW.Transports()
   129  
   130  		// is running
   131  		out.EXPECT().IsRunning().Return(true)
   132  		assert.True(t, outWithMW.IsRunning(), "expected outbound to be running")
   133  
   134  		// stop
   135  		out.EXPECT().Stop().Return(nil)
   136  		assert.NoError(t, outWithMW.Stop(), "unexpected error stopping outbound")
   137  	})
   138  
   139  	t.Run("oneway", func(t *testing.T) {
   140  		out := transporttest.NewMockOnewayOutbound(ctrl)
   141  		mw := middlewaretest.NewMockOnewayOutbound(ctrl)
   142  		outWithMW := middleware.ApplyOnewayOutbound(out, mw)
   143  
   144  		// start
   145  		out.EXPECT().Start().Return(nil)
   146  		assert.NoError(t, outWithMW.Start(), "could not start outbound")
   147  
   148  		// transports
   149  		out.EXPECT().Transports()
   150  		outWithMW.Transports()
   151  
   152  		// is running
   153  		out.EXPECT().IsRunning().Return(true)
   154  		assert.True(t, outWithMW.IsRunning(), "expected outbound to be running")
   155  
   156  		// stop
   157  		out.EXPECT().Stop().Return(nil)
   158  		assert.NoError(t, outWithMW.Stop(), "unexpected error stopping outbound")
   159  	})
   160  }
   161  
   162  func TestStreamNopOutboundMiddleware(t *testing.T) {
   163  	mockCtrl := gomock.NewController(t)
   164  	defer mockCtrl.Finish()
   165  
   166  	o := transporttest.NewMockStreamOutbound(mockCtrl)
   167  	wrappedO := middleware.ApplyStreamOutbound(o, middleware.NopStreamOutbound)
   168  
   169  	ctx, cancel := context.WithTimeout(context.Background(), testtime.Second)
   170  	defer cancel()
   171  	req := &transport.StreamRequest{
   172  		Meta: &transport.RequestMeta{
   173  			Caller:    "somecaller",
   174  			Service:   "someservice",
   175  			Encoding:  raw.Encoding,
   176  			Procedure: "hello",
   177  		},
   178  	}
   179  
   180  	o.EXPECT().CallStream(ctx, req).Return(nil, nil)
   181  
   182  	got, err := wrappedO.CallStream(ctx, req)
   183  	if assert.NoError(t, err) {
   184  		assert.Nil(t, got)
   185  	}
   186  }
   187  
   188  func TestStreamDefaultsToOutboundWhenNil(t *testing.T) {
   189  	mockCtrl := gomock.NewController(t)
   190  	defer mockCtrl.Finish()
   191  
   192  	o := transporttest.NewMockStreamOutbound(mockCtrl)
   193  	wrappedO := middleware.ApplyStreamOutbound(o, nil)
   194  	assert.Equal(t, wrappedO, o)
   195  }
   196  
   197  func TestStreamMiddlewareCallsUnderlyingFunctions(t *testing.T) {
   198  	mockCtrl := gomock.NewController(t)
   199  	defer mockCtrl.Finish()
   200  
   201  	o := transporttest.NewMockStreamOutbound(mockCtrl)
   202  	o.EXPECT().Start().Times(1)
   203  	o.EXPECT().Stop().Times(1)
   204  	o.EXPECT().Transports().Times(1)
   205  	o.EXPECT().IsRunning().Times(1)
   206  	wrappedO := middleware.ApplyStreamOutbound(o, middleware.NopStreamOutbound)
   207  
   208  	wrappedO.IsRunning()
   209  	wrappedO.Transports()
   210  	wrappedO.Start()
   211  	wrappedO.Stop()
   212  }