blob: 02b8e0650262639fcbaf341bdb6cf6e6c52b8574 [file] [log] [blame]
// Copyright 2019 Wongoo, Yincheng Fang
// Licensed 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package hessian
import (
import (
type circular struct {
Num int
Previous *circular
Next *circular
func (circular) JavaClassName() string {
return "circular"
func TestRef(t *testing.T) {
c := &circular{}
c.Num = 12345
c.Previous = c
c.Next = c
e := NewEncoder()
err := e.Encode(c)
if err != nil {
bytes := e.Buffer()
t.Logf("circular bytes hex: %x, string: %s", bytes, string(bytes))
res, err := NewDecoder(bytes).Decode()
if err != nil {
c1, ok := res.(*circular)
if !ok {
t.Fatalf("res:%T is not of type circular", c1)
t.Logf("encode object: %+v, decode object: %+v", c, c1)
if c.Num != c1.Num {
t.Errorf("encoded value %d != decoded value %d", c.Num, c1.Num)
if c1.Previous != c1.Next {
t.Errorf("decoded value previous %p != decoded value next %p", c1.Previous, c1.Next)
type personT struct {
Name string
Relations []*personT
Parent *personT
Marks *map[string]*personT
Tags map[string]*personT
func (personT) JavaClassName() string {
return "person"
func logRefObject(t *testing.T, n string, i interface{}) {
t.Logf("ref obj[%s]: %p, %v", n, i, i)
func doTestRef(t *testing.T, c interface{}, name string) interface{} {
e := NewEncoder()
err := e.Encode(c)
if err != nil {
assert.FailNowf(t, "failed to encode", "error: %v", err)
bytes := e.Buffer()
t.Logf("%s ref bytes: %s", name, string(bytes))
t.Logf("%s ref bytes: %x", name, bytes)
d := NewDecoder(bytes)
decoded, err := EnsureInterface(d.Decode())
if err != nil {
assert.FailNowf(t, "failed to encode", "error: %v", err)
t.Logf("%s ref decoded: %v", name, decoded)
return decoded
func buildComplexLevelPerson() *personT {
p1 := &personT{Name: "p1"}
p2 := &personT{Name: "p2"}
p3 := &personT{Name: "p3"}
p4 := &personT{Name: "p4"}
p5 := &personT{Name: "p5"}
p6 := &personT{Name: "p6"}
p1.Parent = p2
p2.Parent = p3
p3.Parent = p4
relations := []*personT{p5, p6}
p3.Relations = relations
p4.Relations = relations
marks := &map[string]*personT{
"beautiful": p1,
"tall": p2,
"fat": p3,
p4.Marks = marks
p5.Marks = marks
tags := map[string]*personT{
"man": p3,
"woman": p4,
p5.Tags = tags
p6.Tags = tags
return p1
func TestComplexLevelRef(t *testing.T) {
p1 := buildComplexLevelPerson()
decoded := doTestRef(t, p1, "person")
t.Logf("decoded object type: %v", reflect.TypeOf(decoded))
d1, ok := decoded.(*personT)
if !ok {
assert.FailNow(t, "decode object is not a pointer of person")
logRefObject(t, "d1", d1)
d2 := d1.Parent
assert.NotNil(t, d2)
logRefObject(t, "d2", d2)
d3 := d2.Parent
assert.NotNil(t, d3)
logRefObject(t, "d3", d3)
d4 := d3.Parent
logRefObject(t, "d4", d4)
assert.Equal(t, 2, len(d3.Relations))
if len(d3.Relations) != 2 {
assert.FailNow(t, "the length of relation array should be 2")
d5 := d3.Relations[0]
logRefObject(t, "d5", d5)
d6 := d3.Relations[1]
logRefObject(t, "d6", d6)
assert.NotNil(t, d4)
assert.NotNil(t, d5)
assert.NotNil(t, d6)
assert.Equal(t, "p1", d1.Name)
assert.Equal(t, "p2", d2.Name)
assert.Equal(t, "p3", d3.Name)
assert.Equal(t, "p4", d4.Name)
assert.Equal(t, "p5", d5.Name)
assert.Equal(t, "p6", d6.Name)
//value equal
assert.True(t, reflect.DeepEqual(d3.Relations, d4.Relations))
if d4.Marks == nil {
assert.FailNow(t, "d4.Marks should not be nil")
assert.Equal(t, 3, len(*d4.Marks))
assert.True(t, AddrEqual(d4.Marks, d5.Marks))
assert.True(t, AddrEqual(d1, (*d4.Marks)["beautiful"]))
assert.True(t, AddrEqual(d2, (*d4.Marks)["tall"]))
assert.True(t, AddrEqual(d3, (*d4.Marks)["fat"]))
if d5.Tags == nil {
assert.FailNow(t, "d5.Tags should not be nil")
assert.Equal(t, 2, len(d5.Tags))
assert.True(t, reflect.DeepEqual(d5.Tags, d6.Tags))
assert.False(t, AddrEqual(d5.Tags, d6.Tags))
assert.True(t, AddrEqual(d3, d5.Tags["man"]))
assert.True(t, AddrEqual(d4, d5.Tags["woman"]))