github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/valuer/reflect_test.go (about)

     1  // Copyright 2021 ecodeclub
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package valuer
    16  
    17  import (
    18  	"database/sql"
    19  	"reflect"
    20  	"testing"
    21  
    22  	"github.com/ecodeclub/eorm/internal/errs"
    23  	"github.com/ecodeclub/eorm/internal/model"
    24  	"github.com/ecodeclub/eorm/internal/test"
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  func TestReflectValue_Field(t *testing.T) {
    29  	testValueField(t, NewReflectValue)
    30  	invalidCases := []valueFieldTestCase{
    31  		{
    32  			// 不存在的字段
    33  			name:      "invalid field",
    34  			field:     "UpdateTime",
    35  			wantError: errs.NewInvalidFieldError("UpdateTime"),
    36  		},
    37  	}
    38  	t.Run("invalid cases", func(t *testing.T) {
    39  		meta, err := model.NewMetaRegistry().Get(&test.SimpleStruct{})
    40  		if err != nil {
    41  			t.Fatal(err)
    42  		}
    43  		val := NewReflectValue(&test.SimpleStruct{}, meta)
    44  		for _, tc := range invalidCases {
    45  			t.Run(tc.name, func(t *testing.T) {
    46  				v, err := val.Field(tc.field)
    47  				assert.Equal(t, tc.wantError, err)
    48  				if err != nil {
    49  					return
    50  				}
    51  				assert.Equal(t, tc.wantVal, v.Interface())
    52  			})
    53  		}
    54  	})
    55  }
    56  
    57  func Test_reflectValue_SetColumn(t *testing.T) {
    58  	testSetColumn(t, NewReflectValue)
    59  }
    60  
    61  func FuzzReflectValue_Field(f *testing.F) {
    62  	f.Fuzz(fuzzValueField(NewReflectValue))
    63  }
    64  
    65  func fuzzValueField(factory Creator) any {
    66  	meta, _ := model.NewMetaRegistry().Get(&test.SimpleStruct{})
    67  	return func(t *testing.T, b bool,
    68  		i int, i8 int8, i16 int16, i32 int32, i64 int64,
    69  		u uint, u8 uint8, u16 uint16, u32 uint32, u64 uint64,
    70  		f32 float32, f64 float64, bt byte, bs []byte, s string) {
    71  		cb := b
    72  		entity := &test.SimpleStruct{
    73  			Bool: b, BoolPtr: &cb,
    74  			Int: i, IntPtr: &i,
    75  			Int8: i8, Int8Ptr: &i8,
    76  			Int16: i16, Int16Ptr: &i16,
    77  			Int32: i32, Int32Ptr: &i32,
    78  			Int64: i64, Int64Ptr: &i64,
    79  			Uint: u, UintPtr: &u,
    80  			Uint8: u8, Uint8Ptr: &u8,
    81  			Uint16: u16, Uint16Ptr: &u16,
    82  			Uint32: u32, Uint32Ptr: &u32,
    83  			Uint64: u64, Uint64Ptr: &u64,
    84  			Float32: f32, Float32Ptr: &f32,
    85  			Float64: f64, Float64Ptr: &f64,
    86  			String:         s,
    87  			NullStringPtr:  &sql.NullString{String: s, Valid: b},
    88  			NullInt16Ptr:   &sql.NullInt16{Int16: i16, Valid: b},
    89  			NullInt32Ptr:   &sql.NullInt32{Int32: i32, Valid: b},
    90  			NullInt64Ptr:   &sql.NullInt64{Int64: i64, Valid: b},
    91  			NullBoolPtr:    &sql.NullBool{Bool: b, Valid: b},
    92  			NullFloat64Ptr: &sql.NullFloat64{Float64: f64, Valid: b},
    93  		}
    94  		val := factory(entity, meta)
    95  		cases := newValueFieldTestCases(entity)
    96  		for _, c := range cases {
    97  			v, err := val.Field(c.field)
    98  			assert.Nil(t, err)
    99  			assert.Equal(t, c.wantVal, v.Interface())
   100  		}
   101  	}
   102  }
   103  
   104  func BenchmarkReflectValue_Field(b *testing.B) {
   105  	meta, _ := model.NewMetaRegistry().Get(&test.SimpleStruct{})
   106  	ins := NewReflectValue(&test.SimpleStruct{Int64: 13}, meta)
   107  	for i := 0; i < b.N; i++ {
   108  		val, err := ins.Field("Int64")
   109  		assert.Nil(b, err)
   110  		assert.Equal(b, int64(13), val.Interface())
   111  	}
   112  }
   113  
   114  func BenchmarkReflectValue_fieldByIndexes_VS_FieldByName(b *testing.B) {
   115  	meta, _ := model.NewMetaRegistry().Get(&test.SimpleStruct{})
   116  	ins := NewReflectValue(&test.SimpleStruct{Int64: 13}, meta)
   117  	in, ok := ins.(reflectValue)
   118  	assert.True(b, ok)
   119  	fieldName, unknownFieldName := "Int64", "XXXX"
   120  	unknownValue := int64(13)
   121  	var fieldValue reflect.Value
   122  	b.Run("fieldByIndex found", func(b *testing.B) {
   123  		for i := 0; i < b.N; i++ {
   124  			val, ok := in.fieldByIndex(fieldName)
   125  			assert.True(b, ok)
   126  			assert.Equal(b, fieldValue, val.Interface())
   127  		}
   128  	})
   129  	b.Run("fieldByIndex not found", func(b *testing.B) {
   130  		for i := 0; i < b.N; i++ {
   131  			val, ok := in.fieldByIndex(unknownFieldName)
   132  			assert.False(b, ok)
   133  			assert.Equal(b, unknownValue, val)
   134  		}
   135  	})
   136  	b.Run("FieldByName found", func(b *testing.B) {
   137  		for i := 0; i < b.N; i++ {
   138  			val := in.val.FieldByName(fieldName)
   139  			assert.Equal(b, fieldValue, val.Interface())
   140  		}
   141  	})
   142  	b.Run("fieldByIndex not found", func(b *testing.B) {
   143  		for i := 0; i < b.N; i++ {
   144  			val := in.val.FieldByName(unknownFieldName)
   145  			assert.Equal(b, unknownValue, val)
   146  		}
   147  	})
   148  }