@@ -73,7 +73,7 @@ func (s *assertingMultiService) Ping(ctx context.Context, ping *pb.PingRequest)
7373 }, nil
7474}
7575
76- func (s * assertingMultiService ) PingError (ctx context.Context , ping * pb.PingRequest ) (* pb.Empty , error ) {
76+ func (s * assertingMultiService ) PingError (ctx context.Context , ping * pb.PingRequest ) (* pb.EmptyReply , error ) {
7777 return nil , status .Errorf (codes .FailedPrecondition , "Userspace error." )
7878}
7979
@@ -168,10 +168,14 @@ func (b *assertingBackend) AppendInfo(resp []byte) ([]byte, error) {
168168}
169169
170170func (b * assertingBackend ) BuildError (err error ) ([]byte , error ) {
171- return proto .Marshal (& pb.ResponseMetadataPrepender {
172- Metadata : & pb.ResponseMetadata {
173- Hostname : fmt .Sprintf ("server%d" , b .i ),
174- UpstreamError : err .Error (),
171+ return proto .Marshal (& pb.EmptyReply {
172+ Response : []* pb.EmptyResponse {
173+ {
174+ Metadata : & pb.ResponseMetadata {
175+ Hostname : fmt .Sprintf ("server%d" , b .i ),
176+ UpstreamError : err .Error (),
177+ },
178+ },
175179 },
176180 })
177181}
@@ -216,6 +220,53 @@ func (s *MultiServiceSuite) TestPingEmptyCarriesClientMetadata() {
216220 s .Require ().Empty (expectedUpstreams )
217221}
218222
223+ func (s * MultiServiceSuite ) TestPingEmpty_StressTest () {
224+ for i := 0 ; i < 50 ; i ++ {
225+ s .TestPingEmptyCarriesClientMetadata ()
226+ }
227+ }
228+
229+ func (s * MultiServiceSuite ) TestPingCarriesServerHeadersAndTrailers () {
230+ headerMd := make (metadata.MD )
231+ trailerMd := make (metadata.MD )
232+ // This is an awkward calling convention... but meh.
233+ out , err := s .testClient .Ping (s .ctx , & pb.PingRequest {Value : "foo" }, grpc .Header (& headerMd ), grpc .Trailer (& trailerMd ))
234+ require .NoError (s .T (), err , "Ping should succeed without errors" )
235+
236+ s .Require ().Len (out .Response , numUpstreams )
237+ for _ , resp := range out .Response {
238+ s .Require ().Equal ("foo" , resp .Value )
239+ s .Require ().EqualValues (42 , resp .Counter )
240+
241+ // equal metadata set by proxy and server
242+ s .Require ().Equal (resp .Metadata .Hostname , resp .Server )
243+ }
244+
245+ assert .Contains (s .T (), headerMd , serverHeaderMdKey , "server response headers must contain server data" )
246+ assert .Len (s .T (), trailerMd , 1 , "server response trailers must contain server data" )
247+ }
248+
249+ func (s * MultiServiceSuite ) TestPingErrorPropagatesAppError () {
250+ out , err := s .testClient .PingError (s .ctx , & pb.PingRequest {Value : "foo" })
251+ s .Require ().NoError (err , "error should be encapsulated in the response" )
252+
253+ s .Require ().Len (out .Response , numUpstreams )
254+ for _ , resp := range out .Response {
255+ s .Require ().NotEmpty (resp .Metadata .UpstreamError )
256+ s .Require ().NotEmpty (resp .Metadata .Hostname )
257+ s .Assert ().Equal ("rpc error: code = FailedPrecondition desc = Userspace error." , resp .Metadata .UpstreamError )
258+ }
259+ }
260+
261+ func (s * MultiServiceSuite ) TestDirectorErrorIsPropagated () {
262+ // See SetupSuite where the StreamDirector has a special case.
263+ ctx := metadata .NewOutgoingContext (s .ctx , metadata .Pairs (rejectingMdKey , "true" ))
264+ _ , err := s .testClient .Ping (ctx , & pb.PingRequest {Value : "foo" })
265+ require .Error (s .T (), err , "Director should reject this RPC" )
266+ assert .Equal (s .T (), codes .PermissionDenied , status .Code (err ))
267+ assert .Equal (s .T (), "testing rejection" , status .Convert (err ).Message ())
268+ }
269+
219270func (s * MultiServiceSuite ) SetupTest () {
220271 s .ctx , s .ctxCancel = context .WithTimeout (context .TODO (), 120 * time .Second )
221272}
0 commit comments