github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv_z_unit_struct_marshal_unmarshal_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gconv_test
     8  
     9  import (
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/gogf/gf/v2/crypto/gcrc32"
    14  	"github.com/gogf/gf/v2/encoding/gbinary"
    15  	"github.com/gogf/gf/v2/errors/gerror"
    16  	"github.com/gogf/gf/v2/frame/g"
    17  	"github.com/gogf/gf/v2/os/gtime"
    18  	"github.com/gogf/gf/v2/test/gtest"
    19  	"github.com/gogf/gf/v2/util/gconv"
    20  )
    21  
    22  type MyTime struct {
    23  	time.Time
    24  }
    25  
    26  type MyTimeSt struct {
    27  	ServiceDate MyTime
    28  }
    29  
    30  func (st *MyTimeSt) UnmarshalValue(v interface{}) error {
    31  	m := gconv.Map(v)
    32  	t, err := gtime.StrToTime(gconv.String(m["ServiceDate"]))
    33  	if err != nil {
    34  		return err
    35  	}
    36  	st.ServiceDate = MyTime{t.Time}
    37  	return nil
    38  }
    39  
    40  func TestStructUnmarshalValue1(t *testing.T) {
    41  	gtest.C(t, func(t *gtest.T) {
    42  		st := &MyTimeSt{}
    43  		err := gconv.Struct(g.Map{"ServiceDate": "2020-10-10 12:00:01"}, st)
    44  		t.AssertNil(err)
    45  		t.Assert(st.ServiceDate.Time.Format("2006-01-02 15:04:05"), "2020-10-10 12:00:01")
    46  	})
    47  	gtest.C(t, func(t *gtest.T) {
    48  		st := &MyTimeSt{}
    49  		err := gconv.Struct(g.Map{"ServiceDate": nil}, st)
    50  		t.AssertNil(err)
    51  		t.Assert(st.ServiceDate.Time.IsZero(), true)
    52  	})
    53  	gtest.C(t, func(t *gtest.T) {
    54  		st := &MyTimeSt{}
    55  		err := gconv.Struct(g.Map{"ServiceDate": "error"}, st)
    56  		t.AssertNE(err, nil)
    57  	})
    58  }
    59  
    60  type Pkg struct {
    61  	Length uint16 // Total length.
    62  	Crc32  uint32 // CRC32.
    63  	Data   []byte
    64  }
    65  
    66  // NewPkg creates and returns a package with given data.
    67  func NewPkg(data []byte) *Pkg {
    68  	return &Pkg{
    69  		Length: uint16(len(data) + 6),
    70  		Crc32:  gcrc32.Encrypt(data),
    71  		Data:   data,
    72  	}
    73  }
    74  
    75  // Marshal encodes the protocol struct to bytes.
    76  func (p *Pkg) Marshal() []byte {
    77  	b := make([]byte, 6+len(p.Data))
    78  	copy(b, gbinary.EncodeUint16(p.Length))
    79  	copy(b[2:], gbinary.EncodeUint32(p.Crc32))
    80  	copy(b[6:], p.Data)
    81  	return b
    82  }
    83  
    84  // UnmarshalValue decodes bytes to protocol struct.
    85  func (p *Pkg) UnmarshalValue(v interface{}) error {
    86  	b := gconv.Bytes(v)
    87  	if len(b) < 6 {
    88  		return gerror.New("invalid package length")
    89  	}
    90  	p.Length = gbinary.DecodeToUint16(b[:2])
    91  	if len(b) < int(p.Length) {
    92  		return gerror.New("invalid data length")
    93  	}
    94  	p.Crc32 = gbinary.DecodeToUint32(b[2:6])
    95  	p.Data = b[6:]
    96  	if gcrc32.Encrypt(p.Data) != p.Crc32 {
    97  		return gerror.New("crc32 validation failed")
    98  	}
    99  	return nil
   100  }
   101  
   102  func TestStructUnmarshalValue2(t *testing.T) {
   103  	gtest.C(t, func(t *gtest.T) {
   104  		var p1, p2 *Pkg
   105  		p1 = NewPkg([]byte("123"))
   106  		err := gconv.Struct(p1.Marshal(), &p2)
   107  		t.AssertNil(err)
   108  		t.Assert(p1, p2)
   109  	})
   110  }