func runJSON(t crossdock.T, call call) { assert := crossdock.Assert(t) checks := crossdock.Checks(t) headers := map[string]string{ "hello": "json", } token := random.String(5) resp, respHeaders, err := jsonCall(call, headers, token) if checks.NoError(err, "json: call failed") { assert.Equal(token, resp.Token, "body echoed") respHeaders = internal.RemoveVariableMapKeys(respHeaders) assert.Equal(headers, respHeaders, "headers echoed") } }
func runJSON(t crossdock.T, dispatcher yarpc.Dispatcher) { assert := crossdock.Assert(t) checks := crossdock.Checks(t) headers := yarpc.NewHeaders().With("hello", "json") token := random.String(5) resBody, resMeta, err := jsonCall(dispatcher, headers, token) if skipOnConnRefused(t, err) { return } if checks.NoError(err, "json: call failed") { assert.Equal(token, resBody, "body echoed") resHeaders := internal.RemoveVariableHeaderKeys(resMeta.Headers()) assert.Equal(headers, resHeaders, "headers echoed") } }
// Thrift implements the 'thrift' behavior. func Thrift(t crossdock.T) { t = createEchoT("thrift", t) fatals := crossdock.Fatals(t) dispatcher := disp.Create(t) fatals.NoError(dispatcher.Start(), "could not start Dispatcher") defer dispatcher.Stop() client := echoclient.New(dispatcher.Channel("yarpc-test")) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() token := random.String(5) pong, _, err := client.Echo(ctx, nil, &echo.Ping{Beep: token}) crossdock.Fatals(t).NoError(err, "call to Echo::echo failed: %v", err) crossdock.Assert(t).Equal(token, pong.Boop, "server said: %v", pong.Boop) }
func runThrift(t crossdock.T, call call) { assert := crossdock.Assert(t) checks := crossdock.Checks(t) headers := map[string]string{ "hello": "thrift", } token := random.String(5) client := thrift.NewClient(call.Channel, serverName, &thrift.ClientOptions{HostPort: call.ServerHostPort}) resp, respHeaders, err := thriftCall(client, headers, token) if checks.NoError(err, "thrift: call failed") { assert.Equal(token, resp.Boop, "body echoed") respHeaders = internal.RemoveVariableMapKeys(respHeaders) assert.Equal(headers, respHeaders, "headers echoed") } runGauntlet(t, client) }
// JSON implements the 'json' behavior. func JSON(t crossdock.T) { t = createEchoT("json", t) fatals := crossdock.Fatals(t) dispatcher := disp.Create(t) fatals.NoError(dispatcher.Start(), "could not start Dispatcher") defer dispatcher.Stop() client := json.New(dispatcher.Channel("yarpc-test")) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() var response jsonEcho token := random.String(5) _, err := client.Call( ctx, yarpc.NewReqMeta().Procedure("echo"), &jsonEcho{Token: token}, &response, ) crossdock.Fatals(t).NoError(err, "call to echo failed: %v", err) crossdock.Assert(t).Equal(token, response.Token, "server said: %v", response.Token) }
func runThrift(t crossdock.T, dispatcher yarpc.Dispatcher) { assert := crossdock.Assert(t) checks := crossdock.Checks(t) headers := yarpc.NewHeaders().With("hello", "thrift") token := random.String(5) resBody, resMeta, err := thriftCall(dispatcher, headers, token) if skipOnConnRefused(t, err) { return } if checks.NoError(err, "thrift: call failed") { assert.Equal(token, resBody, "body echoed") resHeaders := internal.RemoveVariableHeaderKeys(resMeta.Headers()) assert.Equal(headers, resHeaders, "headers echoed") } t.Tag("server", t.Param(params.Server)) gauntlet.RunGauntlet(t, gauntlet.Config{ Dispatcher: dispatcher, ServerName: serverName, }) }
// Run runs the headers behavior func Run(t crossdock.T) { t = createHeadersT(t) fatals := crossdock.Fatals(t) assert := crossdock.Assert(t) checks := crossdock.Checks(t) dispatcher := disp.Create(t) fatals.NoError(dispatcher.Start(), "could not start Dispatcher") defer dispatcher.Stop() var caller headerCaller encoding := t.Param(params.Encoding) switch encoding { case "raw": caller = rawCaller{raw.New(dispatcher.Channel("yarpc-test"))} case "json": caller = jsonCaller{json.New(dispatcher.Channel("yarpc-test"))} case "thrift": caller = thriftCaller{echoclient.New(dispatcher.Channel("yarpc-test"))} default: fatals.Fail("", "unknown encoding %q", encoding) } token1 := random.String(10) token2 := random.String(10) tests := []struct { desc string give yarpc.Headers want yarpc.Headers }{ { "valid headers", yarpc.NewHeaders().With("token1", token1).With("token2", token2), yarpc.NewHeaders().With("token1", token1).With("token2", token2), }, { "non-string values", yarpc.NewHeaders().With("token", "42"), yarpc.NewHeaders().With("token", "42"), }, { "empty strings", yarpc.NewHeaders().With("token", ""), yarpc.NewHeaders().With("token", ""), }, { "no headers", yarpc.Headers{}, yarpc.NewHeaders(), }, { "empty map", yarpc.NewHeaders(), yarpc.NewHeaders(), }, { "varying casing", yarpc.NewHeaders().With("ToKeN1", token1).With("tOkEn2", token2), yarpc.NewHeaders().With("token1", token1).With("token2", token2), }, { "http header conflict", yarpc.NewHeaders().With("Rpc-Procedure", "does not exist"), yarpc.NewHeaders().With("rpc-procedure", "does not exist"), }, { "mixed case value", yarpc.NewHeaders().With("token", "MIXED case Value"), yarpc.NewHeaders().With("token", "MIXED case Value"), }, } for _, tt := range tests { got, err := caller.Call(tt.give) if checks.NoError(err, "%v: call failed", tt.desc) { gotHeaders := internal.RemoveVariableHeaderKeys(got) assert.Equal(tt.want, gotHeaders, "%v: returns valid headers", tt.desc) } } }
func getRandomID() string { return random.String(10) }
func runGauntlet(t crossdock.T, clientt thrift.TChanClient) { checks := crossdock.Checks(t) token := random.String(5) bytesToken := random.Bytes(1) tests := []gauntlet.TT{ { Function: "TestBinary", Give: []interface{}{bytesToken}, Want: bytesToken, }, { Function: "TestByte", Give: []interface{}{int8(42)}, Want: int8(42), }, { Function: "TestDouble", Give: []interface{}{float64(12.34)}, Want: float64(12.34), }, { Function: "TestEnum", Details: "MyNumberz", Give: []interface{}{gauntlet_tchannel.Numberz(gauntlet_tchannel.MyNumberz)}, Want: gauntlet_tchannel.Numberz(gauntlet_tchannel.MyNumberz), }, { Function: "TestEnum", Details: "NumberzThree", Give: []interface{}{gauntlet_tchannel.Numberz_THREE}, Want: gauntlet_tchannel.Numberz_THREE, }, { Function: "TestEnum", Details: "unrecognized Numberz", Give: []interface{}{gauntlet_tchannel.Numberz(42)}, Want: gauntlet_tchannel.Numberz(42), }, { Function: "TestException", Details: "Xception", Give: []interface{}{"Xception"}, WantError: &gauntlet_tchannel.Xception{ ErrorCode: ptr.Int32(1001), Message: ptr.String("Xception"), }, }, { Function: "TestException", Details: "TException", Give: []interface{}{"TException"}, WantErrorLike: `UnexpectedError: error for procedure "ThriftTest::testException" of service "yarpc-test": great sadness`, }, { Function: "TestException", Details: "no error", Give: []interface{}{"yolo"}, }, { Function: "TestI32", Give: []interface{}{int32(123)}, Want: int32(123), }, { Function: "TestI64", Give: []interface{}{int64(18934714)}, Want: int64(18934714), }, { Function: "TestInsanity", Give: []interface{}{ &gauntlet_tchannel.Insanity{ UserMap: map[gauntlet_tchannel.Numberz]gauntlet_tchannel.UserId{ gauntlet_tchannel.Numberz_THREE: gauntlet_tchannel.UserId(100), gauntlet_tchannel.Numberz(100): gauntlet_tchannel.UserId(200), }, Xtructs: []*gauntlet_tchannel.Xtruct{ {StringThing: ptr.String("0")}, {ByteThing: ptr.Int8(1)}, {I32Thing: ptr.Int32(2)}, {I64Thing: ptr.Int64(3)}, }, }, }, Want: map[gauntlet_tchannel.UserId]map[gauntlet_tchannel.Numberz]*gauntlet_tchannel.Insanity{ 1: { gauntlet_tchannel.Numberz_TWO: &gauntlet_tchannel.Insanity{ UserMap: map[gauntlet_tchannel.Numberz]gauntlet_tchannel.UserId{ gauntlet_tchannel.Numberz_THREE: gauntlet_tchannel.UserId(100), gauntlet_tchannel.Numberz(100): gauntlet_tchannel.UserId(200), }, Xtructs: []*gauntlet_tchannel.Xtruct{ {StringThing: ptr.String("0")}, {ByteThing: ptr.Int8(1)}, {I32Thing: ptr.Int32(2)}, {I64Thing: ptr.Int64(3)}, }, }, gauntlet_tchannel.Numberz_THREE: &gauntlet_tchannel.Insanity{ UserMap: map[gauntlet_tchannel.Numberz]gauntlet_tchannel.UserId{ gauntlet_tchannel.Numberz_THREE: gauntlet_tchannel.UserId(100), gauntlet_tchannel.Numberz(100): gauntlet_tchannel.UserId(200), }, Xtructs: []*gauntlet_tchannel.Xtruct{ {StringThing: ptr.String("0")}, {ByteThing: ptr.Int8(1)}, {I32Thing: ptr.Int32(2)}, {I64Thing: ptr.Int64(3)}, }, }, }, 2: { gauntlet_tchannel.Numberz_SIX: &gauntlet_tchannel.Insanity{}, }, }, }, { Function: "TestList", Give: []interface{}{[]int32{1, 2, 3}}, Want: []int32{1, 2, 3}, }, { Function: "TestMap", Give: []interface{}{map[int32]int32{1: 2, 3: 4, 5: 6}}, Want: map[int32]int32{1: 2, 3: 4, 5: 6}, }, { Function: "TestMapMap", Give: []interface{}{int32(42)}, Want: map[int32]map[int32]int32{ -4: { -4: -4, -3: -3, -2: -2, -1: -1, }, 4: { 1: 1, 2: 2, 3: 3, 4: 4, }, }, }, { Function: "TestMulti", Give: []interface{}{ int8(100), int32(200), int64(300), map[int16]string{1: "1", 2: "2", 3: "3"}, gauntlet_tchannel.Numberz_EIGHT, gauntlet_tchannel.UserId(42), }, Want: &gauntlet_tchannel.Xtruct{ StringThing: ptr.String("Hello2"), ByteThing: ptr.Int8(100), I32Thing: ptr.Int32(200), I64Thing: ptr.Int64(300), }, }, { Function: "TestMultiException", Details: "Xception", Give: []interface{}{"Xception", "foo"}, WantError: &gauntlet_tchannel.Xception{ ErrorCode: ptr.Int32(1001), Message: ptr.String("This is an Xception"), }, }, { Function: "TestMultiException", Details: "Xception2", Give: []interface{}{"Xception2", "foo"}, WantError: &gauntlet_tchannel.Xception2{ ErrorCode: ptr.Int32(2002), StructThing: &gauntlet_tchannel.Xtruct{StringThing: ptr.String("foo")}, }, }, { Function: "TestMultiException", Details: "no error", Give: []interface{}{"hello", "foo"}, Want: &gauntlet_tchannel.Xtruct{StringThing: ptr.String("foo")}, }, { Function: "TestNest", Give: []interface{}{ &gauntlet_tchannel.Xtruct2{ ByteThing: ptr.Int8(-1), I32Thing: ptr.Int32(-1234), StructThing: &gauntlet_tchannel.Xtruct{ StringThing: ptr.String("0"), ByteThing: ptr.Int8(1), I32Thing: ptr.Int32(2), I64Thing: ptr.Int64(3), }, }, }, Want: &gauntlet_tchannel.Xtruct2{ ByteThing: ptr.Int8(-1), I32Thing: ptr.Int32(-1234), StructThing: &gauntlet_tchannel.Xtruct{ StringThing: ptr.String("0"), ByteThing: ptr.Int8(1), I32Thing: ptr.Int32(2), I64Thing: ptr.Int64(3), }, }, }, { Function: "TestSet", Give: []interface{}{ map[int32]bool{ 1: true, 2: true, -1: true, -2: true, }, }, Want: map[int32]bool{ 1: true, 2: true, -1: true, -2: true, }, }, { Function: "TestString", Give: []interface{}{token}, Want: token, }, { Function: "TestStringMap", Give: []interface{}{ map[string]string{ "foo": "bar", "hello": "world", }, }, Want: map[string]string{ "foo": "bar", "hello": "world", }, }, { Function: "TestStruct", Give: []interface{}{ &gauntlet_tchannel.Xtruct{ StringThing: ptr.String("0"), ByteThing: ptr.Int8(1), I32Thing: ptr.Int32(2), I64Thing: ptr.Int64(3), }, }, Want: &gauntlet_tchannel.Xtruct{ StringThing: ptr.String("0"), ByteThing: ptr.Int8(1), I32Thing: ptr.Int32(2), I64Thing: ptr.Int64(3), }, }, { Function: "TestTypedef", Give: []interface{}{gauntlet_tchannel.UserId(42)}, Want: gauntlet_tchannel.UserId(42), }, { Function: "TestVoid", Give: []interface{}{}, }, { Service: "SecondService", Function: "BlahBlah", Give: []interface{}{}, }, { Service: "SecondService", Function: "SecondtestString", Give: []interface{}{"hello"}, Want: "hello", }, } for _, tt := range tests { desc := gauntlet.BuildDesc(tt) client := buildClient(t, desc, tt.Service, clientt) f := client.MethodByName(tt.Function) if !checks.True(f.IsValid(), "%v: invalid function", desc) { continue } ctx, cancel := thrift.NewContext(time.Second) defer cancel() args := []reflect.Value{reflect.ValueOf(ctx)} if give, ok := gauntlet.BuildArgs(t, desc, f.Type(), tt.Give, 1); ok { args = append(args, give...) } else { continue } got, err := extractCallResponse(t, desc, f.Call(args)) if isUnrecognizedProcedure(err) { t.Skipf("%v: procedure not defined", desc) continue } gauntlet.Assert(t, tt, desc, got, err) } }