示例#1
0
文件: json.go 项目: yarpc/yarpc-go
func jsonCall(call call, headers map[string]string, token string) (jsonResp, map[string]string, error) {
	peer := call.Channel.Peers().Add(call.ServerHostPort)

	ctx, cancel := json.NewContext(time.Second)
	ctx = json.WithHeaders(ctx, headers)
	defer cancel()

	var response jsonResp
	err := json.CallPeer(ctx, peer, serverName, "echo", &jsonResp{Token: token}, &response)
	return response, ctx.ResponseHeaders(), err
}
示例#2
0
// Run exercises a YARPC server with outbound TChannel requests from a rigged
// client and validates behavior that might only be visible to a TChannel
// client without the YARPC abstraction interposed, typically errors.
func Run(t crossdock.T) {
	fatals := crossdock.Fatals(t)
	assert := crossdock.Assert(t)

	tests := []test{
		{
			name:      "happy path",
			procedure: "echo",
			body:      []byte("{}"),
			headers:   []byte("{}"),
			validate: func(res3 []byte, isAppErr bool, err error) {
				assert.NoError(err, "is not error")
				assert.False(isAppErr, "malformed body must not be application error")
			},
		},
		{
			name:      "malformed body",
			procedure: "echo",
			body:      []byte(""),
			headers:   []byte("{}"),
			validate: func(res3 []byte, isAppErr bool, err error) {
				assert.Error(err, "is error")
				assert.False(isAppErr, "malformed body must not be application error")
				err, ok := err.(tchannel.SystemError)
				assert.True(ok, "malformed body must produce system error")
				if !ok {
					return
				}
				code := tchannel.GetSystemErrorCode(err)
				assert.Contains(err.Error(), `failed to decode "json"`, "must mention failing to decode JSON in error message")
				assert.Equal(tchannel.ErrCodeBadRequest, code, "must produce bad request error")
			},
		},
		// TODO test invalid headers
		{
			name:      "missing procedure",
			procedure: "",
			body:      []byte{},
			headers:   []byte("{}"),
			validate: func(res3 []byte, isAppErr bool, err error) {
				assert.Error(err, "is error")
				assert.False(isAppErr, "missing procedure must not produce an application error")
				err, ok := err.(tchannel.SystemError)
				assert.True(ok, "missing procedure must produce system error")
				if !ok {
					return
				}
				code := tchannel.GetSystemErrorCode(err)
				assert.Equal(tchannel.ErrCodeBadRequest, code, "missing procedure must produce bad request error")
				assert.Contains(err.Error(), "missing procedure", "must mention missing procedure in error message")
			},
		},
		{
			name:      "invalid procedure",
			procedure: "no-such-procedure",
			body:      []byte{},
			headers:   []byte("{}"),
			validate: func(res3 []byte, isAppErr bool, err error) {
				assert.Error(err, "is error")
				assert.False(isAppErr, "no-such-procedure must not produce application error")
				err, ok := err.(tchannel.SystemError)
				assert.True(ok, "no-such-procedure must produce  system error")
				if !ok {
					return
				}
				code := tchannel.GetSystemErrorCode(err)
				assert.Equal(tchannel.ErrCodeBadRequest, code, "must produce bad request error")
				assert.Contains(err.Error(), `unrecognized procedure "no-such-procedure"`, "must mention unrecongized procedure in error message")
			},
		},
		{
			name:      "bad response",
			procedure: "bad-response",
			body:      []byte("{}"),
			headers:   []byte("{}"),
			validate: func(res3 []byte, isAppErr bool, err error) {
				assert.Error(err, "is error")
				assert.False(isAppErr, "bad-response must not produce an application error")
				err, ok := err.(tchannel.SystemError)
				assert.True(ok, "bad-response must produce system error")
				if !ok {
					return
				}
				code := tchannel.GetSystemErrorCode(err)
				assert.Equal(tchannel.ErrCodeUnexpected, code, "bad-response must produce unexpected error")
				assert.Contains(err.Error(), `failed to encode "json"`, "must mention failure to encode JSON in error message")
			},
		},
		{
			name:      "unexpected error",
			procedure: "unexpected-error",
			body:      []byte("{}"),
			headers:   []byte("{}"),
			validate: func(res3 []byte, isAppErr bool, err error) {
				assert.Error(err, "is error")
				assert.False(isAppErr, "unexpected-error procedure must not produce application error")
				err, ok := err.(tchannel.SystemError)
				assert.True(ok, "unexpected-error procedure must produce system error")
				code := tchannel.GetSystemErrorCode(err)
				assert.Equal(tchannel.ErrCodeUnexpected, code, "must produce transport error")
			},
		},
	}

	server := t.Param(params.Server)
	serverHostPort := fmt.Sprintf("%v:%v", server, serverPort)

	ch, err := tchannel.NewChannel(serviceName, nil)
	fatals.NoError(err, "could not create channel")

	peer := ch.Peers().Add(serverHostPort)

	for _, tt := range tests {
		var res2, res3 []byte
		var headers map[string]string

		t.Tag("case", tt.name)
		t.Tag("procedure", tt.procedure)

		ctx, cancel := json.NewContext(time.Second)
		defer cancel()

		ctx = json.WithHeaders(ctx, headers)

		encoding := "json"
		if tt.encoding != "" {
			encoding = tt.encoding
		}

		call, err := peer.BeginCall(
			ctx,
			serviceName,
			tt.procedure,
			&tchannel.CallOptions{Format: tchannel.Format(encoding)},
		)
		fatals.NoError(err, "could not begin call")

		err = tchannel.NewArgWriter(call.Arg2Writer()).Write(tt.headers)
		fatals.NoError(err, "could not write request headers")

		err = tchannel.NewArgWriter(call.Arg3Writer()).Write(tt.body)
		fatals.NoError(err, "could not write request body")

		err = tchannel.NewArgReader(call.Response().Arg2Reader()).Read(&res2)
		isAppErr := call.Response().ApplicationError()
		if err == nil {
			err = tchannel.NewArgReader(call.Response().Arg3Reader()).Read(&res3)
		}

		tt.validate(res3, isAppErr, err)
	}
}