From ebece39852797208ff5b490ffb0de3c8e055a88c Mon Sep 17 00:00:00 2001
From: fangyincheng <fangyincheng@sina.com>
Date: Fri, 17 May 2019 15:08:06 +0800
Subject: [PATCH] Tst&Mod:add test & formatting code

---
 common/proxy/proxy_test.go               | 34 ++++++++++--
 config/config_loader.go                  |  4 +-
 config/config_loader_test.go             | 28 ++++++++++
 config/mock_rpcservice.go                |  2 +-
 config/reference_config_test.go          |  2 +-
 config/service_config_test.go            |  2 +-
 protocol/dubbo/client.go                 | 69 ++++++++++++------------
 protocol/dubbo/client_test.go            | 17 +++++-
 protocol/dubbo/dubbo_invoker.go          |  8 +--
 protocol/dubbo/listener.go               |  7 ++-
 protocol/jsonrpc/http_test.go            | 27 ++++++++--
 protocol/jsonrpc/jsonrpc_invoker.go      |  9 ++--
 protocol/jsonrpc/jsonrpc_invoker_test.go |  5 +-
 protocol/jsonrpc/server.go               | 25 ++++++---
 14 files changed, 168 insertions(+), 71 deletions(-)

diff --git a/common/proxy/proxy_test.go b/common/proxy/proxy_test.go
index 73a3fb8ba..8a7c8c880 100644
--- a/common/proxy/proxy_test.go
+++ b/common/proxy/proxy_test.go
@@ -12,11 +12,14 @@ import (
 
 import (
 	"github.com/dubbo/go-for-apache-dubbo/common"
+	"github.com/dubbo/go-for-apache-dubbo/common/constant"
 	"github.com/dubbo/go-for-apache-dubbo/protocol"
 )
 
 type TestService struct {
 	MethodOne func(context.Context, []interface{}, *struct{}) error
+	MethodTwo func([]interface{}, *struct{}) error
+	Echo      func([]interface{}, *struct{}) error
 }
 
 func (s *TestService) Service() string {
@@ -26,18 +29,30 @@ func (s *TestService) Version() string {
 	return ""
 }
 
+type TestServiceInt int
+
+func (s *TestServiceInt) Service() string {
+	return "com.test.TestServiceInt"
+}
+func (s *TestServiceInt) Version() string {
+	return ""
+}
+
 func TestProxy_Implement(t *testing.T) {
 
 	invoker := protocol.NewBaseInvoker(common.URL{})
-	p := NewProxy(invoker, nil, nil)
-	s := &TestService{MethodOne: func(i context.Context, i2 []interface{}, i3 *struct{}) error {
-		return errors.New("errors")
-	}}
+	p := NewProxy(invoker, nil, map[string]string{constant.ASYNC_KEY: "false"})
+	s := &TestService{}
 	p.Implement(s)
 	err := p.Get().(*TestService).MethodOne(nil, nil, nil)
 	assert.NoError(t, err)
+	err = p.Get().(*TestService).MethodTwo(nil, nil)
+	assert.NoError(t, err)
+	err = p.Get().(*TestService).Echo(nil, nil)
+	assert.NoError(t, err)
 
 	// inherit & lowercase
+	p.rpc = nil
 	type S1 struct {
 		TestService
 		methodOne func(context.Context, []interface{}, *struct{}) error
@@ -51,7 +66,14 @@ func TestProxy_Implement(t *testing.T) {
 	err = s1.methodOne(nil, nil, nil)
 	assert.EqualError(t, err, "errors")
 
+	// no struct
+	p.rpc = nil
+	it := TestServiceInt(1)
+	p.Implement(&it)
+	assert.Nil(t, p.rpc)
+
 	// args number
+	p.rpc = nil
 	type S2 struct {
 		TestService
 		MethodOne func([]interface{}) error
@@ -61,6 +83,7 @@ func TestProxy_Implement(t *testing.T) {
 	assert.Nil(t, s2.MethodOne)
 
 	// returns number
+	p.rpc = nil
 	type S3 struct {
 		TestService
 		MethodOne func(context.Context, []interface{}, *struct{}) (interface{}, error)
@@ -70,6 +93,7 @@ func TestProxy_Implement(t *testing.T) {
 	assert.Nil(t, s3.MethodOne)
 
 	// returns type
+	p.rpc = nil
 	type S4 struct {
 		TestService
 		MethodOne func(context.Context, []interface{}, *struct{}) interface{}
@@ -79,6 +103,7 @@ func TestProxy_Implement(t *testing.T) {
 	assert.Nil(t, s4.MethodOne)
 
 	// reply type for number 3
+	p.rpc = nil
 	type S5 struct {
 		TestService
 		MethodOne func(context.Context, []interface{}, interface{}) error
@@ -88,6 +113,7 @@ func TestProxy_Implement(t *testing.T) {
 	assert.Nil(t, s5.MethodOne)
 
 	// reply type for number 2
+	p.rpc = nil
 	type S6 struct {
 		TestService
 		MethodOne func([]interface{}, interface{}) error
diff --git a/config/config_loader.go b/config/config_loader.go
index e1f55b373..b364e7cb0 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -222,7 +222,7 @@ func Load() (map[string]*ReferenceConfig, map[string]*ServiceConfig) {
 		length := len(consumerConfig.References)
 		for index := 0; index < length; index++ {
 			con := &consumerConfig.References[index]
-			rpcService := conServices[con.InterfaceName]
+			rpcService := GetConService(con.InterfaceName)
 			if rpcService == nil {
 				log.Warn("%s is not exsist!", con.InterfaceName)
 				continue
@@ -241,7 +241,7 @@ func Load() (map[string]*ReferenceConfig, map[string]*ServiceConfig) {
 		length := len(providerConfig.Services)
 		for index := 0; index < length; index++ {
 			pro := &providerConfig.Services[index]
-			rpcService := proServices[pro.InterfaceName]
+			rpcService := GetProService(pro.InterfaceName)
 			if rpcService == nil {
 				log.Warn("%s is not exsist!", pro.InterfaceName)
 				continue
diff --git a/config/config_loader_test.go b/config/config_loader_test.go
index b67835d56..ed96da81e 100644
--- a/config/config_loader_test.go
+++ b/config/config_loader_test.go
@@ -1,6 +1,7 @@
 package config
 
 import (
+	"github.com/dubbo/go-for-apache-dubbo/common"
 	"path/filepath"
 	"testing"
 )
@@ -9,6 +10,11 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+import (
+	"github.com/dubbo/go-for-apache-dubbo/cluster/cluster_impl"
+	"github.com/dubbo/go-for-apache-dubbo/common/extension"
+)
+
 func TestConfigLoader(t *testing.T) {
 	conPath, err := filepath.Abs("./consumer_config.yml")
 	assert.NoError(t, err)
@@ -30,3 +36,25 @@ func TestConfigLoader(t *testing.T) {
 	assert.NotNil(t, providerConfig)
 	assert.NotEqual(t, ProviderConfig{}, GetProviderConfig())
 }
+
+func TestLoad(t *testing.T) {
+	doInit()
+	doinit()
+
+	SetConService(&MockService{})
+	SetProService(&MockService{})
+
+	extension.SetProtocol("registry", GetProtocol)
+	extension.SetCluster("registryAware", cluster_impl.NewRegistryAwareCluster)
+	consumerConfig.References[0].Registries = []ConfigRegistry{"shanghai_reg1"}
+
+	refConfigs, svcConfigs := Load()
+	assert.NotEqual(t, 0, len(refConfigs))
+	assert.NotEqual(t, 0, len(svcConfigs))
+
+	conServices = map[string]common.RPCService{}
+	proServices = map[string]common.RPCService{}
+	common.ServiceMap.UnRegister("mock", "MockService")
+	consumerConfig = nil
+	providerConfig = nil
+}
diff --git a/config/mock_rpcservice.go b/config/mock_rpcservice.go
index 1bd01bd4f..14641de4e 100644
--- a/config/mock_rpcservice.go
+++ b/config/mock_rpcservice.go
@@ -6,7 +6,7 @@ type MockService struct {
 }
 
 func (*MockService) Service() string {
-	return "mockservice"
+	return "MockService"
 }
 func (*MockService) Version() string {
 	return "1.0"
diff --git a/config/reference_config_test.go b/config/reference_config_test.go
index 6e63b4bc3..a2ba14a66 100644
--- a/config/reference_config_test.go
+++ b/config/reference_config_test.go
@@ -61,7 +61,7 @@ func doInit() {
 		},
 		References: []ReferenceConfig{
 			{
-				InterfaceName: "testInterface",
+				InterfaceName: "MockService",
 				Protocol:      "mock",
 				Registries:    []ConfigRegistry{"shanghai_reg1", "shanghai_reg2", "hangzhou_reg1", "hangzhou_reg2"},
 				Cluster:       "failover",
diff --git a/config/service_config_test.go b/config/service_config_test.go
index 9f991e56c..f6874b15f 100644
--- a/config/service_config_test.go
+++ b/config/service_config_test.go
@@ -55,7 +55,7 @@ func doinit() {
 		},
 		Services: []ServiceConfig{
 			{
-				InterfaceName: "testInterface",
+				InterfaceName: "MockService",
 				Protocol:      "mock",
 				Registries:    []ConfigRegistry{"shanghai_reg1", "shanghai_reg2", "hangzhou_reg1", "hangzhou_reg2"},
 				Cluster:       "failover",
diff --git a/protocol/dubbo/client.go b/protocol/dubbo/client.go
index 6c50f51a2..7477a965a 100644
--- a/protocol/dubbo/client.go
+++ b/protocol/dubbo/client.go
@@ -83,38 +83,38 @@ type CallOptions struct {
 
 type CallOption func(*CallOptions)
 
-func WithCallRequestTimeout(d time.Duration) CallOption {
-	return func(o *CallOptions) {
-		o.RequestTimeout = d
-	}
-}
-
-func WithCallResponseTimeout(d time.Duration) CallOption {
-	return func(o *CallOptions) {
-		o.ResponseTimeout = d
-	}
-}
-
-func WithCallSerialID(s SerialID) CallOption {
-	return func(o *CallOptions) {
-		o.SerialID = s
-	}
-}
-
-func WithCallMeta_All(callMeta map[interface{}]interface{}) CallOption {
-	return func(o *CallOptions) {
-		o.Meta = callMeta
-	}
-}
-
-func WithCallMeta(k, v interface{}) CallOption {
-	return func(o *CallOptions) {
-		if o.Meta == nil {
-			o.Meta = make(map[interface{}]interface{})
-		}
-		o.Meta[k] = v
-	}
-}
+//func WithCallRequestTimeout(d time.Duration) CallOption {
+//	return func(o *CallOptions) {
+//		o.RequestTimeout = d
+//	}
+//}
+//
+//func WithCallResponseTimeout(d time.Duration) CallOption {
+//	return func(o *CallOptions) {
+//		o.ResponseTimeout = d
+//	}
+//}
+//
+//func WithCallSerialID(s SerialID) CallOption {
+//	return func(o *CallOptions) {
+//		o.SerialID = s
+//	}
+//}
+//
+//func WithCallMeta_All(callMeta map[interface{}]interface{}) CallOption {
+//	return func(o *CallOptions) {
+//		o.Meta = callMeta
+//	}
+//}
+
+//func WithCallMeta(k, v interface{}) CallOption {
+//	return func(o *CallOptions) {
+//		if o.Meta == nil {
+//			o.Meta = make(map[interface{}]interface{})
+//		}
+//		o.Meta[k] = v
+//	}
+//}
 
 type CallResponse struct {
 	Opts      CallOptions
@@ -210,11 +210,14 @@ func (c *Client) call(ct CallType, addr string, svcUrl common.URL, method string
 
 	var rsp *PendingResponse
 	if ct != CT_OneWay {
+		p.Header.Type = hessian.PackageRequest_TwoWay
 		rsp = NewPendingResponse()
 		rsp.reply = reply
 		rsp.callback = callback
 		rsp.opts = opts
 	}
+	// todo: it must be PackageRequest because of hessian2, but it is twoway actually
+	p.Header.Type = hessian.PackageRequest
 
 	var (
 		err     error
@@ -281,8 +284,6 @@ func (c *Client) transfer(session getty.Session, pkg *DubboPackage,
 		pkg.Body = []interface{}{}
 		pkg.Header.Type = hessian.PackageHeartbeat
 		pkg.Header.SerialID = byte(S_Dubbo)
-	} else {
-		pkg.Header.Type = hessian.PackageRequest
 	}
 	pkg.Header.ID = int64(sequence)
 
diff --git a/protocol/dubbo/client_test.go b/protocol/dubbo/client_test.go
index 7febfcc59..a22135ba9 100644
--- a/protocol/dubbo/client_test.go
+++ b/protocol/dubbo/client_test.go
@@ -3,13 +3,13 @@ package dubbo
 import (
 	"context"
 	"errors"
-	"github.com/dubbogo/hessian2"
 	"sync"
 	"testing"
 	"time"
 )
 
 import (
+	"github.com/dubbogo/hessian2"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -60,6 +60,11 @@ func TestClient_Call(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, User{Id: "1", Name: "username"}, *user)
 
+	user = &User{}
+	err = c.Call("127.0.0.1:20000", url, "GetUser0", []interface{}{"1", "username"}, user)
+	assert.NoError(t, err)
+	assert.Equal(t, User{Id: "1", Name: "username"}, *user)
+
 	// destroy
 	proto.Destroy()
 }
@@ -95,7 +100,7 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) {
 
 	methods, err := common.ServiceMap.Register("dubbo", &UserProvider{})
 	assert.NoError(t, err)
-	assert.Equal(t, "GetUser,GetUser1", methods)
+	assert.Equal(t, "GetUser,GetUser0,GetUser1", methods)
 
 	// config
 	SetClientConf(ClientConfig{
@@ -153,6 +158,8 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) {
 	assert.NoError(t, err)
 	proto.Export(protocol.NewBaseInvoker(url))
 
+	time.Sleep(time.Second * 2)
+
 	return proto, url
 }
 
@@ -162,6 +169,12 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User
 	return nil
 }
 
+func (u *UserProvider) GetUser0(req []interface{}, rsp *User) error {
+	rsp.Id = req[0].(string)
+	rsp.Name = req[1].(string)
+	return nil
+}
+
 func (u *UserProvider) GetUser1(ctx context.Context, req []interface{}, rsp *User) error {
 	return errors.New("error")
 }
diff --git a/protocol/dubbo/dubbo_invoker.go b/protocol/dubbo/dubbo_invoker.go
index c0e481837..72da3294b 100644
--- a/protocol/dubbo/dubbo_invoker.go
+++ b/protocol/dubbo/dubbo_invoker.go
@@ -53,17 +53,17 @@ func (di *DubboInvoker) Invoke(invocation protocol.Invocation) protocol.Result {
 		} else {
 			result.Err = di.client.CallOneway(url.Location, url, inv.MethodName(), inv.Arguments())
 		}
-		log.Debug("result.Err: %v, result.Rest: %v", result.Err, result.Rest)
 	} else {
 		if inv.Reply() == nil {
 			result.Err = Err_No_Reply
 		} else {
-
 			result.Err = di.client.Call(url.Location, url, inv.MethodName(), inv.Arguments(), inv.Reply())
-			result.Rest = inv.Reply() // reply should be set to result.Rest when sync
 		}
-		log.Debug("result.Err: %v, result.Rest: %v", result.Err, result.Rest)
 	}
+	if result.Err == nil {
+		result.Rest = inv.Reply()
+	}
+	log.Debug("result.Err: %v, result.Rest: %v", result.Err, result.Rest)
 
 	return &result
 }
diff --git a/protocol/dubbo/listener.go b/protocol/dubbo/listener.go
index 99a11feeb..f180ca631 100644
--- a/protocol/dubbo/listener.go
+++ b/protocol/dubbo/listener.go
@@ -183,11 +183,11 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) {
 		return
 	}
 
+	twoway := true
 	// not twoway
 	if p.Header.Type&hessian.PackageRequest_TwoWay == 0x00 {
+		twoway = false
 		h.reply(session, p, hessian.PackageResponse)
-		h.callService(p, nil)
-		return
 	}
 
 	invoker := h.exporter.GetInvoker()
@@ -213,6 +213,9 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) {
 	}
 
 	h.callService(p, nil)
+	if !twoway {
+		return
+	}
 	h.reply(session, p, hessian.PackageResponse)
 }
 
diff --git a/protocol/jsonrpc/http_test.go b/protocol/jsonrpc/http_test.go
index 8c681e8d0..522337cca 100644
--- a/protocol/jsonrpc/http_test.go
+++ b/protocol/jsonrpc/http_test.go
@@ -33,7 +33,7 @@ func TestHTTPClient_Call(t *testing.T) {
 
 	methods, err := common.ServiceMap.Register("jsonrpc", &UserProvider{})
 	assert.NoError(t, err)
-	assert.Equal(t, "GetUser,GetUser1", methods)
+	assert.Equal(t, "GetUser,GetUser0,GetUser1", methods)
 
 	// Export
 	proto := GetProtocol()
@@ -44,11 +44,9 @@ func TestHTTPClient_Call(t *testing.T) {
 		"side=provider&timeout=3000&timestamp=1556509797245")
 	assert.NoError(t, err)
 	proto.Export(protocol.NewBaseInvoker(url))
+	time.Sleep(time.Second * 2)
 
-	client := NewHTTPClient(&HTTPOptions{
-		HandshakeTimeout: time.Second,
-		HTTPTimeout:      time.Second,
-	})
+	client := NewHTTPClient(&HTTPOptions{})
 
 	// call GetUser
 	ctx := context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
@@ -63,6 +61,19 @@ func TestHTTPClient_Call(t *testing.T) {
 	assert.Equal(t, "1", reply.Id)
 	assert.Equal(t, "username", reply.Name)
 
+	// call GetUser
+	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
+		"X-Proxy-Id": "dubbogo",
+		"X-Services": url.Path,
+		"X-Method":   "GetUser",
+	})
+	req = client.NewRequest(url, "GetUser0", []interface{}{"1", "username"})
+	reply = &User{}
+	err = client.Call(ctx, url, req, reply)
+	assert.NoError(t, err)
+	assert.Equal(t, "1", reply.Id)
+	assert.Equal(t, "username", reply.Name)
+
 	// call GetUser1
 	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
 		"X-Proxy-Id": "dubbogo",
@@ -86,6 +97,12 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User
 	return nil
 }
 
+func (u *UserProvider) GetUser0(req []interface{}, rsp *User) error {
+	rsp.Id = req[0].(string)
+	rsp.Name = req[1].(string)
+	return nil
+}
+
 func (u *UserProvider) GetUser1(ctx context.Context, req []interface{}, rsp *User) error {
 	return errors.New("error")
 }
diff --git a/protocol/jsonrpc/jsonrpc_invoker.go b/protocol/jsonrpc/jsonrpc_invoker.go
index 645fe8b0d..e427c554f 100644
--- a/protocol/jsonrpc/jsonrpc_invoker.go
+++ b/protocol/jsonrpc/jsonrpc_invoker.go
@@ -6,7 +6,6 @@ import (
 
 import (
 	log "github.com/AlexStocks/log4go"
-	jerrors "github.com/juju/errors"
 )
 
 import (
@@ -42,13 +41,11 @@ func (ji *JsonrpcInvoker) Invoke(invocation protocol.Invocation) protocol.Result
 		"X-Services": url.Path,
 		"X-Method":   inv.MethodName(),
 	})
-	if err := ji.client.Call(ctx, url, req, inv.Reply()); err != nil {
-		log.Error("client.Call() return error:%+v", jerrors.ErrorStack(err))
-		result.Err = err
-	} else {
-		log.Debug("result: %v", inv.Reply())
+	result.Err = ji.client.Call(ctx, url, req, inv.Reply())
+	if result.Err == nil {
 		result.Rest = inv.Reply()
 	}
+	log.Debug("result.Err: %v, result.Rest: %v", result.Err, result.Rest)
 
 	return &result
 }
diff --git a/protocol/jsonrpc/jsonrpc_invoker_test.go b/protocol/jsonrpc/jsonrpc_invoker_test.go
index cde655623..8bf3f3e3c 100644
--- a/protocol/jsonrpc/jsonrpc_invoker_test.go
+++ b/protocol/jsonrpc/jsonrpc_invoker_test.go
@@ -2,7 +2,6 @@ package jsonrpc
 
 import (
 	"context"
-	"github.com/dubbo/go-for-apache-dubbo/protocol/invocation"
 	"testing"
 	"time"
 )
@@ -14,13 +13,14 @@ import (
 import (
 	"github.com/dubbo/go-for-apache-dubbo/common"
 	"github.com/dubbo/go-for-apache-dubbo/protocol"
+	"github.com/dubbo/go-for-apache-dubbo/protocol/invocation"
 )
 
 func TestJsonrpcInvoker_Invoke(t *testing.T) {
 
 	methods, err := common.ServiceMap.Register("jsonrpc", &UserProvider{})
 	assert.NoError(t, err)
-	assert.Equal(t, "GetUser,GetUser1", methods)
+	assert.Equal(t, "GetUser,GetUser0,GetUser1", methods)
 
 	// Export
 	proto := GetProtocol()
@@ -31,6 +31,7 @@ func TestJsonrpcInvoker_Invoke(t *testing.T) {
 		"side=provider&timeout=3000&timestamp=1556509797245")
 	assert.NoError(t, err)
 	proto.Export(protocol.NewBaseInvoker(url))
+	time.Sleep(time.Second * 2)
 
 	client := NewHTTPClient(&HTTPOptions{
 		HandshakeTimeout: time.Second,
diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go
index dba427b71..78c1b791e 100644
--- a/protocol/jsonrpc/server.go
+++ b/protocol/jsonrpc/server.go
@@ -367,13 +367,24 @@ func serveRequest(ctx context.Context,
 	replyv := reflect.New(mtype.ReplyType().Elem())
 
 	//  call service.method(args)
-	var errMsg string
-	returnValues := mtype.Method().Func.Call([]reflect.Value{
-		svc.Rcvr(),
-		mtype.SuiteContext(ctx),
-		reflect.ValueOf(argvTmp),
-		reflect.ValueOf(replyv.Interface()),
-	})
+	var (
+		errMsg       string
+		returnValues []reflect.Value
+	)
+	if mtype.CtxType() == nil {
+		returnValues = mtype.Method().Func.Call([]reflect.Value{
+			svc.Rcvr(),
+			reflect.ValueOf(argvTmp),
+			reflect.ValueOf(replyv.Interface()),
+		})
+	} else {
+		returnValues = mtype.Method().Func.Call([]reflect.Value{
+			svc.Rcvr(),
+			mtype.SuiteContext(ctx),
+			reflect.ValueOf(argvTmp),
+			reflect.ValueOf(replyv.Interface()),
+		})
+	}
 	// The return value for the method is an error.
 	if retErr := returnValues[0].Interface(); retErr != nil {
 		errMsg = retErr.(error).Error()
-- 
GitLab