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

     1  package evendeep_test
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  	"unsafe"
     9  
    10  	"github.com/hedzr/evendeep"
    11  	"github.com/hedzr/evendeep/flags"
    12  	"github.com/hedzr/evendeep/flags/cms"
    13  	"github.com/hedzr/evendeep/typ"
    14  )
    15  
    16  type FF interface {
    17  	Flags() flags.Flags
    18  }
    19  
    20  func TestFlagsRevert(t *testing.T) {
    21  	var saved = evendeep.DefaultCopyController.Flags().Clone()
    22  	evendeep.DefaultCopyController.Flags().WithFlags(cms.SliceCopyAppend)
    23  	evendeep.DefaultCopyController.SetFlags(saved)
    24  
    25  	if c, ok := evendeep.New().(FF); ok {
    26  		nf := c.Flags()
    27  		b := reflect.DeepEqual(evendeep.DefaultCopyController.Flags(), nf)
    28  		evendeep.HelperAssertYes(t, b, nf, evendeep.DefaultCopyController.Flags())
    29  	}
    30  }
    31  
    32  func TestWithXXX(t *testing.T) {
    33  
    34  	copier := evendeep.NewForTest()
    35  
    36  	type AA struct {
    37  		TestString string
    38  		X          string
    39  	}
    40  	type BB struct {
    41  		X string
    42  	}
    43  
    44  	t.Run("string to duration", func(t *testing.T) {
    45  
    46  		var dur time.Duration
    47  		var src = "9h71ms"
    48  		// var svv = reflect.ValueOf(src)
    49  		// var tvv = reflect.ValueOf(&dur) // .Elem()
    50  
    51  		err := copier.CopyTo(src, &dur)
    52  		if err != nil {
    53  			t.Fatalf("err: %v", err)
    54  		}
    55  		t.Logf("res: %v", dur)
    56  
    57  	})
    58  
    59  	t.Run("ignore names test", func(t *testing.T) {
    60  
    61  		src1 := &AA{TestString: "well", X: "ok"}
    62  		tgt1 := &BB{X: "no"}
    63  		err := copier.CopyTo(src1, &tgt1)
    64  		t.Logf("res bb: %+v", tgt1)
    65  		if err != nil {
    66  			t.Fatalf("err: %v", err)
    67  		}
    68  		if tgt1.X != src1.X {
    69  			t.Fatalf("err: after 'TestString' field was ignored, AA.X should be copied as BB.X")
    70  		}
    71  
    72  	})
    73  
    74  	t.Run("non-ignore names test", func(t *testing.T) {
    75  
    76  		copier = evendeep.New()
    77  
    78  		src1 := &AA{TestString: "well", X: "ok"}
    79  		tgt1 := &BB{X: "no"}
    80  		err := copier.CopyTo(src1, &tgt1)
    81  		if err != nil {
    82  			t.Fatalf("err: %v", err)
    83  		}
    84  		if tgt1.X != src1.TestString {
    85  			t.Fatalf("err: if 'TestString' field was not ignored, AA.TestString should be copied as BB.X")
    86  		}
    87  		t.Logf("res bb: %+v", tgt1)
    88  
    89  	})
    90  
    91  	t.Run("ignore field test", func(t *testing.T) {
    92  		copier = evendeep.New()
    93  
    94  		type AAA struct {
    95  			X1 string `copy:"-"`
    96  			X2 string `copy:",-"`
    97  			Y  int
    98  		}
    99  		type BBB struct {
   100  			X1 string
   101  			X2 string
   102  			Y  int
   103  		}
   104  		src1 := &AAA{X1: "ok", X2: "well", Y: 1}
   105  		tgt1 := &BBB{X1: "no", X2: "longer", Y: -1}
   106  		err := copier.CopyTo(src1, &tgt1, evendeep.WithSyncAdvancing(true))
   107  		if err != nil {
   108  			t.Fatalf("err: %v", err)
   109  		}
   110  
   111  		t.Logf("res bb: %+v", tgt1)
   112  
   113  		if tgt1.X1 == src1.X1 || tgt1.X2 == src1.X2 {
   114  			t.Fatalf("err: 'X1','X2' fields should be ignored, the fact is bad")
   115  		}
   116  		if tgt1.Y != src1.Y {
   117  			t.Fatalf("err: 'Y' field should be copied.")
   118  		}
   119  
   120  	})
   121  
   122  	t.Run("ignore field test - no sync advance", func(t *testing.T) {
   123  		copier = evendeep.New()
   124  
   125  		type AAA struct {
   126  			X1 string `copy:"-"`
   127  			X2 string `copy:",-"`
   128  			Y  int
   129  		}
   130  		type BBB struct {
   131  			Y int
   132  		}
   133  		src1 := &AAA{X1: "ok", X2: "well", Y: 1}
   134  		tgt1 := &BBB{Y: -1}
   135  		err := copier.CopyTo(src1, &tgt1)
   136  		if err != nil {
   137  			t.Fatalf("err: %v", err)
   138  		}
   139  
   140  		t.Logf("res bb: %+v", tgt1)
   141  
   142  		if tgt1.Y != src1.Y {
   143  			t.Fatalf("err: 'Y' field should be copied.")
   144  		}
   145  
   146  	})
   147  
   148  	t.Run("earlier valid test", func(t *testing.T) {
   149  
   150  		var from *AA
   151  		var to *BB
   152  		ret := evendeep.DeepCopy(from, &to)
   153  		t.Logf("to = %v, ret = %v", to, ret)
   154  
   155  		ret = evendeep.DeepCopy(nil, &to)
   156  		t.Logf("to = %v, ret = %v", to, ret)
   157  
   158  		ret = evendeep.MakeClone(from)
   159  		t.Logf("ret = %v", ret)
   160  
   161  		ret = evendeep.MakeClone(nil)
   162  		t.Logf("ret = %v", ret)
   163  
   164  	})
   165  
   166  	t.Run("return error test", func(t *testing.T) {
   167  
   168  		type AAA struct {
   169  			X1 string `copy:"-"`
   170  			X2 string `copy:",-"`
   171  			Y  int
   172  		}
   173  		type BBB struct {
   174  			X1 string
   175  			X2 string
   176  			Y  int
   177  		}
   178  		src1 := &AAA{X1: "ok", X2: "well", Y: 1}
   179  		tgt1 := &BBB{X1: "no", X2: "longer", Y: -1}
   180  
   181  		copier = evendeep.NewForTest()
   182  		err := copier.CopyTo(&src1, tgt1)
   183  		if err != nil {
   184  			t.Fatalf("err: %v", err)
   185  		}
   186  
   187  	})
   188  
   189  }
   190  
   191  func TestIgnoreSourceField(t *testing.T) {
   192  	type AA struct {
   193  		A bool `copy:",ignore"`
   194  		B int
   195  	}
   196  	src := &AA{A: false, B: 9}
   197  	dst := &AA{A: true, B: 19}
   198  	err := evendeep.New().CopyTo(src, dst, evendeep.WithSyncAdvancingOpt)
   199  	if err != nil {
   200  		t.Fatalf("err: %v", err)
   201  	}
   202  	t.Logf("got: %v", *dst)
   203  	if !dst.A || dst.B != 9 {
   204  		t.FailNow()
   205  	}
   206  }
   207  
   208  func TestOmitEmptySourceField(t *testing.T) {
   209  	type AA struct {
   210  		A int `copy:",omitempty"`
   211  		B int
   212  	}
   213  	src := &AA{A: 0, B: 9}
   214  	dst := &AA{A: 11, B: 19}
   215  	err := evendeep.New().CopyTo(src, dst, evendeep.WithOmitEmptyOpt)
   216  	if err != nil {
   217  		t.Fatalf("err: %v", err)
   218  	}
   219  	t.Logf("got: %v", *dst)
   220  	if dst.A != 11 || dst.B != 9 {
   221  		t.FailNow()
   222  	}
   223  }
   224  
   225  func TestDeepCopyGenerally(t *testing.T) {
   226  	// defer dbglog.NewCaptureLog(t).Release()
   227  
   228  	nn := []int{2, 9, 77, 111, 23, 29}
   229  	var a [2]string
   230  	a[0] = "Hello"
   231  	a[1] = "World"
   232  
   233  	x0 := evendeep.X0{}
   234  	x1 := evendeep.X1{
   235  		A: uintptr(unsafe.Pointer(&x0)),
   236  		H: make(chan int, 5),
   237  		M: unsafe.Pointer(&x0),
   238  		// E: []*X0{&x0},
   239  		N: nn[1:3],
   240  		O: a,
   241  		Q: a,
   242  	}
   243  
   244  	t.Run("MakeClone()", func(t *testing.T) {
   245  		var ret typ.Any // nolint:gosimple
   246  		// x2 := &X2{N: nn[1:3]}
   247  
   248  		ret = evendeep.MakeClone(&x1)
   249  		x1.K = &x0
   250  		testIfBadCopy(t, x1, ret, ret, "MakeClone x1 -> new")
   251  		t.Log("MakeClone is done.")
   252  	})
   253  
   254  	t.Run("DeepCopy()", func(t *testing.T) {
   255  		var ret typ.Any
   256  		x2 := &evendeep.X2{N: nn[1:3]}
   257  
   258  		ret = evendeep.DeepCopy(&x1, &x2, evendeep.WithIgnoreNames("Shit", "Memo", "Name"))
   259  		testIfBadCopy(t, x1, *x2, ret, "DeepCopy x1 -> x2", true)
   260  	})
   261  
   262  	t.Run("NewDeepCopier().CopyTo()", func(t *testing.T) {
   263  		var ret typ.Any
   264  		x2 := &evendeep.X2{N: nn[1:3]}
   265  
   266  		ret = evendeep.New().CopyTo(&x1, &x2, evendeep.WithIgnoreNames("Shit", "Memo", "Name"))
   267  		testIfBadCopy(t, x1, *x2, ret, "NewDeepCopier().CopyTo() - DeepCopy x1 -> x2", true)
   268  	})
   269  
   270  }
   271  
   272  func TestDeepCopy(t *testing.T) {
   273  	type AA struct {
   274  		A bool
   275  		B int32
   276  		C string
   277  	}
   278  	type BB struct {
   279  		A int
   280  		B int16
   281  		C *string
   282  	}
   283  
   284  	var aa = AA{A: true, B: 16, C: helloString}
   285  	var bb BB
   286  	var ret = evendeep.DeepCopy(aa, &bb,
   287  		evendeep.WithIgnoreNames("Shit", "Memo", "Name"))
   288  	t.Logf("ret = %v", ret)
   289  	// ret = &{0 16 &"hello"}
   290  	if *bb.C != helloString {
   291  		t.FailNow()
   292  	}
   293  }
   294  
   295  func TestMakeClone(t *testing.T) {
   296  	type AA struct {
   297  		A bool
   298  		B int32
   299  		C string
   300  	}
   301  
   302  	var aa = AA{A: true, B: 16, C: helloString}
   303  	var ret = evendeep.MakeClone(aa)
   304  	var aaCopy = ret.(AA)
   305  	t.Logf("ret = %v", aaCopy)
   306  	// ret = {true 16 hello}
   307  }
   308  
   309  func TestNew(t *testing.T) {
   310  	type AA struct {
   311  		A bool
   312  		B int32
   313  		C string
   314  	}
   315  	type BB struct {
   316  		A int
   317  		B int16
   318  		C *string
   319  	}
   320  
   321  	var aa = AA{A: true, B: 16, C: helloString}
   322  	var bb BB
   323  	var ret typ.Any = evendeep.New().CopyTo(aa, &bb,
   324  		evendeep.WithIgnoreNames("Shit", "Memo", "Name"))
   325  	t.Logf("ret = %v", ret)
   326  	// ret = &{0 16 &"hello"}
   327  	if *bb.C != helloString {
   328  		t.FailNow()
   329  	}
   330  }
   331  
   332  func TestWithIgnoreNames(t *testing.T) {
   333  	type AA struct {
   334  		A bool
   335  		B int32
   336  		C string
   337  		D string
   338  	}
   339  	type BB struct {
   340  		A int
   341  		B int16
   342  		C *string
   343  	}
   344  
   345  	var aa = AA{A: true, B: 16, C: helloString, D: worldString}
   346  	var bb BB
   347  	var ret = evendeep.DeepCopy(aa, &bb,
   348  		evendeep.WithIgnoreNames("C*"),
   349  		evendeep.WithSyncAdvancing(false),
   350  		evendeep.WithByOrdinalStrategyOpt,
   351  	)
   352  	t.Logf("ret = %v, .C = %v", ret, *bb.C)
   353  	// ret = &{0 16 &"world"}
   354  	if *bb.C != worldString {
   355  		t.FailNow()
   356  	}
   357  
   358  	var cc BB
   359  	ret = evendeep.DeepCopy(aa, &cc,
   360  		evendeep.WithIgnoreNames("C*"),
   361  		evendeep.WithSyncAdvancing(true),
   362  		evendeep.WithByOrdinalStrategyOpt,
   363  	)
   364  	t.Logf("ret = %v, .C = %v", ret, *cc.C)
   365  	// ret = &{0 16 &""}
   366  	if *cc.C != "" {
   367  		t.FailNow()
   368  	}
   369  }
   370  
   371  func TestPlainCopyFuncField(t *testing.T) {
   372  
   373  	type AA struct {
   374  		Fn func()
   375  	}
   376  
   377  	t.Run("copy func field", func(t *testing.T) {
   378  
   379  		var a = AA{func() {
   380  			println("yes")
   381  		}}
   382  		var b AA
   383  
   384  		err := evendeep.New().CopyTo(&a, &b, evendeep.WithIgnoreNames("Shit", "Memo", "Name"))
   385  		if err != nil {
   386  			t.Fatalf("err: %v", err)
   387  		}
   388  		if b.Fn != nil {
   389  			b.Fn()
   390  		} else {
   391  			t.Fatalf("bad")
   392  		}
   393  
   394  	})
   395  
   396  	type BB struct {
   397  		fn func()
   398  	}
   399  
   400  	t.Run("copy private func field", func(t *testing.T) {
   401  
   402  		var a = BB{func() {
   403  			println("yes")
   404  		}}
   405  		var b BB
   406  
   407  		err := evendeep.New().CopyTo(&a, &b, evendeep.WithIgnoreNames("Shit", "Memo", "Name"))
   408  		if err != nil {
   409  			t.Fatalf("err: %v", err)
   410  		}
   411  		if b.fn != nil {
   412  			b.fn()
   413  		} else {
   414  			t.Fatalf("bad")
   415  		}
   416  
   417  	})
   418  
   419  	type CC struct {
   420  		Jx func(i1, i2 int) (i3 string)
   421  	}
   422  
   423  	t.Run("copy private func field (complex)", func(t *testing.T) {
   424  		var a = CC{func(i1, i2 int) (i3 string) {
   425  			return fmt.Sprintf("%v+%v", i1, i2)
   426  		}}
   427  
   428  		var v = reflect.ValueOf(&a)
   429  		var vf = v.Elem().Field(0)
   430  		var vft = vf.Type()
   431  		t.Logf("out: %v, %v", vft.NumOut(), vft.Out(0))
   432  	})
   433  
   434  }