mirror of
https://github.com/rs/zerolog
synced 2026-06-08 17:13:30 +00:00
feat: add new global DurationFieldFormat (#733)
This deprecates DurationFieldInteger in favor of DurationFieldFormat with the value of DurationFormatInt
This commit is contained in:
@@ -193,7 +193,7 @@ func (a *Array) Time(t time.Time) *Array {
|
||||
|
||||
// Dur appends d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
return a
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -400,13 +400,13 @@ func (c Context) Times(key string, t []time.Time) Context {
|
||||
|
||||
// Dur adds the field key with d divided by unit and stored as a float.
|
||||
func (c Context) Dur(key string, d time.Duration) Context {
|
||||
c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
// Durs adds the field key with d divided by unit and stored as a float.
|
||||
func (c Context) Durs(key string, d []time.Duration) Context {
|
||||
c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@ type encoder interface {
|
||||
AppendBool(dst []byte, val bool) []byte
|
||||
AppendBools(dst []byte, vals []bool) []byte
|
||||
AppendBytes(dst, s []byte) []byte
|
||||
AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, precision int) []byte
|
||||
AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, precision int) []byte
|
||||
AppendDuration(dst []byte, d time.Duration, unit time.Duration, format string, useInt bool, precision int) []byte
|
||||
AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, format string, useInt bool, precision int) []byte
|
||||
AppendEndMarker(dst []byte) []byte
|
||||
AppendFloat32(dst []byte, val float32, precision int) []byte
|
||||
AppendFloat64(dst []byte, val float64, precision int) []byte
|
||||
|
||||
@@ -729,7 +729,7 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -740,7 +740,7 @@ func (e *Event) Durs(key string, d []time.Duration) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = enc.AppendDurations(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
e.buf = enc.AppendDurations(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -755,7 +755,7 @@ func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
|
||||
if t.After(start) {
|
||||
d = t.Sub(start)
|
||||
}
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
return e
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
case time.Time:
|
||||
dst = enc.AppendTime(dst, val, TimeFieldFormat)
|
||||
case time.Duration:
|
||||
dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
case *string:
|
||||
if val != nil {
|
||||
dst = enc.AppendString(dst, *val)
|
||||
@@ -244,7 +244,7 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
}
|
||||
case *time.Duration:
|
||||
if val != nil {
|
||||
dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
} else {
|
||||
dst = enc.AppendNil(dst)
|
||||
}
|
||||
@@ -278,7 +278,7 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
|
||||
case []time.Time:
|
||||
dst = enc.AppendTimes(dst, val, TimeFieldFormat)
|
||||
case []time.Duration:
|
||||
dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
|
||||
dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldFormat, DurationFieldInteger, FloatingPointPrecision)
|
||||
case nil:
|
||||
dst = enc.AppendNil(dst)
|
||||
case net.IP:
|
||||
|
||||
+14
@@ -24,6 +24,16 @@ const (
|
||||
// TimeFormatUnixNano defines a time format that makes time fields to be
|
||||
// serialized as Unix timestamp integers in nanoseconds.
|
||||
TimeFormatUnixNano = "UNIXNANO"
|
||||
|
||||
// DurationFormatFloat defines a format for Duration fields that makes duration fields to be
|
||||
// serialized as floating point numbers.
|
||||
DurationFormatFloat = "float"
|
||||
// DurationFormatInt defines a format for Duration fields that makes duration fields to be
|
||||
// serialized as integers.
|
||||
DurationFormatInt = "int"
|
||||
// DurationFormatString defines a format for Duration fields that makes duration fields to be
|
||||
// serialized as string.
|
||||
DurationFormatString = "string"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -107,12 +117,16 @@ var (
|
||||
// TimestampFunc defines the function called to generate a timestamp.
|
||||
TimestampFunc = time.Now
|
||||
|
||||
// DurationFieldFormat defines the format of the Duration field type.
|
||||
DurationFieldFormat = DurationFormatFloat
|
||||
|
||||
// DurationFieldUnit defines the unit for time.Duration type fields added
|
||||
// using the Dur method.
|
||||
DurationFieldUnit = time.Millisecond
|
||||
|
||||
// DurationFieldInteger renders Dur fields as integer instead of float if
|
||||
// set to true.
|
||||
// Deprecated: use DurationFieldFormat with DurationFormatInt instead.
|
||||
DurationFieldInteger = false
|
||||
|
||||
// ErrorHandler is called whenever zerolog fails to write an event on its
|
||||
|
||||
+22
-22
@@ -1,22 +1,22 @@
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAppendKey(t *testing.T) {
|
||||
want := make([]byte, 0)
|
||||
want = append(want, 0xbf) // start string
|
||||
want = append(want, 0x63) // length 3
|
||||
want = append(want, []byte("key")...)
|
||||
|
||||
got := enc.AppendKey([]byte{}, "key")
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendKey(%v)\ngot: 0x%s\nwant: 0x%s",
|
||||
"key",
|
||||
hex.EncodeToString(got),
|
||||
hex.EncodeToString(want))
|
||||
}
|
||||
}
|
||||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAppendKey(t *testing.T) {
|
||||
want := make([]byte, 0)
|
||||
want = append(want, 0xbf) // start string
|
||||
want = append(want, 0x63) // length 3
|
||||
want = append(want, []byte("key")...)
|
||||
|
||||
got := enc.AppendKey([]byte{}, "key")
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendKey(%v)\ngot: 0x%s\nwant: 0x%s",
|
||||
"key",
|
||||
hex.EncodeToString(got),
|
||||
hex.EncodeToString(want))
|
||||
}
|
||||
}
|
||||
|
||||
+22
-3
@@ -4,6 +4,17 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// Import from zerolog/global.go
|
||||
timeFormatUnix = ""
|
||||
timeFormatUnixMs = "UNIXMS"
|
||||
timeFormatUnixMicro = "UNIXMICRO"
|
||||
timeFormatUnixNano = "UNIXNANO"
|
||||
durationFormatFloat = "float"
|
||||
durationFormatInt = "int"
|
||||
durationFormatString = "string"
|
||||
)
|
||||
|
||||
func appendIntegerTimestamp(dst []byte, t time.Time) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeTimestamp
|
||||
@@ -63,17 +74,25 @@ func (e Encoder) AppendTimes(dst []byte, vals []time.Time, unused string) []byte
|
||||
// AppendDuration encodes and adds a duration to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, unused int) []byte {
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, format string, useInt bool, unused int) []byte {
|
||||
if useInt {
|
||||
return e.AppendInt64(dst, int64(d/unit))
|
||||
}
|
||||
switch format {
|
||||
case durationFormatFloat:
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit), unused)
|
||||
case durationFormatInt:
|
||||
return e.AppendInt64(dst, int64(d/unit))
|
||||
case durationFormatString:
|
||||
return e.AppendString(dst, d.String())
|
||||
}
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit), unused)
|
||||
}
|
||||
|
||||
// AppendDurations encodes and adds an array of durations to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, unused int) []byte {
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, format string, useInt bool, unused int) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
@@ -86,7 +105,7 @@ func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Dur
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, d := range vals {
|
||||
dst = e.AppendDuration(dst, d, unit, useInt, unused)
|
||||
dst = e.AppendDuration(dst, d, unit, format, useInt, unused)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
+144
-5
@@ -5,12 +5,151 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal"
|
||||
)
|
||||
|
||||
func TestEncoder_AppendDuration(t *testing.T) {
|
||||
type args struct {
|
||||
dst []byte
|
||||
d time.Duration
|
||||
unit time.Duration
|
||||
format string
|
||||
useInt bool
|
||||
unused int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "useInt",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
useInt: true,
|
||||
},
|
||||
want: []byte{1},
|
||||
},
|
||||
{
|
||||
name: "formatFloat",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
format: durationFormatFloat,
|
||||
},
|
||||
want: []byte{251, 63, 243, 192, 202, 66, 131, 222, 27},
|
||||
},
|
||||
{
|
||||
name: "formatInt",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
format: durationFormatInt,
|
||||
},
|
||||
want: []byte{1},
|
||||
},
|
||||
{
|
||||
name: "formatString",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
format: durationFormatString,
|
||||
},
|
||||
want: []byte{107, 49, 46, 50, 51, 52, 53, 54, 55, 56, 57, 115},
|
||||
},
|
||||
{
|
||||
name: "formatBlank",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
},
|
||||
want: []byte{251, 63, 243, 192, 202, 66, 131, 222, 27},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := Encoder{}
|
||||
if got := e.AppendDuration(tt.args.dst, tt.args.d, tt.args.unit, tt.args.format, tt.args.useInt, tt.args.unused); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppendDuration() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoder_AppendDurations(t *testing.T) {
|
||||
type args struct {
|
||||
dst []byte
|
||||
vals []time.Duration
|
||||
unit time.Duration
|
||||
format string
|
||||
useInt bool
|
||||
unused int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "useInt",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
useInt: true,
|
||||
},
|
||||
want: []byte{129, 1},
|
||||
},
|
||||
{
|
||||
name: "formatFloat",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
format: durationFormatFloat,
|
||||
},
|
||||
want: []byte{129, 251, 63, 243, 192, 202, 66, 131, 222, 27},
|
||||
},
|
||||
{
|
||||
name: "formatInt",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
format: durationFormatInt,
|
||||
},
|
||||
want: []byte{129, 1},
|
||||
},
|
||||
{
|
||||
name: "formatString",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
format: durationFormatString,
|
||||
},
|
||||
want: []byte{129, 107, 49, 46, 50, 51, 52, 53, 54, 55, 56, 57, 115},
|
||||
},
|
||||
{
|
||||
name: "formatBlank",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
},
|
||||
want: []byte{129, 251, 63, 243, 192, 202, 66, 131, 222, 27},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := Encoder{}
|
||||
if got := e.AppendDurations(tt.args.dst, tt.args.vals, tt.args.unit, tt.args.format, tt.args.useInt, tt.args.unused); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppendDurations() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTimeNow(t *testing.T) {
|
||||
tm := time.Now()
|
||||
s := enc.AppendTime([]byte{}, tm, "unused")
|
||||
@@ -116,7 +255,7 @@ func TestAppendDurationFloat(t *testing.T) {
|
||||
dur := tt.Duration
|
||||
want := []byte{}
|
||||
want = append(want, []byte(tt.FloatOut)...)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, false, -1)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: 0x%s\nwant: 0x%s",
|
||||
dur,
|
||||
@@ -130,7 +269,7 @@ func TestAppendDurationInteger(t *testing.T) {
|
||||
dur := tt.Duration
|
||||
want := []byte{}
|
||||
want = append(want, []byte(tt.IntegerOut)...)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, true, -1)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, "", true, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: 0x%s\nwant: 0x%s",
|
||||
dur,
|
||||
@@ -148,7 +287,7 @@ func TestAppendDurations(t *testing.T) {
|
||||
want = append(want, []byte(tt.FloatOut)...)
|
||||
}
|
||||
|
||||
got := enc.AppendDurations([]byte{}, array, time.Microsecond, false, -1)
|
||||
got := enc.AppendDurations([]byte{}, array, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: 0x%s\nwant: 0x%s",
|
||||
array, hex.EncodeToString(got),
|
||||
@@ -160,7 +299,7 @@ func TestAppendDurations(t *testing.T) {
|
||||
want = make([]byte, 0)
|
||||
want = append(want, 0x9f) // start and end array
|
||||
want = append(want, 0xff) // for empty array
|
||||
got = enc.AppendDurations([]byte{}, array, time.Microsecond, false, -1)
|
||||
got = enc.AppendDurations([]byte{}, array, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: 0x%s\nwant: 0x%s",
|
||||
array, hex.EncodeToString(got),
|
||||
@@ -178,7 +317,7 @@ func TestAppendDurations(t *testing.T) {
|
||||
array[i] = testtime
|
||||
want = append(want, []byte(outbytes)...)
|
||||
}
|
||||
got = enc.AppendDurations([]byte{}, array, time.Microsecond, false, -1)
|
||||
got = enc.AppendDurations([]byte{}, array, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: 0x%s\nwant: 0x%s",
|
||||
array,
|
||||
|
||||
+30
-30
@@ -1,30 +1,30 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAppendKey(t *testing.T) {
|
||||
want := make([]byte, 0)
|
||||
want = append(want, []byte("{\"key\":")...)
|
||||
|
||||
got := enc.AppendKey([]byte("{"), "key") // test with empty object
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendKey(%v)\ngot: %s\nwant: %s",
|
||||
"key",
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
want = make([]byte, 0)
|
||||
want = append(want, []byte("},\"key\":")...) // test with non-empty object
|
||||
|
||||
got = enc.AppendKey([]byte("}"), "key")
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendKey(%v)\ngot: %s\nwant: %s",
|
||||
"key",
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAppendKey(t *testing.T) {
|
||||
want := make([]byte, 0)
|
||||
want = append(want, []byte("{\"key\":")...)
|
||||
|
||||
got := enc.AppendKey([]byte("{"), "key") // test with empty object
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendKey(%v)\ngot: %s\nwant: %s",
|
||||
"key",
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
want = make([]byte, 0)
|
||||
want = append(want, []byte("},\"key\":")...) // test with non-empty object
|
||||
|
||||
got = enc.AppendKey([]byte("}"), "key")
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendKey(%v)\ngot: %s\nwant: %s",
|
||||
"key",
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
+19
-8
@@ -7,10 +7,13 @@ import (
|
||||
|
||||
const (
|
||||
// Import from zerolog/global.go
|
||||
timeFormatUnix = ""
|
||||
timeFormatUnixMs = "UNIXMS"
|
||||
timeFormatUnixMicro = "UNIXMICRO"
|
||||
timeFormatUnixNano = "UNIXNANO"
|
||||
timeFormatUnix = ""
|
||||
timeFormatUnixMs = "UNIXMS"
|
||||
timeFormatUnixMicro = "UNIXMICRO"
|
||||
timeFormatUnixNano = "UNIXNANO"
|
||||
durationFormatFloat = "float"
|
||||
durationFormatInt = "int"
|
||||
durationFormatString = "string"
|
||||
)
|
||||
|
||||
// AppendTime formats the input time with the given format
|
||||
@@ -88,24 +91,32 @@ func appendUnixNanoTimes(dst []byte, vals []time.Time, div int64) []byte {
|
||||
|
||||
// AppendDuration formats the input duration with the given unit & format
|
||||
// and appends the encoded string to the input byte slice.
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, precision int) []byte {
|
||||
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, format string, useInt bool, precision int) []byte {
|
||||
if useInt {
|
||||
return strconv.AppendInt(dst, int64(d/unit), 10)
|
||||
}
|
||||
switch format {
|
||||
case durationFormatFloat:
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit), precision)
|
||||
case durationFormatInt:
|
||||
return e.AppendInt64(dst, int64(d/unit))
|
||||
case durationFormatString:
|
||||
return e.AppendString(dst, d.String())
|
||||
}
|
||||
return e.AppendFloat64(dst, float64(d)/float64(unit), precision)
|
||||
}
|
||||
|
||||
// AppendDurations formats the input durations with the given unit & format
|
||||
// and appends the encoded string list to the input byte slice.
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, precision int) []byte {
|
||||
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, format string, useInt bool, precision int) []byte {
|
||||
if len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
dst = e.AppendDuration(dst, vals[0], unit, useInt, precision)
|
||||
dst = e.AppendDuration(dst, vals[0], unit, format, useInt, precision)
|
||||
if len(vals) > 1 {
|
||||
for _, d := range vals[1:] {
|
||||
dst = e.AppendDuration(append(dst, ','), d, unit, useInt, precision)
|
||||
dst = e.AppendDuration(append(dst, ','), d, unit, format, useInt, precision)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
|
||||
+373
-234
@@ -1,234 +1,373 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal"
|
||||
)
|
||||
|
||||
func TestAppendTimeNow(t *testing.T) {
|
||||
tm := time.Now()
|
||||
got := enc.AppendTime([]byte{}, tm, time.RFC3339)
|
||||
want := tm.AppendFormat([]byte{'"'}, time.RFC3339)
|
||||
want = append(want, '"')
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendTime(%s)\ngot: %s\nwant: %s",
|
||||
"time.Now()",
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTimePastPresentInteger(t *testing.T) {
|
||||
for _, tt := range internal.TimeIntegerTestcases {
|
||||
tin, err := time.Parse(time.RFC3339, tt.Txt)
|
||||
if err != nil {
|
||||
fmt.Println("Cannot parse input", tt.Txt, ".. Skipping!", err)
|
||||
continue
|
||||
}
|
||||
|
||||
got := enc.AppendTime([]byte{}, tin, timeFormatUnix)
|
||||
want := []byte(fmt.Sprintf("%d", tt.UnixInt))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
got = enc.AppendTime([]byte{}, tin, timeFormatUnixMs)
|
||||
want = []byte(fmt.Sprintf("%d", tt.UnixInt*1000))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
got = enc.AppendTime([]byte{}, tin, timeFormatUnixMicro)
|
||||
want = []byte(fmt.Sprintf("%d", tt.UnixInt*1000000))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
got = enc.AppendTime([]byte{}, tin, timeFormatUnixNano)
|
||||
want = []byte(fmt.Sprintf("%d", tt.UnixInt*1000000000))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTimePastPresentFloat(t *testing.T) {
|
||||
const timeFloatFmt = "2006-01-02T15:04:05.999999-07:00"
|
||||
for _, tt := range internal.TimeFloatTestcases {
|
||||
tin, err := time.Parse(timeFloatFmt, tt.RfcStr)
|
||||
if err != nil {
|
||||
fmt.Println("Cannot parse input", tt.RfcStr, ".. Skipping!")
|
||||
continue
|
||||
}
|
||||
got := enc.AppendTime([]byte{}, tin, timeFormatUnix)
|
||||
want := []byte(fmt.Sprintf("%d", tt.UnixInt))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.RfcStr,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestAppendTimes(t *testing.T) {
|
||||
doOne := func(multiplier int, format string) {
|
||||
array := make([]time.Time, 0)
|
||||
want := append([]byte{}, '[')
|
||||
want = append(want, ']')
|
||||
got := enc.AppendTimes([]byte{}, array, format)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendTimes(%v)\ngot: %s\nwant: %s",
|
||||
array,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
array = make([]time.Time, len(internal.TimeIntegerTestcases))
|
||||
want = append([]byte{}, '[')
|
||||
for i, tt := range internal.TimeIntegerTestcases {
|
||||
if tin, err := time.Parse(time.RFC3339, tt.RfcStr); err != nil {
|
||||
fmt.Println("Cannot parse input", tt.RfcStr, ".. Skipping!")
|
||||
continue
|
||||
} else {
|
||||
array[i] = tin
|
||||
}
|
||||
if multiplier == 0 {
|
||||
want = append(want, '"')
|
||||
formatted := array[i].Format(format)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", formatted))...)
|
||||
want = append(want, '"')
|
||||
} else {
|
||||
scaled := tt.UnixInt * multiplier
|
||||
want = append(want, []byte(fmt.Sprintf("%d", scaled))...)
|
||||
}
|
||||
if i < len(internal.TimeIntegerTestcases)-1 {
|
||||
want = append(want, ',')
|
||||
}
|
||||
}
|
||||
want = append(want, ']')
|
||||
|
||||
got = enc.AppendTimes([]byte{}, array, format)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendTimes(%v) %d %s\ngot: %s\nwant: %s",
|
||||
array, multiplier, format,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
doOne(0, time.RFC3339)
|
||||
doOne(1, timeFormatUnix)
|
||||
doOne(1000, timeFormatUnixMs)
|
||||
doOne(1000000, timeFormatUnixMicro)
|
||||
doOne(1000000000, timeFormatUnixNano)
|
||||
}
|
||||
|
||||
func TestAppendDurationFloat(t *testing.T) {
|
||||
for _, tt := range internal.DurTestcases {
|
||||
dur := tt.Duration
|
||||
want := []byte{}
|
||||
want = append(want, []byte(fmt.Sprintf("%v", dur.Microseconds()))...)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: %s\nwant: %s",
|
||||
dur,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
want = []byte{}
|
||||
fraction := float64(dur) / float64(time.Millisecond)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", fraction))...)
|
||||
got = enc.AppendDuration([]byte{}, dur, time.Millisecond, false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: %s\nwant: %s",
|
||||
dur,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestAppendDurationInteger(t *testing.T) {
|
||||
for _, tt := range internal.DurTestcases {
|
||||
dur := tt.Duration
|
||||
want := []byte{}
|
||||
whole := int(dur) / int(time.Microsecond)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", whole))...)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, true, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: %s\nwant: %s",
|
||||
dur,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestAppendDurations(t *testing.T) {
|
||||
array := make([]time.Duration, len(internal.DurTestcases))
|
||||
want := make([]byte, 0)
|
||||
want = append(want, '[')
|
||||
for i, tt := range internal.DurTestcases {
|
||||
array[i] = tt.Duration
|
||||
whole := int(tt.Duration) / int(time.Microsecond)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", whole))...)
|
||||
if i < len(internal.DurTestcases)-1 {
|
||||
want = append(want, ',')
|
||||
}
|
||||
}
|
||||
want = append(want, ']')
|
||||
|
||||
got := enc.AppendDurations([]byte{}, array, time.Microsecond, false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: %s\nwant: %s",
|
||||
array,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
// now empty array case
|
||||
array = make([]time.Duration, 0)
|
||||
want = make([]byte, 0)
|
||||
want = append(want, '[')
|
||||
want = append(want, ']')
|
||||
got = enc.AppendDurations([]byte{}, array, time.Microsecond, false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: %s\nwant: %s",
|
||||
array,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendTime(b *testing.B) {
|
||||
tests := map[string]string{
|
||||
"Integer": "Feb 3, 2013 at 7:54pm (PST)",
|
||||
"Float": "2006-01-02T15:04:05.999999-08:00",
|
||||
}
|
||||
const timeFloatFmt = "2006-01-02T15:04:05.999999-07:00"
|
||||
|
||||
for name, str := range tests {
|
||||
t, err := time.Parse(time.RFC3339, str)
|
||||
if err != nil {
|
||||
t, _ = time.Parse(timeFloatFmt, str)
|
||||
}
|
||||
b.Run(name, func(b *testing.B) {
|
||||
buf := make([]byte, 0, 100)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = enc.AppendTime(buf, t, "unused")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal"
|
||||
)
|
||||
|
||||
func TestEncoder_AppendDuration(t *testing.T) {
|
||||
type args struct {
|
||||
dst []byte
|
||||
d time.Duration
|
||||
unit time.Duration
|
||||
format string
|
||||
useInt bool
|
||||
unused int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "useInt",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
useInt: true,
|
||||
},
|
||||
want: []byte{49},
|
||||
},
|
||||
{
|
||||
name: "formatFloat",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
format: durationFormatFloat,
|
||||
},
|
||||
want: []byte{49},
|
||||
},
|
||||
{
|
||||
name: "formatInt",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
format: durationFormatInt,
|
||||
},
|
||||
want: []byte{49},
|
||||
},
|
||||
{
|
||||
name: "formatString",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
format: durationFormatString,
|
||||
},
|
||||
want: []byte{34, 49, 46, 50, 51, 52, 53, 54, 55, 56, 57, 115, 34},
|
||||
},
|
||||
{
|
||||
name: "formatBlank",
|
||||
args: args{
|
||||
d: 1234567890,
|
||||
unit: time.Second,
|
||||
},
|
||||
want: []byte{49},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := Encoder{}
|
||||
if got := e.AppendDuration(tt.args.dst, tt.args.d, tt.args.unit, tt.args.format, tt.args.useInt, tt.args.unused); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppendDuration() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncoder_AppendDurations(t *testing.T) {
|
||||
type args struct {
|
||||
dst []byte
|
||||
vals []time.Duration
|
||||
unit time.Duration
|
||||
format string
|
||||
useInt bool
|
||||
unused int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "useInt",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
useInt: true,
|
||||
},
|
||||
want: []byte{91, 49, 93},
|
||||
},
|
||||
{
|
||||
name: "formatFloat",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
format: durationFormatFloat,
|
||||
},
|
||||
want: []byte{91, 49, 93},
|
||||
},
|
||||
{
|
||||
name: "formatInt",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
format: durationFormatInt,
|
||||
},
|
||||
want: []byte{91, 49, 93},
|
||||
},
|
||||
{
|
||||
name: "formatString",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
format: durationFormatString,
|
||||
},
|
||||
want: []byte{91, 34, 49, 46, 50, 51, 52, 53, 54, 55, 56, 57, 115, 34, 93},
|
||||
},
|
||||
{
|
||||
name: "formatBlank",
|
||||
args: args{
|
||||
vals: []time.Duration{1234567890},
|
||||
unit: time.Second,
|
||||
},
|
||||
want: []byte{91, 49, 93},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := Encoder{}
|
||||
if got := e.AppendDurations(tt.args.dst, tt.args.vals, tt.args.unit, tt.args.format, tt.args.useInt, tt.args.unused); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("AppendDurations() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTimeNow(t *testing.T) {
|
||||
tm := time.Now()
|
||||
got := enc.AppendTime([]byte{}, tm, time.RFC3339)
|
||||
want := tm.AppendFormat([]byte{'"'}, time.RFC3339)
|
||||
want = append(want, '"')
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendTime(%s)\ngot: %s\nwant: %s",
|
||||
"time.Now()",
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTimePastPresentInteger(t *testing.T) {
|
||||
for _, tt := range internal.TimeIntegerTestcases {
|
||||
tin, err := time.Parse(time.RFC3339, tt.Txt)
|
||||
if err != nil {
|
||||
fmt.Println("Cannot parse input", tt.Txt, ".. Skipping!", err)
|
||||
continue
|
||||
}
|
||||
|
||||
got := enc.AppendTime([]byte{}, tin, timeFormatUnix)
|
||||
want := []byte(fmt.Sprintf("%d", tt.UnixInt))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
got = enc.AppendTime([]byte{}, tin, timeFormatUnixMs)
|
||||
want = []byte(fmt.Sprintf("%d", tt.UnixInt*1000))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
got = enc.AppendTime([]byte{}, tin, timeFormatUnixMicro)
|
||||
want = []byte(fmt.Sprintf("%d", tt.UnixInt*1000000))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
got = enc.AppendTime([]byte{}, tin, timeFormatUnixNano)
|
||||
want = []byte(fmt.Sprintf("%d", tt.UnixInt*1000000000))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.Txt,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendTimePastPresentFloat(t *testing.T) {
|
||||
const timeFloatFmt = "2006-01-02T15:04:05.999999-07:00"
|
||||
for _, tt := range internal.TimeFloatTestcases {
|
||||
tin, err := time.Parse(timeFloatFmt, tt.RfcStr)
|
||||
if err != nil {
|
||||
fmt.Println("Cannot parse input", tt.RfcStr, ".. Skipping!")
|
||||
continue
|
||||
}
|
||||
got := enc.AppendTime([]byte{}, tin, timeFormatUnix)
|
||||
want := []byte(fmt.Sprintf("%d", tt.UnixInt))
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("appendString(%s)\ngot: %s\nwant: %s",
|
||||
tt.RfcStr,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestAppendTimes(t *testing.T) {
|
||||
doOne := func(multiplier int, format string) {
|
||||
array := make([]time.Time, 0)
|
||||
want := append([]byte{}, '[')
|
||||
want = append(want, ']')
|
||||
got := enc.AppendTimes([]byte{}, array, format)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendTimes(%v)\ngot: %s\nwant: %s",
|
||||
array,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
array = make([]time.Time, len(internal.TimeIntegerTestcases))
|
||||
want = append([]byte{}, '[')
|
||||
for i, tt := range internal.TimeIntegerTestcases {
|
||||
if tin, err := time.Parse(time.RFC3339, tt.RfcStr); err != nil {
|
||||
fmt.Println("Cannot parse input", tt.RfcStr, ".. Skipping!")
|
||||
continue
|
||||
} else {
|
||||
array[i] = tin
|
||||
}
|
||||
if multiplier == 0 {
|
||||
want = append(want, '"')
|
||||
formatted := array[i].Format(format)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", formatted))...)
|
||||
want = append(want, '"')
|
||||
} else {
|
||||
scaled := tt.UnixInt * multiplier
|
||||
want = append(want, []byte(fmt.Sprintf("%d", scaled))...)
|
||||
}
|
||||
if i < len(internal.TimeIntegerTestcases)-1 {
|
||||
want = append(want, ',')
|
||||
}
|
||||
}
|
||||
want = append(want, ']')
|
||||
|
||||
got = enc.AppendTimes([]byte{}, array, format)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendTimes(%v) %d %s\ngot: %s\nwant: %s",
|
||||
array, multiplier, format,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
doOne(0, time.RFC3339)
|
||||
doOne(1, timeFormatUnix)
|
||||
doOne(1000, timeFormatUnixMs)
|
||||
doOne(1000000, timeFormatUnixMicro)
|
||||
doOne(1000000000, timeFormatUnixNano)
|
||||
}
|
||||
|
||||
func TestAppendDurationFloat(t *testing.T) {
|
||||
for _, tt := range internal.DurTestcases {
|
||||
dur := tt.Duration
|
||||
want := []byte{}
|
||||
want = append(want, []byte(fmt.Sprintf("%v", dur.Microseconds()))...)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: %s\nwant: %s",
|
||||
dur,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
want = []byte{}
|
||||
fraction := float64(dur) / float64(time.Millisecond)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", fraction))...)
|
||||
got = enc.AppendDuration([]byte{}, dur, time.Millisecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: %s\nwant: %s",
|
||||
dur,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestAppendDurationInteger(t *testing.T) {
|
||||
for _, tt := range internal.DurTestcases {
|
||||
dur := tt.Duration
|
||||
want := []byte{}
|
||||
whole := int(dur) / int(time.Microsecond)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", whole))...)
|
||||
got := enc.AppendDuration([]byte{}, dur, time.Microsecond, "", true, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDuration(%v)=\ngot: %s\nwant: %s",
|
||||
dur,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestAppendDurations(t *testing.T) {
|
||||
array := make([]time.Duration, len(internal.DurTestcases))
|
||||
want := make([]byte, 0)
|
||||
want = append(want, '[')
|
||||
for i, tt := range internal.DurTestcases {
|
||||
array[i] = tt.Duration
|
||||
whole := int(tt.Duration) / int(time.Microsecond)
|
||||
want = append(want, []byte(fmt.Sprintf("%v", whole))...)
|
||||
if i < len(internal.DurTestcases)-1 {
|
||||
want = append(want, ',')
|
||||
}
|
||||
}
|
||||
want = append(want, ']')
|
||||
|
||||
got := enc.AppendDurations([]byte{}, array, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: %s\nwant: %s",
|
||||
array,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
|
||||
// now empty array case
|
||||
array = make([]time.Duration, 0)
|
||||
want = make([]byte, 0)
|
||||
want = append(want, '[')
|
||||
want = append(want, ']')
|
||||
got = enc.AppendDurations([]byte{}, array, time.Microsecond, "", false, -1)
|
||||
if !bytes.Equal(got, want) {
|
||||
t.Errorf("AppendDurations(%v)\ngot: %s\nwant: %s",
|
||||
array,
|
||||
string(got),
|
||||
string(want))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendTime(b *testing.B) {
|
||||
tests := map[string]string{
|
||||
"Integer": "Feb 3, 2013 at 7:54pm (PST)",
|
||||
"Float": "2006-01-02T15:04:05.999999-08:00",
|
||||
}
|
||||
const timeFloatFmt = "2006-01-02T15:04:05.999999-07:00"
|
||||
|
||||
for name, str := range tests {
|
||||
t, err := time.Parse(time.RFC3339, str)
|
||||
if err != nil {
|
||||
t, _ = time.Parse(timeFloatFmt, str)
|
||||
}
|
||||
b.Run(name, func(b *testing.B) {
|
||||
buf := make([]byte, 0, 100)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = enc.AppendTime(buf, t, "unused")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+375
-375
@@ -1,375 +1,375 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
var BooleanTestCases = []struct {
|
||||
Val bool
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{true, "\xf5", "true"},
|
||||
{false, "\xf4", "false"},
|
||||
}
|
||||
|
||||
var BooleanArrayTestCases = []struct {
|
||||
Val []bool
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]bool{}, "\x9f\xff", "[]"},
|
||||
{[]bool{false}, "\x81\xf4", "[false]"},
|
||||
{[]bool{true, false, true}, "\x83\xf5\xf4\xf5", "[true,false,true]"},
|
||||
{[]bool{true, false, false, true, false, true}, "\x86\xf5\xf4\xf4\xf5\xf4\xf5", "[true,false,false,true,false,true]"},
|
||||
}
|
||||
|
||||
var IntegerTestCases = []struct {
|
||||
Val int
|
||||
Binary string
|
||||
}{
|
||||
// Value included in the type.
|
||||
{0, "\x00"},
|
||||
{1, "\x01"},
|
||||
{2, "\x02"},
|
||||
{3, "\x03"},
|
||||
{8, "\x08"},
|
||||
{9, "\x09"},
|
||||
{10, "\x0a"},
|
||||
{22, "\x16"},
|
||||
{23, "\x17"},
|
||||
|
||||
// Value in 1 byte.
|
||||
{24, "\x18\x18"},
|
||||
{25, "\x18\x19"},
|
||||
{26, "\x18\x1a"},
|
||||
{127, "\x18\x7f"},
|
||||
{254, "\x18\xfe"},
|
||||
{255, "\x18\xff"},
|
||||
|
||||
// Value in 2 bytes.
|
||||
{256, "\x19\x01\x00"},
|
||||
{257, "\x19\x01\x01"},
|
||||
{1000, "\x19\x03\xe8"},
|
||||
{0xFFFF, "\x19\xff\xff"},
|
||||
|
||||
// Value in 4 bytes.
|
||||
{0x10000, "\x1a\x00\x01\x00\x00"},
|
||||
{0x7FFFFFFE, "\x1a\x7f\xff\xff\xfe"},
|
||||
{1000000, "\x1a\x00\x0f\x42\x40"},
|
||||
|
||||
// Negative number test cases.
|
||||
// Value included in the type.
|
||||
{-1, "\x20"},
|
||||
{-2, "\x21"},
|
||||
{-3, "\x22"},
|
||||
{-10, "\x29"},
|
||||
{-21, "\x34"},
|
||||
{-22, "\x35"},
|
||||
{-23, "\x36"},
|
||||
{-24, "\x37"},
|
||||
|
||||
// Value in 1 byte.
|
||||
{-25, "\x38\x18"},
|
||||
{-26, "\x38\x19"},
|
||||
{-100, "\x38\x63"},
|
||||
{-128, "\x38\x7f"},
|
||||
{-254, "\x38\xfd"},
|
||||
{-255, "\x38\xfe"},
|
||||
{-256, "\x38\xff"},
|
||||
|
||||
// Value in 2 bytes.
|
||||
{-257, "\x39\x01\x00"},
|
||||
{-258, "\x39\x01\x01"},
|
||||
{-1000, "\x39\x03\xe7"},
|
||||
|
||||
// Value in 4 bytes.
|
||||
{-0x10001, "\x3a\x00\x01\x00\x00"},
|
||||
{-0x7FFFFFFE, "\x3a\x7f\xff\xff\xfd"},
|
||||
{-1000000, "\x3a\x00\x0f\x42\x3f"},
|
||||
|
||||
//Constants
|
||||
{math.MaxInt8, "\x18\x7f"},
|
||||
{math.MinInt8, "\x38\x7f"},
|
||||
{math.MaxInt16, "\x19\x7f\xff"},
|
||||
{math.MinInt16, "\x39\x7f\xff"},
|
||||
{math.MaxInt32, "\x1a\x7f\xff\xff\xff"},
|
||||
{math.MinInt32, "\x3a\x7f\xff\xff\xff"},
|
||||
{math.MaxInt64, "\x1b\x7f\xff\xff\xff\xff\xff\xff\xff"},
|
||||
{math.MinInt64, "\x3b\x7f\xff\xff\xff\xff\xff\xff\xff"},
|
||||
}
|
||||
|
||||
type UnsignedIntTestCase struct {
|
||||
Val uint
|
||||
Binary string
|
||||
Bigbinary string
|
||||
}
|
||||
|
||||
var AdditionalUnsignedIntegerTestCases = []UnsignedIntTestCase{
|
||||
{0x7FFFFFFF, "\x18\xff", "\x1a\x7f\xff\xff\xff"},
|
||||
{0x80000000, "\x19\xff\xff", "\x1a\x80\x00\x00\x00"},
|
||||
{1000000, "\x1b\x80\x00\x00\x00\x00\x00\x00\x00", "\x1a\x00\x0f\x42\x40"},
|
||||
|
||||
//Constants
|
||||
{math.MaxUint8, "\x18\xff", "\x18\xff"},
|
||||
{math.MaxUint16, "\x19\xff\xff", "\x19\xff\xff"},
|
||||
{math.MaxUint32, "\x1a\xff\xff\xff\xff", "\x1a\xff\xff\xff\xff"},
|
||||
{math.MaxUint64, "\x1b\xff\xff\xff\xff\xff\xff\xff\xff", "\x1b\xff\xff\xff\xff\xff\xff\xff\xff"},
|
||||
}
|
||||
|
||||
func unsignedIntegerTestCases() []UnsignedIntTestCase {
|
||||
size := len(IntegerTestCases) + len(AdditionalUnsignedIntegerTestCases)
|
||||
cases := make([]UnsignedIntTestCase, 0, size)
|
||||
cases = append(cases, AdditionalUnsignedIntegerTestCases...)
|
||||
for _, itc := range IntegerTestCases {
|
||||
if itc.Val < 0 {
|
||||
continue
|
||||
}
|
||||
cases = append(cases, UnsignedIntTestCase{Val: uint(itc.Val), Binary: itc.Binary, Bigbinary: itc.Binary})
|
||||
}
|
||||
return cases
|
||||
}
|
||||
|
||||
var UnsignedIntegerTestCases = unsignedIntegerTestCases()
|
||||
|
||||
var Float32TestCases = []struct {
|
||||
Val float32
|
||||
Binary string
|
||||
}{
|
||||
{0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{-0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{1.0, "\xfa\x3f\x80\x00\x00"},
|
||||
{1.5, "\xfa\x3f\xc0\x00\x00"},
|
||||
{65504.0, "\xfa\x47\x7f\xe0\x00"},
|
||||
{-4.0, "\xfa\xc0\x80\x00\x00"},
|
||||
{0.00006103515625, "\xfa\x38\x80\x00\x00"},
|
||||
{float32(math.Inf(0)), "\xfa\x7f\x80\x00\x00"},
|
||||
{float32(math.Inf(-1)), "\xfa\xff\x80\x00\x00"},
|
||||
{float32(math.NaN()), "\xfa\x7f\xc0\x00\x00"},
|
||||
{math.SmallestNonzeroFloat32, "\xfa\x00\x00\x00\x01"},
|
||||
{math.MaxFloat32, "\xfa\x7f\x7f\xff\xff"},
|
||||
}
|
||||
|
||||
var Float64TestCases = []struct {
|
||||
Val float64
|
||||
Binary string
|
||||
}{
|
||||
{0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{-0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{1.0, "\xfa\x3f\x80\x00\x00"},
|
||||
{1.5, "\xfa\x3f\xc0\x00\x00"},
|
||||
{65504.0, "\xfa\x47\x7f\xe0\x00"},
|
||||
{-4.0, "\xfa\xc0\x80\x00\x00"},
|
||||
{0.00006103515625, "\xfa\x38\x80\x00\x00"},
|
||||
{math.Inf(0), "\xfa\x7f\x80\x00\x00\x00\x00\x00\x00"},
|
||||
{math.Inf(-1), "\xfa\xff\x80\x00\x00\x00\x00\x00\x00"},
|
||||
{math.NaN(), "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"},
|
||||
{math.SmallestNonzeroFloat64, "\xfa\x00\x00\x00\x00\x00\x00\x00\x01"},
|
||||
{math.MaxFloat64, "\xfa\x7f\x7f\xff\xff"},
|
||||
}
|
||||
|
||||
var IntegerArrayTestCases = []struct {
|
||||
Val []int
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]int{}, "\x9f\xff", "[]"},
|
||||
{[]int{32768}, "\x81\x19\x80\x00", "[32768]"},
|
||||
{[]int{-1, 0, 200, 20}, "\x84\x20\x00\x18\xc8\x14", "[-1,0,200,20]"},
|
||||
{[]int{-200, -10, 200, 400}, "\x84\x38\xc7\x29\x18\xc8\x19\x01\x90", "[-200,-10,200,400]"},
|
||||
{[]int{1, 2, 3}, "\x83\x01\x02\x03", "[1,2,3]"},
|
||||
{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
|
||||
"\x98\x19\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x18\x18\x19",
|
||||
"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]"},
|
||||
}
|
||||
|
||||
var IpAddrTestCases = []struct {
|
||||
Ipaddr net.IP
|
||||
Text string
|
||||
Binary string
|
||||
}{
|
||||
{net.IP{10, 0, 0, 1}, "\"10.0.0.1\"", "\xd9\x01\x04\x44\x0a\x00\x00\x01"},
|
||||
{net.IP{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
|
||||
"\"2001:db8:85a3::8a2e:370:7334\"",
|
||||
"\xd9\x01\x04\x50\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34"},
|
||||
}
|
||||
|
||||
var IPAddrArrayTestCases = []struct {
|
||||
Val []net.IP
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]net.IP{}, "\x9f\xff", "[]"},
|
||||
{[]net.IP{{127, 0, 0, 0}}, "\x81\xd9\x01\x04\x44\x7f\x00\x00\x00", "[127.0.0.0]"},
|
||||
{[]net.IP{{0, 0, 0, 0}, {192, 168, 0, 100}}, "\x82\xd9\x01\x04\x44\x00\x00\x00\x00\xd9\x01\x04\x44\xc0\xa8\x00\x64", "[0.0.0.0,192.168.0.100]"},
|
||||
}
|
||||
|
||||
var IPPrefixTestCases = []struct {
|
||||
Pfx net.IPNet
|
||||
Text string // ASCII representation of pfx
|
||||
Binary string // CBOR representation of pfx
|
||||
}{
|
||||
{net.IPNet{IP: net.IP{0, 0, 0, 0}, Mask: net.CIDRMask(0, 32)}, "\"0.0.0.0/0\"", "\xd9\x01\x05\xa1\x44\x00\x00\x00\x00\x00"},
|
||||
{net.IPNet{IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}, "\"192.168.0.100/24\"",
|
||||
"\xd9\x01\x05\xa1\x44\xc0\xa8\x00\x64\x18\x18"},
|
||||
}
|
||||
|
||||
var IPPrefixArrayTestCases = []struct {
|
||||
Val []net.IPNet
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]net.IPNet{}, "\x9f\xff", "[]"},
|
||||
{[]net.IPNet{{IP: net.IP{127, 0, 0, 0}, Mask: net.CIDRMask(24, 32)}}, "\x81\xd9\x01\x05\xa1\x44\x7f\x00\x00\x00\x18\x18", "[127.0.0.0/24]"},
|
||||
{[]net.IPNet{{IP: net.IP{0, 0, 0, 0}, Mask: net.CIDRMask(0, 32)}, {IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}}, "\x82\xd9\x01\x05\xa1\x44\x00\x00\x00\x00\x00\xd9\x01\x05\xa1\x44\xc0\xa8\x00\x64\x18\x18", "[0.0.0.0/0,192.168.0.100/24]"},
|
||||
}
|
||||
|
||||
var MacAddrTestCases = []struct {
|
||||
Macaddr net.HardwareAddr
|
||||
Text string // ASCII representation of macaddr
|
||||
Binary string // CBOR representation of macaddr
|
||||
}{
|
||||
{net.HardwareAddr{0x12, 0x34, 0x56, 0x78, 0x90, 0xab}, "\"12:34:56:78:90:ab\"", "\xd9\x01\x04\x46\x12\x34\x56\x78\x90\xab"},
|
||||
{net.HardwareAddr{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3}, "\"20:01:0d:b8:85:a3\"", "\xd9\x01\x04\x46\x20\x01\x0d\xb8\x85\xa3"},
|
||||
}
|
||||
|
||||
var EncodeHexTests = []struct {
|
||||
In byte
|
||||
Out string
|
||||
}{
|
||||
{0x00, `"00"`},
|
||||
{0x0f, `"0f"`},
|
||||
{0x10, `"10"`},
|
||||
{0xf0, `"f0"`},
|
||||
{0xff, `"ff"`},
|
||||
}
|
||||
|
||||
var EncodeStringTests = []struct {
|
||||
In string
|
||||
Out string
|
||||
}{
|
||||
{"", `""`},
|
||||
{"\\", `"\\"`},
|
||||
{"\x00", `"\u0000"`},
|
||||
{"\x01", `"\u0001"`},
|
||||
{"\x02", `"\u0002"`},
|
||||
{"\x03", `"\u0003"`},
|
||||
{"\x04", `"\u0004"`},
|
||||
{"\x05", `"\u0005"`},
|
||||
{"\x06", `"\u0006"`},
|
||||
{"\x07", `"\u0007"`},
|
||||
{"\x08", `"\b"`},
|
||||
{"\x09", `"\t"`},
|
||||
{"\x0a", `"\n"`},
|
||||
{"\x0b", `"\u000b"`},
|
||||
{"\x0c", `"\f"`},
|
||||
{"\x0d", `"\r"`},
|
||||
{"\x0e", `"\u000e"`},
|
||||
{"\x0f", `"\u000f"`},
|
||||
{"\x10", `"\u0010"`},
|
||||
{"\x11", `"\u0011"`},
|
||||
{"\x12", `"\u0012"`},
|
||||
{"\x13", `"\u0013"`},
|
||||
{"\x14", `"\u0014"`},
|
||||
{"\x15", `"\u0015"`},
|
||||
{"\x16", `"\u0016"`},
|
||||
{"\x17", `"\u0017"`},
|
||||
{"\x18", `"\u0018"`},
|
||||
{"\x19", `"\u0019"`},
|
||||
{"\x1a", `"\u001a"`},
|
||||
{"\x1b", `"\u001b"`},
|
||||
{"\x1c", `"\u001c"`},
|
||||
{"\x1d", `"\u001d"`},
|
||||
{"\x1e", `"\u001e"`},
|
||||
{"\x1f", `"\u001f"`},
|
||||
{"✭", `"✭"`},
|
||||
{"foo\xc2\x7fbar", `"foo\ufffd\u007fbar"`}, // invalid sequence
|
||||
{"ascii", `"ascii"`},
|
||||
{"\"a", `"\"a"`},
|
||||
{"\x1fa", `"\u001fa"`},
|
||||
{"foo\"bar\"baz", `"foo\"bar\"baz"`},
|
||||
{"\x1ffoo\x1fbar\x1fbaz", `"\u001ffoo\u001fbar\u001fbaz"`},
|
||||
{"emoji \u2764\ufe0f!", `"emoji ❤️!"`},
|
||||
}
|
||||
|
||||
var EncodeStringsTests = []struct {
|
||||
In []string
|
||||
Out string
|
||||
}{
|
||||
{nil, `[]`},
|
||||
{[]string{}, `[]`},
|
||||
{[]string{"A"}, `["A"]`},
|
||||
{[]string{"A", "B"}, `["A","B"]`},
|
||||
}
|
||||
|
||||
var EncodeStringerTests = []struct {
|
||||
In fmt.Stringer
|
||||
Out string
|
||||
Binary string
|
||||
}{
|
||||
{nil, `null`, "\xf6"},
|
||||
{fmt.Stringer(nil), `null`, "\xf6"},
|
||||
{net.IPv4bcast, `"255.255.255.255"`, "\x6f\x32\x35\x35\x2e\x32\x35\x35\x2e\x32\x35\x35\x2e\x32\x35\x35"},
|
||||
}
|
||||
|
||||
var EncodeStringersTests = []struct {
|
||||
In []fmt.Stringer
|
||||
Out string
|
||||
Binary string
|
||||
}{
|
||||
{nil, `[]`, "\x9f\xff"},
|
||||
{[]fmt.Stringer{}, `[]`, "\x9f\xff"},
|
||||
{[]fmt.Stringer{net.IPv4bcast}, `["255.255.255.255"]`, "\x9f\x6f255.255.255.255\xff"},
|
||||
{[]fmt.Stringer{net.IPv4allsys, net.IPv4allrouter}, `["224.0.0.1","224.0.0.2"]`, "\x9f\x69224.0.0.1\x69224.0.0.2\xff"},
|
||||
}
|
||||
|
||||
var TimeIntegerTestcases = []struct {
|
||||
Txt string
|
||||
Binary string
|
||||
RfcStr string
|
||||
UnixInt int
|
||||
}{
|
||||
{"2013-02-03T19:54:00-08:00", "\xc1\x1a\x51\x0f\x30\xd8", "2013-02-04T03:54:00Z", 1359950040},
|
||||
{"1950-02-03T19:54:00-08:00", "\xc1\x3a\x25\x71\x93\xa7", "1950-02-04T03:54:00Z", -628200360},
|
||||
}
|
||||
|
||||
var TimeFloatTestcases = []struct {
|
||||
RfcStr string
|
||||
Out string
|
||||
UnixInt int
|
||||
}{
|
||||
{"2006-01-02T15:04:05.999999-08:00", "\xc1\xfb\x41\xd0\xee\x6c\x59\x7f\xff\xfc", 1136243045},
|
||||
{"1956-01-02T15:04:05.999999-08:00", "\xc1\xfb\xc1\xba\x53\x81\x1a\x00\x00\x11", -441680155},
|
||||
}
|
||||
|
||||
var DurTestcases = []struct {
|
||||
Duration time.Duration
|
||||
FloatOut string
|
||||
IntegerOut string
|
||||
}{
|
||||
{1000, "\xfb\x3f\xf0\x00\x00\x00\x00\x00\x00", "\x01"},
|
||||
{2000, "\xfb\x40\x00\x00\x00\x00\x00\x00\x00", "\x02"},
|
||||
{200000, "\xfb\x40\x69\x00\x00\x00\x00\x00\x00", "\x18\xc8"},
|
||||
}
|
||||
|
||||
// inline copy from globals.go of InterfaceMarshalFunc used in tests to avoid import cycle
|
||||
func InterfaceMarshalFunc(v interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encoder := json.NewEncoder(&buf)
|
||||
encoder.SetEscapeHTML(false)
|
||||
err := encoder.Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := buf.Bytes()
|
||||
if len(b) > 0 {
|
||||
// Remove trailing \n which is added by Encode.
|
||||
return b[:len(b)-1], nil
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
var BooleanTestCases = []struct {
|
||||
Val bool
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{true, "\xf5", "true"},
|
||||
{false, "\xf4", "false"},
|
||||
}
|
||||
|
||||
var BooleanArrayTestCases = []struct {
|
||||
Val []bool
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]bool{}, "\x9f\xff", "[]"},
|
||||
{[]bool{false}, "\x81\xf4", "[false]"},
|
||||
{[]bool{true, false, true}, "\x83\xf5\xf4\xf5", "[true,false,true]"},
|
||||
{[]bool{true, false, false, true, false, true}, "\x86\xf5\xf4\xf4\xf5\xf4\xf5", "[true,false,false,true,false,true]"},
|
||||
}
|
||||
|
||||
var IntegerTestCases = []struct {
|
||||
Val int
|
||||
Binary string
|
||||
}{
|
||||
// Value included in the type.
|
||||
{0, "\x00"},
|
||||
{1, "\x01"},
|
||||
{2, "\x02"},
|
||||
{3, "\x03"},
|
||||
{8, "\x08"},
|
||||
{9, "\x09"},
|
||||
{10, "\x0a"},
|
||||
{22, "\x16"},
|
||||
{23, "\x17"},
|
||||
|
||||
// Value in 1 byte.
|
||||
{24, "\x18\x18"},
|
||||
{25, "\x18\x19"},
|
||||
{26, "\x18\x1a"},
|
||||
{127, "\x18\x7f"},
|
||||
{254, "\x18\xfe"},
|
||||
{255, "\x18\xff"},
|
||||
|
||||
// Value in 2 bytes.
|
||||
{256, "\x19\x01\x00"},
|
||||
{257, "\x19\x01\x01"},
|
||||
{1000, "\x19\x03\xe8"},
|
||||
{0xFFFF, "\x19\xff\xff"},
|
||||
|
||||
// Value in 4 bytes.
|
||||
{0x10000, "\x1a\x00\x01\x00\x00"},
|
||||
{0x7FFFFFFE, "\x1a\x7f\xff\xff\xfe"},
|
||||
{1000000, "\x1a\x00\x0f\x42\x40"},
|
||||
|
||||
// Negative number test cases.
|
||||
// Value included in the type.
|
||||
{-1, "\x20"},
|
||||
{-2, "\x21"},
|
||||
{-3, "\x22"},
|
||||
{-10, "\x29"},
|
||||
{-21, "\x34"},
|
||||
{-22, "\x35"},
|
||||
{-23, "\x36"},
|
||||
{-24, "\x37"},
|
||||
|
||||
// Value in 1 byte.
|
||||
{-25, "\x38\x18"},
|
||||
{-26, "\x38\x19"},
|
||||
{-100, "\x38\x63"},
|
||||
{-128, "\x38\x7f"},
|
||||
{-254, "\x38\xfd"},
|
||||
{-255, "\x38\xfe"},
|
||||
{-256, "\x38\xff"},
|
||||
|
||||
// Value in 2 bytes.
|
||||
{-257, "\x39\x01\x00"},
|
||||
{-258, "\x39\x01\x01"},
|
||||
{-1000, "\x39\x03\xe7"},
|
||||
|
||||
// Value in 4 bytes.
|
||||
{-0x10001, "\x3a\x00\x01\x00\x00"},
|
||||
{-0x7FFFFFFE, "\x3a\x7f\xff\xff\xfd"},
|
||||
{-1000000, "\x3a\x00\x0f\x42\x3f"},
|
||||
|
||||
//Constants
|
||||
{math.MaxInt8, "\x18\x7f"},
|
||||
{math.MinInt8, "\x38\x7f"},
|
||||
{math.MaxInt16, "\x19\x7f\xff"},
|
||||
{math.MinInt16, "\x39\x7f\xff"},
|
||||
{math.MaxInt32, "\x1a\x7f\xff\xff\xff"},
|
||||
{math.MinInt32, "\x3a\x7f\xff\xff\xff"},
|
||||
{math.MaxInt64, "\x1b\x7f\xff\xff\xff\xff\xff\xff\xff"},
|
||||
{math.MinInt64, "\x3b\x7f\xff\xff\xff\xff\xff\xff\xff"},
|
||||
}
|
||||
|
||||
type UnsignedIntTestCase struct {
|
||||
Val uint
|
||||
Binary string
|
||||
Bigbinary string
|
||||
}
|
||||
|
||||
var AdditionalUnsignedIntegerTestCases = []UnsignedIntTestCase{
|
||||
{0x7FFFFFFF, "\x18\xff", "\x1a\x7f\xff\xff\xff"},
|
||||
{0x80000000, "\x19\xff\xff", "\x1a\x80\x00\x00\x00"},
|
||||
{1000000, "\x1b\x80\x00\x00\x00\x00\x00\x00\x00", "\x1a\x00\x0f\x42\x40"},
|
||||
|
||||
//Constants
|
||||
{math.MaxUint8, "\x18\xff", "\x18\xff"},
|
||||
{math.MaxUint16, "\x19\xff\xff", "\x19\xff\xff"},
|
||||
{math.MaxUint32, "\x1a\xff\xff\xff\xff", "\x1a\xff\xff\xff\xff"},
|
||||
{math.MaxUint64, "\x1b\xff\xff\xff\xff\xff\xff\xff\xff", "\x1b\xff\xff\xff\xff\xff\xff\xff\xff"},
|
||||
}
|
||||
|
||||
func unsignedIntegerTestCases() []UnsignedIntTestCase {
|
||||
size := len(IntegerTestCases) + len(AdditionalUnsignedIntegerTestCases)
|
||||
cases := make([]UnsignedIntTestCase, 0, size)
|
||||
cases = append(cases, AdditionalUnsignedIntegerTestCases...)
|
||||
for _, itc := range IntegerTestCases {
|
||||
if itc.Val < 0 {
|
||||
continue
|
||||
}
|
||||
cases = append(cases, UnsignedIntTestCase{Val: uint(itc.Val), Binary: itc.Binary, Bigbinary: itc.Binary})
|
||||
}
|
||||
return cases
|
||||
}
|
||||
|
||||
var UnsignedIntegerTestCases = unsignedIntegerTestCases()
|
||||
|
||||
var Float32TestCases = []struct {
|
||||
Val float32
|
||||
Binary string
|
||||
}{
|
||||
{0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{-0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{1.0, "\xfa\x3f\x80\x00\x00"},
|
||||
{1.5, "\xfa\x3f\xc0\x00\x00"},
|
||||
{65504.0, "\xfa\x47\x7f\xe0\x00"},
|
||||
{-4.0, "\xfa\xc0\x80\x00\x00"},
|
||||
{0.00006103515625, "\xfa\x38\x80\x00\x00"},
|
||||
{float32(math.Inf(0)), "\xfa\x7f\x80\x00\x00"},
|
||||
{float32(math.Inf(-1)), "\xfa\xff\x80\x00\x00"},
|
||||
{float32(math.NaN()), "\xfa\x7f\xc0\x00\x00"},
|
||||
{math.SmallestNonzeroFloat32, "\xfa\x00\x00\x00\x01"},
|
||||
{math.MaxFloat32, "\xfa\x7f\x7f\xff\xff"},
|
||||
}
|
||||
|
||||
var Float64TestCases = []struct {
|
||||
Val float64
|
||||
Binary string
|
||||
}{
|
||||
{0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{-0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{1.0, "\xfa\x3f\x80\x00\x00"},
|
||||
{1.5, "\xfa\x3f\xc0\x00\x00"},
|
||||
{65504.0, "\xfa\x47\x7f\xe0\x00"},
|
||||
{-4.0, "\xfa\xc0\x80\x00\x00"},
|
||||
{0.00006103515625, "\xfa\x38\x80\x00\x00"},
|
||||
{math.Inf(0), "\xfa\x7f\x80\x00\x00\x00\x00\x00\x00"},
|
||||
{math.Inf(-1), "\xfa\xff\x80\x00\x00\x00\x00\x00\x00"},
|
||||
{math.NaN(), "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"},
|
||||
{math.SmallestNonzeroFloat64, "\xfa\x00\x00\x00\x00\x00\x00\x00\x01"},
|
||||
{math.MaxFloat64, "\xfa\x7f\x7f\xff\xff"},
|
||||
}
|
||||
|
||||
var IntegerArrayTestCases = []struct {
|
||||
Val []int
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]int{}, "\x9f\xff", "[]"},
|
||||
{[]int{32768}, "\x81\x19\x80\x00", "[32768]"},
|
||||
{[]int{-1, 0, 200, 20}, "\x84\x20\x00\x18\xc8\x14", "[-1,0,200,20]"},
|
||||
{[]int{-200, -10, 200, 400}, "\x84\x38\xc7\x29\x18\xc8\x19\x01\x90", "[-200,-10,200,400]"},
|
||||
{[]int{1, 2, 3}, "\x83\x01\x02\x03", "[1,2,3]"},
|
||||
{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
|
||||
"\x98\x19\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x18\x18\x19",
|
||||
"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]"},
|
||||
}
|
||||
|
||||
var IpAddrTestCases = []struct {
|
||||
Ipaddr net.IP
|
||||
Text string
|
||||
Binary string
|
||||
}{
|
||||
{net.IP{10, 0, 0, 1}, "\"10.0.0.1\"", "\xd9\x01\x04\x44\x0a\x00\x00\x01"},
|
||||
{net.IP{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x0, 0x0, 0x0, 0x0, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
|
||||
"\"2001:db8:85a3::8a2e:370:7334\"",
|
||||
"\xd9\x01\x04\x50\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34"},
|
||||
}
|
||||
|
||||
var IPAddrArrayTestCases = []struct {
|
||||
Val []net.IP
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]net.IP{}, "\x9f\xff", "[]"},
|
||||
{[]net.IP{{127, 0, 0, 0}}, "\x81\xd9\x01\x04\x44\x7f\x00\x00\x00", "[127.0.0.0]"},
|
||||
{[]net.IP{{0, 0, 0, 0}, {192, 168, 0, 100}}, "\x82\xd9\x01\x04\x44\x00\x00\x00\x00\xd9\x01\x04\x44\xc0\xa8\x00\x64", "[0.0.0.0,192.168.0.100]"},
|
||||
}
|
||||
|
||||
var IPPrefixTestCases = []struct {
|
||||
Pfx net.IPNet
|
||||
Text string // ASCII representation of pfx
|
||||
Binary string // CBOR representation of pfx
|
||||
}{
|
||||
{net.IPNet{IP: net.IP{0, 0, 0, 0}, Mask: net.CIDRMask(0, 32)}, "\"0.0.0.0/0\"", "\xd9\x01\x05\xa1\x44\x00\x00\x00\x00\x00"},
|
||||
{net.IPNet{IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}, "\"192.168.0.100/24\"",
|
||||
"\xd9\x01\x05\xa1\x44\xc0\xa8\x00\x64\x18\x18"},
|
||||
}
|
||||
|
||||
var IPPrefixArrayTestCases = []struct {
|
||||
Val []net.IPNet
|
||||
Binary string
|
||||
Json string
|
||||
}{
|
||||
{[]net.IPNet{}, "\x9f\xff", "[]"},
|
||||
{[]net.IPNet{{IP: net.IP{127, 0, 0, 0}, Mask: net.CIDRMask(24, 32)}}, "\x81\xd9\x01\x05\xa1\x44\x7f\x00\x00\x00\x18\x18", "[127.0.0.0/24]"},
|
||||
{[]net.IPNet{{IP: net.IP{0, 0, 0, 0}, Mask: net.CIDRMask(0, 32)}, {IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}}, "\x82\xd9\x01\x05\xa1\x44\x00\x00\x00\x00\x00\xd9\x01\x05\xa1\x44\xc0\xa8\x00\x64\x18\x18", "[0.0.0.0/0,192.168.0.100/24]"},
|
||||
}
|
||||
|
||||
var MacAddrTestCases = []struct {
|
||||
Macaddr net.HardwareAddr
|
||||
Text string // ASCII representation of macaddr
|
||||
Binary string // CBOR representation of macaddr
|
||||
}{
|
||||
{net.HardwareAddr{0x12, 0x34, 0x56, 0x78, 0x90, 0xab}, "\"12:34:56:78:90:ab\"", "\xd9\x01\x04\x46\x12\x34\x56\x78\x90\xab"},
|
||||
{net.HardwareAddr{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3}, "\"20:01:0d:b8:85:a3\"", "\xd9\x01\x04\x46\x20\x01\x0d\xb8\x85\xa3"},
|
||||
}
|
||||
|
||||
var EncodeHexTests = []struct {
|
||||
In byte
|
||||
Out string
|
||||
}{
|
||||
{0x00, `"00"`},
|
||||
{0x0f, `"0f"`},
|
||||
{0x10, `"10"`},
|
||||
{0xf0, `"f0"`},
|
||||
{0xff, `"ff"`},
|
||||
}
|
||||
|
||||
var EncodeStringTests = []struct {
|
||||
In string
|
||||
Out string
|
||||
}{
|
||||
{"", `""`},
|
||||
{"\\", `"\\"`},
|
||||
{"\x00", `"\u0000"`},
|
||||
{"\x01", `"\u0001"`},
|
||||
{"\x02", `"\u0002"`},
|
||||
{"\x03", `"\u0003"`},
|
||||
{"\x04", `"\u0004"`},
|
||||
{"\x05", `"\u0005"`},
|
||||
{"\x06", `"\u0006"`},
|
||||
{"\x07", `"\u0007"`},
|
||||
{"\x08", `"\b"`},
|
||||
{"\x09", `"\t"`},
|
||||
{"\x0a", `"\n"`},
|
||||
{"\x0b", `"\u000b"`},
|
||||
{"\x0c", `"\f"`},
|
||||
{"\x0d", `"\r"`},
|
||||
{"\x0e", `"\u000e"`},
|
||||
{"\x0f", `"\u000f"`},
|
||||
{"\x10", `"\u0010"`},
|
||||
{"\x11", `"\u0011"`},
|
||||
{"\x12", `"\u0012"`},
|
||||
{"\x13", `"\u0013"`},
|
||||
{"\x14", `"\u0014"`},
|
||||
{"\x15", `"\u0015"`},
|
||||
{"\x16", `"\u0016"`},
|
||||
{"\x17", `"\u0017"`},
|
||||
{"\x18", `"\u0018"`},
|
||||
{"\x19", `"\u0019"`},
|
||||
{"\x1a", `"\u001a"`},
|
||||
{"\x1b", `"\u001b"`},
|
||||
{"\x1c", `"\u001c"`},
|
||||
{"\x1d", `"\u001d"`},
|
||||
{"\x1e", `"\u001e"`},
|
||||
{"\x1f", `"\u001f"`},
|
||||
{"✭", `"✭"`},
|
||||
{"foo\xc2\x7fbar", `"foo\ufffd\u007fbar"`}, // invalid sequence
|
||||
{"ascii", `"ascii"`},
|
||||
{"\"a", `"\"a"`},
|
||||
{"\x1fa", `"\u001fa"`},
|
||||
{"foo\"bar\"baz", `"foo\"bar\"baz"`},
|
||||
{"\x1ffoo\x1fbar\x1fbaz", `"\u001ffoo\u001fbar\u001fbaz"`},
|
||||
{"emoji \u2764\ufe0f!", `"emoji ❤️!"`},
|
||||
}
|
||||
|
||||
var EncodeStringsTests = []struct {
|
||||
In []string
|
||||
Out string
|
||||
}{
|
||||
{nil, `[]`},
|
||||
{[]string{}, `[]`},
|
||||
{[]string{"A"}, `["A"]`},
|
||||
{[]string{"A", "B"}, `["A","B"]`},
|
||||
}
|
||||
|
||||
var EncodeStringerTests = []struct {
|
||||
In fmt.Stringer
|
||||
Out string
|
||||
Binary string
|
||||
}{
|
||||
{nil, `null`, "\xf6"},
|
||||
{fmt.Stringer(nil), `null`, "\xf6"},
|
||||
{net.IPv4bcast, `"255.255.255.255"`, "\x6f\x32\x35\x35\x2e\x32\x35\x35\x2e\x32\x35\x35\x2e\x32\x35\x35"},
|
||||
}
|
||||
|
||||
var EncodeStringersTests = []struct {
|
||||
In []fmt.Stringer
|
||||
Out string
|
||||
Binary string
|
||||
}{
|
||||
{nil, `[]`, "\x9f\xff"},
|
||||
{[]fmt.Stringer{}, `[]`, "\x9f\xff"},
|
||||
{[]fmt.Stringer{net.IPv4bcast}, `["255.255.255.255"]`, "\x9f\x6f255.255.255.255\xff"},
|
||||
{[]fmt.Stringer{net.IPv4allsys, net.IPv4allrouter}, `["224.0.0.1","224.0.0.2"]`, "\x9f\x69224.0.0.1\x69224.0.0.2\xff"},
|
||||
}
|
||||
|
||||
var TimeIntegerTestcases = []struct {
|
||||
Txt string
|
||||
Binary string
|
||||
RfcStr string
|
||||
UnixInt int
|
||||
}{
|
||||
{"2013-02-03T19:54:00-08:00", "\xc1\x1a\x51\x0f\x30\xd8", "2013-02-04T03:54:00Z", 1359950040},
|
||||
{"1950-02-03T19:54:00-08:00", "\xc1\x3a\x25\x71\x93\xa7", "1950-02-04T03:54:00Z", -628200360},
|
||||
}
|
||||
|
||||
var TimeFloatTestcases = []struct {
|
||||
RfcStr string
|
||||
Out string
|
||||
UnixInt int
|
||||
}{
|
||||
{"2006-01-02T15:04:05.999999-08:00", "\xc1\xfb\x41\xd0\xee\x6c\x59\x7f\xff\xfc", 1136243045},
|
||||
{"1956-01-02T15:04:05.999999-08:00", "\xc1\xfb\xc1\xba\x53\x81\x1a\x00\x00\x11", -441680155},
|
||||
}
|
||||
|
||||
var DurTestcases = []struct {
|
||||
Duration time.Duration
|
||||
FloatOut string
|
||||
IntegerOut string
|
||||
}{
|
||||
{1000, "\xfb\x3f\xf0\x00\x00\x00\x00\x00\x00", "\x01"},
|
||||
{2000, "\xfb\x40\x00\x00\x00\x00\x00\x00\x00", "\x02"},
|
||||
{200000, "\xfb\x40\x69\x00\x00\x00\x00\x00\x00", "\x18\xc8"},
|
||||
}
|
||||
|
||||
// inline copy from globals.go of InterfaceMarshalFunc used in tests to avoid import cycle
|
||||
func InterfaceMarshalFunc(v interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encoder := json.NewEncoder(&buf)
|
||||
encoder.SetEscapeHTML(false)
|
||||
err := encoder.Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := buf.Bytes()
|
||||
if len(b) > 0 {
|
||||
// Remove trailing \n which is added by Encode.
|
||||
return b[:len(b)-1], nil
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user