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

     1  package evendeep
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"gopkg.in/hedzr/errors.v3"
     9  
    10  	"github.com/hedzr/evendeep/flags"
    11  	"github.com/hedzr/evendeep/flags/cms"
    12  	"github.com/hedzr/evendeep/internal/tool"
    13  )
    14  
    15  func TestRegisterInitRoutines(t *testing.T) {
    16  	registerInitRoutines(nil)
    17  	registerInitRoutines(func() {})
    18  	registerLazyInitRoutines(nil)
    19  	registerLazyInitRoutines(func() {})
    20  }
    21  
    22  // TestCpChan _
    23  func TestCpChan(t *testing.T) {
    24  	var val = make(chan int, 10)
    25  	vv := reflect.ValueOf(&val)
    26  	vi := reflect.Indirect(vv)
    27  	value := reflect.MakeChan(vi.Type(), vi.Cap())
    28  	t.Logf("%v (len: %v),  vv.len: %v", value.Interface(), value.Cap(), vi.Cap())
    29  
    30  	var sval chan string
    31  	var strVal = reflect.ValueOf(&sval)
    32  	indirectStr := reflect.Indirect(strVal)
    33  	svalue := reflect.MakeChan(indirectStr.Type(), 1024)
    34  	t.Logf("Type : [%v] \nCapacity : [%v]", svalue.Kind(), svalue.Cap())
    35  
    36  }
    37  
    38  // func TestVisibleFields(t *testing.T) {
    39  //	var obj = new(Employee2)
    40  //	typ := reflect.TypeOf(obj)
    41  //	for _, sf := range reflect.VisibleFields(typ.Elem()) {
    42  //		fmt.Println(sf)
    43  //	}
    44  // }
    45  
    46  func TestInspectStruct(t *testing.T) {
    47  	a4 := prepareDataA4()
    48  	tool.InspectStruct(reflect.ValueOf(&a4))
    49  }
    50  
    51  func TestParamsBasics(t *testing.T) {
    52  
    53  	t.Run("basics 1", func(t *testing.T) {
    54  		// p1 := newParams() // nolint:ineffassign
    55  		p1 := newParams(withOwnersSimple(nil, nil))
    56  
    57  		p2 := newParams(withOwners(p1.controller, p1, nil, nil, nil, nil))
    58  		t.Logf("p2: %v", p2)
    59  		t.Logf("p1: %v", p1)
    60  		p2.revoke()
    61  		t.Logf("p2: %v", p2)
    62  		t.Logf("p1: %v", p1)
    63  	})
    64  
    65  	t.Run("basics 2", func(t *testing.T) {
    66  		// p1 := newParams() // nolint:ineffassign
    67  		p1 := newParams(withOwnersSimple(nil, nil))
    68  
    69  		p2 := newParams(withOwners(p1.controller, p1, nil, nil, nil, nil))
    70  		defer p2.revoke()
    71  
    72  		a, expects := prepareAFT()
    73  
    74  		v := reflect.ValueOf(&a)
    75  		v = tool.Rindirect(v)
    76  
    77  		for i := 0; i < v.NumField(); i++ {
    78  			fld := v.Type().Field(i)
    79  			fldTags := parseFieldTags(fld.Tag, "")
    80  			if !p2.isFlagExists(cms.Ignore) {
    81  				t.Logf("%q flags: %v [without ignore]", fld.Tag, fldTags)
    82  			} else {
    83  				t.Logf("%q flags: %v [ignore]", fld.Tag, fldTags)
    84  			}
    85  			testDeepEqual(t.Errorf, fldTags.flags, expects[i])
    86  		}
    87  
    88  	})
    89  }
    90  
    91  func TestParamsBasics3(t *testing.T) {
    92  
    93  	t.Run("basics 3", func(t *testing.T) {
    94  		// p1 := newParams() // nolint:ineffassign
    95  		p1 := newParams(withOwnersSimple(nil, nil))
    96  
    97  		p2 := newParams(withOwners(p1.controller, p1, nil, nil, nil, nil))
    98  		defer p2.revoke()
    99  
   100  		type AFS1 struct {
   101  			flags     flags.Flags     `copy:",cleareq,must"`                                   //nolint:unused,structcheck //test
   102  			converter *ValueConverter `copy:",ignore"`                                         //nolint:unused,structcheck //test
   103  			wouldbe   int             `copy:",must,keepneq,omitzero,slicecopyappend,mapmerge"` //nolint:unused,structcheck //test
   104  		}
   105  		var a AFS1
   106  		v := reflect.ValueOf(&a)
   107  		v = tool.Rindirect(v)
   108  		sf, _ := v.Type().FieldByName("wouldbe")
   109  		// sf0, _ := v.Type().FieldByName("flags")
   110  		// sf1, _ := v.Type().FieldByName("converter")
   111  
   112  		fldTags := parseFieldTags(sf.Tag, "")
   113  		// ft.Parse(sf.Tag)
   114  		// ft.Parse(sf0.Tag) // entering 'continue' branch
   115  		// ft.Parse(sf1.Tag) // entering 'delete' branch
   116  
   117  		var z *fieldTags // nolint:gosimple
   118  		z = fldTags
   119  
   120  		z.isFlagExists(cms.Flat)
   121  
   122  		z.isFlagExists(cms.Ignore)
   123  
   124  		z.isFlagExists(cms.SliceCopy)
   125  		p2.isFlagExists(cms.SliceCopy)
   126  		p2.isFlagExists(cms.SliceCopyAppend)
   127  		p2.isFlagExists(cms.SliceMerge)
   128  
   129  		p2.isAnyFlagsOK(cms.SliceMerge, cms.Ignore)
   130  		p2.isAllFlagsOK(cms.SliceCopy, cms.Default)
   131  
   132  		p2.isGroupedFlagOK(cms.SliceCopy)
   133  		p2.isGroupedFlagOK(cms.SliceCopyAppend)
   134  		p2.isGroupedFlagOK(cms.SliceMerge)
   135  
   136  		p2.isGroupedFlagOKDeeply(cms.SliceCopy)
   137  		p2.isGroupedFlagOKDeeply(cms.SliceCopyAppend)
   138  		p2.isGroupedFlagOKDeeply(cms.SliceMerge)
   139  
   140  		if p2.depth() != 2 {
   141  			t.Fail()
   142  		}
   143  
   144  		var p3 *Params
   145  		p3.isFlagExists(cms.SliceCopy)
   146  		p3.isGroupedFlagOK(cms.SliceCopy)
   147  		p3.isGroupedFlagOK(cms.SliceCopyAppend)
   148  		p3.isGroupedFlagOK(cms.SliceMerge)
   149  
   150  		p3.isGroupedFlagOKDeeply(cms.SliceCopy)
   151  		p3.isGroupedFlagOKDeeply(cms.SliceCopyAppend)
   152  		p3.isGroupedFlagOKDeeply(cms.SliceMerge)
   153  
   154  		p3.isAnyFlagsOK(cms.SliceMerge, cms.Ignore)
   155  		p3.isAllFlagsOK(cms.SliceCopy, cms.Default)
   156  
   157  		var p4 Params
   158  		p4.isFlagExists(cms.SliceCopy)
   159  		p4.isGroupedFlagOK(cms.SliceCopy)
   160  		p4.isGroupedFlagOK(cms.SliceCopyAppend)
   161  		p4.isGroupedFlagOK(cms.SliceMerge)
   162  	})
   163  }
   164  
   165  func TestPtrCopy(t *testing.T) {
   166  	type AAA struct {
   167  		P1 *int `copy:",flat"`
   168  	}
   169  	var a, b = 1, 2
   170  	var pa, pb = &AAA{&a}, &AAA{&b}
   171  	Copy(pa, pb)
   172  	t.Logf("pb.P1: %v", *pb.P1)
   173  	if *pb.P1 != a {
   174  		t.Fail()
   175  	}
   176  }
   177  
   178  func TestDeferCatchers(t *testing.T) {
   179  	type AAA struct {
   180  		X1 string `copy:"-"`
   181  		X2 string `copy:",-"`
   182  		X3 bool
   183  		Y  int
   184  		Y1 int
   185  	}
   186  	type BBB struct {
   187  		X1 string // backup field to receive the copying field `X3` from source `AAA`
   188  		X2 string // backup field to receive the copying field `Y` from source `AAA`
   189  		X3 string `copy:"-"` // backup field to receive the copying field `Y1` from source `AAA`
   190  		Y  string
   191  		Y1 int
   192  	} // the 'ignore' Tag inside target field cannot block copying on itself
   193  
   194  	postCatcher := func(runner func()) {
   195  		defer func() {
   196  			if e1 := recover(); e1 != nil {
   197  				t.Logf(`caught by postCatcher, e: %v`, e1)
   198  			}
   199  		}()
   200  		runner()
   201  	}
   202  
   203  	// func TestFieldAccessorT_Normal_Copy(t *testing.T) {
   204  	// 	x1 := x1data()
   205  	// 	x2 := x2data()
   206  	// }
   207  
   208  	t.Run("dbgFrontOfStruct", func(t *testing.T) {
   209  		src1 := &AAA{X1: "ok", X2: "well", Y: 1}
   210  		tgt1 := &BBB{X1: "no", X2: "longer", Y: "-1"}
   211  
   212  		src, dst := reflect.ValueOf(&src1), reflect.ValueOf(&tgt1)
   213  		svv, dvv := tool.Rdecodesimple(src), tool.Rdecodesimple(dst)
   214  		sf1, df1 := svv.Field(1), dvv.Field(1)
   215  
   216  		c := newCopier()
   217  
   218  		// p1 := newParams()
   219  		p1 := newParams(
   220  			withOwnersSimple(c, nil),
   221  			withFlags(cms.ByName),
   222  		)
   223  
   224  		p2 := newParams(withOwners(p1.controller, p1, &sf1, &df1, nil, nil))
   225  		defer p2.revoke()
   226  
   227  		// buildtags.VerboseEnabled = true
   228  		dbgFrontOfStruct(nil, "    ", t.Logf) // just for coverage
   229  		dbgFrontOfStruct(p2, "    ", nil)     // just for coverage
   230  		dbgFrontOfStruct(p2, "    ", t.Logf)
   231  	})
   232  
   233  	slicePanic := func() {
   234  		n := []int{5, 7, 4}
   235  		fmt.Println(n[4])
   236  		fmt.Println("normally returned from a")
   237  	}
   238  
   239  	t.Run("defer in copyStructInternal", func(t *testing.T) {
   240  		src1 := &AAA{X1: "ok", X2: "well", Y: 1}
   241  		tgt1 := &BBB{X1: "no", X2: "longer", Y: "-1"}
   242  
   243  		src, dst := reflect.ValueOf(&src1), reflect.ValueOf(&tgt1)
   244  		svv, dvv := tool.Rdecodesimple(src), tool.Rdecodesimple(dst)
   245  		// sf1, df1 := svv.Field(1), dvv.Field(1)
   246  
   247  		c := newCopier()
   248  		for _, rethrow := range []bool{false, true} {
   249  			c.rethrow = rethrow
   250  
   251  			// p1 := newParams()
   252  			// p1 = newParams(withOwnersSimple(c, nil))
   253  			//
   254  			// p2 := newParams(withOwners(p1.controller, p1, &sf1, &df1, nil, nil))
   255  			// defer p2.revoke()
   256  			//
   257  			// ec := errors.New("error container")
   258  			postCatcher(func() {
   259  				err := copyStructInternal(c, nil, svv, dvv,
   260  					func(paramsChild *Params, ec errors.Error, i, amount *int, padding string) (err error) {
   261  						paramsChild.nextTargetField()
   262  						slicePanic()
   263  						return
   264  					})
   265  				t.Log(err)
   266  			})
   267  		}
   268  	})
   269  
   270  	t.Run("defer rethrew in copyTo", func(t *testing.T) {
   271  		c := newCopier()
   272  		for _, rethrow := range []bool{false, true} {
   273  			c.rethrow = rethrow
   274  
   275  			src1 := &AAA{X1: "ok", X2: "well", Y: 1}
   276  			tgt1 := &BBB{X1: "no", X2: "longer", Y: "-1"}
   277  
   278  			src, dst := reflect.ValueOf(&src1), reflect.ValueOf(&tgt1)
   279  			svv, dvv := tool.Rdecodesimple(src), tool.Rdecodesimple(dst)
   280  			// sf1, df1 := svv.Field(1), dvv.Field(1)
   281  			postCatcher(func() {
   282  				_ = c.copyToInternal(nil, svv, dvv, func(c *cpController, params *Params, from, to reflect.Value) (err error) {
   283  					slicePanic()
   284  					return
   285  				})
   286  			})
   287  		}
   288  	})
   289  
   290  	t.Run("invalid src or dst", func(t *testing.T) {
   291  		c := newCopier()
   292  		c.rethrow = false
   293  
   294  		var src1 AAA
   295  		tgt1 := &BBB{X1: "no", X2: "longer", Y: "-1"}
   296  
   297  		src, dst := reflect.ValueOf(&src1), reflect.ValueOf(&tgt1)
   298  		svv, dvv := tool.Rdecodesimple(src), tool.Rdecodesimple(dst)
   299  		// sf1, df1 := svv.Field(1), dvv.Field(1)
   300  
   301  		t.Logf("src: %v, %v", src.IsValid(), svv.IsValid())
   302  		t.Logf("dst: %v, %v", dst.IsValid(), dvv.IsValid())
   303  
   304  		// src is invalid
   305  		var svv1 reflect.Value
   306  		t.Logf("svv1: %v", svv1.IsValid())
   307  		_ = c.copyToInternal(nil, svv1, dvv, func(c *cpController, params *Params, from, to reflect.Value) (err error) {
   308  			slicePanic()
   309  			return
   310  		})
   311  
   312  		// src is invalid with params has OmitIfEmpty flag
   313  		params := newParams(withFlags(cms.OmitIfEmpty, cms.ByName))
   314  		_ = c.copyToInternal(params, svv1, dvv, func(c *cpController, params *Params, from, to reflect.Value) (err error) {
   315  			slicePanic()
   316  			return
   317  		})
   318  
   319  		// dst is invalid
   320  		var dvv1 reflect.Value
   321  		t.Logf("dvv1: %v", dvv1.IsValid())
   322  		_ = c.copyToInternal(nil, svv, dvv1, func(c *cpController, params *Params, from, to reflect.Value) (err error) {
   323  			slicePanic()
   324  			return
   325  		})
   326  
   327  		// both src and dst are valid and params is also valid
   328  		_ = c.copyToInternal(params, svv, dvv, func(c *cpController, params *Params, from, to reflect.Value) (err error) {
   329  			return
   330  		})
   331  	})
   332  
   333  	t.Run("copy src to dst with params", func(t *testing.T) {
   334  		lazyInitRoutines()
   335  
   336  		c := newCopier()
   337  		c.rethrow = false
   338  
   339  		src1 := &AAA{X1: "ok", X2: "well", X3: true, Y: 7, Y1: 13}
   340  		tgt1 := &BBB{X1: "no", X2: "longer", Y: "-1"}
   341  
   342  		src, dst := reflect.ValueOf(&src1), reflect.ValueOf(&tgt1)
   343  		svv, dvv := tool.Rindirect(src), tool.Rindirect(dst)
   344  		// sf1, df1 := svv.Field(1), dvv.Field(1)
   345  
   346  		root := newParams(withOwners(c, nil, &svv, &dvv, &src, &dst))
   347  		if err := c.copyTo(root, svv, dvv); err != nil {
   348  			t.Fatalf("error: %v", err)
   349  		}
   350  		t.Logf("target BBB is: %+v", tgt1)
   351  	})
   352  }