flabk/pkg/ld/unmarshal_test.go

240 lines
5.5 KiB
Go

package ld_test
import (
"encoding/json"
"fmt"
"math"
"testing"
"time"
"github.com/stretchr/testify/require"
"sectorinf.com/emilis/flabk/pkg/epk"
"sectorinf.com/emilis/flabk/pkg/ld"
)
type testObj struct {
String string `ld:"string" json:"string"`
NoTag string
Int int
Int8 int8
Int16 int16
Int32 int32
Int64 int64
Uint uint
Uint8 uint8
Uint16 uint16
Uint32 uint32
Uint64 uint64
Float32 float32
Float64 float64
// Complex64 complex64
// Complex128 complex128
IntPtr *int
Int8Ptr *int8
Int16Ptr *int16
Int32Ptr *int32
Int64Ptr *int64
UintPtr *uint
Uint8Ptr *uint8
Uint16Ptr *uint16
Uint32Ptr *uint32
Uint64Ptr *uint64
Float32Ptr *float32
Float64Ptr *float64
// Complex64Ptr *complex64
// Complex128Ptr *complex128
TestPtr *testObj
TestArray []testObj
}
func TestUnmarshal(t *testing.T) {
tests := map[string]struct {
obj testObj
errCheck epk.ErrorTest
}{
"string children": {
obj: testObj{
String: "hello",
NoTag: "no_tag",
Int: math.MaxInt,
Int8: math.MaxInt8,
Int16: math.MaxInt16,
Int32: math.MaxInt32,
Int64: math.MaxInt64,
Uint: math.MaxUint,
Uint8: math.MaxUint8,
Uint16: math.MaxUint16,
Uint32: math.MaxUint32,
Uint64: math.MaxUint64,
Float32: math.MaxFloat32,
Float64: math.MaxFloat64,
TestPtr: &testObj{
String: "hello2",
},
TestArray: []testObj{
{
String: "hello3",
},
{
String: "hello4",
TestPtr: &testObj{
TestArray: []testObj{
{
String: "hello5",
},
},
},
},
},
// Complex64: complex(math.MaxFloat32, math.MaxFloat32),
// Complex128: complex(math.MaxFloat64, math.MaxFloat64),
},
},
}
for name, test := range tests {
test := test
t.Run(name, func(tt *testing.T) {
that := require.New(tt)
objJSON, err := json.MarshalIndent(test.obj, "", " ")
that.NoError(err)
result, err := ld.Unmarshal[testObj](objJSON)
that.NoError(err)
that.Equal(test.obj, result)
})
}
}
func TestBench(t *testing.T) {
obj := testObj{
String: "hello",
NoTag: "no_tag",
Int: math.MaxInt,
Int8: math.MaxInt8,
Int16: math.MaxInt16,
Int32: math.MaxInt32,
Int64: math.MaxInt64,
Uint: math.MaxUint,
Uint8: math.MaxUint8,
Uint16: math.MaxUint16,
Uint32: math.MaxUint32,
Uint64: math.MaxUint64,
Float32: math.MaxFloat32,
Float64: math.MaxFloat64,
// Complex64: complex(math.MaxFloat32, math.MaxFloat32),
// Complex128: complex(math.MaxFloat64, math.MaxFloat64),
}
that := require.New(t)
asldTotal := int64(0)
jsonTotal := int64(0)
jsonMax := int64(0)
jsonMin := math.MaxInt64
asldMax := int64(0)
asldMin := math.MaxInt64
count := int64(1 << 20)
for index := int64(0); index < count; index++ {
objJSON, err := json.Marshal(obj)
that.NoError(err)
asldStart := time.Now()
_, err = ld.Unmarshal[testObj](objJSON)
asldDur := time.Since(asldStart)
asldTotal += int64(asldDur)
if asldDur < time.Duration(asldMin) {
asldMin = int(asldDur)
}
if asldDur > time.Duration(asldMax) {
asldMax = int64(asldDur)
}
that.NoError(err)
a := testObj{}
jsonStart := time.Now()
err = json.Unmarshal(objJSON, &a)
jsonDur := time.Since(jsonStart)
jsonTotal += int64(jsonDur)
if jsonDur < time.Duration(jsonMin) {
jsonMin = int(jsonDur)
}
if jsonDur > time.Duration(jsonMax) {
jsonMax = int64(jsonDur)
}
that.NoError(err)
}
fmt.Println(count, "runs")
fmt.Printf("json avg (%s), min (%s), max (%s)\n", time.Duration(jsonTotal/count), time.Duration(jsonMin), time.Duration(jsonMax))
fmt.Printf("asld avg (%s), min (%s), max (%s)\n", time.Duration(asldTotal/count), time.Duration(asldMin), time.Duration(asldMax))
}
func jsonElemList[T any](that *require.Assertions, a any) [][]byte {
that.NotNil(a)
v, ok := a.([]T)
that.True(ok)
fields := make([][]byte, len(v))
for index, field := range v {
jsonField, err := json.Marshal(field)
that.NoError(err)
fields[index] = jsonField
}
return fields
}
type hello struct {
Hello string
}
// func TestArrayMembers(t *testing.T) {
// tests := map[string]struct {
// object any
// errCheck epk.ErrorTest
// toJsonElementList func(*require.Assertions, any) [][]byte
// }{
// "strings": {
// object: []string{"a", "b", "c", "d"},
// toJsonElementList: jsonElemList[string],
// },
// "ints": {
// object: []int{1, 2, 3, 4, 5, 6},
// toJsonElementList: jsonElemList[int],
// },
// "floats": {
// object: []float64{123.456, 789.0123, 456.789},
// toJsonElementList: jsonElemList[float64],
// },
// "strings with commas": {
// object: []string{"this, is what I do", "what, don't like it?"},
// toJsonElementList: jsonElemList[string],
// },
// "objects": {
// object: []hello{{"world"}, {"mom, dad"}},
// toJsonElementList: jsonElemList[hello],
// },
// }
// for name, test := range tests {
// test := test
// t.Run(name, func(tt *testing.T) {
// that := require.New(tt)
// objJson, err := json.Marshal(test.object)
// that.NoError(err)
// w := newWalker(objJson)
// members, err := arrayMembers(w)
// if test.errCheck == nil {
// test.errCheck = epk.NoError
// }
// test.errCheck(that, err)
// expected := test.toJsonElementList(that, test.object)
// that.Len(members, len(expected))
// for index, elem := range expected {
// equivMember := members[index]
// that.Equal(elem, equivMember.content)
// }
// })
// }
// }