go.uber.org/yarpc@v1.72.1/transport/tchannel/tchannel_utils_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 22 23 import ( 24 "bytes" 25 "errors" 26 "io/ioutil" 27 28 "github.com/uber/tchannel-go" 29 ) 30 31 func readArgs(r tchannel.ArgReadable) (arg2, arg3 []byte, err error) { 32 err = tchannel.NewArgReader(r.Arg2Reader()).Read(&arg2) 33 if err != nil { 34 return 35 } 36 37 err = tchannel.NewArgReader(r.Arg3Reader()).Read(&arg3) 38 return 39 } 40 41 func writeArgs(w tchannel.ArgWritable, arg2, arg3 []byte) error { 42 if err := tchannel.NewArgWriter(w.Arg2Writer()).Write(arg2); err != nil { 43 return err 44 } 45 46 return tchannel.NewArgWriter(w.Arg3Writer()).Write(arg3) 47 } 48 49 // This file provides utilities to help test TChannel behavior used by 50 // multiple tests. 51 52 // bufferArgWriter is a Buffer that satisfies the tchannel.ArgWriter 53 // interface. 54 type bufferArgWriter struct{ bytes.Buffer } 55 56 func newBufferArgWriter() *bufferArgWriter { 57 return new(bufferArgWriter) 58 } 59 60 func (w *bufferArgWriter) Close() error { return nil } 61 func (w *bufferArgWriter) Flush() error { return nil } 62 63 // fakeInboundCall is a fake inboundCall that uses a responseRecorder to 64 // record responses. 65 // 66 // Provide nil for arg2 or arg3 to get Arg2Reader or Arg3Reader to fail. 67 type fakeInboundCall struct { 68 service string 69 caller string 70 method string 71 shardkey string 72 routingkey string 73 routingdelegate string 74 format tchannel.Format 75 arg2, arg3 []byte 76 resp inboundCallResponse 77 } 78 79 func (i *fakeInboundCall) ServiceName() string { return i.service } 80 func (i *fakeInboundCall) CallerName() string { return i.caller } 81 func (i *fakeInboundCall) MethodString() string { return i.method } 82 func (i *fakeInboundCall) ShardKey() string { return i.shardkey } 83 func (i *fakeInboundCall) RoutingKey() string { return i.routingkey } 84 func (i *fakeInboundCall) RoutingDelegate() string { return i.routingdelegate } 85 func (i *fakeInboundCall) Format() tchannel.Format { return i.format } 86 func (i *fakeInboundCall) Response() inboundCallResponse { return i.resp } 87 88 func (i *fakeInboundCall) Arg2Reader() (tchannel.ArgReader, error) { 89 if i.arg2 == nil { 90 return nil, errors.New("no arg2 provided") 91 } 92 return ioutil.NopCloser(bytes.NewReader(i.arg2)), nil 93 } 94 95 func (i *fakeInboundCall) Arg3Reader() (tchannel.ArgReader, error) { 96 if i.arg3 == nil { 97 return nil, errors.New("no arg3 provided") 98 } 99 return ioutil.NopCloser(bytes.NewReader(i.arg3)), nil 100 } 101 102 // recorder wraps the inboundCallResponse interface to mock errors from responseRecorder's 103 // methods during testing 104 type recorder interface { 105 inboundCallResponse 106 SystemError() error 107 } 108 109 // responseRecorder is a inboundCallResponse that records whatever is written 110 // to it. 111 // 112 // The recorder will throw an error if arg2 or arg3 are set to nil. 113 type responseRecorder struct { 114 arg2, arg3 *bufferArgWriter 115 systemErr error 116 applicationError bool 117 blackholed bool 118 } 119 120 func newResponseRecorder() *responseRecorder { 121 return &responseRecorder{ 122 arg2: newBufferArgWriter(), 123 arg3: newBufferArgWriter(), 124 } 125 } 126 127 func (rr *responseRecorder) Arg2Writer() (tchannel.ArgWriter, error) { 128 if rr.arg2 == nil { 129 return nil, errors.New("no arg2 provided") 130 } 131 return rr.arg2, nil 132 } 133 134 func (rr *responseRecorder) Arg3Writer() (tchannel.ArgWriter, error) { 135 if rr.arg3 == nil { 136 return nil, errors.New("no arg3 provided") 137 } 138 return rr.arg3, nil 139 } 140 141 func (rr *responseRecorder) SendSystemError(err error) error { 142 rr.systemErr = err 143 return nil 144 } 145 146 func (rr *responseRecorder) SystemError() error { 147 return rr.systemErr 148 } 149 150 func (rr *responseRecorder) SetApplicationError() error { 151 rr.applicationError = true 152 return nil 153 } 154 155 func (rr *responseRecorder) Blackhole() { 156 rr.blackholed = true 157 } 158 159 // faultyResponseRecorder mocks a SendSystemError to test logging behaviour 160 // inside tchannel.Handle 161 type faultyResponseRecorder struct{ responseRecorder } 162 163 func newFaultyResponseRecorder() recorder { 164 return &faultyResponseRecorder{} 165 } 166 167 func (fr *faultyResponseRecorder) SendSystemError(err error) error { 168 fr.systemErr = err 169 return errors.New("SendSystemError failure") 170 } 171 172 // faultyHandlerWriter mocks a responseWriter.Close() error to test logging behaviour 173 // inside tchannel.Handle. 174 type faultyHandlerWriter struct{ handlerWriter } 175 176 func newFaultyHandlerWriter(response inboundCallResponse, format tchannel.Format, headerCase headerCase) responseWriter { 177 return &faultyHandlerWriter{} 178 } 179 180 func (frw *faultyHandlerWriter) Close() error { 181 return errors.New("faultyHandlerWriter failed to close") 182 }