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  }