Browse Source

codec: test: add tests for encoding and decoding of extensions

Ugorji Nwoke 8 years ago
parent
commit
d7f7caed82
3 changed files with 71 additions and 23 deletions
  1. 60 23
      codec/codec_test.go
  2. 5 0
      codec/values_flex_test.go
  3. 6 0
      codec/z_all_test.go

+ 60 - 23
codec/codec_test.go

@@ -173,21 +173,33 @@ type TestRawValue struct {
 
 
 type testUnixNanoTimeExt struct {
 type testUnixNanoTimeExt struct {
 	// keep timestamp here, so that do not incur interface-conversion costs
 	// keep timestamp here, so that do not incur interface-conversion costs
-	ts int64
+	// ts int64
 }
 }
 
 
-// func (x *testUnixNanoTimeExt) WriteExt(interface{}) []byte { panic("unsupported") }
-// func (x *testUnixNanoTimeExt) ReadExt(interface{}, []byte) { panic("unsupported") }
+func (x *testUnixNanoTimeExt) WriteExt(v interface{}) []byte {
+	v2 := v.(*time.Time)
+	bs := make([]byte, 8)
+	bigen.PutUint64(bs, uint64(v2.UnixNano()))
+	return bs
+}
+func (x *testUnixNanoTimeExt) ReadExt(v interface{}, bs []byte) {
+	v2 := v.(*time.Time)
+	ui := bigen.Uint64(bs)
+	*v2 = time.Unix(0, int64(ui)).UTC()
+}
 func (x *testUnixNanoTimeExt) ConvertExt(v interface{}) interface{} {
 func (x *testUnixNanoTimeExt) ConvertExt(v interface{}) interface{} {
-	switch v2 := v.(type) {
-	case time.Time:
-		x.ts = v2.UTC().UnixNano()
-	case *time.Time:
-		x.ts = v2.UTC().UnixNano()
-	default:
-		panic(fmt.Sprintf("unsupported format for time conversion: expecting time.Time; got %T", v))
-	}
-	return &x.ts
+	v2 := v.(*time.Time) // structs are encoded by passing the value
+	return v2.UTC().UnixNano()
+	// return x.ts
+	// switch v2 := v.(type) {
+	// case time.Time:
+	// 	x.ts = v2.UTC().UnixNano()
+	// case *time.Time:
+	// 	x.ts = v2.UTC().UnixNano()
+	// default:
+	// 	panic(fmt.Sprintf("unsupported format for time conversion: expecting time.Time; got %T", v))
+	// }
+	// return &x.ts
 }
 }
 
 
 func (x *testUnixNanoTimeExt) UpdateExt(dest interface{}, v interface{}) {
 func (x *testUnixNanoTimeExt) UpdateExt(dest interface{}, v interface{}) {
@@ -195,12 +207,8 @@ func (x *testUnixNanoTimeExt) UpdateExt(dest interface{}, v interface{}) {
 	switch v2 := v.(type) {
 	switch v2 := v.(type) {
 	case int64:
 	case int64:
 		*tt = time.Unix(0, v2).UTC()
 		*tt = time.Unix(0, v2).UTC()
-	case *int64:
-		*tt = time.Unix(0, *v2).UTC()
 	case uint64:
 	case uint64:
 		*tt = time.Unix(0, int64(v2)).UTC()
 		*tt = time.Unix(0, int64(v2)).UTC()
-	case *uint64:
-		*tt = time.Unix(0, int64(*v2)).UTC()
 	//case float64:
 	//case float64:
 	//case string:
 	//case string:
 	default:
 	default:
@@ -208,6 +216,29 @@ func (x *testUnixNanoTimeExt) UpdateExt(dest interface{}, v interface{}) {
 	}
 	}
 }
 }
 
 
+var testInt64Typ = reflect.TypeOf(testInt64(0))
+
+type testInt64Ext int64
+
+func (x *testInt64Ext) WriteExt(v interface{}) []byte {
+	v2 := uint64(int64(v.(testInt64)))
+	bs := make([]byte, 8)
+	bigen.PutUint64(bs, v2)
+	return bs
+}
+func (x *testInt64Ext) ReadExt(v interface{}, bs []byte) {
+	v2 := v.(*testInt64)
+	ui := bigen.Uint64(bs)
+	*v2 = testInt64(int64(ui))
+}
+func (x *testInt64Ext) ConvertExt(v interface{}) interface{} {
+	return int64(v.(testInt64))
+}
+func (x *testInt64Ext) UpdateExt(dest interface{}, v interface{}) {
+	v2 := dest.(*testInt64)
+	*v2 = testInt64(v.(int64))
+}
+
 func testCodecEncode(ts interface{}, bsIn []byte,
 func testCodecEncode(ts interface{}, bsIn []byte,
 	fn func([]byte) *bytes.Buffer, h Handle) (bs []byte, err error) {
 	fn func([]byte) *bytes.Buffer, h Handle) (bs []byte, err error) {
 	return sTestCodecEncode(ts, bsIn, fn, h, h.getBasicHandle())
 	return sTestCodecEncode(ts, bsIn, fn, h, h.getBasicHandle())
@@ -281,12 +312,25 @@ func testInit() {
 			return
 			return
 		}
 		}
 	)
 	)
+
+	// Although these extensions on time.Time will have no effect
+	// (as time.Time is a native type),
+	// we add these here to ensure nothing happens.
 	testSimpleH.AddExt(timeTyp, 1, timeExtEncFn, timeExtDecFn)
 	testSimpleH.AddExt(timeTyp, 1, timeExtEncFn, timeExtDecFn)
 	// testBincH.SetBytesExt(timeTyp, 1, timeExt{}) // time is builtin for binc
 	// testBincH.SetBytesExt(timeTyp, 1, timeExt{}) // time is builtin for binc
 	testMsgpackH.SetBytesExt(timeTyp, 1, timeExt{})
 	testMsgpackH.SetBytesExt(timeTyp, 1, timeExt{})
 	testCborH.SetInterfaceExt(timeTyp, 1, &testUnixNanoTimeExt{})
 	testCborH.SetInterfaceExt(timeTyp, 1, &testUnixNanoTimeExt{})
 	// testJsonH.SetInterfaceExt(timeTyp, 1, &testUnixNanoTimeExt{})
 	// testJsonH.SetInterfaceExt(timeTyp, 1, &testUnixNanoTimeExt{})
 
 
+	// Now, add extensions for the type testInt64,
+	// so we can execute the Encode/Decode Ext paths.
+	var tI64Ext testInt64Ext
+	testSimpleH.SetBytesExt(testInt64Typ, 18, &tI64Ext)
+	testMsgpackH.SetBytesExt(testInt64Typ, 18, &tI64Ext)
+	testBincH.SetBytesExt(testInt64Typ, 18, &tI64Ext)
+	testJsonH.SetInterfaceExt(testInt64Typ, 18, &tI64Ext)
+	testCborH.SetInterfaceExt(testInt64Typ, 18, &tI64Ext)
+
 	// primitives MUST be an even number, so it can be used as a mapBySlice also.
 	// primitives MUST be an even number, so it can be used as a mapBySlice also.
 	primitives := []interface{}{
 	primitives := []interface{}{
 		int8(-8),
 		int8(-8),
@@ -2711,17 +2755,10 @@ func TestSimpleScalars(t *testing.T) {
 //   - struct tags:
 //   - struct tags:
 //     on anonymous fields, _struct (all fields), etc
 //     on anonymous fields, _struct (all fields), etc
 //   - codecgen of struct containing channels.
 //   - codecgen of struct containing channels.
-//   - (encode extensions: ext, raw ext, etc)
-//   - extension that isn't builtin e.g. type uint64Ext uint64.
-//     it encodes as a uint64.
 //
 //
 //  Add negative tests for failure conditions:
 //  Add negative tests for failure conditions:
 //   - bad input with large array length prefix
 //   - bad input with large array length prefix
 //
 //
-// msgpack
-// - support time as built-in extension:
-//   see https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type
-//
 // decode.go
 // decode.go
 // - UnreadByte: only 2 states (z.ls = 2 and z.ls = 1) (0 --> 2 --> 1)
 // - UnreadByte: only 2 states (z.ls = 2 and z.ls = 1) (0 --> 2 --> 1)
 // - track: z.trb: track, stop track, check
 // - track: z.trb: track, stop track, check

+ 5 - 0
codec/values_flex_test.go

@@ -7,10 +7,14 @@ package codec
 
 
 // This file contains values used by tests and benchmarks.
 // This file contains values used by tests and benchmarks.
 
 
+type testInt64 int64
+
 type TestStrucFlex struct {
 type TestStrucFlex struct {
 	_struct struct{} `codec:",omitempty"` //set omitempty for every field
 	_struct struct{} `codec:",omitempty"` //set omitempty for every field
 	testStrucCommon
 	testStrucCommon
 
 
+	Ci64 testInt64 // added here, so we can execute the extension paths
+
 	Mis     map[int]string
 	Mis     map[int]string
 	Mbu64   map[bool]struct{}
 	Mbu64   map[bool]struct{}
 	Miwu64s map[int]wrapUint64Slice
 	Miwu64s map[int]wrapUint64Slice
@@ -28,6 +32,7 @@ type TestStrucFlex struct {
 
 
 func newTestStrucFlex(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStrucFlex) {
 func newTestStrucFlex(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStrucFlex) {
 	ts = &TestStrucFlex{
 	ts = &TestStrucFlex{
+		Ci64: -22,
 		Miwu64s: map[int]wrapUint64Slice{
 		Miwu64s: map[int]wrapUint64Slice{
 			5: []wrapUint64{1, 2, 3, 4, 5},
 			5: []wrapUint64{1, 2, 3, 4, 5},
 			3: []wrapUint64{1, 2, 3},
 			3: []wrapUint64{1, 2, 3},

+ 6 - 0
codec/z_all_test.go

@@ -393,6 +393,12 @@ func TestCodecSuite(t *testing.T) {
 
 
 	testCborH.IndefiniteLength = oldIndefLen
 	testCborH.IndefiniteLength = oldIndefLen
 
 
+	oldTimeRFC3339 := testCborH.TimeRFC3339
+	testCborH.TimeRFC3339 = !testCborH.TimeRFC3339
+	testReinit()
+	t.Run("cbor-rfc3339", testCborGroup)
+	testCborH.TimeRFC3339 = oldTimeRFC3339
+
 	oldSymbols := testBincH.getBasicHandle().AsSymbols
 	oldSymbols := testBincH.getBasicHandle().AsSymbols
 
 
 	testBincH.getBasicHandle().AsSymbols = AsSymbolNone
 	testBincH.getBasicHandle().AsSymbols = AsSymbolNone