Example #1
0
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")
	}
}
Example #2
0
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")
	}
}
Example #3
0
// 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)
}
Example #4
0
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)
}
Example #5
0
// 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)
}
Example #6
0
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,
	})
}
Example #7
0
// 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)
		}
	}
}
Example #8
0
func getRandomID() string {
	return random.String(10)
}
Example #9
0
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)
	}
}