github.com/hedzr/evendeep@v0.4.8/structiterator_test.go (about)

     1  package evendeep
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  	"unsafe"
    10  
    11  	"github.com/hedzr/evendeep/diff"
    12  	"github.com/hedzr/evendeep/internal/cl"
    13  	"github.com/hedzr/evendeep/typ"
    14  
    15  	"github.com/hedzr/evendeep/dbglog"
    16  	"github.com/hedzr/evendeep/flags/cms"
    17  	"github.com/hedzr/evendeep/internal/tool"
    18  )
    19  
    20  func TestFieldsTableT_getFields_special(t *testing.T) {
    21  	tr := fieldsTableT{}
    22  	s := struct {
    23  		vv int
    24  	}{vv: 1}
    25  	sv := reflect.ValueOf(s)
    26  	tr.getFields(&sv, sv.Type(), "vv", 0)
    27  
    28  	iv := reflect.ValueOf(123)
    29  	tr.getFields(&iv, iv.Type(), "an", 0)
    30  }
    31  
    32  func TestTableRecT_FieldName(t *testing.T) {
    33  	tr := tableRecT{
    34  		names: nil,
    35  	}
    36  	if tr.FieldName() != "" {
    37  		t.FailNow()
    38  	}
    39  
    40  	tr = tableRecT{
    41  		names: []string{"C", "B", "A"},
    42  	}
    43  	if tr.FieldName() != "A.B.C" {
    44  		t.FailNow()
    45  	}
    46  }
    47  
    48  func TestTableRecT_ShortFieldName(t *testing.T) {
    49  	tr := tableRecT{
    50  		names: nil,
    51  	}
    52  	if tr.ShortFieldName() != "" {
    53  		t.FailNow()
    54  	}
    55  }
    56  
    57  func TestSetToZero(t *testing.T) {
    58  	val := 10
    59  	type Tmp struct {
    60  		A int16
    61  	}
    62  
    63  	run := func(v reflect.Value) {
    64  		// v := reflect.ValueOf(c)
    65  		vind := tool.Rdecodesimple(v)
    66  		vf := vind.Field(0)
    67  		// vf = vf.Elem()
    68  		t.Logf("src: %v", tool.Valfmt(&vf))
    69  		setToZero(&vf)
    70  	}
    71  
    72  	t.Run("TestSetToZero.bool", func(t *testing.T) {
    73  		type Case struct {
    74  			Src, Zero bool
    75  		}
    76  		c := &Case{true, false}
    77  		v := reflect.ValueOf(c)
    78  		run(v)
    79  		if !DeepEqual(c.Src, c.Zero) {
    80  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
    81  			t.FailNow()
    82  		}
    83  	})
    84  	t.Run("TestSetToZero.int", func(t *testing.T) {
    85  		type Case struct {
    86  			Src, Zero int
    87  		}
    88  		c := &Case{9, 0}
    89  
    90  		v := reflect.ValueOf(c)
    91  		run(v)
    92  		if !DeepEqual(c.Src, c.Zero) {
    93  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
    94  			t.FailNow()
    95  		}
    96  	})
    97  	t.Run("TestSetToZero.uint", func(t *testing.T) {
    98  		type Case struct {
    99  			Src, Zero uint
   100  		}
   101  		c := &Case{9, 0}
   102  
   103  		v := reflect.ValueOf(c)
   104  		run(v)
   105  		if !DeepEqual(c.Src, c.Zero) {
   106  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   107  			t.FailNow()
   108  		}
   109  	})
   110  	t.Run("TestSetToZero.float", func(t *testing.T) {
   111  		type Case struct {
   112  			Src, Zero float32
   113  		}
   114  		c := &Case{9, 0}
   115  
   116  		v := reflect.ValueOf(c)
   117  		run(v)
   118  		if !DeepEqual(c.Src, c.Zero) {
   119  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   120  			t.FailNow()
   121  		}
   122  	})
   123  	t.Run("TestSetToZero.complex", func(t *testing.T) {
   124  		type Case struct {
   125  			Src, Zero complex128
   126  		}
   127  		c := &Case{9, 0}
   128  
   129  		v := reflect.ValueOf(c)
   130  		run(v)
   131  		if !DeepEqual(c.Src, c.Zero) {
   132  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   133  			t.FailNow()
   134  		}
   135  	})
   136  	t.Run("TestSetToZero.string", func(t *testing.T) {
   137  		type Case struct {
   138  			Src, Zero string
   139  		}
   140  		c := &Case{"9hello", ""}
   141  
   142  		v := reflect.ValueOf(c)
   143  		run(v)
   144  		if !DeepEqual(c.Src, c.Zero) {
   145  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   146  			t.FailNow()
   147  		}
   148  	})
   149  	t.Run("TestSetToZero.slice", func(t *testing.T) {
   150  		type Case struct {
   151  			Src, Zero []int
   152  		}
   153  		c := &Case{[]int{9, 12}, []int{}}
   154  
   155  		v := reflect.ValueOf(c)
   156  		run(v)
   157  		if !DeepEqual(c.Src, c.Zero) {
   158  			t.Logf("-. For source '%+v', expect '%v' but failed.", c.Src, c.Zero)
   159  			t.FailNow()
   160  		}
   161  	})
   162  	t.Run("TestSetToZero.array", func(t *testing.T) {
   163  		type Case struct {
   164  			Src, Zero [1]int
   165  		}
   166  		c := &Case{[1]int{1}, [1]int{0}}
   167  
   168  		v := reflect.ValueOf(c)
   169  		run(v)
   170  		if !DeepEqual(c.Src, c.Zero) {
   171  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   172  			t.FailNow()
   173  		}
   174  	})
   175  	t.Run("TestSetToZero.map", func(t *testing.T) {
   176  		type Case struct {
   177  			Src, Zero map[string]int
   178  		}
   179  		c := &Case{map[string]int{"x": 1, "y": 2}, map[string]int{}}
   180  
   181  		v := reflect.ValueOf(c)
   182  		run(v)
   183  		if !DeepEqual(c.Src, c.Zero) {
   184  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   185  			t.FailNow()
   186  		}
   187  	})
   188  	t.Run("TestSetToZero.ptr", func(t *testing.T) {
   189  		type Case struct {
   190  			Src, Zero *int
   191  		}
   192  		c := &Case{&val, (*int)(nil)}
   193  
   194  		v := reflect.ValueOf(c)
   195  		run(v)
   196  		if !DeepEqual(c.Src, c.Zero) {
   197  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   198  			t.FailNow()
   199  		}
   200  	})
   201  	t.Run("TestSetToZero.struct", func(t *testing.T) {
   202  		type Case struct {
   203  			Src, Zero Tmp
   204  		}
   205  		c := &Case{Tmp{A: 3}, Tmp{}}
   206  
   207  		v := reflect.ValueOf(c)
   208  		run(v)
   209  		if !DeepEqual(c.Src, c.Zero) {
   210  			t.Logf("-. For source '%v', expect '%v' but failed.", c.Src, c.Zero)
   211  			t.FailNow()
   212  		}
   213  	})
   214  
   215  	type Func func()
   216  	var fn Func = func() {}
   217  	for i, case_ := range []*struct {
   218  		Src  typ.Any
   219  		Zero typ.Any
   220  	}{
   221  		{true, false},
   222  		{9, 0},
   223  		{uint32(9), uint32(0)},
   224  		{float64(9), float64(0)},
   225  		{complex128(9), complex128(0)},
   226  		{"9hello", ""},
   227  		{[]int{9, 12}, []int{}},
   228  		{[1]int{1}, [1]int{0}},
   229  		{map[string]int{"x": 1, "y": 2}, map[string]int{}},
   230  		{&val, (*int)(nil)},
   231  
   232  		{Tmp{A: 3}, Tmp{}},
   233  
   234  		{fn, Func(nil)},
   235  	} {
   236  		v := reflect.ValueOf(case_)
   237  		vind := tool.Rdecodesimple(v)
   238  
   239  		vf := vind.Field(0) // vf = vf.Elem()
   240  		t.Logf("%d. src: %+v", i, tool.Valfmt(&vf))
   241  		setToZero(&vf)
   242  
   243  		if why, equal := diff.New(case_.Src, case_.Zero, diff.WithTreatEmptyStructPtrAsNilPtr(true)); !equal {
   244  			t.Logf("%d. FAILED: Setting to Zero for source '%v', expect '%v' but failed.\n   why: %v", i, case_.Src, case_.Zero, why)
   245  			t.FailNow()
   246  		}
   247  	}
   248  
   249  	// for unsupported types
   250  
   251  	v := reflect.ValueOf(&fn).Elem()
   252  	setToZero(&v)
   253  }
   254  
   255  func TestIgnoredPackagePrefixesContains(t *testing.T) {
   256  	if _ignoredpackageprefixes.contains("abc") {
   257  		t.Fatal(`unwanted ignored package prefix found: 'abc'`)
   258  	}
   259  	if !_ignoredpackageprefixes.contains("golang.org/grpc") {
   260  		t.Fatal(`ignored package prefix cannot be found: golang.org/grpc`)
   261  	}
   262  }
   263  
   264  func TestFieldAccessorT_mapkey_special(t *testing.T) {
   265  	const byName = false
   266  	x2 := x2data()
   267  	v1 := reflect.ValueOf(&x2)
   268  	t1, _ := tool.Rdecode(v1)
   269  	it := newStructIterator(t1)
   270  	t.Logf("%v", it)
   271  }
   272  
   273  func TestFieldAccessorT_IsAnyFlagsOK(t *testing.T) {
   274  	const byName = false
   275  	x2 := x2data()
   276  	v1 := reflect.ValueOf(&x2)
   277  	t1, _ := tool.Rdecode(v1)
   278  	it := newStructIterator(t1)
   279  	loopIt(t, it, byName, nil)
   280  }
   281  
   282  func TestFieldAccessorT_FieldType_is_nil(t *testing.T) {
   283  	var a *fieldAccessorT = nil
   284  	_ = a.FieldType()
   285  
   286  	a = &fieldAccessorT{isStruct: false}
   287  	_ = a.NumField()
   288  }
   289  
   290  type zPart struct {
   291  	S string
   292  }
   293  
   294  func (s zPart) String() string {
   295  	return s.S
   296  }
   297  
   298  func TestFieldAccessorT_forMap(t *testing.T) {
   299  	const byName = false
   300  	x2 := map[zPart]bool{
   301  		{"x"}: true, //nolint:gofmt
   302  	}
   303  	v1 := reflect.ValueOf(&x2)
   304  	t1, _ := tool.Rdecode(v1)
   305  	it := newStructIterator(t1)
   306  	loopIt(t, it, byName, nil)
   307  }
   308  
   309  func TestFieldAccessorT_Operations(t *testing.T) {
   310  	x1 := x1data()
   311  	v1 := reflect.ValueOf(&x1)
   312  	t1, _ := tool.Rdecode(v1)
   313  
   314  	// x2 := new(X1)
   315  	// t2 := rdecodesimple(reflect.ValueOf(&x2))
   316  
   317  	for _, byName := range []bool{false, true} {
   318  		it := newStructIterator(t1)
   319  		loopIt(t, it, byName, func(accessor accessor, field *reflect.StructField) {
   320  			switch field.Name {
   321  			case "O":
   322  				accessor.Set(reflect.ValueOf([2]string{"zed", "bee"}))
   323  			case "Zignored01":
   324  				accessor.Set(reflect.ValueOf("bee"))
   325  			}
   326  		})
   327  		t.Logf("x1: %+v", x1)
   328  	}
   329  
   330  	// for i := 0; ; i++ {
   331  	// 	accessor, ok := it.Next(nil, byName)
   332  	// 	if !ok {
   333  	// 		break
   334  	// 	}
   335  	// 	field := accessor.StructField()
   336  	// 	if field == nil {
   337  	// 		t.Logf("%d. field info missed", i)
   338  	// 		continue
   339  	// 	}
   340  	// 	if field.Name == "O" {
   341  	// 		accessor.Set(reflect.ValueOf([2]string{"zed", "bee"}))
   342  	// 	}
   343  	// 	t.Logf("%d. %q (%v) %v %q | %v", i, field.Name, tool.Typfmt(field.Type), field.Index, field.PkgPath, accessor.FieldValue().Interface())
   344  	// }
   345  }
   346  
   347  func TestStructIteratorT_Next_X1(t *testing.T) {
   348  	x1 := x1data()
   349  	v1 := reflect.ValueOf(&x1)
   350  	t1, _ := tool.Rdecode(v1)
   351  
   352  	x2 := new(X1)
   353  	t2 := tool.Rdecodesimple(reflect.ValueOf(&x2))
   354  
   355  	const byName = false
   356  
   357  	t.Run("getAllFields at once", testGetAllFieldsX1)
   358  
   359  	t.Run("by struct iterator", testStructIteratorNextT1)
   360  
   361  	t.Run("get further: loop src & dst at same time", func(t *testing.T) {
   362  		targetIterator := newStructIterator(t1)
   363  
   364  		var sourcefields fieldsTableT
   365  		sourcefields = sourcefields.getAllFields(t1, false)
   366  		for i, amount := 0, len(sourcefields.tableRecordsT); i < amount; i++ {
   367  			sourcefield := sourcefields.tableRecordsT[i]
   368  			flags := parseFieldTags(sourcefield.structField.Tag, "")
   369  			accessor, ok := targetIterator.Next(nil, byName) //nolint:govet
   370  			if flags.isFlagIgnored() || !ok {
   371  				continue
   372  			}
   373  			srcval, dstval := sourcefield.FieldValue(), accessor.FieldValue()
   374  			if srcval == nil || dstval == nil {
   375  				t.Logf("%d. field info missed", i)
   376  				continue
   377  			}
   378  			t.Logf("%d. %s (%v) -> %s (%v) | %v", i, strings.Join(tool.ReverseStringSlice(sourcefield.names), "."), tool.Valfmt(srcval), accessor.StructFieldName(), tool.Valfmt(dstval), tool.Typfmt(accessor.StructField().Type))
   379  			// ec.Attach(invokeStructFieldTransformer(c, params, srcval, dstval, padding))
   380  		}
   381  	})
   382  
   383  	t.Run("zero: loop src & dst at same time", func(t *testing.T) {
   384  		targetIterator := newStructIterator(t2, withStructPtrAutoExpand(true))
   385  
   386  		var sourcefields fieldsTableT
   387  		sourcefields = sourcefields.getAllFields(t2, true)
   388  
   389  		for i, amount := 0, len(sourcefields.tableRecordsT); i < amount; i++ {
   390  			sourcefield := sourcefields.tableRecordsT[i]
   391  			flags := parseFieldTags(sourcefield.structField.Tag, "")
   392  			accessor, ok := targetIterator.Next(nil, byName) //nolint:govet
   393  			if flags.isFlagIgnored() || !ok {
   394  				continue
   395  			}
   396  			srcval, dstval := sourcefield.FieldValue(), accessor.FieldValue()
   397  			if srcval == nil || dstval == nil {
   398  				t.Logf("%d. field info missed", i)
   399  				continue
   400  			}
   401  			t.Logf("%d. %s (%v) -> %s (%v) | %v", i, strings.Join(tool.ReverseStringSlice(sourcefield.names), "."), tool.Valfmt(srcval), accessor.StructFieldName(), tool.Valfmt(dstval), tool.Typfmt(accessor.StructField().Type))
   402  			// ec.Attach(invokeStructFieldTransformer(c, params, srcval, dstval, padding))
   403  		}
   404  	})
   405  }
   406  
   407  func loopIt(t *testing.T, it structIterable, byName bool, checkName func(accessor accessor, field *reflect.StructField)) {
   408  	for i := 0; ; i++ {
   409  		accessor, ok := it.Next(nil, byName)
   410  		if !ok {
   411  			break
   412  		}
   413  		field := accessor.StructField()
   414  		if accessor.IsStruct() && field == nil {
   415  			t.Logf("%d. field info missed", i)
   416  			continue
   417  		}
   418  
   419  		if checkName != nil {
   420  			checkName(accessor, field)
   421  		}
   422  
   423  		var name string
   424  		var fieldType *reflect.Type
   425  		if accessor.IsStruct() {
   426  			name = field.Name
   427  			fieldType = &field.Type
   428  		} else {
   429  			name = accessor.StructFieldName()
   430  			fieldType = accessor.FieldType()
   431  		}
   432  
   433  		// dbglog.Log("  - for field %q", name)
   434  
   435  		if name == "Name" {
   436  			accessor.Set(reflect.ValueOf("Meg"))
   437  			if p, ok := accessor.(*fieldAccessorT); ok {
   438  				p.fieldTags = parseFieldTags(field.Tag, "")
   439  				accessor.IsAnyFlagsOK(cms.Default, cms.KeepIfNotEq)
   440  				accessor.IsAllFlagsOK(cms.Default, cms.KeepIfNotEq)
   441  			}
   442  		} else {
   443  			if p, ok := accessor.(*fieldAccessorT); ok {
   444  				p.fieldTags = nil
   445  				accessor.IsAnyFlagsOK(cms.Default, cms.KeepIfNotEq)
   446  				accessor.IsAllFlagsOK(cms.Default, cms.KeepIfNotEq)
   447  			}
   448  		}
   449  
   450  		var val reflect.Value
   451  		if accessor.IsStruct() && !tool.IsExported(field) {
   452  			val = *accessor.FieldValue()
   453  			val = cl.GetUnexportedField(val)
   454  			// cl.SetUnexportedField(target, newval)
   455  		} else {
   456  			val = *accessor.FieldValue()
   457  		}
   458  		t.Logf("%d. %q (%v) | %v", i, name, tool.Typfmt(*fieldType), tool.Valfmt(&val))
   459  	}
   460  }
   461  
   462  func x1data() X1 {
   463  	nn := []int{2, 9, 77, 111, 23, 29}
   464  	var a [2]string
   465  	a[0] = "Hello"
   466  	a[1] = "World"
   467  
   468  	x0 := X0{}
   469  
   470  	x1 := X1{
   471  		A: uintptr(unsafe.Pointer(&x0)),
   472  		H: make(chan int, 5),
   473  		M: unsafe.Pointer(&x0),
   474  		// E: []*X0{&x0},
   475  		N:          nn[1:3],
   476  		O:          a,
   477  		Q:          a,
   478  		Zignored01: 111,
   479  	}
   480  	return x1
   481  }
   482  
   483  func x2data() Employee {
   484  	return Employee{
   485  		Name:       "Bob",
   486  		Zignored01: 222,
   487  	}
   488  }
   489  
   490  func testGetAllFieldsX1(t *testing.T) {
   491  
   492  	x1 := x1data()
   493  	v1 := reflect.ValueOf(&x1)
   494  	t1, _ := tool.Rdecode(v1)
   495  
   496  	var sourcefields fieldsTableT
   497  	sourcefields = sourcefields.getAllFields(t1, false)
   498  	for i, amount := 0, len(sourcefields.tableRecordsT); i < amount; i++ {
   499  		sourcefield := sourcefields.tableRecordsT[i]
   500  		srcval := sourcefield.FieldValue()
   501  		srctypstr := tool.Typfmtv(srcval)
   502  		dbglog.Log("%d. %s (%v) %v -> %s (%v)", i, strings.Join(tool.ReverseStringSlice(sourcefield.names), "."), tool.Valfmt(srcval), srctypstr, "", "")
   503  	}
   504  }
   505  
   506  func testStructIteratorNextT1(t *testing.T) {
   507  
   508  	x1 := x1data()
   509  	v1 := reflect.ValueOf(&x1)
   510  	t1, _ := tool.Rdecode(v1)
   511  
   512  	const byName = false
   513  
   514  	it := newStructIterator(t1)
   515  	for i := 0; ; i++ {
   516  		accessor, ok := it.Next(nil, byName)
   517  		if !ok {
   518  			break
   519  		}
   520  		field := accessor.StructField()
   521  		if field == nil {
   522  			t.Logf("%d. field info missed", i)
   523  			continue
   524  		}
   525  		dbglog.Log("%d. %q (%v) %v %q", i, field.Name, tool.Typfmt(field.Type), field.Index, field.PkgPath)
   526  	}
   527  }
   528  
   529  func TestStructIterator_Next_Employee2(t *testing.T) {
   530  	t.Run("testStructIterator_Next_Employee2", testStructIteratorNextEmployee2)
   531  	t.Run("testStructIterator_Next_Employee2_exp", testStructIteratorNextEmployee2Exp)
   532  }
   533  
   534  func testStructIteratorNextEmployee2(t *testing.T) {
   535  
   536  	timeZone, _ := time.LoadLocation("America/Phoenix")
   537  	tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
   538  
   539  	src := Employee2{
   540  		Base: Base{
   541  			Name:      "Bob",
   542  			Birthday:  &tm,
   543  			Age:       24,
   544  			EmployeID: 7,
   545  		},
   546  		Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
   547  		Image:  []byte{95, 27, 43, 66, 0, 21, 210},
   548  		Attr:   &Attr{Attrs: []string{"hello", "world"}},
   549  		Valid:  true,
   550  	}
   551  
   552  	var sb strings.Builder
   553  	defer func() { t.Log(sb.String()) }()
   554  
   555  	v1 := reflect.ValueOf(&src)
   556  	t1, _ := tool.Rdecode(v1)
   557  	it := newStructIterator(t1)
   558  	const byName = false
   559  	for i := 0; ; i++ {
   560  		accessor, ok := it.Next(nil, byName)
   561  		if !ok {
   562  			break
   563  		}
   564  		field := accessor.StructField()
   565  		if field == nil {
   566  			t.Logf("%d. field info missed", i)
   567  			continue
   568  		}
   569  		t.Logf("%d. %q (%v) %v %q", i, field.Name, tool.Typfmt(field.Type), field.Index, field.PkgPath)
   570  		sb.WriteString(fmt.Sprintf("%d. %q (%v) %v %q\n", i, field.Name, tool.Typfmt(field.Type), field.Index, field.PkgPath))
   571  	}
   572  
   573  	if sb.String() != `0. "Base" (evendeep.Base (struct)) [0] ""
   574  1. "Avatar" (string (string)) [1] ""
   575  2. "Image" ([]uint8 (slice)) [2] ""
   576  3. "Attr" (*evendeep.Attr (ptr)) [3] ""
   577  4. "Valid" (bool (bool)) [4] ""
   578  5. "Deleted" (bool (bool)) [5] ""
   579  ` {
   580  		t.Fail()
   581  	} else {
   582  		t.Log("The loops and outputs verified")
   583  	}
   584  }
   585  
   586  func testStructIteratorNextEmployee2Exp(t *testing.T) {
   587  
   588  	timeZone, _ := time.LoadLocation("America/Phoenix")
   589  	tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
   590  
   591  	src := Employee2{
   592  		Base: Base{
   593  			Name:      "Bob",
   594  			Birthday:  &tm,
   595  			Age:       24,
   596  			EmployeID: 7,
   597  		},
   598  		Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
   599  		Image:  []byte{95, 27, 43, 66, 0, 21, 210},
   600  		Attr:   &Attr{Attrs: []string{"hello", "world"}},
   601  		Valid:  true,
   602  	}
   603  
   604  	var sb strings.Builder
   605  	defer func() { t.Log(sb.String()) }()
   606  
   607  	v1 := reflect.ValueOf(&src)
   608  	t1, _ := tool.Rdecode(v1)
   609  	it := newStructIterator(t1, withStructPtrAutoExpand(true))
   610  	const byName = false
   611  	for i := 0; ; i++ {
   612  		accessor, ok := it.Next(nil, byName)
   613  		if !ok {
   614  			break
   615  		}
   616  		field := accessor.StructField()
   617  		if field == nil {
   618  			t.Logf("%d. field info missed", i)
   619  			continue
   620  		}
   621  		t.Logf("%d. %q (%v) %v %q", i, field.Name, tool.Typfmt(field.Type), field.Index, field.PkgPath)
   622  		sb.WriteString(fmt.Sprintf("%d. %q (%v) %v %q\n", i, field.Name, tool.Typfmt(field.Type), field.Index, field.PkgPath))
   623  	}
   624  
   625  	if sb.String() != `0. "Name" (string (string)) [0] ""
   626  1. "Birthday" (*time.Time (ptr)) [1] ""
   627  2. "Age" (int (int)) [2] ""
   628  3. "EmployeID" (int64 (int64)) [3] ""
   629  4. "Avatar" (string (string)) [1] ""
   630  5. "Image" ([]uint8 (slice)) [2] ""
   631  6. "Attrs" ([]string (slice)) [0] ""
   632  7. "Valid" (bool (bool)) [4] ""
   633  8. "Deleted" (bool (bool)) [5] ""
   634  ` {
   635  		t.Fail()
   636  	} else {
   637  		t.Log("The loops and outputs verified")
   638  	}
   639  }
   640  
   641  func TestStructIterator_Next_User(t *testing.T) {
   642  	// new target with new children automatically
   643  	t.Run("testStructIterator_Next_User_new", testStructIteratorNextUserNew)
   644  
   645  	t.Run("testStructIterator_Next_User", testStructIteratorNextUser)
   646  	t.Run("testStructIterator_Next_User_zero", testStructIteratorNextUserZero)
   647  	t.Run("testStructIterator_Next_User_more", testStructIteratorNextUserMore)
   648  }
   649  
   650  func testStructIteratorNextUser(t *testing.T) {
   651  
   652  	timeZone, _ := time.LoadLocation("America/Phoenix")
   653  	tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
   654  	tgt := User{
   655  		Name:      "Frank",
   656  		Birthday:  &tm2,
   657  		Age:       18,
   658  		EmployeID: 9,
   659  		Attr:      &Attr{Attrs: []string{"baby"}},
   660  		Deleted:   true,
   661  	}
   662  
   663  	var sb strings.Builder
   664  	defer func() {
   665  		t.Logf("\n%v\n", sb.String())
   666  	}()
   667  
   668  	v1 := reflect.ValueOf(&tgt)
   669  	t1, _ := tool.Rdecode(v1)
   670  	it := newStructIterator(t1)
   671  	const byName = false
   672  	for i := 0; ; i++ {
   673  		accessor, ok := it.Next(nil, byName)
   674  		if !ok {
   675  			break
   676  		}
   677  		field := accessor.StructField()
   678  		_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v(%v) | fld: %+v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index, field)
   679  	}
   680  
   681  }
   682  
   683  func testStructIteratorNextUserNew(t *testing.T) {
   684  
   685  	// timeZone, _ := time.LoadLocation("America/Phoenix")
   686  	// timeZone2, _ := time.LoadLocation("Asia/Chongqing")
   687  	// //tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
   688  	// tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
   689  	// //tm1 := time.Date(2021, 2, 28, 13, 1, 23, 800, timeZone2)
   690  	// tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)
   691  
   692  	const byName = false
   693  	var sb strings.Builder
   694  	defer func() {
   695  		t.Logf("\n%v\n", sb.String())
   696  	}()
   697  
   698  	for _, tgt := range []*User{
   699  		new(User),
   700  	} {
   701  		sb.WriteString("\n")
   702  		v1 := reflect.ValueOf(&tgt) // nolint:gosec // G601: Implicit memory aliasing in for loop
   703  		t1, _ := tool.Rdecode(v1)
   704  		it := newStructIterator(t1, withStructPtrAutoExpand(true), withStructFieldPtrAutoNew(true))
   705  		for i := 0; ; i++ {
   706  			accessor, ok := it.Next(nil, false)
   707  			if !ok {
   708  				break
   709  			}
   710  			field := accessor.StructField()
   711  			_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v(%v) | fld: %+v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index, field)
   712  		}
   713  	}
   714  
   715  }
   716  
   717  func testStructIteratorNextUserZero(t *testing.T) {
   718  
   719  	// timeZone, _ := time.LoadLocation("America/Phoenix")
   720  	// timeZone2, _ := time.LoadLocation("Asia/Chongqing")
   721  	// tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
   722  	// tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
   723  	// tm1 := time.Date(2021, 2, 28, 13, 1, 23, 800, timeZone2)
   724  	// tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)
   725  
   726  	const byName = false
   727  	var sb strings.Builder
   728  	defer func() {
   729  		t.Logf("\n%v\n", sb.String())
   730  	}()
   731  
   732  	for _, tgt := range []*User{
   733  		new(User),
   734  	} {
   735  		sb.WriteString("\n\n\n")
   736  		v1 := reflect.ValueOf(&tgt) // nolint:gosec // G601: Implicit memory aliasing in for loop
   737  		t1, _ := tool.Rdecode(v1)
   738  		it := newStructIterator(t1)
   739  		for i := 0; ; i++ {
   740  			accessor, ok := it.Next(nil, byName)
   741  			if !ok {
   742  				break
   743  			}
   744  			field := accessor.StructField()
   745  			_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v(%v) | fld: %+v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index, field)
   746  		}
   747  	}
   748  
   749  }
   750  
   751  func testStructIteratorNextUserMore(t *testing.T) {
   752  
   753  	timeZone, _ := time.LoadLocation("America/Phoenix")
   754  	timeZone2, _ := time.LoadLocation("Asia/Chongqing")
   755  	// tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
   756  	tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
   757  	// tm1 := time.Date(2021, 2, 28, 13, 1, 23, 800, timeZone2)
   758  	tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)
   759  
   760  	const byName = false
   761  	var sb strings.Builder
   762  	defer func() {
   763  		t.Logf("\n%v\n", sb.String())
   764  	}()
   765  
   766  	for _, tgt := range []*User{
   767  		{
   768  			Name:      "Frank",
   769  			Birthday:  &tm2,
   770  			Age:       18,
   771  			EmployeID: 9,
   772  			Attr:      &Attr{Attrs: []string{"baby"}},
   773  		},
   774  		{
   775  			Name:      "Mathews",
   776  			Birthday:  &tm3,
   777  			Age:       3,
   778  			EmployeID: 92,
   779  			Attr:      &Attr{Attrs: []string{"get"}},
   780  			Deleted:   false,
   781  		},
   782  	} {
   783  		sb.WriteString("\n\n\n")
   784  		v1 := reflect.ValueOf(&tgt) // nolint:gosec // G601: Implicit memory aliasing in for loop
   785  		t1, _ := tool.Rdecode(v1)
   786  		it := newStructIterator(t1)
   787  		for i := 0; ; i++ {
   788  			accessor, ok := it.Next(nil, byName)
   789  			if !ok {
   790  				break
   791  			}
   792  			field := accessor.StructField()
   793  			_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v(%v) | fld: %+v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index, field)
   794  		}
   795  	}
   796  
   797  }
   798  
   799  func TestStructIterator_Next_A4(t *testing.T) {
   800  	t.Run("testStructIterator_Next_A4_new", teststructiteratorNextA4New)
   801  
   802  	t.Run("testStructIterator_Next_A4_zero", teststructiteratorNextA4Zero)
   803  	t.Run("testStructIterator_Next_A4", teststructiteratorNextA4)
   804  }
   805  
   806  func teststructiteratorNextA4New(t *testing.T) {
   807  	var sb strings.Builder
   808  	const byName = false
   809  	a4 := new(A4)
   810  	v1 := reflect.ValueOf(&a4)
   811  	t1, _ := tool.Rdecode(v1)
   812  	it := newStructIterator(t1, withStructPtrAutoExpand(true), withStructFieldPtrAutoNew(true))
   813  	for i := 0; ; i++ {
   814  		accessor, ok := it.Next(nil, byName)
   815  		if !ok {
   816  			break
   817  		}
   818  		field := accessor.StructField()
   819  		_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v %v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index)
   820  	}
   821  
   822  	t.Logf(sb.String())
   823  	//nolint:goconst
   824  	if sb.String() != `0. "Name2" (string (string)) | evendeep.A2 (struct) [0]
   825  1. "Int2" (int (int)) | evendeep.A2 (struct) [1]
   826  2. "Bool2" (bool (bool)) | evendeep.A2 (struct) [2]
   827  3. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   828  4. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   829  5. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   830  6. "Name3" (string (string)) | evendeep.A3 (struct) [1]
   831  7. "Int3" (int (int)) | evendeep.A3 (struct) [2]
   832  8. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   833  9. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   834  10. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   835  11. "Bool3" (bool (bool)) | evendeep.A3 (struct) [4]
   836  12. "Int4" (int (int)) | evendeep.A4 (struct) [1]
   837  13. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   838  14. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   839  15. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   840  ` {
   841  		t.Fail()
   842  	} else {
   843  		t.Log("The loops and outputs verified")
   844  	}
   845  
   846  	// Output:
   847  	// 0. "Name2" (string (string)) | evendeep.A2 (struct) (0) [0]
   848  	// 1. "Int2" (int (int)) | evendeep.A2 (struct) (1) [1]
   849  	// 2. "Bool2" (bool (bool)) | evendeep.A2 (struct) (2) [2]
   850  	// 3. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   851  	// 4. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   852  	// 5. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   853  	// 6. "Name3" (string (string)) | evendeep.A3 (struct) (1) [1]
   854  	// 7. "Int3" (int (int)) | evendeep.A3 (struct) (2) [2]
   855  	// 8. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   856  	// 9. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   857  	// 10. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   858  	// 11. "Bool3" (bool (bool)) | evendeep.A3 (struct) (4) [4]
   859  	// 12. "Int4" (int (int)) | evendeep.A4 (struct) (1) [1]
   860  	// 13. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   861  	// 14. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   862  	// 15. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   863  }
   864  
   865  func teststructiteratorNextA4Zero(t *testing.T) {
   866  	var sb strings.Builder
   867  	const byName = false
   868  	a4 := new(A4)
   869  	v1 := reflect.ValueOf(&a4)
   870  	t1, _ := tool.Rdecode(v1)
   871  	it := newStructIterator(t1, withStructPtrAutoExpand(true))
   872  	for i := 0; ; i++ {
   873  		accessor, ok := it.Next(nil, byName)
   874  		if !ok {
   875  			break
   876  		}
   877  		field := accessor.StructField()
   878  		_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v %v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index)
   879  	}
   880  
   881  	t.Logf(sb.String())
   882  	if sb.String() != `0. "Name2" (string (string)) | evendeep.A2 (struct) [0]
   883  1. "Int2" (int (int)) | evendeep.A2 (struct) [1]
   884  2. "Bool2" (bool (bool)) | evendeep.A2 (struct) [2]
   885  3. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   886  4. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   887  5. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   888  6. "Name3" (string (string)) | evendeep.A3 (struct) [1]
   889  7. "Int3" (int (int)) | evendeep.A3 (struct) [2]
   890  8. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   891  9. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   892  10. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   893  11. "Bool3" (bool (bool)) | evendeep.A3 (struct) [4]
   894  12. "Int4" (int (int)) | evendeep.A4 (struct) [1]
   895  13. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   896  14. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   897  15. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   898  ` {
   899  		t.Fail()
   900  	} else {
   901  		t.Log("The loops and outputs verified")
   902  	}
   903  
   904  	// Output:
   905  	// 0. "Name2" (string (string)) | evendeep.A2 (struct) (0) [0]
   906  	// 1. "Int2" (int (int)) | evendeep.A2 (struct) (1) [1]
   907  	// 2. "Bool2" (bool (bool)) | evendeep.A2 (struct) (2) [2]
   908  	// 3. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   909  	// 4. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   910  	// 5. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   911  	// 6. "Name3" (string (string)) | evendeep.A3 (struct) (1) [1]
   912  	// 7. "Int3" (int (int)) | evendeep.A3 (struct) (2) [2]
   913  	// 8. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   914  	// 9. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   915  	// 10. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   916  	// 11. "Bool3" (bool (bool)) | evendeep.A3 (struct) (4) [4]
   917  	// 12. "Int4" (int (int)) | evendeep.A4 (struct) (1) [1]
   918  	// 13. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   919  	// 14. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   920  	// 15. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   921  }
   922  
   923  func teststructiteratorNextA4(t *testing.T) {
   924  	var sb strings.Builder
   925  	const byName = false
   926  	a4 := prepareDataA4()
   927  	v1 := reflect.ValueOf(&a4)
   928  	t1, _ := tool.Rdecode(v1)
   929  	it := newStructIterator(t1, withStructPtrAutoExpand(true))
   930  	for i := 0; ; i++ {
   931  		accessor, ok := it.Next(nil, byName)
   932  		if !ok {
   933  			break
   934  		}
   935  		field := accessor.StructField()
   936  		_, _ = fmt.Fprintf(&sb, "%d. %q (%v) | %v %v\n", i, field.Name, tool.Typfmt(field.Type), tool.Typfmt(accessor.Type()), field.Index)
   937  	}
   938  
   939  	t.Logf(sb.String())
   940  	if sb.String() != `0. "Name2" (string (string)) | evendeep.A2 (struct) [0]
   941  1. "Int2" (int (int)) | evendeep.A2 (struct) [1]
   942  2. "Bool2" (bool (bool)) | evendeep.A2 (struct) [2]
   943  3. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   944  4. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   945  5. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   946  6. "Name3" (string (string)) | evendeep.A3 (struct) [1]
   947  7. "Int3" (int (int)) | evendeep.A3 (struct) [2]
   948  8. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   949  9. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   950  10. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   951  11. "Bool3" (bool (bool)) | evendeep.A3 (struct) [4]
   952  12. "Int4" (int (int)) | evendeep.A4 (struct) [1]
   953  13. "Name1" (string (string)) | evendeep.A1 (struct) [0]
   954  14. "Int1" (int (int)) | evendeep.A1 (struct) [1]
   955  15. "Bool1" (bool (bool)) | evendeep.A1 (struct) [2]
   956  ` {
   957  		t.Fail()
   958  	} else {
   959  		t.Log("The loops and outputs verified")
   960  	}
   961  
   962  	// Output:
   963  	// 0. "Name2" (string (string)) | evendeep.A2 (struct) (0) [0]
   964  	// 1. "Int2" (int (int)) | evendeep.A2 (struct) (1) [1]
   965  	// 2. "Bool2" (bool (bool)) | evendeep.A2 (struct) (2) [2]
   966  	// 3. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   967  	// 4. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   968  	// 5. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   969  	// 6. "Name3" (string (string)) | evendeep.A3 (struct) (1) [1]
   970  	// 7. "Int3" (int (int)) | evendeep.A3 (struct) (2) [2]
   971  	// 8. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   972  	// 9. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   973  	// 10. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   974  	// 11. "Bool3" (bool (bool)) | evendeep.A3 (struct) (4) [4]
   975  	// 12. "Int4" (int (int)) | evendeep.A4 (struct) (1) [1]
   976  	// 13. "Name1" (string (string)) | evendeep.A1 (struct) (0) [0]
   977  	// 14. "Int1" (int (int)) | evendeep.A1 (struct) (1) [1]
   978  	// 15. "Bool1" (bool (bool)) | evendeep.A1 (struct) (2) [2]
   979  }
   980  
   981  func TestFieldsTable_getallfields(t *testing.T) {
   982  	t.Run("test_getallfields X1 deep", testFieldsTableGetFieldsDeeply)
   983  	t.Run("test_getallfields", testFieldsTableGetAllFields)
   984  	t.Run("test_getallfields_Employee2", testFieldsTableGetAllFieldsEmployee2)
   985  	t.Run("test_getallfields_Employee2_2", testFieldsTableGetAllFieldsEmployee22)
   986  	t.Run("test_getallfields_User", testFieldsTableGetAllFieldsUser)
   987  }
   988  
   989  func testFieldsTableGetFieldsDeeply(t *testing.T) {
   990  
   991  	x2 := new(X1)
   992  	t2 := tool.Rdecodesimple(reflect.ValueOf(&x2))
   993  
   994  	var sourcefields fieldsTableT
   995  	sourcefields.getAllFields(t2, true)
   996  
   997  	var sb strings.Builder
   998  	defer func() { t.Log(sb.String()) }()
   999  
  1000  	for i, f := range sourcefields.tableRecordsT {
  1001  		_, _ = fmt.Fprintf(&sb, "%v. %v, %v | %v, %q, %q\n", i,
  1002  			f.FieldName(), f.indexes,
  1003  			tool.Typfmt(f.structField.Type), f.structField.Tag, f.structField.PkgPath,
  1004  		)
  1005  	}
  1006  
  1007  }
  1008  
  1009  func testFieldsTableGetAllFields(t *testing.T) {
  1010  	a4 := prepareDataA4()
  1011  	v4 := reflect.ValueOf(&a4)
  1012  
  1013  	var sourcefields fieldsTableT
  1014  	sourcefields.getAllFields(v4, true)
  1015  
  1016  	var sb strings.Builder
  1017  	defer func() { t.Log(sb.String()) }()
  1018  
  1019  	for i, f := range sourcefields.tableRecordsT {
  1020  		_, _ = fmt.Fprintf(&sb, "%v. %v, %v | %v, %q, %q\n", i,
  1021  			f.FieldName(), f.indexes,
  1022  			tool.Typfmt(f.structField.Type), f.structField.Tag, f.structField.PkgPath,
  1023  		)
  1024  	}
  1025  
  1026  	if sb.String() != `0. A2.Name2, [0 0] | string (string), "", ""
  1027  1. A2.Int2, [1 0] | int (int), "", ""
  1028  2. A2.Bool2, [2 0] | bool (bool), "", ""
  1029  3. A1.Name1, [0 3] | string (string), "", ""
  1030  4. A1.Int1, [1 3] | int (int), "", ""
  1031  5. A1.Bool1, [2 3] | bool (bool), "", ""
  1032  6. A3.Name3, [1 0] | string (string), "", ""
  1033  7. A3.Int3, [2 0] | int (int), "", ""
  1034  8. A1.Name1, [0 3] | string (string), "", ""
  1035  9. A1.Int1, [1 3] | int (int), "", ""
  1036  10. A1.Bool1, [2 3] | bool (bool), "", ""
  1037  11. A3.Bool3, [4 0] | bool (bool), "", ""
  1038  12. Int4, [1] | int (int), "", ""
  1039  13. A1.Name1, [0 2] | string (string), "", ""
  1040  14. A1.Int1, [1 2] | int (int), "", ""
  1041  15. A1.Bool1, [2 2] | bool (bool), "", ""
  1042  ` {
  1043  		t.Fail()
  1044  	} else {
  1045  		t.Log("The loops and outputs verified")
  1046  	}
  1047  
  1048  	// Output:
  1049  	// 0. [Name2 A2], [0 0] | &{Name2  string  0 [0] false}
  1050  	// 1. [Int2 A2], [1 0] | &{Int2  int  16 [1] false}
  1051  	// 2. [Bool2 A2], [2 0] | &{Bool2  bool  24 [2] false}
  1052  	// 3. [Name1 A1], [0 3] | &{Name1  string  0 [0] false}
  1053  	// 4. [Int1 A1], [1 3] | &{Int1  int  16 [1] false}
  1054  	// 5. [Bool1 A1], [2 3] | &{Bool1  bool  24 [2] false}
  1055  	// 6. [Name3 A3], [1 0] | &{Name3  string  8 [1] false}
  1056  	// 7. [Int3 A3], [2 0] | &{Int3  int  24 [2] false}
  1057  	// 8. [Name1 A1], [0 3] | &{Name1  string  0 [0] false}
  1058  	// 9. [Int1 A1], [1 3] | &{Int1  int  16 [1] false}
  1059  	// 10. [Bool1 A1], [2 3] | &{Bool1  bool  24 [2] false}
  1060  	// 11. [Bool3 A3], [4 0] | &{Bool3  bool  64 [4] false}
  1061  	// 12. [Int4], [1] | &{Int4  int  8 [1] false}
  1062  	// 13. [Name1 A1], [0 2] | &{Name1  string  0 [0] false}
  1063  	// 14. [Int1 A1], [1 2] | &{Int1  int  16 [1] false}
  1064  	// 15. [Bool1 A1], [2 2] | &{Bool1  bool  24 [2] false}
  1065  }
  1066  
  1067  func testFieldsTableGetAllFieldsEmployee2(t *testing.T) {
  1068  
  1069  	// timeZone, _ := time.LoadLocation("America/Phoenix")
  1070  	// timeZone2, _ := time.LoadLocation("Asia/Chongqing")
  1071  	// tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
  1072  	// tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
  1073  	// tm1 := time.Date(2021, 2, 28, 13, 1, 23, 800, timeZone2)
  1074  	// tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)
  1075  
  1076  	// var sb strings.Builder
  1077  	// defer func() {
  1078  	// 	t.Logf("\n%v\n", sb.String())
  1079  	// }()
  1080  
  1081  	for _, a4 := range []*Employee2{
  1082  		new(Employee2),
  1083  		// {
  1084  		//	Base: Base{
  1085  		//		Name:      "Bob",
  1086  		//		Birthday:  &tm,
  1087  		//		Age:       24,
  1088  		//		EmployeID: 7,
  1089  		//	},
  1090  		//	Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
  1091  		//	Image:  []byte{95, 27, 43, 66, 0, 21, 210},
  1092  		//	Attr:   &Attr{Attrs: []string{"hello", "world"}},
  1093  		//	Valid:  true,
  1094  		// },
  1095  	} {
  1096  		// sb.WriteString("\n")
  1097  
  1098  		v4 := reflect.ValueOf(&a4) // nolint:gosec // G601: Implicit memory aliasing in for loop
  1099  
  1100  		var sourcefields fieldsTableT
  1101  		sourcefields.getAllFields(v4, true)
  1102  
  1103  		var sb1 strings.Builder
  1104  		// defer func() { t.Log(sb.String()) }()
  1105  
  1106  		for i, f := range sourcefields.tableRecordsT {
  1107  			_, _ = fmt.Fprintf(&sb1, "%v. %v, %v | %v, %q, %q\n", i,
  1108  				f.FieldName(), f.indexes,
  1109  				tool.Typfmt(f.structField.Type), f.structField.Tag, f.structField.PkgPath,
  1110  			)
  1111  		}
  1112  
  1113  		if sb1.String() != `0. Base.Name, [0 0] | string (string), "", ""
  1114  1. Base.Birthday, [1 0] | *time.Time (ptr), "", ""
  1115  2. Base.Age, [2 0] | int (int), "", ""
  1116  3. Base.EmployeID, [3 0] | int64 (int64), "", ""
  1117  4. Avatar, [1] | string (string), "", ""
  1118  5. Image, [2] | []uint8 (slice), "", ""
  1119  6. Attr.Attrs, [0 3] | []string (slice), "copy:\",slicemerge\"", ""
  1120  7. Valid, [4] | bool (bool), "", ""
  1121  8. Deleted, [5] | bool (bool), "", ""
  1122  ` {
  1123  			t.Fail()
  1124  		} else {
  1125  			t.Log("The loops and outputs verified")
  1126  		}
  1127  
  1128  	}
  1129  }
  1130  
  1131  func testFieldsTableGetAllFieldsEmployee22(t *testing.T) {
  1132  
  1133  	timeZone, _ := time.LoadLocation("America/Phoenix")
  1134  	// timeZone2, _ := time.LoadLocation("Asia/Chongqing")
  1135  	tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
  1136  	// tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
  1137  	// tm1 := time.Date(2021, 2, 28, 13, 1, 23, 800, timeZone2)
  1138  	// tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)
  1139  
  1140  	var sb strings.Builder
  1141  	defer func() { t.Logf("\n%v\n", sb.String()) }()
  1142  
  1143  	for _, a4 := range []*Employee2{
  1144  		// new(Employee2),
  1145  		{
  1146  			Base: Base{
  1147  				Name:      "Bob",
  1148  				Birthday:  &tm,
  1149  				Age:       24,
  1150  				EmployeID: 7,
  1151  			},
  1152  			Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
  1153  			Image:  []byte{95, 27, 43, 66, 0, 21, 210},
  1154  			Attr:   &Attr{Attrs: []string{"hello", "world"}},
  1155  			Valid:  true,
  1156  		},
  1157  	} {
  1158  		sb.WriteString("\n")
  1159  
  1160  		v4 := reflect.ValueOf(&a4) // nolint:gosec // G601: Implicit memory aliasing in for loop
  1161  
  1162  		var sourcefields fieldsTableT
  1163  		sourcefields.getAllFields(v4, true)
  1164  
  1165  		for i, f := range sourcefields.tableRecordsT {
  1166  			_, _ = fmt.Fprintf(&sb, "%v. %v, %v | %v, %q, %q\n", i,
  1167  				f.FieldName(), f.indexes,
  1168  				tool.Typfmt(f.structField.Type), f.structField.Tag, f.structField.PkgPath,
  1169  			)
  1170  		}
  1171  
  1172  		if sb.String() != `
  1173  0. Base.Name, [0 0] | string (string), "", ""
  1174  1. Base.Birthday, [1 0] | *time.Time (ptr), "", ""
  1175  2. Base.Age, [2 0] | int (int), "", ""
  1176  3. Base.EmployeID, [3 0] | int64 (int64), "", ""
  1177  4. Avatar, [1] | string (string), "", ""
  1178  5. Image, [2] | []uint8 (slice), "", ""
  1179  6. Attr.Attrs, [0 3] | []string (slice), "copy:\",slicemerge\"", ""
  1180  7. Valid, [4] | bool (bool), "", ""
  1181  8. Deleted, [5] | bool (bool), "", ""
  1182  ` {
  1183  			t.Fail()
  1184  		} else {
  1185  			t.Log("The loops and outputs verified")
  1186  		}
  1187  	}
  1188  }
  1189  
  1190  func testFieldsTableGetAllFieldsUser(t *testing.T) {
  1191  
  1192  	timeZone, _ := time.LoadLocation("America/Phoenix")
  1193  	timeZone2, _ := time.LoadLocation("Asia/Chongqing")
  1194  	// tm := time.Date(1999, 3, 13, 5, 57, 11, 1901, timeZone)
  1195  	// tm1 := time.Date(2021, 2, 28, 13, 1, 23, 800, timeZone2)
  1196  	tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
  1197  	tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)
  1198  
  1199  	var sb strings.Builder
  1200  	defer func() {
  1201  		t.Logf("\n%v\n", sb.String())
  1202  	}()
  1203  
  1204  	for _, a4 := range []*User{
  1205  		new(User),
  1206  		{
  1207  			Name:      "Frank",
  1208  			Birthday:  &tm2,
  1209  			Age:       18,
  1210  			EmployeID: 9,
  1211  			Attr:      &Attr{Attrs: []string{"baby"}},
  1212  		},
  1213  		{
  1214  			Name:      "Mathews",
  1215  			Birthday:  &tm3,
  1216  			Age:       3,
  1217  			EmployeID: 92,
  1218  			Attr:      &Attr{Attrs: []string{"get"}},
  1219  			Deleted:   false,
  1220  		},
  1221  	} {
  1222  		// sb.WriteString("\n")
  1223  
  1224  		v4 := reflect.ValueOf(&a4) // nolint:gosec // G601: Implicit memory aliasing in for loop
  1225  
  1226  		var sourcefields fieldsTableT
  1227  		sourcefields.getAllFields(v4, true)
  1228  
  1229  		for i, f := range sourcefields.tableRecordsT {
  1230  			_, _ = fmt.Fprintf(&sb, "%v. %v, %v | %v, %q, %q\n", i,
  1231  				f.FieldName(), f.indexes,
  1232  				tool.Typfmt(f.structField.Type), f.structField.Tag, f.structField.PkgPath,
  1233  			)
  1234  		}
  1235  
  1236  		t.Logf("%v\n\n", sb.String())
  1237  		if sb.String() != `0. Name, [0] | string (string), "", ""
  1238  1. Birthday, [1] | *time.Time (ptr), "", ""
  1239  2. Age, [2] | int (int), "", ""
  1240  3. EmployeID, [3] | int64 (int64), "", ""
  1241  4. Avatar, [4] | string (string), "", ""
  1242  5. Image, [5] | []uint8 (slice), "", ""
  1243  6. Attr.Attrs, [0 6] | []string (slice), "copy:\",slicemerge\"", ""
  1244  7. Valid, [7] | bool (bool), "", ""
  1245  8. Deleted, [8] | bool (bool), "", ""
  1246  ` {
  1247  			t.Fail()
  1248  		} else {
  1249  			t.Log("The loops and outputs verified")
  1250  		}
  1251  
  1252  		sb.Reset()
  1253  	}
  1254  }
  1255  
  1256  func prepareDataA4() *A4 {
  1257  	a4 := &A4{
  1258  		A3: &A3{
  1259  			A2: &A2{
  1260  				Name2: "",
  1261  				Int2:  0,
  1262  				Bool2: false,
  1263  				A1: A1{
  1264  					Name1: "",
  1265  					Int1:  0,
  1266  					Bool1: false,
  1267  				},
  1268  			},
  1269  			Name3: "",
  1270  			Int3:  0,
  1271  			A1: A1{
  1272  				Name1: "",
  1273  				Int1:  0,
  1274  				Bool1: false,
  1275  			},
  1276  			Bool3: false,
  1277  		},
  1278  		Int4: 0,
  1279  		A1: &A1{
  1280  			Name1: "",
  1281  			Int1:  0,
  1282  			Bool1: false,
  1283  		},
  1284  	}
  1285  	return a4
  1286  }
  1287  
  1288  type A1 struct {
  1289  	Name1 string
  1290  	Int1  int
  1291  	Bool1 bool
  1292  }
  1293  type A2 struct {
  1294  	Name2 string
  1295  	Int2  int
  1296  	Bool2 bool
  1297  	A1
  1298  }
  1299  type A3 struct {
  1300  	*A2
  1301  	Name3 string
  1302  	Int3  int
  1303  	A1
  1304  	Bool3 bool
  1305  }
  1306  type A4 struct {
  1307  	A3   *A3
  1308  	Int4 int
  1309  	*A1
  1310  }