github.com/clubpay/ronykit/kit@v0.14.4-0.20240515065620-d0dace45cbc7/utils/reflector/reflector_test.go (about) 1 package reflector_test 2 3 import ( 4 "testing" 5 6 "github.com/clubpay/ronykit/kit/utils" 7 "github.com/clubpay/ronykit/kit/utils/reflector" 8 goreflect "github.com/goccy/go-reflect" 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 ) 12 13 func TestReflector(t *testing.T) { 14 RegisterFailHandler(Fail) 15 RunSpecs(t, "Reflector Suite") 16 } 17 18 type testMessage struct { 19 X string `json:"xTag" otherTag:"xOther"` 20 Y int64 `json:"yTag" otherTag:"yOther"` 21 z string 22 M map[string]string 23 } 24 25 var _ = Describe("Reflector", func() { 26 r := reflector.New() 27 m := &testMessage{ 28 X: "xValue", 29 Y: 10, 30 z: "zValue", 31 M: nil, 32 } 33 rObj := r.Load(m, "json") 34 35 It("Load by Struct Fields", func() { 36 obj := rObj.Obj() 37 Expect(obj.GetStringDefault(m, "X", "")).To(Equal(m.X)) 38 Expect(obj.GetInt64Default(m, "Y", 0)).To(Equal(m.Y)) 39 Expect(obj.GetStringDefault(m, "z", "")).To(BeEmpty()) 40 }) 41 42 It("Load by ToJSON tag", func() { 43 byTag, ok := rObj.ByTag("json") 44 Expect(ok).To(BeTrue()) 45 Expect(byTag.GetStringDefault(m, "xTag", "")).To(Equal(m.X)) 46 Expect(byTag.GetInt64Default(m, "yTag", 0)).To(Equal(m.Y)) 47 Expect(byTag.GetStringDefault(m, "z", "def")).To(Equal("def")) 48 }) 49 }) 50 51 /* 52 Benchmark results: 53 54 cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz 55 BenchmarkReflector/unsafe-16 15217726 78.51 ns/op 0 B/op 0 allocs/op 56 BenchmarkReflector/unsafeRegistered-16 97216087 11.58 ns/op 0 B/op 0 allocs/op 57 BenchmarkReflector/reflect-16 30267793 37.32 ns/op 16 B/op 2 allocs/op 58 BenchmarkReflector/ccyReflect-16 58138024 22.71 ns/op 8 B/op 1 allocs/op 59 */ 60 func BenchmarkReflector(b *testing.B) { 61 benchs := []struct { 62 name string 63 f func(*testing.B) 64 }{ 65 {"unsafe", benchUnsafe}, 66 {"unsafeRegistered", benchUnsafeRegistered}, 67 {"reflect", benchReflect}, 68 {"ccyReflect", benchGoReflect}, 69 } 70 71 for idx := range benchs { 72 b.ResetTimer() 73 b.ReportAllocs() 74 b.Run(benchs[idx].name, benchs[idx].f) 75 } 76 } 77 78 func benchUnsafe(b *testing.B) { 79 r := reflector.New() 80 b.RunParallel(func(pb *testing.PB) { 81 t := &testMessage{} 82 t.X = utils.RandomID(5) 83 for pb.Next() { 84 obj := r.Load(t).Obj() 85 xR, err := obj.GetString(t, "X") 86 if err != nil { 87 b.Fatal(err) 88 } 89 if xR != t.X { 90 b.Fatal(xR, t.X) 91 } 92 } 93 }) 94 } 95 96 func benchUnsafeRegistered(b *testing.B) { 97 r := reflector.New() 98 reflector.Register(&testMessage{}) 99 b.RunParallel(func(pb *testing.PB) { 100 t := &testMessage{} 101 t.X = utils.RandomID(5) 102 for pb.Next() { 103 obj := r.Load(t).Obj() 104 xR, err := obj.GetString(t, "X") 105 if err != nil { 106 b.Fatal(err) 107 } 108 if err != nil { 109 b.Fatal(err) 110 } 111 if xR != t.X { 112 b.Fatal(xR, t.X) 113 } 114 } 115 }) 116 } 117 118 func benchReflect(b *testing.B) { 119 r := reflector.New() 120 b.RunParallel(func(pb *testing.PB) { 121 t := &testMessage{} 122 t.X = utils.RandomID(5) 123 for pb.Next() { 124 xR, err := r.GetString(t, "X") 125 if err != nil { 126 b.Fatal(err) 127 } 128 if xR != t.X { 129 b.Fatal(xR, t.X) 130 } 131 } 132 }) 133 } 134 135 func benchGoReflect(b *testing.B) { 136 b.RunParallel(func(pb *testing.PB) { 137 t := &testMessage{} 138 t.X = utils.RandomID(5) 139 for pb.Next() { 140 xR := goreflect.Indirect(goreflect.ValueOf(t)).FieldByName("X").String() 141 if xR != t.X { 142 b.Fatal(xR, t.X) 143 } 144 } 145 }) 146 }