From 821d21bd93993f6f476183ceb660df4a975cf672 Mon Sep 17 00:00:00 2001 From: Sinelnikov Michail Date: Wed, 16 Jul 2025 17:51:03 +0300 Subject: [PATCH 1/6] fix and add tests Signed-off-by: Sinelnikov Michail --- pkg/module_manager/go_hook/filter_result.go | 16 ++- .../go_hook/filter_result_test.go | 136 ++++++++++++++++++ 2 files changed, 147 insertions(+), 5 deletions(-) diff --git a/pkg/module_manager/go_hook/filter_result.go b/pkg/module_manager/go_hook/filter_result.go index ec6b97c10..e1c4ec720 100644 --- a/pkg/module_manager/go_hook/filter_result.go +++ b/pkg/module_manager/go_hook/filter_result.go @@ -37,18 +37,24 @@ func (f *Wrapped) UnmarshalTo(v any) error { } rw := reflect.ValueOf(f.Wrapped) - if rw.Kind() != reflect.Pointer || rw.IsNil() { + if rw.Type().AssignableTo(rv.Elem().Type()) { rv.Elem().Set(rw) - return nil } - if rw.Type() != rv.Type() { - return ErrUnmarshalToTypesNotMatch + if rw.Kind() == reflect.Pointer { + if rw.IsNil() { + rv.Elem().Set(reflect.Zero(rv.Elem().Type())) + return nil + } + rw = rw.Elem() } - rv.Elem().Set(rw.Elem()) + if !rw.Type().AssignableTo(rv.Elem().Type()) { + return ErrUnmarshalToTypesNotMatch + } + rv.Elem().Set(rw) return nil } diff --git a/pkg/module_manager/go_hook/filter_result_test.go b/pkg/module_manager/go_hook/filter_result_test.go index b0b7a3bf6..54ea51884 100644 --- a/pkg/module_manager/go_hook/filter_result_test.go +++ b/pkg/module_manager/go_hook/filter_result_test.go @@ -112,6 +112,142 @@ func Test_FilterResult(t *testing.T) { assert.Equal(t, os, w.Wrapped) }) + t.Run("UnmarshalTo_PointerToStruct", func(t *testing.T) { + type SomeStruct struct { + String string + } + + w := &go_hook.Wrapped{ + Wrapped: &SomeStruct{String: "pointer"}, + } + + ss := &SomeStruct{} + err := w.UnmarshalTo(ss) + assert.NoError(t, err) + assert.NotNil(t, ss) + assert.Equal(t, "pointer", ss.String) + }) + + t.Run("UnmarshalTo_Int32ToString", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: int32(6443), + } + + var portData string + err := w.UnmarshalTo(&portData) + + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_NestedStruct", func(t *testing.T) { + type InnerStruct struct { + Value string + } + type OuterStruct struct { + Inner InnerStruct + } + + w := &go_hook.Wrapped{ + Wrapped: OuterStruct{ + Inner: InnerStruct{Value: "nested"}, + }, + } + + os := OuterStruct{} + err := w.UnmarshalTo(&os) + assert.NoError(t, err) + assert.Equal(t, "nested", os.Inner.Value) + }) + + t.Run("UnmarshalTo_NilTarget", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: &SomeStruct{ + String: "INPUT STRING", + }, + } + + var ss *SomeStruct + err := w.UnmarshalTo(ss) + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_IncompatibleTypes", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: "string value", + } + + var num int + err := w.UnmarshalTo(&num) + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_NilPointer", func(t *testing.T) { + var nilPtr *SomeStruct + w := &go_hook.Wrapped{ + Wrapped: nilPtr, + } + + var ss *SomeStruct + err := w.UnmarshalTo(&ss) + assert.NoError(t, err) + assert.Nil(t, ss) + }) + + t.Run("UnmarshalTo_PrimitiveTypes", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var num int + err := w.UnmarshalTo(&num) + assert.NoError(t, err) + assert.Equal(t, 42, num) + }) + + t.Run("UnmarshalTo_Slice", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: []int{1, 2, 3}, + } + + var slice []int + err := w.UnmarshalTo(&slice) + assert.NoError(t, err) + assert.Equal(t, []int{1, 2, 3}, slice) + }) + + t.Run("UnmarshalTo_Map", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: map[string]int{"one": 1, "two": 2}, + } + + var m map[string]int + err := w.UnmarshalTo(&m) + assert.NoError(t, err) + assert.Equal(t, map[string]int{"one": 1, "two": 2}, m) + }) + + t.Run("UnmarshalTo_ZeroValue", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 0, + } + + var num int + err := w.UnmarshalTo(&num) + assert.NoError(t, err) + assert.Equal(t, 0, num) + }) + + t.Run("UnmarshalTo_UninitializedTarget", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: "test", + } + + var str string + err := w.UnmarshalTo(&str) + assert.NoError(t, err) + assert.Equal(t, "test", str) + }) + t.Run("AsString", func(t *testing.T) { w := &go_hook.Wrapped{ Wrapped: "test string", From 75878f23130022bcdf8e18a9d996fe5e758606b9 Mon Sep 17 00:00:00 2001 From: Sinelnikov Michail Date: Thu, 17 Jul 2025 15:17:52 +0300 Subject: [PATCH 2/6] another tests Signed-off-by: Sinelnikov Michail --- .../go_hook/filter_result_test.go | 183 +++++++++++++++++- 1 file changed, 178 insertions(+), 5 deletions(-) diff --git a/pkg/module_manager/go_hook/filter_result_test.go b/pkg/module_manager/go_hook/filter_result_test.go index 54ea51884..b8ad588e8 100644 --- a/pkg/module_manager/go_hook/filter_result_test.go +++ b/pkg/module_manager/go_hook/filter_result_test.go @@ -61,19 +61,192 @@ func Test_FilterResult(t *testing.T) { assert.Error(t, err) }) - t.Run("UnmarshalTo_NilTarget", func(t *testing.T) { + t.Run("UnmarshalTo_IntToFloat64Error", func(t *testing.T) { w := &go_hook.Wrapped{ - Wrapped: &SomeStruct{ - String: "INPUT STRING", + Wrapped: 32, + } + + var target float32 + err := w.UnmarshalTo(&target) + + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_IntToFloat64PtrError", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target *float64 + err := w.UnmarshalTo(&target) + + assert.Error(t, err) + assert.Nil(t, target) + }) + + t.Run("UnmarshalTo_IntPtrToFloat64Error", func(t *testing.T) { + val := 42 + w := &go_hook.Wrapped{ + Wrapped: &val, + } + + var target float64 + err := w.UnmarshalTo(&target) + + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_CustomIntTypeError", func(t *testing.T) { + type MyInt int + w := &go_hook.Wrapped{ + Wrapped: MyInt(42), + } + + var target int + err := w.UnmarshalTo(&target) + + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_IntToEmptyInterface", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target interface{} + err := w.UnmarshalTo(&target) + + assert.NoError(t, err) + assert.Equal(t, 42, target) + }) + + t.Run("UnmarshalTo_DifferentStructs", func(t *testing.T) { + type StructA struct{ X int } + type StructB struct{ X int } + + w := &go_hook.Wrapped{ + Wrapped: StructA{X: 42}, + } + + var target StructB + err := w.UnmarshalTo(&target) + + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_SameStructType", func(t *testing.T) { + type Person struct { + Name string + Age int + } + + w := &go_hook.Wrapped{ + Wrapped: Person{Name: "Alice", Age: 30}, + } + + var target Person + err := w.UnmarshalTo(&target) + + assert.NoError(t, err) + assert.Equal(t, "Alice", target.Name) + assert.Equal(t, 30, target.Age) + }) + + t.Run("UnmarshalTo_DifferentStructsWithSameFields", func(t *testing.T) { + type A struct{ X int } + type B struct{ X int } + + w := &go_hook.Wrapped{ + Wrapped: A{X: 42}, + } + + var target B + err := w.UnmarshalTo(&target) + + assert.Error(t, err) + }) + + t.Run("UnmarshalTo_AnonymousField", func(t *testing.T) { + type Base struct { + ID int + } + type Extended struct { + Base + Name string + } + + w := &go_hook.Wrapped{ + Wrapped: Extended{ + Base: Base{ID: 1}, + Name: "Test", }, } - var ss *SomeStruct + var target Extended + err := w.UnmarshalTo(&target) - err := w.UnmarshalTo(ss) + assert.NoError(t, err) + assert.Equal(t, 1, target.ID) + }) + + t.Run("UnmarshalTo_NoInitPointerToStruct", func(t *testing.T) { + type Item struct { + Value string + } + + w := &go_hook.Wrapped{ + Wrapped: &Item{Value: "pointer"}, + } + + var target *Item + err := w.UnmarshalTo(&target) + + assert.NoError(t, err) + assert.Equal(t, "pointer", target.Value) + }) + + t.Run("UnmarshalTo_NotPointerTarget", func(t *testing.T) { + w := &go_hook.Wrapped{Wrapped: 10} + var num int + err := w.UnmarshalTo(num) assert.Error(t, err) }) + t.Run("UnmarshalTo_NilPointerWrappedToValue", func(t *testing.T) { + type MyStruct struct{ Field string } + + var nilPtr *MyStruct + w := &go_hook.Wrapped{Wrapped: nilPtr} + + var target MyStruct + err := w.UnmarshalTo(&target) + assert.NoError(t, err) + assert.Equal(t, "", target.Field) + }) + + t.Run("UnmarshalTo_DoublePointerToPointer", func(t *testing.T) { + val := 100 + ptr1 := &val + ptr2 := &ptr1 + w := &go_hook.Wrapped{Wrapped: ptr2} + + var target *int + err := w.UnmarshalTo(&target) + assert.NoError(t, err) + assert.NotNil(t, target) + assert.Equal(t, 100, *target) + }) + + t.Run("String_ComplexStruct", func(t *testing.T) { + type Person struct { + Name string `json:"Name"` + Age int `json:"Age"` + } + w := &go_hook.Wrapped{Wrapped: Person{Name: "John", Age: 25}} + result := w.String() + assert.Equal(t, `{"Name":"John","Age":25}`, result) + }) + t.Run("UnmarshalTo_DifferentTypes", func(t *testing.T) { type OtherStruct struct { Field int From 26693430ef959aab9af77f42e530cfc42201adf5 Mon Sep 17 00:00:00 2001 From: Sinelnikov Michail Date: Thu, 17 Jul 2025 15:48:16 +0300 Subject: [PATCH 3/6] add test Signed-off-by: Sinelnikov Michail --- pkg/module_manager/go_hook/filter_result_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/module_manager/go_hook/filter_result_test.go b/pkg/module_manager/go_hook/filter_result_test.go index b8ad588e8..1313d10e5 100644 --- a/pkg/module_manager/go_hook/filter_result_test.go +++ b/pkg/module_manager/go_hook/filter_result_test.go @@ -1,6 +1,8 @@ package go_hook_test import ( + "bytes" + "io" "testing" "github.com/stretchr/testify/assert" @@ -212,6 +214,17 @@ func Test_FilterResult(t *testing.T) { assert.Error(t, err) }) + t.Run("UnmarshalTo_CommonInterface", func(t *testing.T) { + var buf bytes.Buffer + + w := &go_hook.Wrapped{Wrapped: &buf} + var writer io.Writer + err := w.UnmarshalTo(&writer) + + assert.NoError(t, err) + assert.Equal(t, &buf, writer) + }) + t.Run("UnmarshalTo_NilPointerWrappedToValue", func(t *testing.T) { type MyStruct struct{ Field string } From 7a5f7c1be2bb0654261a40fe6a2c8402c080f015 Mon Sep 17 00:00:00 2001 From: Sinelnikov Michail Date: Thu, 21 Aug 2025 15:53:18 +0300 Subject: [PATCH 4/6] add bench and tests Signed-off-by: Sinelnikov Michail --- pkg/module_manager/go_hook/filter_result.go | 69 ++ .../go_hook/filter_result_bench_test.go | 669 ++++++++++++++++++ .../go_hook/filter_result_test.go | 354 +++++++++ 3 files changed, 1092 insertions(+) create mode 100644 pkg/module_manager/go_hook/filter_result_bench_test.go diff --git a/pkg/module_manager/go_hook/filter_result.go b/pkg/module_manager/go_hook/filter_result.go index e1c4ec720..a0ea7e588 100644 --- a/pkg/module_manager/go_hook/filter_result.go +++ b/pkg/module_manager/go_hook/filter_result.go @@ -58,6 +58,75 @@ func (f *Wrapped) UnmarshalTo(v any) error { return nil } +func (f *Wrapped) UnmarshalToWithoutAssignable(v any) error { + if f.Wrapped == nil { + return ErrEmptyWrapped + } + + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Pointer || rv.IsNil() { + // error replace with "not pointer" + return fmt.Errorf("reflect.TypeOf(v): %s", reflect.TypeOf(v)) + } + + rw := reflect.ValueOf(f.Wrapped) + targetType := rv.Elem().Type() + wrappedType := rw.Type() + + // Handle nil pointer case + if rw.Kind() == reflect.Pointer && rw.IsNil() { + rv.Elem().Set(reflect.Zero(targetType)) + return nil + } + + // Check for exact type match + if wrappedType == targetType { + rv.Elem().Set(rw) + return nil + } + + // Handle pointer to value conversion + if rw.Kind() == reflect.Pointer { + rw = rw.Elem() + wrappedType = rw.Type() + } + + // Check for exact type match after dereferencing + if wrappedType == targetType { + rv.Elem().Set(rw) + return nil + } + + return ErrUnmarshalToTypesNotMatch +} + +func (f *Wrapped) UnmarshalToOld(v any) error { + if f.Wrapped == nil { + return ErrEmptyWrapped + } + + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Pointer || rv.IsNil() { + // error replace with "not pointer" + return fmt.Errorf("reflect.TypeOf(v): %s", reflect.TypeOf(v)) + } + + rw := reflect.ValueOf(f.Wrapped) + if rw.Kind() != reflect.Pointer || rw.IsNil() { + rv.Elem().Set(rw) + + return nil + } + + if rw.Type() != rv.Type() { + return ErrUnmarshalToTypesNotMatch + } + + rv.Elem().Set(rw.Elem()) + + return nil +} + func (f *Wrapped) String() string { buf := bytes.NewBuffer([]byte{}) _ = json.NewEncoder(buf).Encode(f.Wrapped) diff --git a/pkg/module_manager/go_hook/filter_result_bench_test.go b/pkg/module_manager/go_hook/filter_result_bench_test.go new file mode 100644 index 000000000..bc44c85b2 --- /dev/null +++ b/pkg/module_manager/go_hook/filter_result_bench_test.go @@ -0,0 +1,669 @@ +package go_hook_test + +import ( + "testing" + + "github.com/flant/addon-operator/pkg/module_manager/go_hook" +) + +type BenchmarkData struct { + String string + Int int + Float float64 + Bool bool + Slice []int + Map map[string]int + NestedData *BenchmarkData +} + +func createTestData() *BenchmarkData { + return &BenchmarkData{ + String: "benchmark test string with some length to simulate real data", + Int: 42, + Float: 3.14159, + Bool: true, + Slice: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + Map: map[string]int{ + "key1": 1, + "key2": 2, + "key3": 3, + }, + NestedData: &BenchmarkData{ + String: "nested string", + Int: 123, + Float: 2.71828, + Bool: false, + }, + } +} + +func BenchmarkUnmarshalTo_Int(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_Int(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_Int(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_String(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: "benchmark test string with some length"} + var target string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_String(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: "benchmark test string with some length"} + var target string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_String(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: "benchmark test string with some length"} + var target string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_Slice(b *testing.B) { + slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + w := &go_hook.Wrapped{Wrapped: slice} + var target []int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_Slice(b *testing.B) { + slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + w := &go_hook.Wrapped{Wrapped: slice} + var target []int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_Slice(b *testing.B) { + slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + w := &go_hook.Wrapped{Wrapped: slice} + var target []int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_Map(b *testing.B) { + m := map[string]int{"key1": 1, "key2": 2, "key3": 3} + w := &go_hook.Wrapped{Wrapped: m} + var target map[string]int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_Map(b *testing.B) { + m := map[string]int{"key1": 1, "key2": 2, "key3": 3} + w := &go_hook.Wrapped{Wrapped: m} + var target map[string]int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_Map(b *testing.B) { + m := map[string]int{"key1": 1, "key2": 2, "key3": 3} + w := &go_hook.Wrapped{Wrapped: m} + var target map[string]int + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_Struct(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: *data} + var target BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_Struct(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: *data} + var target BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_Struct(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: *data} + var target BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_Pointer(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: data} + var target *BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_Pointer(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: data} + var target *BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_Pointer(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: data} + var target *BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_PointerToValue(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: data} + var target BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_PointerToValue(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: data} + var target BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_PointerToValue(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: data} + var target BenchmarkData + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_ErrorCase(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_ErrorCase(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalTo_PointerTypeMismatch(b *testing.B) { + val := 42 + w := &go_hook.Wrapped{Wrapped: &val} + var target *string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_PointerTypeMismatch(b *testing.B) { + val := 42 + w := &go_hook.Wrapped{Wrapped: &val} + var target *string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_PointerTypeMismatch(b *testing.B) { + val := 42 + w := &go_hook.Wrapped{Wrapped: &val} + var target *string + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_DifferentStructs(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + w := &go_hook.Wrapped{Wrapped: StructA{Field: 42}} + var target StructB + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_DifferentStructs(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + w := &go_hook.Wrapped{Wrapped: StructA{Field: 42}} + var target StructB + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_DifferentStructs(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + w := &go_hook.Wrapped{Wrapped: StructA{Field: 42}} + var target StructB + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkUnmarshalTo_PointerToDifferentStructs(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + val := StructA{Field: 42} + w := &go_hook.Wrapped{Wrapped: &val} + var target *StructB + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } +} + +func BenchmarkUnmarshalToWithoutAssignable_PointerToDifferentStructs(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + val := StructA{Field: 42} + w := &go_hook.Wrapped{Wrapped: &val} + var target *StructB + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } +} + +func BenchmarkUnmarshalToOld_PointerToDifferentStructs(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + val := StructA{Field: 42} + w := &go_hook.Wrapped{Wrapped: &val} + var target *StructB + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } +} + +func BenchmarkCompareAllMethods_Int(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + + b.Run("UnmarshalTo", func(b *testing.B) { + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } + }) + + b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) + + b.Run("UnmarshalToOld", func(b *testing.B) { + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} + +func BenchmarkCompareAllMethods_Struct(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: *data} + + b.Run("UnmarshalTo", func(b *testing.B) { + var target BenchmarkData + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } + }) + + b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { + var target BenchmarkData + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) + + b.Run("UnmarshalToOld", func(b *testing.B) { + var target BenchmarkData + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} + +func BenchmarkMemoryUsage_Int(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + + b.Run("UnmarshalTo", func(b *testing.B) { + b.ReportAllocs() + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } + }) + + b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { + b.ReportAllocs() + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) + + b.Run("UnmarshalToOld", func(b *testing.B) { + b.ReportAllocs() + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} + +func BenchmarkMemoryUsage_Struct(b *testing.B) { + data := createTestData() + w := &go_hook.Wrapped{Wrapped: *data} + + b.Run("UnmarshalTo", func(b *testing.B) { + b.ReportAllocs() + var target BenchmarkData + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } + }) + + b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { + b.ReportAllocs() + var target BenchmarkData + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) + + b.Run("UnmarshalToOld", func(b *testing.B) { + b.ReportAllocs() + var target BenchmarkData + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} + +func BenchmarkErrorVsPanic(b *testing.B) { + b.Run("ErrorCase_UnmarshalTo", func(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target string + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } + }) + + b.Run("ErrorCase_UnmarshalToWithoutAssignable", func(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: 42} + var target string + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) + + b.Run("ErrorCase_UnmarshalToOld_PointerMismatch", func(b *testing.B) { + val := 42 + w := &go_hook.Wrapped{Wrapped: &val} + var target *string + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) + + b.Run("ErrorCase_UnmarshalToOld_PointerToPointerMismatch", func(b *testing.B) { + val := 42 + w := &go_hook.Wrapped{Wrapped: &val} + var target *string + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) + + b.Run("ErrorCase_UnmarshalToOld_PointerToDifferentStructs", func(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + val := StructA{Field: 42} + w := &go_hook.Wrapped{Wrapped: &val} + var target *StructB + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} + +func BenchmarkUnmarshalToOld_ErrorVsPanic(b *testing.B) { + b.Run("ErrorCase_PointerToDifferentStructs", func(b *testing.B) { + type StructA struct { + Field int + } + type StructB struct { + Field string + } + + val := StructA{Field: 42} + w := &go_hook.Wrapped{Wrapped: &val} + var target *StructB + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) + + b.Run("ErrorCase_PointerTypeMismatch", func(b *testing.B) { + val := 42 + w := &go_hook.Wrapped{Wrapped: &val} + var target *string + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) + + b.Run("ErrorCase_NilPointerToPointer", func(b *testing.B) { + var nilPtr *int + w := &go_hook.Wrapped{Wrapped: nilPtr} + var target *int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} + +func BenchmarkNilPointerCases(b *testing.B) { + b.Run("NilPointer_UnmarshalTo", func(b *testing.B) { + var nilPtr *int + w := &go_hook.Wrapped{Wrapped: nilPtr} + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalTo(&target) + } + }) + + b.Run("NilPointer_UnmarshalToWithoutAssignable", func(b *testing.B) { + var nilPtr *int + w := &go_hook.Wrapped{Wrapped: nilPtr} + var target int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) + + b.Run("NilPointer_UnmarshalToOld", func(b *testing.B) { + var nilPtr *int + w := &go_hook.Wrapped{Wrapped: nilPtr} + var target *int + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) +} diff --git a/pkg/module_manager/go_hook/filter_result_test.go b/pkg/module_manager/go_hook/filter_result_test.go index 1313d10e5..223cba550 100644 --- a/pkg/module_manager/go_hook/filter_result_test.go +++ b/pkg/module_manager/go_hook/filter_result_test.go @@ -470,3 +470,357 @@ func Test_FilterResult(t *testing.T) { assert.Equal(t, "333", result) }) } + +func Test_FilterResult_UnmarshalToWithoutAssignable(t *testing.T) { + type SomeStruct struct { + String string + } + + t.Run("ExactTypeMatch", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: &SomeStruct{ + String: "INPUT STRING", + }, + } + + ss := &SomeStruct{} + + err := w.UnmarshalToWithoutAssignable(ss) + assert.NoError(t, err) + + assert.Equal(t, "INPUT STRING", ss.String) + }) + + t.Run("ExactTypeMatch_ValueToValue", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: SomeStruct{ + String: "INPUT STRING", + }, + } + + ss := SomeStruct{} + + err := w.UnmarshalToWithoutAssignable(&ss) + assert.NoError(t, err) + + assert.Equal(t, "INPUT STRING", ss.String) + }) + + t.Run("ExactTypeMatch_PointerToPointer", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: &SomeStruct{ + String: "INPUT STRING", + }, + } + + var ss *SomeStruct + + err := w.UnmarshalToWithoutAssignable(&ss) + assert.NoError(t, err) + + assert.Equal(t, "INPUT STRING", ss.String) + }) + + t.Run("ExactTypeMatch_PrimitiveTypes", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var num int + err := w.UnmarshalToWithoutAssignable(&num) + assert.NoError(t, err) + assert.Equal(t, 42, num) + }) + + t.Run("ExactTypeMatch_String", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: "test string", + } + + var str string + err := w.UnmarshalToWithoutAssignable(&str) + assert.NoError(t, err) + assert.Equal(t, "test string", str) + }) + + t.Run("ExactTypeMatch_Slice", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: []int{1, 2, 3}, + } + + var slice []int + err := w.UnmarshalToWithoutAssignable(&slice) + assert.NoError(t, err) + assert.Equal(t, []int{1, 2, 3}, slice) + }) + + t.Run("ExactTypeMatch_Map", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: map[string]int{"one": 1, "two": 2}, + } + + var m map[string]int + err := w.UnmarshalToWithoutAssignable(&m) + assert.NoError(t, err) + assert.Equal(t, map[string]int{"one": 1, "two": 2}, m) + }) + + t.Run("NilPointerWrapped", func(t *testing.T) { + var nilPtr *SomeStruct + w := &go_hook.Wrapped{ + Wrapped: nilPtr, + } + + var ss *SomeStruct + err := w.UnmarshalToWithoutAssignable(&ss) + assert.NoError(t, err) + assert.Nil(t, ss) + }) + + t.Run("NilPointerWrappedToValue", func(t *testing.T) { + var nilPtr *SomeStruct + w := &go_hook.Wrapped{ + Wrapped: nilPtr, + } + + var ss SomeStruct + err := w.UnmarshalToWithoutAssignable(&ss) + assert.NoError(t, err) + assert.Equal(t, "", ss.String) + }) + + t.Run("DifferentTypes_ShouldFail", func(t *testing.T) { + type OtherStruct struct { + Field int + } + + w := &go_hook.Wrapped{ + Wrapped: &SomeStruct{ + String: "INPUT STRING", + }, + } + + os := &OtherStruct{} + + err := w.UnmarshalToWithoutAssignable(os) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err) + }) + + t.Run("DifferentPrimitiveTypes_ShouldFail", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target float64 + err := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err) + }) + + t.Run("CustomTypeToBaseType_ShouldFail", func(t *testing.T) { + type MyInt int + w := &go_hook.Wrapped{ + Wrapped: MyInt(42), + } + + var target int + err := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err) + }) + + t.Run("BaseTypeToCustomType_ShouldFail", func(t *testing.T) { + type MyInt int + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target MyInt + err := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err) + }) + + t.Run("DifferentStructsWithSameFields_ShouldFail", func(t *testing.T) { + type A struct{ X int } + type B struct{ X int } + + w := &go_hook.Wrapped{ + Wrapped: A{X: 42}, + } + + var target B + err := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err) + }) + + t.Run("Int32ToString_ShouldFail", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: int32(6443), + } + + var portData string + err := w.UnmarshalToWithoutAssignable(&portData) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err) + }) + + t.Run("NilWrapped_ShouldFail", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: nil, + } + + ss := &SomeStruct{} + + err := w.UnmarshalToWithoutAssignable(ss) + assert.Error(t, err) + assert.Equal(t, go_hook.ErrEmptyWrapped, err) + }) + + t.Run("NotPointerTarget_ShouldFail", func(t *testing.T) { + w := &go_hook.Wrapped{Wrapped: 10} + var num int + err := w.UnmarshalToWithoutAssignable(num) + assert.Error(t, err) + }) + + t.Run("NilTarget_ShouldFail", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: &SomeStruct{ + String: "INPUT STRING", + }, + } + + var ss *SomeStruct + err := w.UnmarshalToWithoutAssignable(ss) + assert.Error(t, err) + }) + + t.Run("CompareWithOriginalUnmarshalTo", func(t *testing.T) { + type MyInt int + + w := &go_hook.Wrapped{ + Wrapped: MyInt(42), + } + + var target int + + err1 := w.UnmarshalTo(&target) + assert.Error(t, err1) + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err2) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err2) + }) + + t.Run("CompareUnmarshalToOldAndUnmarshalToWithoutAssignable", func(t *testing.T) { + t.Run("IntToString_ShouldFailInBoth", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target string + + assert.Panics(t, func() { + w.UnmarshalToOld(&target) + }) + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err2) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err2) + }) + + t.Run("StringToInt_ShouldFailInBoth", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: "42", + } + + var target int + + assert.Panics(t, func() { + w.UnmarshalToOld(&target) + }) + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err2) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err2) + }) + + t.Run("ExactTypeMatch_ShouldWorkInBoth", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target int + + err1 := w.UnmarshalToOld(&target) + assert.NoError(t, err1) + assert.Equal(t, 42, target) + + target = 0 + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.NoError(t, err2) + assert.Equal(t, 42, target) + }) + + t.Run("PointerToValue_ShouldWorkInBoth", func(t *testing.T) { + val := 42 + w := &go_hook.Wrapped{ + Wrapped: &val, + } + + var target int + + err1 := w.UnmarshalToOld(&target) + assert.NoError(t, err1) + assert.Equal(t, 42, target) + + target = 0 + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.NoError(t, err2) + assert.Equal(t, 42, target) + }) + + t.Run("ValueToPointer_ShouldFailInBoth", func(t *testing.T) { + w := &go_hook.Wrapped{ + Wrapped: 42, + } + + var target *int + + assert.Panics(t, func() { + w.UnmarshalToOld(&target) + }) + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.Error(t, err2) + assert.Equal(t, go_hook.ErrUnmarshalToTypesNotMatch, err2) + }) + + t.Run("StructExactMatch_ShouldWorkInBoth", func(t *testing.T) { + type TestStruct struct { + Field string + } + + w := &go_hook.Wrapped{ + Wrapped: TestStruct{Field: "test"}, + } + + var target TestStruct + + err1 := w.UnmarshalToOld(&target) + assert.NoError(t, err1) + assert.Equal(t, "test", target.Field) + + target = TestStruct{} + + err2 := w.UnmarshalToWithoutAssignable(&target) + assert.NoError(t, err2) + assert.Equal(t, "test", target.Field) + }) + }) +} From db9b56717afa4f1b3cf2d54a82fc81c90bf6fd1d Mon Sep 17 00:00:00 2001 From: Sinelnikov Michail Date: Tue, 26 Aug 2025 12:00:07 +0300 Subject: [PATCH 5/6] add more bench Signed-off-by: Sinelnikov Michail --- .../go_hook/filter_result_bench_test.go | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/pkg/module_manager/go_hook/filter_result_bench_test.go b/pkg/module_manager/go_hook/filter_result_bench_test.go index bc44c85b2..94b8460b0 100644 --- a/pkg/module_manager/go_hook/filter_result_bench_test.go +++ b/pkg/module_manager/go_hook/filter_result_bench_test.go @@ -667,3 +667,73 @@ func BenchmarkNilPointerCases(b *testing.B) { } }) } + +func BenchmarkCompareDirectCast_ValueStruct(b *testing.B) { + data := createTestData() + var anyVal any = *data + + b.Run("DirectCast", func(b *testing.B) { + var target BenchmarkData + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + target = anyVal.(BenchmarkData) + } + _ = target + }) + + b.Run("UnmarshalToOld", func(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: *data} + var target BenchmarkData + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) + + b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: *data} + var target BenchmarkData + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) +} + +func BenchmarkCompareDirectCast_PointerStruct(b *testing.B) { + data := createTestData() + var anyVal any = data + + b.Run("DirectCast", func(b *testing.B) { + var target *BenchmarkData + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + target = anyVal.(*BenchmarkData) + } + _ = target + }) + + b.Run("UnmarshalToOld", func(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: data} + var target *BenchmarkData + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToOld(&target) + } + }) + + b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { + w := &go_hook.Wrapped{Wrapped: data} + var target *BenchmarkData + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _ = w.UnmarshalToWithoutAssignable(&target) + } + }) +} From 76e5008f68aa88b292f6c1040faf2c6ded9228e0 Mon Sep 17 00:00:00 2001 From: Sinelnikov Michail Date: Tue, 26 Aug 2025 12:07:02 +0300 Subject: [PATCH 6/6] fix Signed-off-by: Sinelnikov Michail --- .../go_hook/filter_result_bench_test.go | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/module_manager/go_hook/filter_result_bench_test.go b/pkg/module_manager/go_hook/filter_result_bench_test.go index 94b8460b0..6f555fa3f 100644 --- a/pkg/module_manager/go_hook/filter_result_bench_test.go +++ b/pkg/module_manager/go_hook/filter_result_bench_test.go @@ -669,22 +669,22 @@ func BenchmarkNilPointerCases(b *testing.B) { } func BenchmarkCompareDirectCast_ValueStruct(b *testing.B) { - data := createTestData() - var anyVal any = *data + data := 10 + var anyVal any = data b.Run("DirectCast", func(b *testing.B) { - var target BenchmarkData + var target int b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - target = anyVal.(BenchmarkData) + target = anyVal.(int) } _ = target }) b.Run("UnmarshalToOld", func(b *testing.B) { - w := &go_hook.Wrapped{Wrapped: *data} - var target BenchmarkData + w := &go_hook.Wrapped{Wrapped: data} + var target int b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -693,8 +693,8 @@ func BenchmarkCompareDirectCast_ValueStruct(b *testing.B) { }) b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { - w := &go_hook.Wrapped{Wrapped: *data} - var target BenchmarkData + w := &go_hook.Wrapped{Wrapped: data} + var target int b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -719,7 +719,7 @@ func BenchmarkCompareDirectCast_PointerStruct(b *testing.B) { b.Run("UnmarshalToOld", func(b *testing.B) { w := &go_hook.Wrapped{Wrapped: data} - var target *BenchmarkData + var target BenchmarkData b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -729,7 +729,7 @@ func BenchmarkCompareDirectCast_PointerStruct(b *testing.B) { b.Run("UnmarshalToWithoutAssignable", func(b *testing.B) { w := &go_hook.Wrapped{Wrapped: data} - var target *BenchmarkData + var target BenchmarkData b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ {