Skip to content
Permalink
Browse files
Merge pull request #279 from Chans-Open-Source/feature/optimizing_the…
…_registration_goname

Fix: dobbo-go issue #1454
  • Loading branch information
AlexStocks committed Sep 25, 2021
2 parents 74a8ece + 8959733 commit a0c5132ce20b13ad397873265fcd28e82ac2c6e6
Showing 5 changed files with 192 additions and 4 deletions.
@@ -0,0 +1,163 @@
/*
* 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 hessian

import (
"bufio"
"bytes"
"testing"
)

import (
dup "dubbo-go-hessian2-dup-struct-name-test"
)

import (
"github.com/stretchr/testify/assert"
)

const (
ExpectedErrorMsg = "reflect.Set: value of type hessian.CaseZ is not assignable to type hessian.CaseZ"
)

type CaseZ struct {
Name string
}

func (CaseZ) JavaClassName() string {
return "com.test.caseZ"
}

func TestDupStructNameRequest(t *testing.T) {
RegisterPOJO(&dup.CaseZ{})
RegisterPOJO(&CaseZ{})

packageType := PackageRequest
responseStatus := Zero
var body interface{}
body = []interface{}{"a"}
resp, err := doTestHessianEncodeHeader(t, packageType, responseStatus, body)
assert.Nil(t, err)

codecR := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))

h := &DubboHeader{}
err = codecR.ReadHeader(h)
assert.Nil(t, err)
assert.Equal(t, byte(2), h.SerialID)
assert.Equal(t, packageType, h.Type&(PackageRequest|PackageResponse|PackageHeartbeat))
assert.Equal(t, int64(1), h.ID)
assert.Equal(t, responseStatus, h.ResponseStatus)

c := make([]interface{}, 7)
err = codecR.ReadBody(c)
assert.Nil(t, err)
t.Log(c)
assert.True(t, len(body.([]interface{})) == len(c[5].([]interface{})))
}

func TestDupStructNameResponse(t *testing.T) {
defer func() {
if err := recover(); err != nil {
if errStr, ok := err.(string); ok {
assert.Equal(t, ExpectedErrorMsg, errStr)
}
}
}()

var body interface{}
body = &CaseZ{Name: "TestDupStructNameResponse"}
err, codecR, h := doTestHeader(t, body)
assert.Nil(t, err)

decodedResponse := &Response{}
decodedResponse.RspObj = &dup.CaseZ{}
err = codecR.ReadBody(decodedResponse)
assert.NotNil(t, err)
assert.Equal(t, ExpectedErrorMsg, err.Error())

decodedResponse = &Response{}
decodedResponse.RspObj = &CaseZ{}
err = codecR.ReadBody(decodedResponse)
assert.Nil(t, err)

checkResponseBody(t, decodedResponse, h, body)
}

func TestDupStructNameResponse2(t *testing.T) {
defer func() {
if err := recover(); err != nil {
if errStr, ok := err.(string); ok {
assert.Equal(t, ExpectedErrorMsg, errStr)
}
}
}()

var body interface{}
body = &dup.CaseZ{Name: "TestDupStructNameResponse"}
err, codecR, h := doTestHeader(t, body)
assert.Nil(t, err)

decodedResponse := &Response{}
decodedResponse.RspObj = &CaseZ{}
err = codecR.ReadBody(decodedResponse)
assert.NotNil(t, err)
assert.Equal(t, ExpectedErrorMsg, err.Error())

decodedResponse = &Response{}
decodedResponse.RspObj = &dup.CaseZ{}
err = codecR.ReadBody(decodedResponse)
assert.Nil(t, err)

checkResponseBody(t, decodedResponse, h, body)
}

func doTestHeader(t *testing.T, body interface{}) (error, *HessianCodec, *DubboHeader) {
RegisterPOJO(&dup.CaseZ{})
RegisterPOJO(&CaseZ{})

packageType := PackageResponse
responseStatus := Response_OK
resp, err := doTestHessianEncodeHeader(t, packageType, responseStatus, body)
assert.Nil(t, err)

codecR := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))

h := &DubboHeader{}
err = codecR.ReadHeader(h)
assert.Nil(t, err)

assert.Equal(t, byte(2), h.SerialID)
assert.Equal(t, packageType, h.Type&(PackageRequest|PackageResponse|PackageHeartbeat))
assert.Equal(t, int64(1), h.ID)
assert.Equal(t, responseStatus, h.ResponseStatus)
return err, codecR, h
}

func checkResponseBody(t *testing.T, decodedResponse *Response, h *DubboHeader, body interface{}) {
t.Log(decodedResponse)

if h.ResponseStatus != Zero && h.ResponseStatus != Response_OK {
assert.Equal(t, "java exception:"+body.(string), decodedResponse.Exception.Error())
return
}

in, _ := EnsureInterface(UnpackPtrValue(EnsurePackValue(body)), nil)
out, _ := EnsureInterface(UnpackPtrValue(EnsurePackValue(decodedResponse.RspObj)), nil)
assert.Equal(t, in, out)
}
2 go.mod
@@ -1,8 +1,10 @@
module github.com/apache/dubbo-go-hessian2

require (
dubbo-go-hessian2-dup-struct-name-test v0.0.3
github.com/dubbogo/gost v1.9.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.4.0
)

replace dubbo-go-hessian2-dup-struct-name-test => github.com/changedenczd/dubbo-go-hessian2-dup-struct-name-test v0.0.3
2 go.sum
@@ -1,3 +1,5 @@
github.com/changedenczd/dubbo-go-hessian2-dup-struct-name-test v0.0.3 h1:31bvQXq/6SUwQlr72MUSloySci2nM6Rdfc2A0cT4eGA=
github.com/changedenczd/dubbo-go-hessian2-dup-struct-name-test v0.0.3/go.mod h1:hDdmLYpL9E/pGzbUrBl5mWkibKysKDYaKVkC3CcWtcA=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dubbogo/gost v1.9.0 h1:UT+dWwvLyJiDotxJERO75jB3Yxgsdy10KztR5ycxRAk=
@@ -160,7 +160,8 @@ func (e *Encoder) writeTypedList(v interface{}) error {
}

value = UnpackPtrValue(value)
totype := UnpackPtrType(value.Type().Elem()).String()
goType := UnpackPtrType(value.Type().Elem())
totype := combineGoName(goType)
typeName := getListTypeName(totype)
if typeName == "" {
return perrors.New("no this type name: " + totype)
26 pojo.go
@@ -20,6 +20,7 @@ package hessian
import (
"fmt"
"reflect"
"regexp"
"strings"
"sync"
"unicode"
@@ -101,6 +102,8 @@ var (
}
pojoType = reflect.TypeOf((*POJO)(nil)).Elem()
javaEnumType = reflect.TypeOf((*POJOEnum)(nil)).Elem()

goPkgPathWhiteListRegexp = regexp.MustCompile(`^(github\.com/apache/dubbo-go-hessian2|time)`)
)

// struct parsing
@@ -126,6 +129,7 @@ func RegisterPOJOMapping(javaClassName string, o interface{}) int {
defer pojoRegistry.Unlock()

if goName, ok := pojoRegistry.j2g[javaClassName]; ok {
// TODO print warning message about duplicate registration JavaClass
return pojoRegistry.registry[goName].index
}

@@ -143,8 +147,7 @@ func RegisterPOJOMapping(javaClassName string, o interface{}) int {
)

sttInfo.typ = obtainValueType(o)

sttInfo.goName = sttInfo.typ.String()
sttInfo.goName = getGoName(o)
sttInfo.javaName = javaClassName
sttInfo.inst = o
pojoRegistry.j2g[sttInfo.javaName] = sttInfo.goName
@@ -225,7 +228,7 @@ func unRegisterPOJO(o POJO) int {
pojoRegistry.Lock()
defer pojoRegistry.Unlock()

goName := obtainValueType(o).String()
goName := getGoName(o)

if structInfo, ok := pojoRegistry.registry[goName]; ok {
delete(pojoRegistry.j2g, structInfo.javaName)
@@ -240,6 +243,23 @@ func unRegisterPOJO(o POJO) int {
return -1
}

func getGoName(o interface{}) string {
goType := reflect.TypeOf(o)
for reflect.Ptr == goType.Kind() {
goType = goType.Elem()
}
return combineGoName(goType)
}

func combineGoName(t reflect.Type) string {
pkgPath := t.PkgPath()
goName := t.String()
if pkgPath == "" || goPkgPathWhiteListRegexp.Match([]byte(pkgPath)) {
return goName
}
return pkgPath + "/" + goName
}

func obtainValueType(o interface{}) reflect.Type {
v := reflect.ValueOf(o)
switch v.Kind() {

0 comments on commit a0c5132

Please sign in to comment.