dubbo.apache.org/dubbo-go/v3@v3.1.1/protocol/dubbo/hessian2/hessian_dubbo_test.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package hessian2
    19  
    20  import (
    21  	"bufio"
    22  	"bytes"
    23  	"reflect"
    24  	"testing"
    25  	"time"
    26  )
    27  
    28  import (
    29  	hessian "github.com/apache/dubbo-go-hessian2"
    30  
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  type Case struct {
    35  	A string
    36  	B int
    37  }
    38  
    39  type CaseA struct {
    40  	A string
    41  	B int
    42  	C Case
    43  }
    44  
    45  type CaseB struct {
    46  	A string
    47  	B CaseA
    48  }
    49  
    50  func (c *CaseB) JavaClassName() string {
    51  	return "com.test.caseb"
    52  }
    53  
    54  func (c CaseA) JavaClassName() string {
    55  	return "com.test.casea"
    56  }
    57  
    58  // JavaClassName  java fully qualified path
    59  func (c Case) JavaClassName() string {
    60  	return "com.test.case"
    61  }
    62  
    63  func doTestHessianEncodeHeader(t *testing.T, packageType PackageType, responseStatus byte, body interface{}) ([]byte, error) {
    64  	hessian.RegisterPOJO(&Case{})
    65  	codecW := NewHessianCodec(nil)
    66  	resp, err := codecW.Write(Service{
    67  		Path:      "test",
    68  		Interface: "ITest",
    69  		Version:   "v1.0",
    70  		Method:    "test",
    71  		Timeout:   time.Second * 10,
    72  	}, DubboHeader{
    73  		SerialID:       2,
    74  		Type:           packageType,
    75  		ID:             1,
    76  		ResponseStatus: responseStatus,
    77  	}, body)
    78  	assert.Nil(t, err)
    79  	return resp, err
    80  }
    81  
    82  func doTestResponse(t *testing.T, packageType PackageType, responseStatus byte, body interface{}, decodedResponse *DubboResponse, assertFunc func()) {
    83  	resp, err := doTestHessianEncodeHeader(t, packageType, responseStatus, body)
    84  	assert.NoError(t, err)
    85  
    86  	codecR := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
    87  
    88  	h := &DubboHeader{}
    89  	err = codecR.ReadHeader(h)
    90  	assert.Nil(t, err)
    91  
    92  	assert.Equal(t, byte(2), h.SerialID)
    93  	assert.Equal(t, packageType, h.Type&(PackageRequest|PackageResponse|PackageHeartbeat))
    94  	assert.Equal(t, int64(1), h.ID)
    95  	assert.Equal(t, responseStatus, h.ResponseStatus)
    96  
    97  	err = codecR.ReadBody(decodedResponse)
    98  	assert.Nil(t, err)
    99  	t.Log(decodedResponse)
   100  
   101  	if assertFunc != nil {
   102  		assertFunc()
   103  		return
   104  	}
   105  
   106  	if h.ResponseStatus != Zero && h.ResponseStatus != Response_OK {
   107  		assert.Equal(t, "java exception:"+body.(string), decodedResponse.Exception.Error())
   108  		return
   109  	}
   110  
   111  	in, _ := hessian.EnsureInterface(hessian.UnpackPtrValue(hessian.EnsurePackValue(body)), nil)
   112  	out, _ := hessian.EnsureInterface(hessian.UnpackPtrValue(hessian.EnsurePackValue(decodedResponse.RspObj)), nil)
   113  	assert.Equal(t, in, out)
   114  }
   115  
   116  func TestResponse(t *testing.T) {
   117  	caseObj := Case{A: "a", B: 1}
   118  	decodedResponse := &DubboResponse{}
   119  	hessian.RegisterPOJO(&caseObj)
   120  
   121  	arr := []*Case{&caseObj}
   122  	decodedResponse.RspObj = nil
   123  	doTestResponse(t, PackageResponse, Response_OK, arr, decodedResponse, func() {
   124  		arrRes, ok := decodedResponse.RspObj.([]*Case)
   125  		if !ok {
   126  			t.Errorf("expect []*Case, but get %s", reflect.TypeOf(decodedResponse.RspObj).String())
   127  			return
   128  		}
   129  		assert.Equal(t, 1, len(arrRes))
   130  		assert.Equal(t, &caseObj, arrRes[0])
   131  	})
   132  
   133  	doTestResponse(t, PackageResponse, Response_OK, &caseObj, decodedResponse, func() {
   134  		assert.Equal(t, &caseObj, decodedResponse.RspObj)
   135  	})
   136  
   137  	s := "ok!!!!!"
   138  	doTestResponse(t, PackageResponse, Response_OK, s, decodedResponse, func() {
   139  		assert.Equal(t, s, decodedResponse.RspObj)
   140  	})
   141  
   142  	doTestResponse(t, PackageResponse, Response_OK, int64(3), decodedResponse, func() {
   143  		assert.Equal(t, int64(3), decodedResponse.RspObj)
   144  	})
   145  
   146  	doTestResponse(t, PackageResponse, Response_OK, true, decodedResponse, func() {
   147  		assert.Equal(t, true, decodedResponse.RspObj)
   148  	})
   149  
   150  	errorMsg := "error!!!!!"
   151  	decodedResponse.RspObj = nil
   152  	doTestResponse(t, PackageResponse, Response_SERVER_ERROR, errorMsg, decodedResponse, func() {
   153  		assert.Equal(t, "java exception:error!!!!!", decodedResponse.Exception.Error())
   154  	})
   155  
   156  	decodedResponse.RspObj = nil
   157  	decodedResponse.Exception = nil
   158  	mapObj := map[string][]*Case{"key": {&caseObj}}
   159  	doTestResponse(t, PackageResponse, Response_OK, mapObj, decodedResponse, func() {
   160  		mapRes, ok := decodedResponse.RspObj.(map[interface{}]interface{})
   161  		if !ok {
   162  			t.Errorf("expect map[string][]*Case, but get %s", reflect.TypeOf(decodedResponse.RspObj).String())
   163  			return
   164  		}
   165  		c, ok := mapRes["key"]
   166  		if !ok {
   167  			assert.FailNow(t, "no key in decoded response map")
   168  		}
   169  
   170  		mapValueArr, ok := c.([]*Case)
   171  		if !ok {
   172  			assert.FailNow(t, "invalid decoded response map value", "expect []*Case, but get %v", reflect.TypeOf(c))
   173  		}
   174  		assert.Equal(t, 1, len(mapValueArr))
   175  		assert.Equal(t, &caseObj, mapValueArr[0])
   176  	})
   177  }
   178  
   179  func doTestRequest(t *testing.T, packageType PackageType, responseStatus byte, body interface{}) {
   180  	resp, err := doTestHessianEncodeHeader(t, packageType, responseStatus, body)
   181  	assert.NoError(t, err)
   182  
   183  	codecR := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
   184  
   185  	h := &DubboHeader{}
   186  	err = codecR.ReadHeader(h)
   187  	assert.Nil(t, err)
   188  	assert.Equal(t, byte(2), h.SerialID)
   189  	assert.Equal(t, packageType, h.Type&(PackageRequest|PackageResponse|PackageHeartbeat))
   190  	assert.Equal(t, int64(1), h.ID)
   191  	assert.Equal(t, responseStatus, h.ResponseStatus)
   192  
   193  	c := make([]interface{}, 7)
   194  	err = codecR.ReadBody(c)
   195  	assert.Nil(t, err)
   196  	t.Log(c)
   197  	assert.True(t, len(body.([]interface{})) == len(c[5].([]interface{})))
   198  }
   199  
   200  func TestRequest(t *testing.T) {
   201  	doTestRequest(t, PackageRequest, Zero, []interface{}{"a"})
   202  	doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3})
   203  	doTestRequest(t, PackageRequest, Zero, []interface{}{"a", true})
   204  	doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3, true})
   205  	doTestRequest(t, PackageRequest, Zero, []interface{}{3.2, true})
   206  	doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3, true, &Case{A: "a", B: 3}})
   207  	doTestRequest(t, PackageRequest, Zero, []interface{}{"a", 3, true, []*Case{{A: "a", B: 3}}})
   208  	doTestRequest(t, PackageRequest, Zero, []interface{}{map[string][]*Case{"key": {{A: "a", B: 3}}}})
   209  }
   210  
   211  func TestHessianCodec_ReadAttachments(t *testing.T) {
   212  	hessian.RegisterPOJO(&AttachTestObject{})
   213  	body := &DubboResponse{
   214  		RspObj:      &CaseB{A: "A", B: CaseA{A: "a", B: 1, C: Case{A: "c", B: 2}}},
   215  		Exception:   nil,
   216  		Attachments: map[string]interface{}{DUBBO_VERSION_KEY: "2.6.4", "att": AttachTestObject{ID: 23, Name: "haha"}},
   217  	}
   218  	resp, err := doTestHessianEncodeHeader(t, PackageResponse, Response_OK, body)
   219  	assert.NoError(t, err)
   220  	hessian.UnRegisterPOJOs(&CaseB{}, &CaseA{})
   221  	codecR1 := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
   222  	codecR2 := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
   223  	h := &DubboHeader{}
   224  	assert.NoError(t, codecR1.ReadHeader(h))
   225  	t.Log(h)
   226  	assert.NoError(t, codecR2.ReadHeader(h))
   227  	t.Log(h)
   228  
   229  	err = codecR1.ReadBody(body)
   230  	assert.NoError(t, err)
   231  	attrs, err := codecR2.ReadAttachments()
   232  	assert.NoError(t, err)
   233  	assert.Equal(t, "2.6.4", attrs[DUBBO_VERSION_KEY])
   234  	assert.Equal(t, AttachTestObject{ID: 23, Name: "haha"}, *(attrs["att"].(*AttachTestObject)))
   235  	assert.NotEqual(t, AttachTestObject{ID: 24, Name: "nohaha"}, *(attrs["att"].(*AttachTestObject)))
   236  
   237  	t.Log(attrs)
   238  }
   239  
   240  type AttachTestObject struct {
   241  	ID   int32
   242  	Name string `dubbo:"name"`
   243  }
   244  
   245  func (AttachTestObject) JavaClassName() string {
   246  	return "com.test.Test"
   247  }