Skip to content

Commit

Permalink
Merge pull request #102 from aliiohs/feature/FixDateNilBug
Browse files Browse the repository at this point in the history
Fix: date nil bug
  • Loading branch information
wongoo authored Jul 24, 2019
2 parents 659a652 + 0d65025 commit 1e1cb6a
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 15 deletions.
10 changes: 8 additions & 2 deletions codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,14 @@ func SetValue(dest, v reflect.Value) {
return
}
}
//temporary process, only handle the same type of situation
if v.IsValid() && UnpackPtrType(dest.Type()) == UnpackPtrType(v.Type()) && dest.Kind() == reflect.Ptr && dest.CanSet() {
for dest.Type() != v.Type() {
v = PackPtr(v)
}
dest.Set(v)
return
}

// if the kind of dest is Ptr, the original value will be zero value
// set value on zero value is not allowed
Expand All @@ -307,7 +315,6 @@ func SetValue(dest, v reflect.Value) {
for v.IsValid() && v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Ptr {
v = v.Elem()
}

// zero value not need to set
if !v.IsValid() {
return
Expand All @@ -320,7 +327,6 @@ func SetValue(dest, v reflect.Value) {
} else {
v = UnpackPtrValue(v)
}

// zero value not need to set
if !v.IsValid() {
return
Expand Down
16 changes: 14 additions & 2 deletions date.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package hessian

import (
"reflect"
"time"
)

Expand All @@ -26,12 +27,21 @@ import (
// Date
/////////////////////////////////////////

var ZeroDate = time.Time{}

// # time in UTC encoded as 64-bit long milliseconds since epoch
// ::= x4a b7 b6 b5 b4 b3 b2 b1 b0
// ::= x4b b3 b2 b1 b0 # minutes since epoch
func encDateInMs(b []byte, v time.Time) []byte {
func encDateInMs(b []byte, i interface{}) []byte {

value := UnpackPtrValue(reflect.ValueOf(i))
vi := value.Interface().(time.Time)
if vi == ZeroDate {
b = append(b, BC_NULL)
return nil
}
b = append(b, BC_DATE)
return append(b, PackInt64(v.UnixNano()/1e6)...)
return append(b, PackInt64(vi.UnixNano()/1e6)...)
}

func encDateInMimute(b []byte, v time.Time) []byte {
Expand Down Expand Up @@ -64,6 +74,8 @@ func (d *Decoder) decDate(flag int32) (time.Time, error) {
}

switch {
case tag == BC_NULL:
return ZeroDate, nil
case tag == BC_DATE: //'d': //date
s = buf[:8]
l, err = d.next(s)
Expand Down
82 changes: 82 additions & 0 deletions date_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@ import (
"testing"
"time"
)
import (
"github.com/stretchr/testify/assert"
)

func init() {
RegisterPOJO(&DateDemo{})
}

type DateDemo struct {
Name string
Date time.Time
Dates []**time.Time
NilDate *time.Time
Date1 *time.Time
Date2 **time.Time
Date3 ***time.Time
}

func (DateDemo) JavaClassName() string {
return "test.model.DateDemo"
}

func TestEncDate(t *testing.T) {
var (
Expand Down Expand Up @@ -71,3 +92,64 @@ func TestDateEncode(t *testing.T) {
testJavaDecode(t, "argDate_1", time.Date(1998, 5, 8, 9, 51, 31, 0, time.UTC))
testJavaDecode(t, "argDate_2", time.Date(1998, 5, 8, 9, 51, 0, 0, time.UTC))
}

func TestEncDateNull(t *testing.T) {
var (
v string
tz time.Time
e *Encoder
d *Decoder
res interface{}
)
v = "2014-02-09 06:15:23 +0800 CST"
tz, _ = time.Parse("2006-01-02 15:04:05 +0800 CST", v)
d1 := &tz
d2 := &d1
d3 := &d2

date := DateDemo{
Name: "zs",
Date: ZeroDate,
Dates: []**time.Time{d2, d2},
NilDate: nil,
Date1: nil,
Date2: d2,
Date3: d3,
}
e = NewEncoder()
e.Encode(date)
if len(e.Buffer()) == 0 {
t.Fail()
}
d = NewDecoder(e.Buffer())
res, _ = d.Decode()
assert.Equal(t, ZeroDate, res.(*DateDemo).Date)
assert.Equal(t, 2, len(res.(*DateDemo).Dates))
assert.Equal(t, tz.Local().String(), (*res.(*DateDemo).Dates[0]).String())
assert.Equal(t, &ZeroDate, res.(*DateDemo).NilDate)
assert.Equal(t, ZeroDate, *res.(*DateDemo).Date1)
assert.Equal(t, tz.Local().String(), (*res.(*DateDemo).Date2).String())
assert.Equal(t, tz.Local().String(), (*(*res.(*DateDemo).Date3)).String())

}

func TestDateNulJavaDecode(t *testing.T) {
date := DateDemo{
Name: "zs",
Date: ZeroDate,
}
testJavaDecode(t, "customArgTypedFixedList_DateNull", date)
}

func TestDateNilDecode(t *testing.T) {

doTestDateNull(t, "customReplyTypedFixedDateNull")
}

func doTestDateNull(t *testing.T, method string) {
testDecodeFrameworkFunc(t, method, func(r interface{}) {
t.Logf("%#v", r)
assert.Equal(t, ZeroDate, r.(*DateDemo).Date)
assert.Equal(t, &ZeroDate, r.(*DateDemo).Date1)
})
}
28 changes: 19 additions & 9 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,12 @@ func (e *Encoder) Encode(v interface{}) error {
e.buffer = encInt64(e.buffer, int64(val))

case time.Time:
e.buffer = encDateInMs(e.buffer, val)
// e.buffer = encDateInMimute(v.(time.Time), e.buffer)
if ZeroDate == val {
e.buffer = encNull(e.buffer)
} else {
e.buffer = encDateInMs(e.buffer, &val)
// e.buffer = encDateInMimute(v.(time.Time), e.buffer)
}

case float32:
e.buffer = encFloat(e.buffer, float64(val))
Expand All @@ -123,15 +127,21 @@ func (e *Encoder) Encode(v interface{}) error {
t := UnpackPtrType(reflect.TypeOf(v))
switch t.Kind() {
case reflect.Struct:
vv := reflect.ValueOf(v)
vv = UnpackPtr(vv)
if !vv.IsValid() {
e.buffer = encNull(e.buffer)
return nil
}
if vv.Type().String() == "time.Time" {
e.buffer = encDateInMs(e.buffer, v)
return nil
}
if p, ok := v.(POJO); ok {
var clazz string
vv := reflect.ValueOf(v)
vv = UnpackPtr(vv)
if vv.IsValid() {
clazz = p.JavaClassName()
if c, ok := GetSerializer(clazz); ok {
return c.EncObject(e, p)
}
clazz = p.JavaClassName()
if c, ok := GetSerializer(clazz); ok {
return c.EncObject(e, p)
}
return e.encObject(p)
}
Expand Down
5 changes: 3 additions & 2 deletions object.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,13 @@ func (d *Decoder) decInstance(typ reflect.Type, cls classInfo) (interface{}, err
err error
s interface{}
)
if fldRawValue.Type().String() == "time.Time" {
typ := UnpackPtrType(fldRawValue.Type())
if typ.String() == "time.Time" {
s, err = d.decDate(TAG_READ)
if err != nil {
return nil, perrors.WithStack(err)
}
fldRawValue.Set(reflect.ValueOf(s))
SetValue(fldRawValue, EnsurePackValue(s))
} else {
s, err = d.decObject(TAG_READ)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions test_hessian/src/main/java/test/TestCustomDecode.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Date;
import java.util.List;
import java.math.BigDecimal;
import test.model.DateDemo;

public class TestCustomDecode {

Expand Down Expand Up @@ -168,4 +169,9 @@ public Object customArgTypedFixedList_Decimal() throws Exception {
BigDecimal o = (BigDecimal) input.readObject();
return o.toString().equals( "100.256");
}

public Object customArgTypedFixedList_DateNull() throws Exception {
DateDemo o = (DateDemo) input.readObject();
return o.getDate() == null && o.getDate1() == null;
}
}
7 changes: 7 additions & 0 deletions test_hessian/src/main/java/test/TestCustomReply.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Date;
import java.util.HashMap;
import java.math.BigDecimal;
import test.model.DateDemo;

public class TestCustomReply {

Expand Down Expand Up @@ -346,6 +347,12 @@ public void customReplyTypedFixedDecimal() throws Exception {
output.flush();
}

public void customReplyTypedFixedDateNull() throws Exception {
DateDemo demo = new DateDemo("zhangshan",null,null);
output.writeObject(demo);
output.flush();
}

}

class TypedListTest implements Serializable {
Expand Down
58 changes: 58 additions & 0 deletions test_hessian/src/main/java/test/model/DateDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 test.model;

import java.io.Serializable;
import java.util.Date;

public class DateDemo implements Serializable {
private String name;
private Date date;
private Date date1;

public String getName() {
return name;
}

public DateDemo() {}

public DateDemo(String name,Date date,Date date1) {
this.name = name;
this.date = date;
this.date1 = date1;
}

public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}
public Date getDate1() {
return date1;
}

public void setDate1(Date date1) {
this.date1 = date1;
}

}

0 comments on commit 1e1cb6a

Please sign in to comment.