예제 #1
0
// TestJSONResponse verifies that a request sent with JSON content and an accepting JSON response, does in fact yield a
// JSON response (from a proto handler)
func (suite *serverSuite) TestJSONResponse() {
	srv := suite.server
	srv.AddEndpoints(Endpoint{
		Name:     "dummy",
		Request:  new(testproto.DummyRequest),
		Response: new(testproto.DummyResponse),
		Handler: func(req mercury.Request) (mercury.Response, error) {
			request := req.Body().(*testproto.DummyRequest)
			return req.Response(&testproto.DummyResponse{
				Pong: request.Ping,
			}), nil
		}})

	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("dummy")
	req.SetBody(map[string]string{
		"ping": "json"})
	req.SetHeader(marshaling.AcceptHeader, "application/json")
	suite.Assert().NoError(tmsg.JSONMarshaler().MarshalBody(req))

	rsp, err := suite.trans.Send(req, time.Second)
	suite.Require().NoError(err)
	suite.Require().NotNil(rsp)

	suite.Assert().Equal("application/json", rsp.Headers()[marshaling.ContentTypeHeader])
	suite.Assert().Equal(`{"pong":"json"}`, string(rsp.Payload()))
}
예제 #2
0
// TestRouting verifies a registered endpoint receives messages destined for it, and that responses are sent
// appropriately
func (suite *serverSuite) TestRouting() {
	srv := suite.server
	srv.AddEndpoints(Endpoint{
		Name:     "dummy",
		Request:  new(testproto.DummyRequest),
		Response: new(testproto.DummyResponse),
		Handler: func(req mercury.Request) (mercury.Response, error) {
			request := req.Body().(*testproto.DummyRequest)
			rsp := req.Response(&testproto.DummyResponse{
				Pong: request.Ping,
			})
			rsp.SetHeader("X-Ping-Pong", request.Ping)
			return rsp, nil
		}})

	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("dummy")
	req.SetBody(&testproto.DummyRequest{
		Ping: "routing"})
	suite.Assert().NoError(tmsg.JSONMarshaler().MarshalBody(req))

	rsp, err := suite.trans.Send(req, time.Second)
	suite.Require().NoError(err)
	suite.Require().NotNil(rsp)

	suite.Require().NoError(tmsg.JSONUnmarshaler(new(testproto.DummyResponse)).UnmarshalPayload(rsp))
	suite.Require().NotNil(rsp.Body())
	suite.Require().IsType(new(testproto.DummyResponse), rsp.Body())
	response := rsp.Body().(*testproto.DummyResponse)
	suite.Assert().Equal("routing", response.Pong)
	suite.Assert().Equal("routing", rsp.Headers()["X-Ping-Pong"])
}
예제 #3
0
// TestErrorResponse tests that errors are serialised and returned to callers appropriately (as we are using the
// transport directly here, we actually get a response containing an error, not a transport error)
func (suite *serverSuite) TestErrorResponse() {
	srv := suite.server
	srv.AddEndpoints(Endpoint{
		Name:     "err",
		Request:  new(testproto.DummyRequest),
		Response: new(testproto.DummyResponse),
		Handler: func(req mercury.Request) (mercury.Response, error) {
			request := req.Body().(*testproto.DummyRequest)
			return nil, terrors.NotFound("", request.Ping, nil)
		}})

	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("err")
	req.SetBody(&testproto.DummyRequest{
		Ping: "Foo bar baz"})
	suite.Assert().NoError(tmsg.JSONMarshaler().MarshalBody(req))

	rsp_, err := suite.trans.Send(req, time.Second)
	suite.Assert().NoError(err)
	suite.Assert().NotNil(rsp_)
	rsp := mercury.FromTyphonResponse(rsp_)
	suite.Assert().True(rsp.IsError())

	errResponse := &pe.Error{}
	suite.Assert().NoError(json.Unmarshal(rsp.Payload(), errResponse))
	terr := terrors.Unmarshal(errResponse)
	suite.Require().NotNil(terr)
	suite.Assert().Equal("Foo bar baz", terr.Message, string(rsp.Payload()))
	suite.Assert().Equal(terrors.ErrNotFound, terr.Code)
}
예제 #4
0
// TestE2E verifies parent request IDs are properly set on child requests
func (suite *parentRequestIdMiddlewareSuite) TestE2E() {
	cli := client.
		NewClient().
		SetTransport(suite.trans).
		SetMiddleware([]client.ClientMiddleware{Middleware()})

	dummyOrigin := mercury.NewRequest()
	dummyOrigin.SetId("foobarbaz")
	ctx := context.WithValue(dummyOrigin.Context(), "Current-Service", testOriginServiceName)
	ctx = context.WithValue(ctx, "Current-Endpoint", "e2etest")
	dummyOrigin.SetContext(ctx)

	cli.Add(client.Call{
		Uid:      "call",
		Service:  testServiceName,
		Endpoint: "foo",
		Context:  dummyOrigin,
		Response: &testproto.DummyResponse{},
		Body:     &testproto.DummyRequest{}})
	cli.Execute()

	suite.Assert().NoError(cli.Errors().Combined())
	rsp := cli.Response("call")
	response := rsp.Body().(*testproto.DummyResponse)
	suite.Assert().NotEmpty(response.Pong)
	suite.Assert().Equal(response.Pong, rsp.Headers()[parentIdHeader])
}
예제 #5
0
// TestRoutingParallel sends a bunch of requests in parallel to different endpoints and checks that the responses match
// correctly. 200 workers, 100 requests each.
func (suite *serverSuite) TestRoutingParallel() {
	if testing.Short() {
		suite.T().Skip("Skipping TestRoutingParallel in short mode")
	}

	names := [...]string{"1", "2", "3"}
	srv := suite.server
	srv.AddEndpoints(
		Endpoint{
			Name:     names[0],
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				return req.Response(&testproto.DummyResponse{Pong: names[0]}), nil
			}},
		Endpoint{
			Name:     names[1],
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				return req.Response(&testproto.DummyResponse{Pong: names[1]}), nil
			}},
		Endpoint{
			Name:     names[2],
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				return req.Response(&testproto.DummyResponse{Pong: names[2]}), nil
			}})

	workers := 200
	wg := sync.WaitGroup{}
	wg.Add(workers)
	unmarshaler := tmsg.JSONUnmarshaler(new(testproto.DummyResponse))
	work := func(i int) {
		defer wg.Done()
		rng := rand.New(rand.NewSource(time.Now().UnixNano()))
		ep := names[rng.Int()%len(names)]
		for i := 0; i < 100; i++ {
			req := mercury.NewRequest()
			req.SetService(testServiceName)
			req.SetEndpoint(ep)
			req.SetBody(&testproto.DummyRequest{})
			suite.Assert().NoError(tmsg.JSONMarshaler().MarshalBody(req))

			rsp, err := suite.trans.Send(req, time.Second)
			suite.Require().NoError(err)
			suite.Require().NotNil(rsp)
			suite.Require().NoError(unmarshaler.UnmarshalPayload(rsp))
			response := rsp.Body().(*testproto.DummyResponse)
			suite.Assert().Equal(ep, response.Pong)
		}
	}

	for i := 0; i < workers; i++ {
		go work(i)
	}
	wg.Wait()
}
예제 #6
0
파일: message.go 프로젝트: mondough/mercury
func new2OldRequest(newReq typhon.Request) mercury.Request {
	req := mercury.NewRequest()
	req.SetService(newReq.Host)
	req.SetEndpoint(newReq.URL.Path)
	req.SetHeaders(fromHeader(newReq.Header))
	b, _ := newReq.BodyBytes(true)
	req.SetPayload(b)
	req.SetId(newReq.Header.Get(legacyIdHeader))
	req.SetContext(newReq)
	return req
}
예제 #7
0
파일: call.go 프로젝트: robmurtha/mercury
// Request yields a Request formed from this Call
func (c Call) Request() (mercury.Request, error) {
	req := mercury.NewRequest()
	req.SetService(c.Service)
	req.SetEndpoint(c.Endpoint)
	req.SetHeaders(c.Headers)
	if c.Context != nil {
		req.SetContext(c.Context)
	}
	if c.Body != nil {
		req.SetBody(c.Body)
		if err := c.marshaler().MarshalBody(req); err != nil {
			return nil, terrors.WrapWithCode(err, nil, terrors.ErrBadRequest)
		}
	}
	return req, nil
}
예제 #8
0
func main() {
	req := mercury.NewRequest()
	req.SetService("foo")
	req.SetEndpoint("Say.Hello")
	req.SetBody(&hello.Request{
		Name: "John",
	})
	tmsg.ProtoMarshaler().MarshalBody(req)
	trans := rabbit.NewTransport()
	rsp, err := trans.Send(req, time.Second)
	if err != nil {
		fmt.Println(err)
		return
	}
	tmsg.ProtoUnmarshaler(new(hello.Response)).UnmarshalPayload(rsp)

	fmt.Println(rsp.Body())
}
예제 #9
0
// TestEndpointNotFound tests that a Bad Request error is correctly returned on receiving an event for an unknown
// endpoing
func (suite *serverSuite) TestEndpointNotFound() {
	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("dummy")
	req.SetBody(&testproto.DummyRequest{
		Ping: "routing"})
	suite.Assert().NoError(tmsg.JSONMarshaler().MarshalBody(req))

	rsp_, err := suite.trans.Send(req, time.Second)
	rsp := mercury.FromTyphonResponse(rsp_)
	suite.Require().NoError(err)
	suite.Require().NotNil(rsp)
	suite.Assert().True(rsp.IsError())

	suite.Assert().NoError(tmsg.JSONUnmarshaler(new(pe.Error)).UnmarshalPayload(rsp))
	suite.Assert().IsType(new(pe.Error), rsp.Body())
	terr := terrors.Unmarshal(rsp.Body().(*pe.Error))
	suite.Assert().Equal(terrors.ErrBadRequest+".endpoint_not_found", terr.Code)
	suite.Assert().Contains(terr.Error(), "Endpoint not found")
}
예제 #10
0
// TestNilResponse tests that a nil response correctly returns a Response with an empty payload to the caller
func (suite *serverSuite) TestNilResponse() {
	srv := suite.server
	srv.AddEndpoints(Endpoint{
		Name:     "nil",
		Request:  new(testproto.DummyRequest),
		Response: new(testproto.DummyResponse),
		Handler: func(req mercury.Request) (mercury.Response, error) {
			return nil, nil
		}})

	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetBody(&testproto.DummyRequest{})
	suite.Assert().NoError(tmsg.JSONMarshaler().MarshalBody(req))
	req.SetEndpoint("nil")

	rsp, err := suite.trans.Send(req, time.Second)
	suite.Require().NoError(err)
	suite.Require().NotNil(rsp)
	suite.Assert().Len(rsp.Payload(), 0)
}
예제 #11
0
// TestJSON verifies a JSON request and response can be received from a protobuf handler
func (suite *clientServerSuite) TestJSON() {
	suite.server.AddEndpoints(
		server.Endpoint{
			Name:     "test",
			Request:  new(testproto.DummyRequest),
			Response: new(testproto.DummyResponse),
			Handler: func(req mercury.Request) (mercury.Response, error) {
				request := req.Body().(*testproto.DummyRequest)
				return req.Response(&testproto.DummyResponse{
					Pong: request.Ping,
				}), nil
			}})

	req := mercury.NewRequest()
	req.SetService(testServiceName)
	req.SetEndpoint("test")
	req.SetPayload([]byte(`{ "ping": "blah blah blah" }`))
	req.SetHeader(marshaling.ContentTypeHeader, "application/json")
	req.SetHeader(marshaling.AcceptHeader, "application/json")

	cl := client.NewClient().
		SetMiddleware(DefaultClientMiddleware()).
		AddRequest("call", req).
		SetTransport(suite.trans).
		SetTimeout(time.Second).
		Execute()

	suite.Assert().False(cl.Errors().Any())
	rsp := cl.Response("call")
	suite.Assert().NotNil(rsp)
	var body map[string]string
	suite.Assert().NoError(json.Unmarshal(rsp.Payload(), &body))
	suite.Assert().NotNil(body)
	suite.Assert().Equal(1, len(body))
	suite.Assert().Equal("blah blah blah", body["pong"])
}