func TestCallOnewayFailure(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() ctx := context.Background() caller := "caller" service := "service" procedure := "procedure" body := []byte{1, 2, 3} outbound := transporttest.NewMockOnewayOutbound(mockCtrl) client := New(channel.MultiOutbound(caller, service, transport.Outbounds{ Oneway: outbound, })) outbound.EXPECT().CallOneway(gomock.Any(), transporttest.NewRequestMatcher(t, &transport.Request{ Service: service, Caller: caller, Procedure: procedure, Encoding: Encoding, Body: bytes.NewReader(body), }), ).Return(nil, errors.New("some error")) _, err := client.CallOneway( ctx, yarpc.NewReqMeta().Procedure(procedure), body) assert.Error(t, err) }
func TestClientOneway(t *testing.T) { caller, service, procedure := "caller", "MyService", "someMethod" tests := []struct { desc string giveRequestBody envelope.Enveloper // outgoing request body clientOptions []ClientOption expectCall bool // whether outbound.Call is expected wantRequestEnvelope *wire.Envelope // expect EncodeEnveloped(x) wantRequestBody *wire.Value // expect Encode(x) wantError string // whether an error is expected }{ { desc: "happy case", giveRequestBody: fakeEnveloper(wire.Call), clientOptions: []ClientOption{Enveloped}, expectCall: true, wantRequestEnvelope: &wire.Envelope{ Name: procedure, SeqID: 1, Type: wire.Call, Value: wire.NewValueStruct(wire.Struct{}), }, }, { desc: "happy case without enveloping", giveRequestBody: fakeEnveloper(wire.Call), expectCall: true, wantRequestBody: valueptr(wire.NewValueStruct(wire.Struct{})), }, { desc: "wrong envelope type for request", giveRequestBody: fakeEnveloper(wire.Reply), clientOptions: []ClientOption{Enveloped}, wantError: `failed to encode "thrift" request body for procedure ` + `"MyService::someMethod" of service "MyService": unexpected envelope type: Reply`, }, } for _, tt := range tests { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockProtocol(mockCtrl) bodyBytes := []byte("irrelevant") if tt.wantRequestEnvelope != nil { proto.EXPECT().EncodeEnveloped(*tt.wantRequestEnvelope, gomock.Any()). Do(func(_ wire.Envelope, w io.Writer) { _, err := w.Write(bodyBytes) require.NoError(t, err, "Write() failed") }).Return(nil) } if tt.wantRequestBody != nil { proto.EXPECT().Encode(*tt.wantRequestBody, gomock.Any()). Do(func(_ wire.Value, w io.Writer) { _, err := w.Write(bodyBytes) require.NoError(t, err, "Write() failed") }).Return(nil) } ctx := context.Background() onewayOutbound := transporttest.NewMockOnewayOutbound(mockCtrl) requestMatcher := transporttest.NewRequestMatcher(t, &transport.Request{ Caller: caller, Service: service, Encoding: Encoding, Procedure: procedureName(service, procedure), Body: bytes.NewReader(bodyBytes), }) if tt.expectCall { if tt.wantError != "" { onewayOutbound. EXPECT(). CallOneway(ctx, requestMatcher). Return(nil, errors.New(tt.wantError)) } else { onewayOutbound. EXPECT(). CallOneway(ctx, requestMatcher). Return(&successAck{}, nil) } } opts := tt.clientOptions opts = append(opts, Protocol(proto)) c := New(Config{ Service: service, Channel: channel.MultiOutbound(caller, service, transport.Outbounds{ Oneway: onewayOutbound, }), }, opts...) ack, err := c.CallOneway(ctx, nil, tt.giveRequestBody) if tt.wantError != "" { if assert.Error(t, err, "%v: expected failure", tt.desc) { assert.Contains(t, err.Error(), tt.wantError, "%v: error mismatch", tt.desc) } } else { assert.NoError(t, err, "%v: expected success", tt.desc) assert.Equal(t, "success", ack.String()) } } }
func TestCallOneway(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() ctx := context.Background() caller := "caller" service := "service" tests := []struct { procedure string headers yarpc.Headers body []byte wantErr string wantHeaders yarpc.Headers }{ { procedure: "foo", body: []byte{1, 2, 3}, }, { procedure: "headers", headers: yarpc.NewHeaders().With("x", "y"), body: []byte{}, }, } for _, tt := range tests { outbound := transporttest.NewMockOnewayOutbound(mockCtrl) client := New(channel.MultiOutbound(caller, service, transport.Outbounds{ Oneway: outbound, })) outbound.EXPECT().CallOneway(gomock.Any(), transporttest.NewRequestMatcher(t, &transport.Request{ Caller: caller, Service: service, Procedure: tt.procedure, Headers: transport.Headers(tt.headers), Encoding: Encoding, Body: bytes.NewReader(tt.body), }), ).Return(&successAck{}, nil) ack, err := client.CallOneway( ctx, yarpc.NewReqMeta().Procedure(tt.procedure).Headers(tt.headers), tt.body) if tt.wantErr != "" { if assert.Error(t, err) { assert.Equal(t, err.Error(), tt.wantErr) } } else { assert.Equal(t, "success", ack.String()) } } }
func TestCallOneway(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() ctx := context.Background() caller := "caller" service := "service" tests := []struct { procedure string headers yarpc.Headers body interface{} encodedRequest string // whether the outbound receives the request noCall bool wantErr string // error message }{ { procedure: "foo", body: []string{"foo", "bar"}, encodedRequest: `["foo","bar"]` + "\n", }, { procedure: "baz", body: func() {}, // funcs cannot be json.Marshal'ed noCall: true, wantErr: `failed to encode "json" request body for procedure "baz" of service "service"`, }, { procedure: "requestHeaders", headers: yarpc.NewHeaders().With("user-id", "42"), body: map[string]interface{}{}, encodedRequest: "{}\n", }, } for _, tt := range tests { outbound := transporttest.NewMockOnewayOutbound(mockCtrl) client := New(channel.MultiOutbound(caller, service, transport.Outbounds{ Oneway: outbound, })) if !tt.noCall { reqMatcher := transporttest.NewRequestMatcher(t, &transport.Request{ Caller: caller, Service: service, Procedure: tt.procedure, Encoding: Encoding, Headers: transport.Headers(tt.headers), Body: bytes.NewReader([]byte(tt.encodedRequest)), }) if tt.wantErr != "" { outbound. EXPECT(). CallOneway(gomock.Any(), reqMatcher). Return(nil, errors.New(tt.wantErr)) } else { outbound. EXPECT(). CallOneway(gomock.Any(), reqMatcher). Return(&successAck{}, nil) } } ack, err := client.CallOneway( ctx, yarpc.NewReqMeta().Procedure(tt.procedure).Headers(tt.headers), tt.body) if tt.wantErr != "" { assert.Error(t, err) assert.Contains(t, err.Error(), tt.wantErr) } else { assert.NoError(t, err, "") assert.Equal(t, ack.String(), "success") } } }