go.uber.org/yarpc@v1.72.1/transport/tchannel/error_external_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 tchannel_test
    22  
    23  import (
    24  	"bytes"
    25  	"context"
    26  	"errors"
    27  	"net"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/require"
    33  	"github.com/uber/tchannel-go"
    34  	"go.uber.org/yarpc/api/transport"
    35  	ytchannel "go.uber.org/yarpc/transport/tchannel"
    36  	"go.uber.org/yarpc/yarpcerrors"
    37  )
    38  
    39  func TestResponseErrorMetaIntegration(t *testing.T) {
    40  	const networkErrMsg = "a network error!"
    41  
    42  	// use vanilla TChannel server to force return a system error
    43  	tchHandler := func(ctx context.Context, call *tchannel.InboundCall) {
    44  		networkErr := tchannel.NewSystemError(tchannel.ErrCodeNetwork, networkErrMsg)
    45  		require.NoError(t, call.Response().SendSystemError(networkErr), "failed to send system error")
    46  	}
    47  	server, err := tchannel.NewChannel("test", &tchannel.ChannelOptions{
    48  		Handler: tchannel.HandlerFunc(tchHandler),
    49  	})
    50  	require.NoError(t, err, "could not create TChannel channel")
    51  
    52  	listener, err := net.Listen("tcp", "127.0.0.1:0")
    53  	require.NoError(t, err, "failed to create listener")
    54  	server.Serve(listener)
    55  	defer server.Close()
    56  
    57  	// init client
    58  	clientTransport, err := ytchannel.NewTransport(ytchannel.ServiceName("foo"))
    59  	require.NoError(t, err, "failed to create TChannel client transport")
    60  	require.NoError(t, clientTransport.Start(), "could not start client transport")
    61  	defer func() { assert.NoError(t, clientTransport.Stop(), "did not cleanly shutdown client transport") }()
    62  
    63  	client := clientTransport.NewSingleOutbound(listener.Addr().String())
    64  	require.NoError(t, client.Start(), "could not start outbound")
    65  	defer func() { assert.NoError(t, client.Stop(), "did not cleanly shutdown outbound") }()
    66  
    67  	// call server
    68  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    69  	defer cancel()
    70  	_, err = client.Call(ctx, &transport.Request{
    71  		Service: "foo",
    72  		Body:    bytes.NewBufferString("bar"),
    73  	})
    74  	require.Error(t, err, "expected call failure")
    75  
    76  	// ensure this is still a `yarpcerrors.Status` error
    77  	require.True(t, yarpcerrors.IsStatus(err), "expected YARPC status error")
    78  	require.Equal(t, networkErrMsg, yarpcerrors.FromError(err).Message(), "unexpected 'yarpcerrors' error message")
    79  	require.Equal(t, networkErrMsg, errors.Unwrap(err).Error(), "unexpected unwrapped error message")
    80  	assert.IsType(t, &yarpcerrors.Status{}, err, "expected YARPC status type") // ensure type switching still works
    81  
    82  	// verify response meta
    83  	meta := ytchannel.GetResponseErrorMeta(err)
    84  	require.NotNil(t, meta, "unable to retrieve response meta")
    85  	assert.Equal(t, tchannel.ErrCodeNetwork.String(), meta.Code.String(), "unexpected response code")
    86  }