Пример #1
0
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)
}
Пример #2
0
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())
		}
	}
}
Пример #3
0
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())
		}
	}
}
Пример #4
0
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")
		}
	}
}