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 a78e2a3 BREAKING CHANGE: remove dubbo protocol impl which replaced by
the impl in dubbo-go project (#364)
a78e2a3 is described below
commit a78e2a36a46009adc56139f94f5c20515e2a5efb
Author: 望哥 <[email protected]>
AuthorDate: Thu Apr 17 06:28:15 2025 +0800
BREAKING CHANGE: remove dubbo protocol impl which replaced by the impl in
dubbo-go project (#364)
Co-authored-by: tiltwind <[email protected]>
---
hessian.go | 249 -----------------------
hessian_test.go | 234 ----------------------
hessian_test/dup_struct_name_test.go | 126 ------------
request.go | 358 ---------------------------------
request_test.go | 157 ---------------
response.go | 370 -----------------------------------
response_test.go | 220 ---------------------
7 files changed, 1714 deletions(-)
diff --git a/hessian.go b/hessian.go
deleted file mode 100644
index 231dbea..0000000
--- a/hessian.go
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * 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.
- */
-
-// This file contains the implementation of
-// [dubbo2 rpc
protocol](https://dubbo.apache.org/zh/docs/concepts/rpc-protocol/#dubbo2),
which is deprecated.
-// Use the
[implementation](https://github.com/apache/dubbo-go/tree/master/protocol/dubbo/hessian2)
in dubbo-go project instead.
-
-package hessian
-
-import (
- "bufio"
- "encoding/binary"
- "time"
-)
-
-import (
- perrors "github.com/pkg/errors"
-)
-
-// enum part
-const (
- PackageError = PackageType(0x01)
- PackageRequest = PackageType(0x02)
- PackageResponse = PackageType(0x04)
- PackageHeartbeat = PackageType(0x08)
- PackageRequest_TwoWay = PackageType(0x10)
- PackageResponse_Exception = PackageType(0x20)
- PackageType_BitSize = 0x2f
-)
-
-// PackageType defines dubbo package type.
-type PackageType int
-
-// DubboHeader dubbo header
-type DubboHeader struct {
- SerialID byte
- Type PackageType
- ID int64
- BodyLen int
- ResponseStatus byte
-}
-
-// Service defines service instance
-type Service struct {
- Path string
- Interface string
- Group string
- Version string
- Method string
- Timeout time.Duration // request timeout
-}
-
-// HessianCodec defines hessian codec
-type HessianCodec struct {
- pkgType PackageType
- reader *bufio.Reader
- bodyLen int
-}
-
-// NewHessianCodec generate a new hessian codec instance
-func NewHessianCodec(reader *bufio.Reader) *HessianCodec {
- return &HessianCodec{
- reader: reader,
- }
-}
-
-// NewHessianCodecCustom generate a new hessian codec instance.
-func NewHessianCodecCustom(pkgType PackageType, reader *bufio.Reader, bodyLen
int) *HessianCodec {
- return &HessianCodec{
- pkgType: pkgType,
- reader: reader,
- bodyLen: bodyLen,
- }
-}
-
-func (h *HessianCodec) Write(service Service, header DubboHeader, body
interface{}) ([]byte, error) {
- switch header.Type {
- case PackageHeartbeat:
- if header.ResponseStatus == Zero {
- return packRequest(service, header, body)
- }
- return packResponse(header, body)
-
- case PackageRequest, PackageRequest_TwoWay:
- return packRequest(service, header, body)
-
- case PackageResponse:
- return packResponse(header, body)
-
- default:
- return nil, perrors.Errorf("Unrecognized message type: %v",
header.Type)
- }
-}
-
-// ReadHeader uses hessian codec to read dubbo header
-func (h *HessianCodec) ReadHeader(header *DubboHeader) error {
- var err error
-
- if h.reader.Size() < HEADER_LENGTH {
- return ErrHeaderNotEnough
- }
- buf, err := h.reader.Peek(HEADER_LENGTH)
- if err != nil { // this is impossible
- return perrors.WithStack(err)
- }
- _, err = h.reader.Discard(HEADER_LENGTH)
- if err != nil { // this is impossible
- return perrors.WithStack(err)
- }
-
- //// read header
-
- if buf[0] != MAGIC_HIGH && buf[1] != MAGIC_LOW {
- return ErrIllegalPackage
- }
-
- // Header{serialization id(5 bit), event, two way, req/response}
- if header.SerialID = buf[2] & SERIAL_MASK; header.SerialID == Zero {
- return perrors.Errorf("serialization ID:%v", header.SerialID)
- }
-
- headerFlag := buf[2] & FLAG_EVENT
- if headerFlag != Zero {
- header.Type |= PackageHeartbeat
- }
- headerFlag = buf[2] & FLAG_REQUEST
- if headerFlag != Zero {
- header.Type |= PackageRequest
- headerFlag = buf[2] & FLAG_TWOWAY
- if headerFlag != Zero {
- header.Type |= PackageRequest_TwoWay
- }
- } else {
- header.Type |= PackageResponse
- header.ResponseStatus = buf[3]
- if header.ResponseStatus != Response_OK {
- header.Type |= PackageResponse_Exception
- }
- }
-
- // Header{req id}
- header.ID = int64(binary.BigEndian.Uint64(buf[4:]))
-
- // Header{body len}
- header.BodyLen = int(binary.BigEndian.Uint32(buf[12:]))
- if header.BodyLen < 0 {
- return ErrIllegalPackage
- }
-
- h.pkgType = header.Type
- h.bodyLen = header.BodyLen
-
- if h.reader.Buffered() < h.bodyLen {
- return ErrBodyNotEnough
- }
-
- return perrors.WithStack(err)
-}
-
-// ReadBody uses hessian codec to read response body
-func (h *HessianCodec) ReadBody(rspObj interface{}) error {
- if h.reader.Buffered() < h.bodyLen {
- return ErrBodyNotEnough
- }
- buf, err := h.reader.Peek(h.bodyLen)
- if err != nil {
- return perrors.WithStack(err)
- }
- _, err = h.reader.Discard(h.bodyLen)
- if err != nil { // this is impossible
- return perrors.WithStack(err)
- }
-
- switch h.pkgType & PackageType_BitSize {
- case PackageResponse | PackageHeartbeat | PackageResponse_Exception,
PackageResponse | PackageResponse_Exception:
- decoder := NewDecoder(buf[:])
- exception, decErr := decoder.Decode()
- if decErr != nil {
- return perrors.WithStack(decErr)
- }
- rsp, ok := rspObj.(*Response)
- if !ok {
- return perrors.Errorf("java exception:%s",
exception.(string))
- }
- rsp.Exception = perrors.Errorf("java exception:%s",
exception.(string))
- return nil
- case PackageRequest | PackageHeartbeat, PackageResponse |
PackageHeartbeat:
- case PackageRequest:
- if rspObj != nil {
- if err = unpackRequestBody(NewStrictDecoder(buf[:]),
rspObj); err != nil {
- return perrors.WithStack(err)
- }
- }
- case PackageResponse:
- if rspObj != nil {
- if err = unpackResponseBody(NewDecoder(buf[:]),
rspObj); err != nil {
- return perrors.WithStack(err)
- }
- }
- }
-
- return nil
-}
-
-// ReadAttachments ignore body, but only read attachments
-func (h *HessianCodec) ReadAttachments() (map[string]string, error) {
- if h.reader.Buffered() < h.bodyLen {
- return nil, ErrBodyNotEnough
- }
- buf, err := h.reader.Peek(h.bodyLen)
- if err != nil {
- return nil, perrors.WithStack(err)
- }
- _, err = h.reader.Discard(h.bodyLen)
- if err != nil { // this is impossible
- return nil, perrors.WithStack(err)
- }
-
- switch h.pkgType & PackageType_BitSize {
- case PackageRequest:
- rspObj := make([]interface{}, 7)
- if err = unpackRequestBody(NewDecoderWithSkip(buf[:]), rspObj);
err != nil {
- return nil, perrors.WithStack(err)
- }
- return rspObj[6].(map[string]string), nil
- case PackageResponse:
- rspObj := &Response{}
- if err = unpackResponseBody(NewDecoderWithSkip(buf[:]),
rspObj); err != nil {
- return nil, perrors.WithStack(err)
- }
- return rspObj.Attachments, nil
- }
-
- return nil, nil
-}
diff --git a/hessian_test.go b/hessian_test.go
deleted file mode 100644
index 5a46b13..0000000
--- a/hessian_test.go
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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"
- "reflect"
- "testing"
- "time"
-)
-
-import (
- "github.com/stretchr/testify/assert"
-)
-
-type Case struct {
- A string
- 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 {
- return "com.test.case"
-}
-
-func doTestHessianEncodeHeader(t *testing.T, packageType PackageType,
responseStatus byte, body interface{}) ([]byte, error) {
- RegisterPOJO(&Case{})
- codecW := NewHessianCodec(nil)
- resp, err := codecW.Write(Service{
- Path: "test",
- Interface: "ITest",
- Version: "v1.0",
- Method: "test",
- Timeout: time.Second * 10,
- }, DubboHeader{
- SerialID: 2,
- Type: packageType,
- ID: 1,
- ResponseStatus: responseStatus,
- }, body)
- assert.Nil(t, err)
- return resp, err
-}
-
-func doTestResponse(t *testing.T, packageType PackageType, responseStatus
byte, body interface{}, decodedResponse *Response, assertFunc func()) {
- 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)
-
- err = codecR.ReadBody(decodedResponse)
- assert.Nil(t, err)
- t.Log(decodedResponse)
-
- if assertFunc != nil {
- assertFunc()
- return
- }
-
- if h.ResponseStatus != Zero && h.ResponseStatus != Response_OK {
- assert.Equal(t, "java exception:"+body.(string),
decodedResponse.Exception.Error())
- return
- }
-
- in := EnsureRawAny(UnpackPtrValue(EnsurePackValue(body)))
- out :=
EnsureRawAny(UnpackPtrValue(EnsurePackValue(decodedResponse.RspObj)))
- assert.Equal(t, in, out)
-}
-
-func TestResponse(t *testing.T) {
- caseObj := Case{A: "a", B: 1}
- decodedResponse := &Response{}
- RegisterPOJO(&caseObj)
-
- arr := []*Case{&caseObj}
- decodedResponse.RspObj = nil
- doTestResponse(t, PackageResponse, Response_OK, arr, decodedResponse,
func() {
- arrRes, ok := decodedResponse.RspObj.([]*Case)
- if !ok {
- t.Errorf("expect []*Case, but get %s",
reflect.TypeOf(decodedResponse.RspObj).String())
- return
- }
- assert.Equal(t, 1, len(arrRes))
- assert.Equal(t, &caseObj, arrRes[0])
- })
-
- doTestResponse(t, PackageResponse, Response_OK, &caseObj,
decodedResponse, func() {
- assert.Equal(t, &caseObj, decodedResponse.RspObj)
- })
-
- s := "ok!!!!!"
- doTestResponse(t, PackageResponse, Response_OK, s, decodedResponse,
func() {
- assert.Equal(t, s, decodedResponse.RspObj)
- })
-
- doTestResponse(t, PackageResponse, Response_OK, int64(3),
decodedResponse, func() {
- assert.Equal(t, int64(3), decodedResponse.RspObj)
- })
-
- doTestResponse(t, PackageResponse, Response_OK, true, decodedResponse,
func() {
- assert.Equal(t, true, decodedResponse.RspObj)
- })
-
- errorMsg := "error!!!!!"
- decodedResponse.RspObj = nil
- doTestResponse(t, PackageResponse, Response_SERVER_ERROR, errorMsg,
decodedResponse, func() {
- assert.Equal(t, "java exception:error!!!!!",
decodedResponse.Exception.Error())
- })
-
- decodedResponse.RspObj = nil
- decodedResponse.Exception = nil
- mapObj := map[string][]*Case{"key": {&caseObj}}
- doTestResponse(t, PackageResponse, Response_OK, mapObj,
decodedResponse, func() {
- mapRes, ok :=
decodedResponse.RspObj.(map[interface{}]interface{})
- if !ok {
- t.Errorf("expect map[string][]*Case, but get %s",
reflect.TypeOf(decodedResponse.RspObj).String())
- return
- }
- c, ok := mapRes["key"]
- if !ok {
- assert.FailNow(t, "no key in decoded response map")
- }
-
- mapValueArr, ok := c.([]*Case)
- if !ok {
- assert.FailNow(t, "invalid decoded response map value",
"expect []*Case, but get %v", reflect.TypeOf(c))
- }
- assert.Equal(t, 1, len(mapValueArr))
- assert.Equal(t, &caseObj, mapValueArr[0])
- })
-}
-
-func doTestRequest(t *testing.T, packageType PackageType, responseStatus byte,
body interface{}) {
- 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 TestRequest(t *testing.T) {
- doTestRequest(t, PackageRequest, Zero, []interface{}{"a"})
- doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3})
- doTestRequest(t, PackageRequest, Zero, []interface{}{"a", true})
- doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3, true})
- doTestRequest(t, PackageRequest, Zero, []interface{}{3.2, true})
- doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3, true,
&Case{A: "a", B: 3}})
- 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.NoError(t, err)
- // 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/hessian_test/dup_struct_name_test.go
b/hessian_test/dup_struct_name_test.go
index 0c4954f..b5d6950 100644
--- a/hessian_test/dup_struct_name_test.go
+++ b/hessian_test/dup_struct_name_test.go
@@ -18,10 +18,7 @@
package hessian_test
import (
- "bufio"
- "bytes"
"testing"
- "time"
)
import (
@@ -45,129 +42,6 @@ func (CaseZ) JavaClassName() string {
return "com.test.caseZ"
}
-func doTestHessianEncodeHeader(t *testing.T, packageType hessian.PackageType,
responseStatus byte, body interface{}) ([]byte, error) {
- codecW := hessian.NewHessianCodec(nil)
- resp, err := codecW.Write(hessian.Service{
- Path: "test",
- Interface: "ITest",
- Version: "v1.0",
- Method: "test",
- Timeout: time.Second * 10,
- }, hessian.DubboHeader{
- SerialID: 2,
- Type: packageType,
- ID: 1,
- ResponseStatus: responseStatus,
- }, body)
- assert.Nil(t, err)
- return resp, err
-}
-
-func TestDupStructNameRequest(t *testing.T) {
- hessian.RegisterPOJO(&dupclass.CaseZ{})
- hessian.RegisterPOJO(&CaseZ{})
-
- packageType := hessian.PackageRequest
- responseStatus := hessian.Zero
- var body interface{}
- body = []interface{}{"a"}
- resp, err := doTestHessianEncodeHeader(t, packageType, responseStatus,
body)
- assert.Nil(t, err)
-
- codecR :=
hessian.NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
-
- h := &hessian.DubboHeader{}
- err = codecR.ReadHeader(h)
- assert.Nil(t, err)
- assert.Equal(t, byte(2), h.SerialID)
- assert.Equal(t, packageType,
h.Type&(hessian.PackageRequest|hessian.PackageResponse|hessian.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 := &hessian.Response{}
- 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 = &dupclass.CaseZ{Name: "TestDupStructNameResponse"}
- err, codecR, h := doTestHeader(t, body)
- assert.Nil(t, err)
-
- decodedResponse := &hessian.Response{}
- err = codecR.ReadBody(decodedResponse)
- assert.Nil(t, err)
-
- checkResponseBody(t, decodedResponse, h, body)
-}
-
-func doTestHeader(t *testing.T, body interface{}) (error,
*hessian.HessianCodec, *hessian.DubboHeader) {
- hessian.RegisterPOJO(&dupclass.CaseZ{})
- hessian.RegisterPOJO(&CaseZ{})
-
- packageType := hessian.PackageResponse
- responseStatus := hessian.Response_OK
- resp, err := doTestHessianEncodeHeader(t, packageType, responseStatus,
body)
- assert.Nil(t, err)
-
- codecR :=
hessian.NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
-
- h := &hessian.DubboHeader{}
- err = codecR.ReadHeader(h)
- assert.Nil(t, err)
-
- assert.Equal(t, byte(2), h.SerialID)
- assert.Equal(t, packageType,
h.Type&(hessian.PackageRequest|hessian.PackageResponse|hessian.PackageHeartbeat))
- assert.Equal(t, int64(1), h.ID)
- assert.Equal(t, responseStatus, h.ResponseStatus)
- return err, codecR, h
-}
-
-func checkResponseBody(t *testing.T, decodedResponse *hessian.Response, h
*hessian.DubboHeader, body interface{}) {
- t.Log(decodedResponse)
-
- if h.ResponseStatus != hessian.Zero && h.ResponseStatus !=
hessian.Response_OK {
- assert.Equal(t, "java exception:"+body.(string),
decodedResponse.Exception.Error())
- return
- }
-
- in :=
hessian.EnsureRawAny(hessian.UnpackPtrValue(hessian.EnsurePackValue(body)))
- out :=
hessian.EnsureRawAny(hessian.UnpackPtrValue(hessian.EnsurePackValue(decodedResponse.RspObj)))
- assert.Equal(t, in, out)
-}
-
func TestDuplicatedClassGetGoType(t *testing.T) {
assert.Equal(t,
"github.com/apache/dubbo-go-hessian2/hessian_test_test/hessian_test.CaseZ",
hessian.GetGoType(&CaseZ{}))
assert.Equal(t,
"github.com/apache/dubbo-go-hessian2/hessian_test/hessian_test/hessian_test.CaseZ",
hessian.GetGoType(&dupclass.CaseZ{}))
diff --git a/request.go b/request.go
deleted file mode 100644
index a6def73..0000000
--- a/request.go
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * 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.
- */
-
-// This file contains the implementation of
-// [dubbo2 rpc
protocol](https://dubbo.apache.org/zh/docs/concepts/rpc-protocol/#dubbo2),
which is deprecated.
-// Use the
[implementation](https://github.com/apache/dubbo-go/tree/master/protocol/dubbo/hessian2)
in dubbo-go project instead.
-
-package hessian
-
-import (
- "encoding/binary"
- "reflect"
- "strconv"
- "strings"
- "time"
-)
-
-import (
- perrors "github.com/pkg/errors"
-)
-
-/////////////////////////////////////////
-// dubbo
-/////////////////////////////////////////
-
-func getArgType(v interface{}) string {
- if v == nil {
- return "V"
- }
-
- switch v.(type) {
- // Serialized tags for base types
- case nil:
- return "V"
- case bool:
- return "Z"
- case []bool:
- return "[Z"
- case byte:
- return "B"
- case []byte:
- return "[B"
- case int8:
- return "B"
- case []int8:
- return "[B"
- case int16:
- return "S"
- case []int16:
- return "[S"
- case uint16: // Equivalent to Char of Java
- return "C"
- case []uint16:
- return "[C"
- // case rune:
- // return "C"
- case int:
- return "J"
- case []int:
- return "[J"
- case int32:
- return "I"
- case []int32:
- return "[I"
- case int64:
- return "J"
- case []int64:
- return "[J"
- case time.Time:
- return "java.util.Date"
- case []time.Time:
- return "[Ljava.util.Date"
- case float32:
- return "F"
- case []float32:
- return "[F"
- case float64:
- return "D"
- case []float64:
- return "[D"
- case string:
- return "java.lang.String"
- case []string:
- return "[Ljava.lang.String;"
- case []Object:
- return "[Ljava.lang.Object;"
- case map[interface{}]interface{}:
- // return "java.util.HashMap"
- return "java.util.Map"
- case POJOEnum:
- return v.(POJOEnum).JavaClassName()
- // Serialized tags for complex types
- default:
- t := reflect.TypeOf(v)
- if reflect.Ptr == t.Kind() {
- t = t.Elem()
- }
- switch t.Kind() {
- case reflect.Struct:
- v, ok := v.(POJO)
- if ok {
- return v.JavaClassName()
- }
- return "java.lang.Object"
- case reflect.Slice, reflect.Array:
- if t.Elem().Kind() == reflect.Struct {
- return "[Ljava.lang.Object;"
- }
- // return "java.util.ArrayList"
- return "java.util.List"
- case reflect.Map: // Enter here, map may be map[string]int
- return "java.util.Map"
- default:
- return ""
- }
- }
-
- // unreachable
- // return "java.lang.RuntimeException"
-}
-
-func getArgsTypeList(args []interface{}) (string, error) {
- var (
- typ string
- types string
- )
-
- for i := range args {
- typ = getArgType(args[i])
- if typ == "" {
- return types, perrors.Errorf("cat not get arg %#v
type", args[i])
- }
- if !strings.Contains(typ, ".") {
- types += typ
- } else if strings.Index(typ, "[") == 0 {
- types += strings.Replace(typ, ".", "/", -1)
- } else {
- // java.util.List -> Ljava/util/List;
- types += "L" + strings.Replace(typ, ".", "/", -1) + ";"
- }
- }
-
- return types, nil
-}
-
-type Request struct {
- Params interface{}
- Attachments map[string]string
-}
-
-// NewRequest create a new Request
-func NewRequest(params interface{}, atta map[string]string) *Request {
- if atta == nil {
- atta = make(map[string]string)
- }
- return &Request{
- Params: params,
- Attachments: atta,
- }
-}
-
-func EnsureRequest(body interface{}) *Request {
- if req, ok := body.(*Request); ok {
- return req
- }
- return NewRequest(body, nil)
-}
-
-func packRequest(service Service, header DubboHeader, req interface{})
([]byte, error) {
- var (
- err error
- types string
- byteArray []byte
- pkgLen int
- )
-
- request := EnsureRequest(req)
-
- args, ok := request.Params.([]interface{})
- if !ok {
- return nil, perrors.Errorf("@params is not of type:
[]interface{}")
- }
-
- hb := header.Type == PackageHeartbeat
-
- //////////////////////////////////////////
- // byteArray
- //////////////////////////////////////////
- // magic
- switch header.Type {
- case PackageHeartbeat:
- byteArray = append(byteArray, DubboRequestHeartbeatHeader[:]...)
- case PackageRequest_TwoWay:
- byteArray = append(byteArray,
DubboRequestHeaderBytesTwoWay[:]...)
- default:
- byteArray = append(byteArray, DubboRequestHeaderBytes[:]...)
- }
-
- // serialization id, two way flag, event, request/response flag
- // SerialID is id of serialization approach in java dubbo
- byteArray[2] |= header.SerialID & SERIAL_MASK
- // request id
- binary.BigEndian.PutUint64(byteArray[4:], uint64(header.ID))
-
- encoder := NewEncoder()
- encoder.Append(byteArray[:HEADER_LENGTH])
-
- //////////////////////////////////////////
- // body
- //////////////////////////////////////////
- if hb {
- encoder.Encode(nil)
- goto END
- }
-
- // dubbo version + path + version + method
- encoder.Encode(DEFAULT_DUBBO_PROTOCOL_VERSION)
- encoder.Encode(service.Path)
- encoder.Encode(service.Version)
- encoder.Encode(service.Method)
-
- // args = args type list + args value list
- if types, err = getArgsTypeList(args); err != nil {
- return nil, perrors.Wrapf(err, " PackRequest(args:%+v)", args)
- }
- encoder.Encode(types)
- for _, v := range args {
- encoder.Encode(v)
- }
-
- request.Attachments[PATH_KEY] = service.Path
- request.Attachments[VERSION_KEY] = service.Version
- if len(service.Group) > 0 {
- request.Attachments[GROUP_KEY] = service.Group
- }
- if len(service.Interface) > 0 {
- request.Attachments[INTERFACE_KEY] = service.Interface
- }
- if service.Timeout != 0 {
- request.Attachments[TIMEOUT_KEY] =
strconv.Itoa(int(service.Timeout / time.Millisecond))
- }
-
- encoder.Encode(request.Attachments)
-
-END:
- byteArray = encoder.Buffer()
- pkgLen = len(byteArray)
- if pkgLen > int(DEFAULT_LEN) { // 8M
- return nil, perrors.Errorf("Data length %d too large, max
payload %d", pkgLen, DEFAULT_LEN)
- }
- // byteArray{body length}
- binary.BigEndian.PutUint32(byteArray[12:], uint32(pkgLen-HEADER_LENGTH))
- return byteArray, nil
-}
-
-// hessian decode request body
-func unpackRequestBody(decoder *Decoder, reqObj interface{}) error {
- if decoder == nil {
- return perrors.Errorf("@decoder is nil")
- }
-
- req, ok := reqObj.([]interface{})
- if !ok {
- return perrors.Errorf("@reqObj is not of type: []interface{}")
- }
- if len(req) < 7 {
- return perrors.New("length of @reqObj should be 7")
- }
-
- var (
- err error
- dubboVersion, target, serviceVersion, method, argsTypes
interface{}
- args
[]interface{}
- )
-
- dubboVersion, err = decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- req[0] = dubboVersion
-
- target, err = decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- req[1] = target
-
- serviceVersion, err = decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- req[2] = serviceVersion
-
- method, err = decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- req[3] = method
-
- argsTypes, err = decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- req[4] = argsTypes
-
- ats := DescRegex.FindAllString(argsTypes.(string), -1)
- var arg interface{}
- for i := 0; i < len(ats); i++ {
- arg, err = decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- args = append(args, arg)
- }
- req[5] = args
-
- attachments, err := decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
- if v, ok := attachments.(map[interface{}]interface{}); ok {
- v[DUBBO_VERSION_KEY] = dubboVersion
- req[6] = ToMapStringString(v)
- return nil
- }
-
- return perrors.Errorf("get wrong attachments: %+v", attachments)
-}
-
-func ToMapStringString(origin map[interface{}]interface{}) map[string]string {
- dest := make(map[string]string, len(origin))
- for k, v := range origin {
- if kv, ok := k.(string); ok {
- if v == nil {
- dest[kv] = ""
- continue
- }
- if vv, ok := v.(string); ok {
- dest[kv] = vv
- }
- }
- }
- return dest
-}
diff --git a/request_test.go b/request_test.go
deleted file mode 100644
index 2b7f1f3..0000000
--- a/request_test.go
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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 (
- "reflect"
- "strconv"
- "testing"
- "time"
-)
-
-import (
- "github.com/stretchr/testify/assert"
-)
-
-type TestEnumGender JavaEnum
-
-const (
- MAN JavaEnum = iota
- WOMAN
-)
-
-var genderName = map[JavaEnum]string{
- MAN: "MAN",
- WOMAN: "WOMAN",
-}
-
-var genderValue = map[string]JavaEnum{
- "MAN": MAN,
- "WOMAN": WOMAN,
-}
-
-func (g TestEnumGender) JavaClassName() string {
- return "com.ikurento.test.TestEnumGender"
-}
-
-func (g TestEnumGender) String() string {
- s, ok := genderName[JavaEnum(g)]
- if ok {
- return s
- }
-
- return strconv.Itoa(int(g))
-}
-
-func (g TestEnumGender) EnumValue(s string) JavaEnum {
- v, ok := genderValue[s]
- if ok {
- return v
- }
-
- return InvalidJavaEnum
-}
-
-func TestPackRequest(t *testing.T) {
- bytes, err := packRequest(Service{
- Path: "test",
- Interface: "ITest",
- Version: "v1.0",
- Method: "test",
- Timeout: time.Second * 10,
- }, DubboHeader{
- SerialID: 0,
- Type: PackageRequest,
- ID: 123,
- }, []interface{}{1, 2})
-
- assert.Nil(t, err)
-
- if bytes != nil {
- t.Logf("pack request: %s", string(bytes))
- }
-}
-
-func TestGetArgsTypeList(t *testing.T) {
- type Test struct{}
- str, err := getArgsTypeList([]interface{}{nil, 1, []int{2}, true,
[]bool{false}, "a", []string{"b"}, Test{}, &Test{}, []Test{},
map[string]Test{}, TestEnumGender(MAN)})
- assert.NoError(t, err)
- assert.Equal(t,
"VJ[JZ[ZLjava/lang/String;[Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;Ljava/util/Map;Lcom/ikurento/test/TestEnumGender;",
str)
-}
-
-func TestDescRegex(t *testing.T) {
- results := DescRegex.FindAllString("Ljava/lang/String;", -1)
- assert.Equal(t, 1, len(results))
- assert.Equal(t, "Ljava/lang/String;", results[0])
-
- results = DescRegex.FindAllString("Ljava/lang/String;I", -1)
- assert.Equal(t, 2, len(results))
- assert.Equal(t, "Ljava/lang/String;", results[0])
- assert.Equal(t, "I", results[1])
-
- results = DescRegex.FindAllString("ILjava/lang/String;", -1)
- assert.Equal(t, 2, len(results))
- assert.Equal(t, "I", results[0])
- assert.Equal(t, "Ljava/lang/String;", results[1])
-
- results = DescRegex.FindAllString("ILjava/lang/String;IZ", -1)
- assert.Equal(t, 4, len(results))
- assert.Equal(t, "I", results[0])
- assert.Equal(t, "Ljava/lang/String;", results[1])
- assert.Equal(t, "I", results[2])
- assert.Equal(t, "Z", results[3])
-
- results = DescRegex.FindAllString("[Ljava/lang/String;[I", -1)
- assert.Equal(t, 2, len(results))
- assert.Equal(t, "[Ljava/lang/String;", results[0])
- assert.Equal(t, "[I", results[1])
-}
-
-func TestIssue192(t *testing.T) {
- type args struct {
- origin map[interface{}]interface{}
- }
- tests := []struct {
- name string
- args args
- want map[string]string
- }{
- {
- name: "not null",
- args: args{
- origin: map[interface{}]interface{}{
- "1": nil,
- "2": "3",
- "": "",
- },
- },
- want: map[string]string{
- "1": "",
- "2": "3",
- "": "",
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if got := ToMapStringString(tt.args.origin);
!reflect.DeepEqual(got, tt.want) {
- t.Errorf("ToMapStringString() = %v, want %v",
got, tt.want)
- }
- })
- }
-}
diff --git a/response.go b/response.go
deleted file mode 100644
index 5f90592..0000000
--- a/response.go
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * 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.
- */
-
-// This file contains the implementation of
-// [dubbo2 rpc
protocol](https://dubbo.apache.org/zh/docs/concepts/rpc-protocol/#dubbo2),
which is deprecated.
-// Use the
[implementation](https://github.com/apache/dubbo-go/tree/master/protocol/dubbo/hessian2)
in dubbo-go project instead.
-
-package hessian
-
-import (
- "encoding/binary"
- "math"
- "reflect"
- "strconv"
- "strings"
-
- "github.com/apache/dubbo-go-hessian2/java_exception"
- perrors "github.com/pkg/errors"
-)
-
-// Response dubbo response
-type Response struct {
- RspObj interface{}
- Exception error
- Attachments map[string]string
-}
-
-// NewResponse create a new Response
-func NewResponse(rspObj interface{}, exception error, attachments
map[string]string) *Response {
- if attachments == nil {
- attachments = make(map[string]string, 8)
- }
- return &Response{
- RspObj: rspObj,
- Exception: exception,
- Attachments: attachments,
- }
-}
-
-// EnsureResponse check body type, make sure it's a Response or package it as
a Response
-func EnsureResponse(body interface{}) *Response {
- if res, ok := body.(*Response); ok {
- return res
- }
- if exp, ok := body.(error); ok {
- return NewResponse(nil, exp, nil)
- }
- return NewResponse(body, nil, nil)
-}
-
-//
https://github.com/apache/dubbo/blob/dubbo-2.7.1/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java#L256
-// hessian encode response
-func packResponse(header DubboHeader, ret interface{}) ([]byte, error) {
- var byteArray []byte
-
- response := EnsureResponse(ret)
-
- hb := header.Type == PackageHeartbeat
-
- // magic
- if hb {
- byteArray = append(byteArray,
DubboResponseHeartbeatHeader[:]...)
- } else {
- byteArray = append(byteArray, DubboResponseHeaderBytes[:]...)
- }
- // set serialID, identify serialization types, eg: fastjson->6,
hessian2->2
- byteArray[2] |= header.SerialID & SERIAL_MASK
- // response status
- if header.ResponseStatus != 0 {
- byteArray[3] = header.ResponseStatus
- }
-
- // request id
- binary.BigEndian.PutUint64(byteArray[4:], uint64(header.ID))
-
- // body
- encoder := NewEncoder()
- encoder.Append(byteArray[:HEADER_LENGTH])
-
- if header.ResponseStatus == Response_OK {
- if hb {
- encoder.Encode(nil)
- } else {
- atta :=
isSupportResponseAttachment(response.Attachments[DUBBO_VERSION_KEY])
-
- var resWithException, resValue, resNullValue int32
- if atta {
- resWithException =
RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS
- resValue = RESPONSE_VALUE_WITH_ATTACHMENTS
- resNullValue =
RESPONSE_NULL_VALUE_WITH_ATTACHMENTS
- } else {
- resWithException = RESPONSE_WITH_EXCEPTION
- resValue = RESPONSE_VALUE
- resNullValue = RESPONSE_NULL_VALUE
- }
-
- if response.Exception != nil { // throw error
- encoder.Encode(resWithException)
- if t, ok :=
response.Exception.(java_exception.Throwabler); ok {
- encoder.Encode(t)
- } else {
-
encoder.Encode(java_exception.NewThrowable(response.Exception.Error()))
- }
- } else {
- if response.RspObj == nil {
- encoder.Encode(resNullValue)
- } else {
- encoder.Encode(resValue)
- encoder.Encode(response.RspObj) //
result
- }
- }
-
- if atta {
- encoder.Encode(response.Attachments) //
attachments
- }
- }
- } else {
- if response.Exception != nil { // throw error
- encoder.Encode(response.Exception.Error())
- } else {
- encoder.Encode(response.RspObj)
- }
- }
-
- byteArray = encoder.Buffer()
- byteArray = EncNull(byteArray) // if not, "java client" will throw
exception "unexpected end of file"
- pkgLen := len(byteArray)
- if pkgLen > int(DEFAULT_LEN) { // 8M
- return nil, perrors.Errorf("Data length %d too large, max
payload %d", pkgLen, DEFAULT_LEN)
- }
- // byteArray{body length}
- binary.BigEndian.PutUint32(byteArray[12:], uint32(pkgLen-HEADER_LENGTH))
- return byteArray, nil
-}
-
-// hessian decode response body
-func unpackResponseBody(decoder *Decoder, resp interface{}) error {
- // body
- if decoder == nil {
- return perrors.Errorf("@decoder is nil")
- }
- rspType, err := decoder.Decode()
- if err != nil {
- return perrors.WithStack(err)
- }
-
- response := EnsureResponse(resp)
-
- switch rspType {
- case RESPONSE_WITH_EXCEPTION, RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
- expt, decErr := decoder.Decode()
- if decErr != nil {
- return perrors.WithStack(decErr)
- }
- if rspType == RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS {
- attachments, attErr := decoder.Decode()
- if attErr != nil {
- return perrors.WithStack(attErr)
- }
- if v, ok := attachments.(map[interface{}]interface{});
ok {
- atta := ToMapStringString(v)
- response.Attachments = atta
- } else {
- return perrors.Errorf("get wrong attachments:
%+v", attachments)
- }
- }
-
- if e, ok := expt.(error); ok {
- response.Exception = e
- } else {
- response.Exception = perrors.Errorf("got exception:
%+v", expt)
- }
- return nil
-
- case RESPONSE_VALUE, RESPONSE_VALUE_WITH_ATTACHMENTS:
- rsp, decErr := decoder.Decode()
- if decErr != nil {
- return perrors.WithStack(decErr)
- }
- if rspType == RESPONSE_VALUE_WITH_ATTACHMENTS {
- attachments, attErr := decoder.Decode()
- if attErr != nil {
- return perrors.WithStack(attErr)
- }
- if v, ok := attachments.(map[interface{}]interface{});
ok {
- response.Attachments = ToMapStringString(v)
- } else {
- return perrors.Errorf("get wrong attachments:
%+v", attachments)
- }
- }
-
- response.RspObj = rsp
-
- return nil
-
- case RESPONSE_NULL_VALUE, RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
- if rspType == RESPONSE_NULL_VALUE_WITH_ATTACHMENTS {
- attachments, decErr := decoder.Decode()
- if decErr != nil {
- return perrors.WithStack(decErr)
- }
- if v, ok := attachments.(map[interface{}]interface{});
ok {
- atta := ToMapStringString(v)
- response.Attachments = atta
- } else {
- return perrors.Errorf("get wrong attachments:
%+v", attachments)
- }
- }
- return nil
- }
-
- return nil
-}
-
-// CopySlice copy from inSlice to outSlice
-func CopySlice(inSlice, outSlice reflect.Value) error {
- if inSlice.IsNil() {
- return perrors.New("@in is nil")
- }
- if inSlice.Kind() != reflect.Slice {
- return perrors.Errorf("@in is not slice, but %v",
inSlice.Kind())
- }
-
- for outSlice.Kind() == reflect.Ptr {
- outSlice = outSlice.Elem()
- }
-
- size := inSlice.Len()
- outSlice.Set(reflect.MakeSlice(outSlice.Type(), size, size))
-
- for i := 0; i < size; i++ {
- inSliceValue := inSlice.Index(i)
- if !inSliceValue.Type().AssignableTo(outSlice.Index(i).Type()) {
- return perrors.Errorf("in element type [%s] can not
assign to out element type [%s]",
- inSliceValue.Type().String(),
outSlice.Type().String())
- }
- outSlice.Index(i).Set(inSliceValue)
- }
-
- return nil
-}
-
-// CopyMap copy from in map to out map
-func CopyMap(inMapValue, outMapValue reflect.Value) error {
- if inMapValue.IsNil() {
- return perrors.New("@in is nil")
- }
- if !inMapValue.CanInterface() {
- return perrors.New("@in's Interface can not be used.")
- }
- if inMapValue.Kind() != reflect.Map {
- return perrors.Errorf("@in is not map, but %v",
inMapValue.Kind())
- }
-
- outMapType := UnpackPtrType(outMapValue.Type())
- SetValue(outMapValue, reflect.MakeMap(outMapType))
-
- outKeyType := outMapType.Key()
-
- outMapValue = UnpackPtrValue(outMapValue)
- outValueType := outMapValue.Type().Elem()
-
- for _, inKey := range inMapValue.MapKeys() {
- inValue := inMapValue.MapIndex(inKey)
-
- if !inKey.Type().AssignableTo(outKeyType) {
- return perrors.Errorf("in Key:{type:%s, value:%#v} can
not assign to out Key:{type:%s} ",
- inKey.Type().String(), inKey,
outKeyType.String())
- }
- if !inValue.Type().AssignableTo(outValueType) {
- return perrors.Errorf("in Value:{type:%s, value:%#v}
can not assign to out value:{type:%s}",
- inValue.Type().String(), inValue,
outValueType.String())
- }
- outMapValue.SetMapIndex(inKey, inValue)
- }
-
- return nil
-}
-
-// ReflectResponse reflect return value
-// TODO response object should not be copied again to another object, it
should be the exact type of the object
-func ReflectResponse(in interface{}, out interface{}) error {
- if in == nil {
- return perrors.Errorf("@in is nil")
- }
-
- if out == nil {
- return perrors.Errorf("@out is nil")
- }
- if reflect.TypeOf(out).Kind() != reflect.Ptr {
- return perrors.Errorf("@out should be a pointer")
- }
-
- inValue := EnsurePackValue(in)
- outValue := EnsurePackValue(out)
-
- outType := outValue.Type().String()
- if outType == "interface {}" || outType == "*interface {}" {
- SetValue(outValue, inValue)
- return nil
- }
-
- switch inValue.Type().Kind() {
- case reflect.Slice, reflect.Array:
- return CopySlice(inValue, outValue)
- case reflect.Map:
- return CopyMap(inValue, outValue)
- default:
- SetValue(outValue, inValue)
- }
-
- return nil
-}
-
-var versionInt = make(map[string]int)
-
-//
https://github.com/apache/dubbo/blob/dubbo-2.7.1/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java#L96
-// isSupportResponseAttachment is for compatibility among some dubbo version
-func isSupportResponseAttachment(version string) bool {
- if len(version) == 0 {
- return false
- }
-
- v, ok := versionInt[version]
- if !ok {
- v = version2Int(version)
- if v == -1 {
- return false
- }
- }
-
- if v >= 2001000 && v <= 2060200 { // 2.0.10 ~ 2.6.2
- return false
- }
- return v >= LOWEST_VERSION_FOR_RESPONSE_ATTACHMENT
-}
-
-func version2Int(version string) int {
- if len(version) == 0 {
- return 0
- }
- v := 0
- varr := strings.Split(version, ".")
- length := len(varr)
- for key, value := range varr {
- v0, err := strconv.Atoi(value)
- if err != nil {
- return -1
- }
- v += v0 * int(math.Pow10((length-key-1)*2))
- }
- if length == 3 {
- return v * 100
- }
- return v
-}
diff --git a/response_test.go b/response_test.go
deleted file mode 100644
index 7632657..0000000
--- a/response_test.go
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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 (
- "reflect"
- "testing"
-)
-
-import (
- "github.com/stretchr/testify/assert"
-)
-
-func doTestReflectResponse(t *testing.T, in interface{}, out interface{}) {
- err := ReflectResponse(in, out)
- if err != nil {
- t.Error(err)
- t.FailNow()
- }
-
- result := UnpackPtrValue(reflect.ValueOf(out)).Interface()
-
- equal := reflect.DeepEqual(in, result)
- if !equal {
- t.Errorf("expect [%v]: %v, but got [%v]: %v",
reflect.TypeOf(in), in, reflect.TypeOf(result), result)
- }
-}
-
-func TestReflectResponse(t *testing.T) {
- var b bool
- doTestReflectResponse(t, true, &b)
- doTestReflectResponse(t, false, &b)
-
- var i int
- doTestReflectResponse(t, 123, &i)
- doTestReflectResponse(t, 234, &i)
-
- var i16 int16
- doTestReflectResponse(t, int16(456), &i16)
-
- var i64 int64
- doTestReflectResponse(t, int64(789), &i64)
-
- var s string
- doTestReflectResponse(t, "hello world", &s)
-
- type rr struct {
- Name string
- Num int
- }
-
- var r1 rr
- doTestReflectResponse(t, rr{"dubbogo", 32}, &r1)
-
- // ------ map test -------
- m1 := make(map[interface{}]interface{})
- var m1r map[interface{}]interface{}
- m1["hello"] = "world"
- m1[1] = "go"
- m1["dubbo"] = 666
- doTestReflectResponse(t, m1, &m1r)
-
- m2 := make(map[string]string)
- var m2r map[string]string
- m2["hello"] = "world"
- m2["dubbo"] = "666"
- doTestReflectResponse(t, m2, &m2r)
-
- m3 := make(map[string]rr)
- var m3r map[string]rr
- m3["dubbo"] = rr{"hello", 123}
- m3["go"] = rr{"world", 456}
- doTestReflectResponse(t, m3, &m3r)
-
- // ------ slice test -------
- s1 := []string{"abc", "def", "hello", "world"}
- var s1r []string
- doTestReflectResponse(t, s1, &s1r)
-
- s2 := []rr{{"dubbo", 666}, {"go", 999}}
- var s2r []rr
- doTestReflectResponse(t, s2, &s2r)
-
- s3 := []interface{}{rr{"dubbo", 666}, 123, "hello"}
- var s3r []interface{}
- doTestReflectResponse(t, s3, &s3r)
-
- // ------ interface test -------
- in1 := []interface{}{rr{"dubbo", 666}, 123, "hello"}
- var inr1 *interface{}
- doTestReflectResponse(t, in1,
reflect.New(reflect.TypeOf(inr1).Elem()).Interface())
-
- in2 := make(map[string]rr)
- var inr2 map[string]rr
- m3["dubbo"] = rr{"hello", 123}
- m3["go"] = rr{"world", 456}
- doTestReflectResponse(t, in2, &inr2)
-}
-
-// separately test copy normal map to map[interface{}]interface{}
-func TestCopyMap(t *testing.T) {
- type rr struct {
- Name string
- Num int
- }
-
- m3 := make(map[string]rr)
- var m3r map[interface{}]interface{}
- r1 := rr{"hello", 123}
- r2 := rr{"world", 456}
- m3["dubbo"] = r1
- m3["go"] = r2
-
- err := ReflectResponse(m3, &m3r)
- if err != nil {
- t.Error(err)
- t.FailNow()
- }
-
- assert.Equal(t, 2, len(m3r))
-
- rr1, ok := m3r["dubbo"]
- assert.True(t, ok)
- assert.True(t, reflect.DeepEqual(r1, rr1))
-
- rr2, ok := m3r["go"]
- assert.True(t, ok)
- assert.True(t, reflect.DeepEqual(r2, rr2))
-}
-
-// separately test copy normal slice to []interface{}
-func TestCopySlice(t *testing.T) {
- type rr struct {
- Name string
- Num int
- }
-
- r1 := rr{"hello", 123}
- r2 := rr{"world", 456}
-
- s1 := []rr{r1, r2}
- var s1r []interface{}
-
- err := ReflectResponse(s1, &s1r)
- if err != nil {
- t.Error(err)
- t.FailNow()
- }
-
- assert.Equal(t, 2, len(s1r))
- assert.True(t, reflect.DeepEqual(r1, s1r[0]))
- assert.True(t, reflect.DeepEqual(r2, s1r[1]))
-}
-
-func TestIsSupportResponseAttachment(t *testing.T) {
- is := isSupportResponseAttachment("2.0.10")
- assert.False(t, is)
-
- is = isSupportResponseAttachment("2.5.3")
- assert.False(t, is)
-
- is = isSupportResponseAttachment("2.6.2")
- assert.False(t, is)
-
- is = isSupportResponseAttachment("1.5.5")
- assert.False(t, is)
-
- is = isSupportResponseAttachment("0.0.0")
- assert.False(t, is)
-
- is = isSupportResponseAttachment("2.0.2")
- assert.True(t, is)
-
- is = isSupportResponseAttachment("2.7.2")
- assert.True(t, is)
-}
-
-func TestVersion2Int(t *testing.T) {
- v := version2Int("2.1.3")
- assert.Equal(t, 2010300, v)
-
- v = version2Int("22.11.33")
- assert.Equal(t, 22113300, v)
-
- v = version2Int("222.111.333")
- assert.Equal(t, 223143300, v)
-
- v = version2Int("220.110.333")
- assert.Equal(t, 221133300, v)
-
- v = version2Int("229.119.333")
- assert.Equal(t, 230223300, v)
-
- v = version2Int("2222.1111.3333")
- assert.Equal(t, 2233443300, v)
-
- v = version2Int("2.11")
- assert.Equal(t, 211, v)
-
- v = version2Int("2.1.3.4")
- assert.Equal(t, 2010304, v)
-
- v = version2Int("2.1.3.4.5")
- assert.Equal(t, 201030405, v)
-}