Repository: apache/dubbo-go-hessian2 (go)

Issue:
完善对Java枚举类型可变长参数方法的支持
我正在做一份重构工作，使用go重构原有的java服务，dubbo版本2.5.4、dubbgo-go版本3.0.1，使用hessian2协议。
正常情况，dubbo-go-hessian2对java枚举类型支持的很好，但是我们遇到要重构的Java方法中出现枚举类型可变长参数时，就出现问题了。
![image](https://user-images.githubusercontent.com/834323/197317360-a77b1726-df4d-42ae-b684-7ad89cf10024.png)
![image](https://user-images.githubusercontent.com/834323/197317811-34c6ac53-a5cc-47ec-9b9c-b3cf4df2d104.png)

比如上图中的getBooksByStatuses1、getBooksByStatuses2两个方法。前者在Go服务中的实现可以正常工作，但是后者被调用后就会报错。
![image](https://user-images.githubusercontent.com/834323/197317445-a4bbcb0d-a60e-4d56-b4e7-e0b733b3f2ad.png)
通过调试发现问题出在github.com/apache/dubbo-go-hessian2@v1.11.1/list.go:382行。进一步调试后发现aryValue是[]*BookStatusTypeEnum类型，而EnsureRawValue(it)方法的返回值是hessian.JavaEnum类型，类型不匹配，所以在赋值时这里就panic了。
目前想到一个解决方案，在这里介绍下，请大佬看看这么改是否合理。
将接参的变量类型改为[]interface{}，这样就可以解决当前的问题。
可以通过getListType方法来实现，在里面增加一个判断，如果当前是枚举类型，那么就直接返回nil，这样会生成一个interface{}类型的切片。
![image](https://user-images.githubusercontent.com/834323/197317605-6c5d2c5d-6a47-45a1-bcf6-bf2b4c923175.png)

![image](https://user-images.githubusercontent.com/834323/197317574-d0c109d6-6871-4eb6-a4f8-1a1292c1445d.png)


Pull request:
Fix decode enum not correctly

**What this PR does**:
Fix decode enum not correctly,  for new defined enum type cant be converted to the original type

**Which issue(s) this PR fixes**:
Fixes #325


Patch:
diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
index 459f4f8..132f03e 100644
--- a/.github/workflows/github-actions.yml
+++ b/.github/workflows/github-actions.yml
@@ -80,7 +80,7 @@ jobs:
       run: golangci-lint run --timeout=10m -v
 
     - name: Go Test
-      run: GO111MODULE=on && go mod vendor && go test -race -v && go test -bench . -race -coverprofile=coverage.txt
+      run: GO111MODULE=on && go mod vendor && go test ./... -race -v && go test -bench . -race -coverprofile=coverage.txt
 
     - name: Coverage
       run: bash <(curl -s https://codecov.io/bash)
diff --git a/object.go b/object.go
index 3d16043..f5898cf 100644
--- a/object.go
+++ b/object.go
@@ -508,17 +508,20 @@ func (d *Decoder) decInstance(typ reflect.Type, cls *ClassInfo) (interface{}, er
 			if err != nil {
 				// java enum
 				if fldRawValue.Type().Implements(javaEnumType) {
-					d.unreadByte() // Enum parsing, decInt64 above has read a byte, so you need to return a byte here
-					s, decErr := d.DecodeValue()
+					_ = d.unreadByte() // Enum parsing, decInt64 above has read a byte, so you need to return a byte here
+					enumVal, decErr := d.DecodeValue()
 					if decErr != nil {
 						return nil, perrors.Wrapf(decErr, "decInstance->decObject field name:%s", fieldName)
 					}
-					enumValue, _ := s.(JavaEnum)
-					num = int32(enumValue)
-				} else {
-					return nil, perrors.Wrapf(err, "decInstance->decInt32, field name:%s", fieldName)
+
+					SetValue(fldRawValue, reflect.ValueOf(enumVal))
+
+					continue
 				}
+
+				return nil, perrors.Wrapf(err, "decInstance->decInt32, field name:%s", fieldName)
 			}
+
 			fldRawValue.SetInt(int64(num))
 		case reflect.Uint16, reflect.Uint8:
 			num, err := d.decInt32(TAG_READ)


Test patch:
diff --git a/hessian_test/dup_struct_name_test.go b/hessian_test/dup_struct_name_test.go
index 14a0666..0c4954f 100644
--- a/hessian_test/dup_struct_name_test.go
+++ b/hessian_test/dup_struct_name_test.go
@@ -106,13 +106,6 @@ func TestDupStructNameResponse(t *testing.T) {
 	assert.Nil(t, err)
 
 	decodedResponse := &hessian.Response{}
-	decodedResponse.RspObj = &dupclass.CaseZ{}
-	err = codecR.ReadBody(decodedResponse)
-	assert.NotNil(t, err)
-	assert.Equal(t, ExpectedErrorMsg, err.Error())
-
-	decodedResponse = &hessian.Response{}
-	decodedResponse.RspObj = &CaseZ{}
 	err = codecR.ReadBody(decodedResponse)
 	assert.Nil(t, err)
 
@@ -134,13 +127,6 @@ func TestDupStructNameResponse2(t *testing.T) {
 	assert.Nil(t, err)
 
 	decodedResponse := &hessian.Response{}
-	decodedResponse.RspObj = &CaseZ{}
-	err = codecR.ReadBody(decodedResponse)
-	assert.NotNil(t, err)
-	assert.Equal(t, ExpectedErrorMsg, err.Error())
-
-	decodedResponse = &hessian.Response{}
-	decodedResponse.RspObj = &dupclass.CaseZ{}
 	err = codecR.ReadBody(decodedResponse)
 	assert.Nil(t, err)
 
diff --git a/testcases/user/user.go b/testcases/user/user.go
new file mode 100644
index 0000000..888951b
--- /dev/null
+++ b/testcases/user/user.go
@@ -0,0 +1,87 @@
+/*
+ * 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 user
+
+import (
+	"fmt"
+	"strconv"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+type Gender hessian.JavaEnum
+
+const (
+	MAN Gender = iota
+	WOMAN
+)
+
+var genderName = map[Gender]string{
+	MAN:   "MAN",
+	WOMAN: "WOMAN",
+}
+
+var genderValue = map[string]Gender{
+	"MAN":   MAN,
+	"WOMAN": WOMAN,
+}
+
+func (g Gender) JavaClassName() string {
+	return "org.apache.dubbo.sample.Gender"
+}
+
+func (g Gender) String() string {
+	s, ok := genderName[g]
+	if ok {
+		return s
+	}
+
+	return strconv.Itoa(int(g))
+}
+
+func (g Gender) EnumValue(s string) hessian.JavaEnum {
+	v, ok := genderValue[s]
+	if ok {
+		return hessian.JavaEnum(v)
+	}
+
+	return hessian.InvalidJavaEnum
+}
+
+type User struct {
+	// !!! Cannot define lowercase names of variable
+	ID   string
+	Name string
+	Age  int32
+	Time time.Time
+	Sex  Gender // notice: java enum Object <--> go string
+}
+
+func (u User) String() string {
+	return fmt.Sprintf(
+		"User{ID:%s, Name:%s, Age:%d, Time:%s, Sex:%s}",
+		u.ID, u.Name, u.Age, u.Time, u.Sex,
+	)
+}
+
+func (u *User) JavaClassName() string {
+	return "org.apache.dubbo.sample.User"
+}
diff --git a/testcases/user/user_test.go b/testcases/user/user_test.go
new file mode 100644
index 0000000..3c7cf9d
--- /dev/null
+++ b/testcases/user/user_test.go
@@ -0,0 +1,57 @@
+/*
+ * 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 user
+
+import (
+	"testing"
+	"time"
+)
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+func TestEnumConvert(t *testing.T) {
+	var g interface{}
+	g = WOMAN
+
+	// new defined type cant be converted to the original type.
+	failConvertedValue, ok := g.(hessian.JavaEnum)
+	assert.False(t, ok)
+	assert.Equal(t, hessian.JavaEnum(0), failConvertedValue)
+}
+
+func TestUserEncodeDecode(t *testing.T) {
+	ts, _ := time.Parse("2006-01-02 15:04:05", "2019-01-01 12:34:56")
+	u1 := &User{ID: "001", Name: "Lily", Age: 18, Time: ts.Local(), Sex: WOMAN}
+	hessian.RegisterPOJO(u1)
+
+	encoder := hessian.NewEncoder()
+	err := encoder.Encode(u1)
+	assert.Nil(t, err)
+
+	buf := encoder.Buffer()
+	decoder := hessian.NewDecoder(buf)
+	dec, err := decoder.Decode()
+	assert.Nil(t, err)
+	assert.Equal(t, u1, dec)
+}