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) // } // }) // } // }