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 }