Example #1
0
func BenchmarkBothSerial(b *testing.B) {
	serverAddr, err := setupBenchServer()
	require.NoError(b, err, "setupBenchServer failed")

	opts := testutils.NewOpts().SetFramePool(tchannel.NewSyncFramePool())
	clientCh := testutils.NewClient(b, opts)
	for _, addr := range serverAddr {
		clientCh.Peers().Add(addr)
	}

	thriftClient := thrift.NewClient(clientCh, "bench-server", nil)
	client := gen.NewTChanSecondServiceClient(thriftClient)
	ctx, cancel := thrift.NewContext(10 * time.Millisecond)
	client.Echo(ctx, "make connection")
	cancel()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ctx, cancel := thrift.NewContext(10 * time.Millisecond)
		defer cancel()

		_, err := client.Echo(ctx, "hello world")
		if err != nil {
			b.Errorf("Echo failed: %v", err)
		}
	}
}
func TestMakeRemoteClient(t *testing.T) {
	rp := &mocks.Ringpop{}
	rp.On("RegisterListener", mock.Anything).Return()
	rp.On("Lookup", "hello").Return("127.0.0.1:3001")
	rp.On("WhoAmI").Return("127.0.0.1:3000")

	serviceImpl := &servicemocks.TChanRemoteService{}
	serviceImpl.On("RemoteCall", mock.Anything, "hello").Return(nil)
	ctx, _ := thrift.NewContext(0 * time.Second)

	ch, err := tchannel.NewChannel("remote", nil)
	assert.Equal(t, err, nil, "could not create tchannel")

	adapter, err := NewRingpopRemoteServiceAdapter(serviceImpl, rp, ch, RemoteServiceConfiguration{
		RemoteCall: &RemoteServiceRemoteCallConfiguration{
			Key: func(ctx thrift.Context, name string) (string, error) {
				return name, nil
			},
		},
	})

	tchanClient := &mocks.TChanClient{}
	tchanClient.On("Call", mock.Anything, "RemoteService", "RemoteCall", &RemoteServiceRemoteCallArgs{Name: "hello"}, mock.Anything).Return(true, nil)

	cf := adapter.(router.ClientFactory)
	remoteClient := cf.MakeRemoteClient(tchanClient).(TChanRemoteService)
	err = remoteClient.RemoteCall(ctx, "hello")
	assert.Equal(t, err, nil, "calling the remote client gave an error")

	tchanClient.AssertCalled(t, "Call", mock.Anything, "RemoteService", "RemoteCall", &RemoteServiceRemoteCallArgs{Name: "hello"}, mock.Anything)
}
func TestRingpopRemoteServiceAdapterCallRemote(t *testing.T) {
	rp := &mocks.Ringpop{}
	rp.On("RegisterListener", mock.Anything).Return()
	rp.On("Lookup", "hello").Return("127.0.0.1:3001", nil)
	rp.On("WhoAmI").Return("127.0.0.1:3000", nil)

	serviceImpl := &servicemocks.TChanRemoteService{}
	serviceImpl.On("RemoteCall", mock.Anything, "hello").Return(nil)
	ctx, _ := thrift.NewContext(0 * time.Second)

	ch, err := tchannel.NewChannel("remote", nil)
	assert.Equal(t, err, nil, "could not create tchannel")

	adapter, err := NewRingpopRemoteServiceAdapter(serviceImpl, rp, ch, RemoteServiceConfiguration{
		RemoteCall: &RemoteServiceRemoteCallConfiguration{
			Key: func(ctx thrift.Context, name string) (string, error) {
				return name, nil
			},
		},
	})
	assert.Equal(t, err, nil, "creation of adator gave an error")

	// Because it is not easily possible to stub a remote call we assert that the remote call failed.
	// If it didn't fail it is likely that the serviceImpl was called, which we assert that it isn't called either
	err = adapter.RemoteCall(ctx, "hello")
	assert.NotEqual(t, err, nil, "we expected an error from the remote call since it could not reach anything over the network")
	serviceImpl.AssertNotCalled(t, "RemoteCall", mock.Anything, "hello")
}
Example #4
0
func thriftCall(clientt thrift.TChanClient, headers map[string]string, token string) (*echo.Pong, map[string]string, error) {
	client := echo.NewTChanEchoClient(clientt)

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

	pong, err := client.Echo(ctx, &echo.Ping{Beep: token})
	return pong, ctx.ResponseHeaders(), err
}
Example #5
0
func TestSetForwardedHeader(t *testing.T) {
	ctx, _ := thrift.NewContext(0 * time.Second)
	ctx = SetForwardedHeader(ctx)
	if ctx.Headers()["ringpop-forwarded"] != "true" {
		t.Errorf("ringpop forwarding header is not set")
	}

	ctx, _ = thrift.NewContext(0 * time.Second)
	ctx = thrift.WithHeaders(ctx, map[string]string{
		"keep": "this key",
	})
	ctx = SetForwardedHeader(ctx)

	if ctx.Headers()["ringpop-forwarded"] != "true" {
		t.Errorf("ringpop forwarding header is not set if there were headers set already")
	}
	if ctx.Headers()["keep"] != "this key" {
		t.Errorf("ringpop forwarding header removed a header that was already present")
	}
}
Example #6
0
func TestHasForwardedHeader(t *testing.T) {
	ctx, _ := thrift.NewContext(0 * time.Second)
	if HasForwardedHeader(ctx) {
		t.Errorf("ringpop claimed that the forwarded header was set before it was set")
	}
	ctx = SetForwardedHeader(ctx)
	if !HasForwardedHeader(ctx) {
		t.Errorf("ringpop was not able to identify that the forwarded header was set")
	}

	ctx, _ = thrift.NewContext(0 * time.Second)
	ctx = thrift.WithHeaders(ctx, map[string]string{
		"keep": "this key",
	})
	if HasForwardedHeader(ctx) {
		t.Errorf("ringpop claimed that the forwarded header was set before it was set in the case of alread present headers")
	}
	ctx = SetForwardedHeader(ctx)
	if !HasForwardedHeader(ctx) {
		t.Errorf("ringpop was not able to identify that the forwarded header was set in the case of alread present headers")
	}
}
Example #7
0
// Discover queries Hyperbahn for a list of peers that are currently
// advertised with the specified service name.
func (c *Client) Discover(serviceName string) ([]string, error) {
	ctx, cancel := thrift.NewContext(time.Second)
	defer cancel()

	result, err := c.hyperbahnClient.Discover(ctx, &hyperbahn.DiscoveryQuery{ServiceName: serviceName})
	if err != nil {
		return nil, err
	}

	var hostPorts []string
	for _, peer := range result.GetPeers() {
		hostPorts = append(hostPorts, servicePeerToHostPort(peer))
	}

	return hostPorts, nil
}
Example #8
0
func makeCall(client gen.TChanSecondService) {
	ctx, cancel := thrift.NewContext(*timeout)
	defer cancel()

	arg := makeArg()
	started := time.Now()
	res, err := client.Echo(ctx, arg)
	if err != nil {
		fmt.Println("failed:", err)
		return
	}
	if res != arg {
		log.Fatalf("Echo gave different string!")
	}
	duration := time.Since(started)
	fmt.Println(duration)
}
Example #9
0
func runClient2(hyperbahnService string, addr net.Addr) error {
	tchan, err := tchannel.NewChannel("client2", optsFor("client2"))
	if err != nil {
		return err
	}
	tchan.Peers().Add(addr.String())
	tclient := thrift.NewClient(tchan, hyperbahnService, nil)
	client := gen.NewTChanSecondClient(tclient)

	go func() {
		for {
			ctx, cancel := thrift.NewContext(time.Second)
			client.Test(ctx)
			cancel()
			time.Sleep(100 * time.Millisecond)
		}
	}()
	return nil
}
Example #10
0
func withSetup(t *testing.T, f func(ctx thrift.Context, args testArgs)) {
	args := testArgs{
		s: new(mocks.TChanTCollector),
	}

	ctx, cancel := thrift.NewContext(time.Second * 10)
	defer cancel()

	// Start server
	tchan := setupServer(t, args.s)
	defer tchan.Close()

	// Get client1
	args.c = getClient(t, tchan.PeerInfo().HostPort)

	f(ctx, args)

	args.s.AssertExpectations(t)
}
Example #11
0
func (c *internalClient) ThriftCallBuffer(latencies []time.Duration) error {
	return c.makeCalls(latencies, func() (time.Duration, error) {
		ctx, cancel := thrift.NewContext(c.opts.timeout)
		defer cancel()

		started := time.Now()
		res, err := c.tClient.Echo(ctx, c.argStr)
		duration := time.Since(started)

		if err != nil {
			return 0, err
		}
		if c.checkResult {
			if res != c.argStr {
				panic("thrift Echo returned wrong result")
			}
		}
		return duration, nil
	})
}
Example #12
0
func runClient1(hyperbahnService string, addr net.Addr) error {
	tchan, err := tchannel.NewChannel("client1", optsFor("client1"))
	if err != nil {
		return err
	}
	tchan.Peers().Add(addr.String())
	tclient := thrift.NewClient(tchan, hyperbahnService, nil)
	client := gen.NewTChanFirstClient(tclient)

	go func() {
		for {
			ctx, cancel := thrift.NewContext(time.Second)
			res, err := client.Echo(ctx, "Hi")
			log.Println("Echo(Hi) = ", res, ", err: ", err)
			log.Println("AppError() = ", client.AppError(ctx))
			log.Println("BaseCall() = ", client.BaseCall(ctx))
			cancel()
			time.Sleep(100 * time.Millisecond)
		}
	}()
	return nil
}
Example #13
0
func main() {
	ch, err := tchannel.NewChannel("tcheck", nil)
	if err != nil {
		fmt.Println("failed to create tchannel:", err)
		os.Exit(1)
	}

	hostsFile := flag.String("hostsFile", "/etc/uber/hyperbahn/hosts.json", "hyperbahn hosts file")
	serviceName := flag.String("serviceName", "hyperbahn", "service name to check health of")
	peer := flag.String("peer", "", "peer to hit directly")

	flag.Parse()

	var config hyperbahn.Configuration
	if *peer != "" {
		config = hyperbahn.Configuration{InitialNodes: []string{*peer}}
	} else {
		config = hyperbahn.Configuration{InitialNodesFile: *hostsFile}
	}
	hyperbahn.NewClient(ch, config, nil)

	thriftClient := thrift.NewClient(ch, *serviceName, nil)
	client := meta.NewTChanMetaClient(thriftClient)

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

	val, err := client.Health(ctx)

	if err != nil {
		fmt.Printf("NOT OK %v\nError: %v\n", *serviceName, err)
		os.Exit(2)
	} else if val.Ok != true {
		fmt.Printf("NOT OK %v\n", *val.Message)
		os.Exit(3)
	} else {
		fmt.Printf("OK\n")
	}
}
Example #14
0
func TestRingpopRemoteServiceAdapterCallLocal(t *testing.T) {
	rp := &mocks.Ringpop{}
	rp.On("RegisterListener", mock.Anything).Return()
	rp.On("Lookup", "hello").Return("127.0.0.1:3000", nil)
	rp.On("WhoAmI").Return("127.0.0.1:3000", nil)

	serviceImpl := &servicemocks.TChanRemoteService{}
	serviceImpl.On("RemoteCall", mock.Anything, "hello").Return(nil)
	ctx, _ := thrift.NewContext(0 * time.Second)

	adapter, err := NewRingpopRemoteServiceAdapter(serviceImpl, rp, nil, RemoteServiceConfiguration{
		RemoteCall: &RemoteServiceRemoteCallConfiguration{
			Key: func(ctx thrift.Context, name string) (string, error) {
				return name, nil
			},
		},
	})
	assert.Equal(t, err, nil, "creation of adator gave an error")

	err = adapter.RemoteCall(ctx, "hello")
	assert.Equal(t, err, nil, "calling RemoteCall gave an error")

	serviceImpl.AssertCalled(t, "RemoteCall", mock.Anything, "hello")
}
Example #15
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)
	}
}
Example #16
0
func createContext() (thrift.Context, func()) {
	ctx, cancel := thrift.NewContext(time.Second)
	ctx = thrift.WithHeaders(ctx, map[string]string{"user": curUser})
	return ctx, cancel
}