You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by wo...@apache.org on 2020/03/18 06:54:52 UTC

[dubbo-go-hessian2] branch master updated: Fix hessian codec bugs (#167)

This is an automated email from the ASF dual-hosted git repository.

wongoo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-go-hessian2.git


The following commit(s) were added to refs/heads/master by this push:
     new 0da2291  Fix hessian codec bugs (#167)
0da2291 is described below

commit 0da22914f92b7826a0c76d3ccca3ac8887110b48
Author: 诣极 yì jí <yi...@apache.org>
AuthorDate: Wed Mar 18 14:54:44 2020 +0800

    Fix hessian codec bugs (#167)
    
    * fix skip class fields.
    
    * fix skip class fields & decode response attachments.
    
    * remove unit tests.
    
    * fix code review problems.
    
    * Fix when the return value is nil
    
    * refactor code.
    
    * add UnRegisterPOJO for tests.
    
    * refactor codes.
    
    * remove construct structInfo.
    
    * cancel export unRegisterPOJOs method
---
 hessian_test.go | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 object.go       | 14 +++++++++++---
 pojo.go         | 52 ++++++++++++++++++++++++++++++++++++++++++----------
 response.go     |  9 +++++++--
 4 files changed, 107 insertions(+), 16 deletions(-)

diff --git a/hessian_test.go b/hessian_test.go
index fa74abe..e466cf2 100644
--- a/hessian_test.go
+++ b/hessian_test.go
@@ -34,8 +34,27 @@ type Case struct {
 	B int
 }
 
+type CaseA struct {
+	A string
+	B int
+	C Case
+}
+
+type CaseB struct {
+	A string
+	B CaseA
+}
+
+func (c *CaseB) JavaClassName() string {
+	return "com.test.caseb"
+}
+
+func (c CaseA) JavaClassName() string {
+	return "com.test.casea"
+}
+
 //JavaClassName  java fully qualified path
-func (c *Case) JavaClassName() string {
+func (c Case) JavaClassName() string {
 	return "com.test.case"
 }
 
@@ -171,3 +190,30 @@ func TestRequest(t *testing.T) {
 	doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3, true, []*Case{{A: "a", B: 3}}})
 	doTestRequest(t, PackageRequest, Zero, []interface{}{map[string][]*Case{"key": {{A: "a", B: 3}}}})
 }
+
+func TestHessianCodec_ReadAttachments(t *testing.T) {
+	body := &Response{
+		RspObj:      &CaseB{A: "A", B: CaseA{A: "a", B: 1, C: Case{A: "c", B: 2}}},
+		Exception:   nil,
+		Attachments: map[string]string{DUBBO_VERSION_KEY: "2.6.4"},
+	}
+	resp, err := doTestHessianEncodeHeader(t, PackageResponse, Response_OK, body)
+	assert.NoError(t, err)
+
+	unRegisterPOJOs(&CaseB{}, &CaseA{})
+	codecR1 := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
+	codecR2 := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
+	h := &DubboHeader{}
+	assert.NoError(t, codecR1.ReadHeader(h))
+	t.Log(h)
+	assert.NoError(t, codecR2.ReadHeader(h))
+	t.Log(h)
+
+	err = codecR1.ReadBody(body)
+	assert.Equal(t, "can not find go type name com.test.caseb in registry", err.Error())
+	attrs, err := codecR2.ReadAttachments()
+	assert.NoError(t, err)
+	assert.Equal(t, "2.6.4", attrs[DUBBO_VERSION_KEY])
+
+	t.Log(attrs)
+}
diff --git a/object.go b/object.go
index 857ae05..4025dac 100644
--- a/object.go
+++ b/object.go
@@ -541,11 +541,19 @@ func (d *Decoder) decEnum(javaName string, flag int32) (JavaEnum, error) {
 
 // skip this object
 func (d *Decoder) skip(cls classInfo) error {
-	if len(cls.fieldNameList) < 1 {
+	len := len(cls.fieldNameList)
+	if len < 1 {
 		return nil
 	}
-	_, err := d.DecodeValue()
-	return err
+
+	for i := 0; i < len; i++ {
+		// skip class fields.
+		if _, err := d.DecodeValue(); err != nil {
+			return err
+		}
+	}
+
+	return nil
 }
 
 func (d *Decoder) decObject(flag int32) (interface{}, error) {
diff --git a/pojo.go b/pojo.go
index ed5ab8b..0c9f9aa 100644
--- a/pojo.go
+++ b/pojo.go
@@ -130,18 +130,9 @@ func RegisterPOJO(o POJO) int {
 		fieldList  []string
 		structInfo structInfo
 		clsDef     classInfo
-		v          reflect.Value
 	)
 
-	v = reflect.ValueOf(o)
-	switch v.Kind() {
-	case reflect.Struct:
-		structInfo.typ = v.Type()
-	case reflect.Ptr:
-		structInfo.typ = v.Elem().Type()
-	default:
-		structInfo.typ = reflect.TypeOf(o)
-	}
+	structInfo.typ = obtainValueType(o)
 
 	structInfo.goName = structInfo.typ.String()
 	structInfo.javaName = o.JavaClassName()
@@ -210,6 +201,47 @@ func RegisterPOJO(o POJO) int {
 	return structInfo.index
 }
 
+// easy for test
+func unRegisterPOJOs(os ...POJO) []int {
+	arr := make([]int, len(os))
+	for i := range os {
+		arr[i] = unRegisterPOJO(os[i])
+	}
+
+	return arr
+}
+
+func unRegisterPOJO(o POJO) int {
+	pojoRegistry.Lock()
+	defer pojoRegistry.Unlock()
+
+	goName := obtainValueType(o).String()
+
+	if structInfo, ok := pojoRegistry.registry[goName]; ok {
+		delete(pojoRegistry.j2g, structInfo.javaName)
+		listTypeNameMapper.Delete(structInfo.goName)
+		// remove registry cache.
+		delete(pojoRegistry.registry, structInfo.goName)
+		// don't remove registry classInfoList,
+		// indexes of registered pojo may be affected.
+		return structInfo.index
+	}
+
+	return -1
+}
+
+func obtainValueType(o POJO) reflect.Type {
+	v := reflect.ValueOf(o)
+	switch v.Kind() {
+	case reflect.Struct:
+		return v.Type()
+	case reflect.Ptr:
+		return v.Elem().Type()
+	}
+
+	return reflect.TypeOf(o)
+}
+
 // RegisterPOJOs register a POJO instance arr @os. The return value is @os's
 // mathching index array, in which "-1" means its matching POJO has been registered.
 func RegisterPOJOs(os ...POJO) []int {
diff --git a/response.go b/response.go
index 4ba9e39..1fede8e 100644
--- a/response.go
+++ b/response.go
@@ -199,13 +199,18 @@ func unpackResponseBody(decoder *Decoder, resp interface{}) error {
 				return perrors.WithStack(err)
 			}
 			if v, ok := attachments.(map[interface{}]interface{}); ok {
-				atta := ToMapStringString(v)
-				response.Attachments = atta
+				response.Attachments = ToMapStringString(v)
 			} else {
 				return perrors.Errorf("get wrong attachments: %+v", attachments)
 			}
 		}
 
+		// If the return value is nil,
+		// we should consider it normal
+		if rsp == nil {
+			return nil
+		}
+
 		return perrors.WithStack(ReflectResponse(rsp, response.RspObj))
 
 	case RESPONSE_NULL_VALUE, RESPONSE_NULL_VALUE_WITH_ATTACHMENTS: