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 }