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 2021/03/17 04:44:11 UTC

[dubbo-go-hessian2] branch master updated: fix duplicatedly adding list type in type map (#263)

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 bdf7603  fix duplicatedly adding list type in type map (#263)
bdf7603 is described below

commit bdf7603e08a09a6d2c5c4527121e58beea887a2b
Author: 望哥 <ge...@163.com>
AuthorDate: Wed Mar 17 12:44:05 2021 +0800

    fix duplicatedly adding list type in type map (#263)
    
    * fix duplicatedly adding list type in type map
    
    * add unit test for map/list self ref
    
    * using assert.Equal to check ref object
---
 list.go                                            | 22 +++++++---
 list_test.go                                       | 16 +++++++
 map.go                                             |  7 +--
 map_test.go                                        | 43 ++++++++++++++++++
 .../src/main/java/test/TestCustomReply.java        | 51 ++++++++++++++++++++++
 .../src/main/java/test/model/CustomMap.java        | 23 ++++++++++
 6 files changed, 150 insertions(+), 12 deletions(-)

diff --git a/list.go b/list.go
index c3c761c..da0ca39 100644
--- a/list.go
+++ b/list.go
@@ -332,20 +332,28 @@ func (d *Decoder) readTypedListValue(length int, listTyp string, isVariableArr b
 		aryValue reflect.Value
 		arrType  reflect.Type
 	)
+
 	t, err := strconv.Atoi(listTyp)
 	if err == nil {
+		// find the ref list type
 		arrType = d.typeRefs.Get(t)
+		if arrType == nil {
+			return nil, perrors.Errorf("can't find ref list type at index %d", t)
+		}
+		aryValue = reflect.MakeSlice(arrType, length, length)
 	} else {
+		// try to find the registered list type
 		arrType = getListType(listTyp)
+		if arrType != nil {
+			aryValue = reflect.MakeSlice(arrType, length, length)
+			d.typeRefs.appendTypeRefs(listTyp, arrType)
+		} else {
+			// using default generic list type if not found registered
+			aryValue = reflect.ValueOf(make([]interface{}, length, length))
+			d.typeRefs.appendTypeRefs(listTyp, aryValue.Type())
+		}
 	}
 
-	if arrType != nil {
-		aryValue = reflect.MakeSlice(arrType, length, length)
-		d.typeRefs.appendTypeRefs(arrType.String(), arrType)
-	} else {
-		aryValue = reflect.ValueOf(make([]interface{}, length, length))
-		d.typeRefs.appendTypeRefs(strings.Replace(listTyp, "[", "", -1), aryValue.Type())
-	}
 	holder := d.appendRefs(aryValue)
 	for j := 0; j < length || isVariableArr; j++ {
 		it, err := d.DecodeValue()
diff --git a/list_test.go b/list_test.go
index 0e96ae6..6578366 100644
--- a/list_test.go
+++ b/list_test.go
@@ -70,6 +70,22 @@ func TestEncList(t *testing.T) {
 	assert.True(t, reflect.DeepEqual(res, list_2))
 }
 
+func TestListRefSelf(t *testing.T) {
+	RegisterPOJOs(new(A0), new(A1))
+
+	r, e := decodeJavaResponse("customReplyTypedFixedListRefSelf", "", true)
+	if e != nil {
+		t.Errorf("%s: decode fail with error: %v", "customReplyTypedFixedListRefSelf", e)
+		return
+	}
+
+	res := r.([]Object)
+	assert.Equal(t, 3, len(res))
+	assert.Equal(t, new(A0), res[0])
+	assert.Equal(t, new(A1), res[1])
+	assert.Equal(t, res, res[2])
+}
+
 func TestList(t *testing.T) {
 	RegisterPOJOs(new(A0), new(A1), new(TypedListTest))
 
diff --git a/map.go b/map.go
index d43b915..64227bf 100644
--- a/map.go
+++ b/map.go
@@ -226,7 +226,6 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
 		m          map[interface{}]interface{}
 		k          interface{}
 		v          interface{}
-		inst       interface{}
 		instValue  reflect.Value
 		fieldName  string
 		fieldValue reflect.Value
@@ -255,9 +254,7 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
 			instValue = reflect.New(typ).Elem()
 		}
 
-		inst = instValue.Interface()
-
-		d.appendRefs(inst)
+		d.appendRefs(instValue)
 
 		for d.peekByte() != BC_END {
 			k, err = d.Decode()
@@ -286,7 +283,7 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
 		if err != nil {
 			return nil, perrors.WithStack(err)
 		}
-		return inst, nil
+		return instValue.Interface(), nil
 	case tag == BC_MAP_UNTYPED:
 		m = make(map[interface{}]interface{})
 		d.appendRefs(m)
diff --git a/map_test.go b/map_test.go
index e80fbe6..5fc0855 100644
--- a/map_test.go
+++ b/map_test.go
@@ -23,6 +23,7 @@ import (
 
 import (
 	big "github.com/dubbogo/gost/math/big"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestEncUntypedMap(t *testing.T) {
@@ -101,6 +102,23 @@ func TestMapEncode(t *testing.T) {
 	testJavaDecode(t, "argUntypedMap_2", map[interface{}]interface{}{int32(0): "a", int32(1): "b"})
 }
 
+func TestCustomMapRefMap(t *testing.T) {
+	r, e := decodeJavaResponse("customReplyMapRefMap", "", true)
+	if e != nil {
+		t.Errorf("%s: decode fail with error: %v", "customReplyMapRefMap", e)
+		return
+	}
+	res := r.(map[interface{}]interface{})
+	assert.Equal(t, int32(1), res["a"])
+	assert.Equal(t, int32(2), res["b"])
+	assert.Equal(t, res, res["self"])
+}
+
+type customMapObject struct {
+	Int int32
+	S   string
+}
+
 func TestCustomMap(t *testing.T) {
 	testDecodeFramework(t, "customReplyMap", map[interface{}]interface{}{"a": int32(1), "b": int32(2)})
 
@@ -126,4 +144,29 @@ func TestCustomMap(t *testing.T) {
 	}
 
 	testDecodeFramework(t, "customReplyMultipleTypeMap", multipleTypeMap)
+
+	RegisterPOJOMapping("test.model.CustomMap", &customMapObject{})
+
+	listMapListMap := []interface{}{
+
+		map[interface{}]interface{}{
+			"a": int32(1),
+			"b": int32(2),
+			"items": []interface{}{
+				b5,
+				"hello",
+				int32(123),
+				customMapObject{
+					Int: 456,
+					S:   "string",
+				},
+			},
+		},
+		customMapObject{
+			Int: 789,
+			S:   "string2",
+		},
+	}
+
+	testDecodeFramework(t, "customReplyListMapListMap", listMapListMap)
 }
diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java
index d4c6d13..a3fa27c 100644
--- a/test_hessian/src/main/java/test/TestCustomReply.java
+++ b/test_hessian/src/main/java/test/TestCustomReply.java
@@ -24,15 +24,18 @@ import com.caucho.hessian.test.A0;
 import com.caucho.hessian.test.A1;
 import test.generic.BusinessData;
 import test.generic.Response;
+import test.model.CustomMap;
 import test.model.DateDemo;
 
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -87,6 +90,13 @@ public class TestCustomReply {
         output.flush();
     }
 
+    public void customReplyTypedFixedListRefSelf() throws Exception {
+        Object[] o = new Object[]{new A0(), new A1(), null};
+        o[2] = o;
+        output.writeObject(o);
+        output.flush();
+    }
+
     public void customReplyTypedVariableListHasNull() throws Exception {
         Object[] o = new Object[]{new A0(), new A1(), null};
         if (output.addRef(o)) {
@@ -501,6 +511,16 @@ public class TestCustomReply {
         output.flush();
     }
 
+    public void customReplyMapRefMap() throws Exception {
+        Map<String, Object> map = new HashMap<String, Object>(4);
+        map.put("a", 1);
+        map.put("b", 2);
+        map.put("self", map);
+
+        output.writeObject(map);
+        output.flush();
+    }
+
     public void customReplyMultipleTypeMap() throws Exception {
         Map<String, Integer> map1 = new HashMap<String, Integer>(4);
         map1.put("a", 1);
@@ -520,6 +540,37 @@ public class TestCustomReply {
         output.flush();
     }
 
+    public void customReplyListMapListMap() throws Exception {
+        List<Object> list = new ArrayList<>();
+
+        Map<String, Object> listMap1 = new HashMap<String, Object>(4);
+        listMap1.put("a", 1);
+        listMap1.put("b", 2);
+
+        List<Object> items = new ArrayList<>();
+        items.add(new BigDecimal("55.55"));
+        items.add("hello");
+        items.add(123);
+
+        CustomMap<String, Object> innerMap = new CustomMap<String, Object>();
+        innerMap.put("Int", 456);
+        innerMap.put("S", "string");
+        items.add(innerMap);
+
+        listMap1.put("items",items);
+
+        list.add(listMap1);
+
+        CustomMap<String, Object> listMap2 = new CustomMap<String, Object>();
+        listMap2.put("Int", 789);
+        listMap2.put("S", "string2");
+
+        list.add(listMap2);
+
+        output.writeObject(list);
+        output.flush();
+    }
+
     public Map<String, Object> mapInMap() throws Exception {
         Map<String, Object> map1 = new HashMap<String, Object>();
         map1.put("a", 1);
diff --git a/test_hessian/src/main/java/test/model/CustomMap.java b/test_hessian/src/main/java/test/model/CustomMap.java
new file mode 100644
index 0000000..7887d98
--- /dev/null
+++ b/test_hessian/src/main/java/test/model/CustomMap.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package test.model;
+
+import java.util.HashMap;
+
+public class CustomMap<K,V> extends HashMap<K,V> {
+}