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

     1  package evendeep
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math"
     7  	"reflect"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  	"unsafe"
    13  
    14  	"github.com/hedzr/evendeep/dbglog"
    15  	"github.com/hedzr/evendeep/flags/cms"
    16  	"github.com/hedzr/evendeep/internal/cl"
    17  	"github.com/hedzr/evendeep/internal/tool"
    18  	"github.com/hedzr/evendeep/typ"
    19  )
    20  
    21  type sample struct {
    22  	a int
    23  	b string
    24  }
    25  
    26  func TestUintptrAndUnsafePointer(t *testing.T) {
    27  	s := &sample{a: 1, b: "test"}
    28  
    29  	// Getting the address of field b in struct s
    30  	p := unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Offsetof(s.b))
    31  
    32  	// Typecasting it to a string pointer and printing the value of it
    33  	fmt.Println(*(*string)(p))
    34  
    35  	u := uintptr(unsafe.Pointer(s))
    36  	us := fmt.Sprintf("%v", u)
    37  	t.Logf("us = 0x%v", us)
    38  	v := reflect.ValueOf(us)
    39  	ret := rToUIntegerHex(v, reflect.TypeOf(uintptr(unsafe.Pointer(s))))
    40  	t.Logf("ret.type: %v, %v / 0x%x", ret.Type(), ret.Interface(), ret.Interface())
    41  
    42  	// t.Logf("ret.type: %v, %v", ret.Type(), ret.Pointer())
    43  }
    44  
    45  func TestGetPointerAsUintptr(t *testing.T) {
    46  	s := &sample{a: 1, b: "test"}
    47  
    48  	v := reflect.ValueOf(s)
    49  	u := getPointerAsUintptr(v)
    50  	fmt.Println(u)
    51  }
    52  
    53  func TestForBool(t *testing.T) {
    54  	var b1, b2 bool
    55  	b2 = true
    56  
    57  	v1, v2 := reflect.ValueOf(b1), reflect.ValueOf(b2)
    58  	if rForBool(v1).Interface() != "false" {
    59  		t.Fail()
    60  	}
    61  
    62  	if rForBool(v2).Interface() != "true" {
    63  		t.Fail()
    64  	}
    65  }
    66  
    67  func TestToBool(t *testing.T) {
    68  
    69  	for _, vi := range []typ.Any{
    70  		false,
    71  		0,
    72  		uint(0),
    73  		math.Float64frombits(0),
    74  		complex(math.Float64frombits(0), math.Float64frombits(0)),
    75  		[0]int{},
    76  		[1]int{0},
    77  		(func())(nil), // nolint:gocritic // cannot remove paran
    78  		struct{}{},
    79  		"f",
    80  		"false",
    81  		"off",
    82  		"no",
    83  		"famale",
    84  	} {
    85  		v1 := reflect.ValueOf(vi)
    86  		v2, _ := tool.Rdecode(v1)
    87  		if rToBool(v2).Interface() != false {
    88  			t.Fatalf("for %v (%v) toBool failed", vi, tool.Typfmtv(&v2))
    89  		}
    90  	}
    91  
    92  	for _, vi := range []typ.Any{
    93  		true,
    94  		-1,
    95  		uint(1),
    96  		math.Float64frombits(1),
    97  		complex(math.Float64frombits(1), math.Float64frombits(0)),
    98  		[1]int{1},
    99  		[1]int{3},
   100  		map[int]int{1: 1},
   101  		struct{ v int }{1},
   102  		"1", "t", "y", "m",
   103  		"true",
   104  		"on",
   105  		"yes",
   106  		"male",
   107  	} {
   108  		v1 := reflect.ValueOf(vi)
   109  		v2, _ := tool.Rdecode(v1)
   110  		if rToBool(v2).Interface() != true {
   111  			t.Fatalf("for %v (%v) toBool failed", vi, tool.Typfmtv(&v2))
   112  		}
   113  	}
   114  
   115  }
   116  
   117  func TestForInteger(t *testing.T) {
   118  	for _, src := range []typ.Any{
   119  		13579,
   120  		uint(13579),
   121  	} {
   122  		v1 := reflect.ValueOf(src)
   123  		v1 = tool.Rdecodesimple(v1)
   124  		if rForInteger(v1).Interface() != "13579" {
   125  			t.Fail()
   126  		}
   127  	}
   128  
   129  	var z typ.Any
   130  	v1 := reflect.ValueOf(z)
   131  	v1 = tool.Rdecodesimple(v1)
   132  	if x := rForInteger(v1).Interface(); x != "0" {
   133  		t.Fatalf("failed, x = %v", x)
   134  	}
   135  
   136  	z = "bug" //nolint:goconst
   137  	v1 = reflect.ValueOf(z)
   138  	v1 = tool.Rdecodesimple(v1)
   139  	if x := rForInteger(v1).Interface(); x != "0" {
   140  		t.Fatalf("failed, x = %v", x)
   141  	}
   142  
   143  }
   144  
   145  func TestToInteger(t *testing.T) {
   146  	for _, dt := range []reflect.Type{
   147  		reflect.TypeOf((*int)(nil)).Elem(),
   148  		reflect.TypeOf((*int64)(nil)).Elem(),
   149  		reflect.TypeOf((*int32)(nil)).Elem(),
   150  		reflect.TypeOf((*int16)(nil)).Elem(),
   151  		reflect.TypeOf((*int8)(nil)).Elem(),
   152  	} {
   153  		for vv, ii := range map[string]int64{
   154  			"123":  123,
   155  			"-123": -123,
   156  			"8.75": 9,
   157  			"8.49": 8,
   158  		} {
   159  			v := reflect.ValueOf(vv)
   160  			ret, err := rToInteger(v, dt)
   161  			if err != nil {
   162  				t.Fatalf("err: %v", err)
   163  			}
   164  			if ret.Int() != ii {
   165  				t.Fatalf("expect %v but got %v", ii, ret.Int())
   166  			}
   167  		}
   168  	}
   169  }
   170  
   171  func TestForUInteger(t *testing.T) {
   172  	for _, src := range []typ.Any{
   173  		13579,
   174  		uint(13579),
   175  	} {
   176  		v1 := reflect.ValueOf(src)
   177  		v1 = tool.Rdecodesimple(v1)
   178  		if rForUInteger(v1).Interface() != "13579" {
   179  			t.Fail()
   180  		}
   181  	}
   182  
   183  	var z typ.Any
   184  	v1 := reflect.ValueOf(z)
   185  	v1 = tool.Rdecodesimple(v1)
   186  	if x := rForUInteger(v1).Interface(); x != "0" {
   187  		t.Fatalf("failed, x = %v", x)
   188  	}
   189  
   190  	z = "bug"
   191  	v1 = reflect.ValueOf(z)
   192  	v1 = tool.Rdecodesimple(v1)
   193  	if x := rForUInteger(v1).Interface(); x != "0" {
   194  		t.Fatalf("failed, x = %v", x)
   195  	}
   196  }
   197  
   198  func TestToUInteger(t *testing.T) {
   199  	for _, dt := range []reflect.Type{
   200  		reflect.TypeOf((*uint)(nil)).Elem(),
   201  		reflect.TypeOf((*uint64)(nil)).Elem(),
   202  		reflect.TypeOf((*uint32)(nil)).Elem(),
   203  		reflect.TypeOf((*uint16)(nil)).Elem(),
   204  		reflect.TypeOf((*uint8)(nil)).Elem(),
   205  	} {
   206  		for vv, ii := range map[string]uint64{
   207  			"123":  123,
   208  			"9":    9,
   209  			"8.75": 9,
   210  			"8.49": 8,
   211  		} {
   212  			v := reflect.ValueOf(vv)
   213  			ret, err := rToUInteger(v, dt)
   214  			if err != nil {
   215  				t.Fatalf("err: %v", err)
   216  			}
   217  			if ret.Uint() != ii {
   218  				t.Fatalf("expect %v but got %v", ii, ret.Int())
   219  			}
   220  		}
   221  	}
   222  }
   223  
   224  func TestForUIntegerHex(t *testing.T) {
   225  	for _, src := range []uint64{
   226  		0x3e67,
   227  		uint64(0x3e67),
   228  	} {
   229  		// v1 := reflect.ValueOf(src)
   230  		// v1 = rdecodesimple(v1)
   231  		if x := rForUIntegerHex(uintptr(src)).Interface(); x != "0x3e67" {
   232  			t.Fatalf("expect %v but got %v", "0x3e67", x)
   233  		}
   234  	}
   235  
   236  	var z typ.Any
   237  	v1 := reflect.ValueOf(z)
   238  	v1 = tool.Rdecodesimple(v1)
   239  	if x := rForUInteger(v1).Interface(); x != "0" {
   240  		t.Fatalf("failed, x = %v", x)
   241  	}
   242  
   243  	z = "bug"
   244  	v1 = reflect.ValueOf(z)
   245  	v1 = tool.Rdecodesimple(v1)
   246  	if x := rForUInteger(v1).Interface(); x != "0" {
   247  		t.Fatalf("failed, x = %v", x)
   248  	}
   249  
   250  	z = "0x3e59"
   251  	v1 = reflect.ValueOf(z)
   252  	v1 = tool.Rdecodesimple(v1)
   253  	uintptrType := reflect.TypeOf(uintptr(0))
   254  	if x := uintptr(rToUIntegerHex(v1, uintptrType).Uint()); x != uintptr(0x3e59) {
   255  		t.Fatalf("failed, x = %v", x)
   256  	}
   257  
   258  	vz := "0x3e59"
   259  	v1 = reflect.ValueOf(vz)
   260  	ptrType := reflect.TypeOf(&vz)
   261  	t.Logf("v1.kind: %v, ptrType.kind: %v", v1.Kind(), ptrType.Kind())
   262  	if x := uintptr(rToUIntegerHex(v1, ptrType).Uint()); x == 0 {
   263  		t.Fatalf("failed, x = %v", x)
   264  	}
   265  }
   266  
   267  func TestForFloat(t *testing.T) {
   268  	for _, src := range []typ.Any{
   269  		13579,
   270  		uint(13579),
   271  	} {
   272  		v1 := reflect.ValueOf(src)
   273  		v1 = tool.Rdecodesimple(v1)
   274  		if rForFloat(v1).Interface() != "13579" {
   275  			t.Fail()
   276  		}
   277  	}
   278  
   279  	var z typ.Any
   280  	v1 := reflect.ValueOf(z)
   281  	v1 = tool.Rdecodesimple(v1)
   282  	if x := rForFloat(v1).Interface(); x != "0" {
   283  		t.Fatalf("failed, x = %v", x)
   284  	}
   285  
   286  	z = "bug"
   287  	v1 = reflect.ValueOf(z)
   288  	v1 = tool.Rdecodesimple(v1)
   289  	if x := rForFloat(v1).Interface(); x != "0" {
   290  		t.Fatalf("failed, x = %v", x)
   291  	}
   292  
   293  }
   294  
   295  func TestToFloat(t *testing.T) {
   296  	for _, dt := range []reflect.Type{
   297  		reflect.TypeOf((*float64)(nil)).Elem(),
   298  		// reflect.TypeOf((*float32)(nil)).Elem(),
   299  	} {
   300  		for vv, ii := range map[string]float64{
   301  			"123":                                  123,
   302  			"-123":                                 -123,
   303  			"8.75":                                 8.75,
   304  			strconv.FormatUint(math.MaxUint64, 10): 1.8446744073709552e+19,
   305  			"(8.1+3.5i)":                           8.1,
   306  		} {
   307  			v := reflect.ValueOf(vv)
   308  			ret, err := rToFloat(v, dt)
   309  			if err != nil {
   310  				t.Fatalf("err: %v", err)
   311  			}
   312  			if ret.Float() != ii {
   313  				t.Fatalf("expect %v but got %v", ii, ret.Float())
   314  			}
   315  		}
   316  	}
   317  }
   318  
   319  func TestForComplex(t *testing.T) {
   320  	for src, exp := range map[typ.Any]string{
   321  		13579:        "(13579+0i)",
   322  		uint(13579):  "(13579+0i)",
   323  		1.316:        "(1.316+0i)",
   324  		8.5 + 7.13i:  "(8.5+7.13i)",
   325  		-8.5 - 7.13i: "(-8.5-7.13i)",
   326  	} {
   327  		v1 := reflect.ValueOf(src)
   328  		v1 = tool.Rdecodesimple(v1)
   329  		if x := rForComplex(v1).Interface(); x != exp {
   330  			t.Fatalf("failed, x = %v, expect = %v", x, exp)
   331  		}
   332  	}
   333  
   334  	var z typ.Any
   335  	v1 := reflect.ValueOf(z)
   336  	v1 = tool.Rdecodesimple(v1)
   337  	if x := rForComplex(v1).Interface(); x != "(0+0i)" {
   338  		t.Fatalf("failed, x = %v", x)
   339  	}
   340  
   341  	z = "bug"
   342  	v1 = reflect.ValueOf(z)
   343  	v1 = tool.Rdecodesimple(v1)
   344  	if x := rForComplex(v1).Interface(); x != "(0+0i)" {
   345  		t.Fatalf("failed, x = %v", x)
   346  	}
   347  
   348  }
   349  
   350  func TestToComplex(t *testing.T) {
   351  	for _, dt := range []reflect.Type{
   352  		// reflect.TypeOf((*complex64)(nil)).Elem(),
   353  		reflect.TypeOf((*complex128)(nil)).Elem(),
   354  	} {
   355  		for vv, ii := range map[string]complex128{
   356  			"123+1i":     123 + 1i,
   357  			"-123-7i":    -123 - 7i,
   358  			"8.75-3.13i": 8.75 - 3.13i,
   359  			// strconv.FormatUint(math.MaxUint64, 10): 1.8446744073709552e+19,
   360  			"(8.1+3.5i)": 8.1 + 3.5i,
   361  		} {
   362  			v := reflect.ValueOf(vv)
   363  			ret, err := rToComplex(v, dt)
   364  			if err != nil {
   365  				t.Fatalf("err: %v, for src: %q", err, vv)
   366  			}
   367  			if ret.Complex() != ii {
   368  				t.Fatalf("expect %v but got %v", ii, ret.Complex())
   369  			}
   370  		}
   371  	}
   372  }
   373  
   374  func TestBytesBufferConverter_Transform(t *testing.T) {
   375  	var bbc fromBytesBufferConverter
   376  	tgtType := reflect.TypeOf((*bytes.Buffer)(nil)).Elem()
   377  	var bb bytes.Buffer
   378  	bb.WriteString("hello")
   379  	src := reflect.ValueOf(bb)
   380  	tgt, err := bbc.Transform(nil, src, tgtType)
   381  	if err != nil {
   382  		t.Fatalf("err: %v", err)
   383  	}
   384  	if x, ok := tgt.Interface().(bytes.Buffer); !ok {
   385  		t.Fatalf("unexpect target value type: %v", tgt.Type())
   386  	} else if x.String() != "hello" { //nolint:goconst
   387  		t.Fatalf("convert failed, want 'hello' but got %q", x.String())
   388  	}
   389  }
   390  
   391  func TestToStringConverter_Transform(t *testing.T) {
   392  	var bbc toStringConverter
   393  	tgtType := reflect.TypeOf((*string)(nil)).Elem()
   394  
   395  	var bb bytes.Buffer
   396  	bb.WriteString("hello")
   397  	var sb strings.Builder
   398  	sb.WriteString("hello")
   399  
   400  	for sv, exp := range map[typ.Any]string{
   401  		"sss":           "sss",
   402  		true:            "true",
   403  		false:           "false",
   404  		123:             "123",
   405  		-123:            "-123",
   406  		uint(123):       "123",
   407  		8.79:            "8.79",
   408  		uintptr(0x3e7c): "0x3e7c",
   409  		9 + 3i:          "(9+3i)",
   410  		&bb:             "hello",
   411  		&sb:             "hello",
   412  		nil:             "",
   413  	} {
   414  		svv := reflect.ValueOf(sv)
   415  		// src := rdecodesimple(svv)
   416  		tgt, err := bbc.Transform(nil, svv, tgtType)
   417  		if err != nil {
   418  			t.Fatalf("err: %v", err)
   419  		}
   420  		if x, ok := tgt.Interface().(string); !ok {
   421  			t.Fatalf("unexpect target value type: %v", tgt.Type())
   422  		} else if x != exp {
   423  			t.Fatalf("convert failed, want %q but got %q", exp, x)
   424  		}
   425  
   426  		var tgtstr = "1"
   427  		tgt = reflect.ValueOf(&tgtstr).Elem()
   428  		dbglog.Log("target/; %v %v", tool.Valfmt(&tgt), tool.Typfmtv(&tgt))
   429  		err = bbc.CopyTo(nil, svv, tgt)
   430  		if err != nil {
   431  			t.Fatalf("err: %v", err)
   432  		}
   433  		if x, ok := tgt.Interface().(string); !ok {
   434  			t.Fatalf("unexpect target value type: %v", tgt.Type())
   435  		} else if x != exp {
   436  			t.Fatalf("convert failed, want %q but got %q", exp, x)
   437  		}
   438  		t.Logf("   tgtstr = %v", tgtstr)
   439  	}
   440  
   441  	//
   442  
   443  	type sss struct {
   444  		string
   445  	}
   446  	var sss1 = sss{"hello"}
   447  	var exp = "{hello}"
   448  
   449  	svv := reflect.ValueOf(sss1)
   450  	// src := rdecodesimple(svv)
   451  	tgt, err := bbc.Transform(nil, svv, tgtType)
   452  	if err != nil {
   453  		t.Fatalf("err: %v", err)
   454  	}
   455  	if x, ok := tgt.Interface().(string); !ok {
   456  		t.Fatalf("unexpect target value type: %v", tgt.Type())
   457  	} else if x != exp {
   458  		t.Fatalf("convert failed, want %q but got %q", exp, x)
   459  	}
   460  }
   461  
   462  var tgtTypes = map[reflect.Kind]reflect.Type{
   463  	reflect.String:     reflect.TypeOf((*string)(nil)).Elem(),
   464  	reflect.Bool:       reflect.TypeOf((*bool)(nil)).Elem(),
   465  	reflect.Uint:       reflect.TypeOf((*uint)(nil)).Elem(),
   466  	reflect.Int:        reflect.TypeOf((*int)(nil)).Elem(),
   467  	reflect.Float64:    reflect.TypeOf((*float64)(nil)).Elem(),
   468  	reflect.Complex128: reflect.TypeOf((*complex128)(nil)).Elem(),
   469  	reflect.Ptr:        reflect.TypeOf((*int)(nil)).Elem(),
   470  	reflect.Uintptr:    reflect.TypeOf((*uintptr)(nil)).Elem(),
   471  }
   472  
   473  func TestFromStringConverter_Transform(t *testing.T) {
   474  	var bbc fromStringConverter
   475  
   476  	for src, tgtm := range map[string]map[reflect.Kind]typ.Any{
   477  		"sss":    {reflect.String: "sss"},
   478  		"true":   {reflect.Bool: true},
   479  		"false":  {reflect.Bool: false},
   480  		"123":    {reflect.Uint: uint(123)},
   481  		"-123":   {reflect.Int: -123},
   482  		"8.79":   {reflect.Float64: 8.79},
   483  		"(3+4i)": {reflect.Complex128: 3 + 4i},
   484  		"0x3e4a": {reflect.Uintptr: uintptr(0x3e4a)},
   485  		// "":      {reflect.Ptr: uintptr(0)},
   486  	} {
   487  		for kind, exp := range tgtm {
   488  			svv := reflect.ValueOf(src)
   489  			tgtType := tgtTypes[kind]
   490  			// src := rdecodesimple(svv)
   491  			tgt, err := bbc.Transform(nil, svv, tgtType)
   492  			if err != nil {
   493  				t.Fatalf("err: %v", err)
   494  			}
   495  
   496  			if x := tgt.Interface(); x != exp {
   497  				t.Fatalf("convert failed, want %v but got %v (%v)", exp, x, tool.Typfmt(tgt.Type()))
   498  			}
   499  
   500  			tgt = reflect.New(tgtType).Elem()
   501  			err = bbc.CopyTo(nil, svv, tgt)
   502  			if err != nil {
   503  				t.Fatalf("err: %v", err)
   504  			}
   505  			if x := tgt.Interface(); x != exp {
   506  				t.Fatalf("convert failed, want %v but got %v (%v)", exp, x, tool.Typfmt(tgt.Type()))
   507  			}
   508  		}
   509  	}
   510  
   511  }
   512  
   513  func TestToDurationConverter_Transform(t *testing.T) {
   514  	var bbc fromStringConverter
   515  	var dur = 3 * time.Second
   516  
   517  	var v = reflect.ValueOf(dur)
   518  	t.Logf("dur: %v (%v, kind: %v, name: %v, pkgpath: %v)", dur, tool.Typfmtv(&v), v.Kind(), v.Type().Name(), v.Type().PkgPath())
   519  
   520  	tgtType := reflect.TypeOf((*time.Duration)(nil)).Elem()
   521  
   522  	var src typ.Any = int64(13 * time.Hour)
   523  	svv := reflect.ValueOf(src)
   524  	tgt, err := bbc.Transform(nil, svv, tgtType)
   525  	if err != nil {
   526  		t.Fatalf("err: %v", err)
   527  	}
   528  	t.Logf("res: %v (%v)", tgt.Interface(), tool.Typfmtv(&tgt))
   529  
   530  	t.Run("toDurationConverter = pre", func(t *testing.T) {
   531  
   532  		for ix, cas := range []struct {
   533  			src, tgt, expect typ.Any
   534  		}{
   535  			{"71ms", &dur, 71 * time.Millisecond},
   536  			{"9h71ms", &dur, 9*time.Hour + 71*time.Millisecond},
   537  			{int64(13 * time.Hour), &dur, 13 * time.Hour},
   538  		} {
   539  			var c = newDeepCopier()
   540  			// var ctx = newValueConverterContextForTest(c)
   541  			svv = reflect.ValueOf(cas.src)
   542  			err = c.CopyTo(cas.src, cas.tgt)
   543  			// tgt, err = bbc.Transform(ctx, svv, tgtType)
   544  			if err != nil {
   545  				t.Fatalf("err: %v", err)
   546  			}
   547  			if reflect.DeepEqual(dur, cas.expect) == false {
   548  				t.Fatalf("err transform: expect %v but got %v", cas.expect, tgt)
   549  			}
   550  			t.Logf("res #%d: %v", ix, dur)
   551  		}
   552  
   553  	})
   554  
   555  	//
   556  
   557  	t.Run("fromDurationConverter - normal test", func(t *testing.T) {
   558  
   559  		inttyp := reflect.TypeOf((*int)(nil)).Elem()
   560  		int64typ := reflect.TypeOf((*int64)(nil)).Elem()
   561  		stringtyp := reflect.TypeOf((*string)(nil)).Elem()
   562  		booltyp := reflect.TypeOf((*bool)(nil)).Elem()
   563  
   564  		var fdc fromDurationConverter
   565  
   566  		for ix, cas := range []struct {
   567  			src, tgt, expect interface{}
   568  			desiredType      reflect.Type
   569  		}{
   570  			{13 * time.Hour, &dur, "13h0m0s", stringtyp},
   571  			{71 * time.Millisecond, &dur, int(71 * time.Millisecond), inttyp},
   572  			{9*time.Hour + 71*time.Millisecond, &dur, int64(9*time.Hour + 71*time.Millisecond), int64typ},
   573  			{13 * time.Hour, &dur, true, booltyp},
   574  			{0 * time.Hour, &dur, false, booltyp},
   575  		} {
   576  			var c = newDeepCopier()
   577  			var ctx = newValueConverterContextForTest(c)
   578  			svv = reflect.ValueOf(cas.src)
   579  			// err = c.CopyTo(cas.src, cas.tgt)
   580  			tgt, err = fdc.Transform(ctx, svv, cas.desiredType)
   581  			if err != nil {
   582  				t.Fatalf("err: %v", err)
   583  			}
   584  			if reflect.DeepEqual(tgt.Interface(), cas.expect) == false {
   585  				t.Fatalf("err transform: expect %v but got %v (%v)", cas.expect, tgt.Interface(), tool.Typfmt(tgt.Type()))
   586  			}
   587  			t.Logf("res #%d: %v (%v)", ix, tgt.Interface(), tool.Typfmt(tgt.Type()))
   588  		}
   589  
   590  	})
   591  
   592  	//
   593  
   594  	t.Run("toDurationConverter - normal test", func(t *testing.T) {
   595  
   596  		var tdc toDurationConverter
   597  
   598  		for ix, cas := range []struct {
   599  			src, tgt, expect interface{}
   600  		}{
   601  			{"71ms", &dur, 71 * time.Millisecond},
   602  			{"9h71ms", &dur, 9*time.Hour + 71*time.Millisecond},
   603  			{int64(13 * time.Hour), &dur, 13 * time.Hour},
   604  			{false, &dur, 0 * time.Second},
   605  			{true, &dur, 1 * time.Nanosecond},
   606  		} {
   607  			var c = newDeepCopier()
   608  			var ctx = newValueConverterContextForTest(c)
   609  			svv = reflect.ValueOf(cas.src)
   610  			// err = c.CopyTo(cas.src, cas.tgt)
   611  			tgt, err = tdc.Transform(ctx, svv, tgtType)
   612  			if err != nil {
   613  				t.Fatalf("err: %v", err)
   614  			}
   615  			if reflect.DeepEqual(tgt.Interface(), cas.expect) == false {
   616  				t.Fatalf("err transform: expect %v but got %v (%v)", cas.expect, tgt.Interface(), tool.Typfmt(tgt.Type()))
   617  			}
   618  			t.Logf("res #%d: %v (%v)", ix, tgt.Interface(), tool.Typfmt(tgt.Type()))
   619  		}
   620  
   621  	})
   622  
   623  	// var c = newDeepCopier()
   624  	// c.withConverters(&toDurationConverter{})
   625  	// var ctx = newValueConverterContextForTest(c)
   626  	// src = "71ms"
   627  	// svv = reflect.ValueOf(src)
   628  	// tgt, err = bbc.Transform(ctx, svv, tgtType)
   629  	// if err != nil {
   630  	//	t.Fatalf("err: %v", err)
   631  	// }
   632  	// t.Logf("res: %v (%v)", tgt.Interface(), typfmtv(&tgt))
   633  	//
   634  	// src = "9h71ms"
   635  	// svv = reflect.ValueOf(src)
   636  	// err = bbc.CopyTo(ctx, svv, reflect.ValueOf(&dur).Elem())
   637  	// if err != nil {
   638  	//	t.Fatalf("err: %v", err)
   639  	// }
   640  	// t.Logf("res: %v", dur)
   641  	//
   642  	// //
   643  	//
   644  	// c = newDeepCopier()
   645  	// c.withCopiers(&toDurationConverter{})
   646  	// ctx = newValueConverterContextForTest(c)
   647  	// src = "71ms"
   648  	// svv = reflect.ValueOf(src)
   649  	// tgt, err = bbc.Transform(ctx, svv, tgtType)
   650  	// if err != nil {
   651  	//	t.Fatalf("err: %v", err)
   652  	// }
   653  	// t.Logf("res: %v (%v)", tgt.Interface(), typfmtv(&tgt))
   654  	//
   655  	// src = "9h71ms"
   656  	// svv = reflect.ValueOf(src)
   657  	// err = bbc.CopyTo(ctx, svv, reflect.ValueOf(&dur).Elem())
   658  	// if err != nil {
   659  	//	t.Fatalf("err: %v", err)
   660  	// }
   661  	// t.Logf("res: %v", dur)
   662  
   663  	//
   664  
   665  	c := newCopier()
   666  	c.withFlags(cms.SliceMerge)
   667  	c.withFlags(cms.MapMerge)
   668  }
   669  
   670  func TestToDurationConverter_fallback(t *testing.T) {
   671  	var tdfs toDurationConverter
   672  	var dur = 3 * time.Second
   673  	var v = reflect.ValueOf(&dur)
   674  	_ = tdfs.fallback(v)
   675  	t.Logf("dur: %v", dur)
   676  }
   677  
   678  func TestToTimeConverter_Transform(t *testing.T) {
   679  
   680  	t.Run("fromTimeConverter - normal test", func(t *testing.T) {
   681  
   682  		inttyp := reflect.TypeOf((*int)(nil)).Elem()
   683  		int64typ := reflect.TypeOf((*int64)(nil)).Elem()
   684  		stringtyp := reflect.TypeOf((*string)(nil)).Elem()
   685  		// booltyp := reflect.TypeOf((*bool)(nil)).Elem()
   686  		floattyp := reflect.TypeOf((*float64)(nil)).Elem()
   687  
   688  		var ftc fromTimeConverter
   689  		var dur int
   690  
   691  		for ix, cas := range []struct {
   692  			src         string
   693  			tgt, expect interface{}
   694  			desiredType reflect.Type
   695  		}{
   696  			{"2001-02-03 04:05:06.078912", &dur, "2001-02-03T04:05:06Z", stringtyp},
   697  			{"2001-02-03 04:05:06.078912", &dur, int(981173106), inttyp},
   698  			{"2001-02-03 04:05:06.078912", &dur, int64(981173106), int64typ},
   699  			{"2001-02-03 04:05:06.078912", &dur, float64(981173106.078912), floattyp},
   700  		} {
   701  			var c = newDeepCopier()
   702  			var ctx = newValueConverterContextForTest(c)
   703  			var tm, err = time.Parse("2006-01-02 15:04:05.000000", cas.src)
   704  			t.Logf("%q parsed: %v (%v)", cas.src, tm, err)
   705  			var svv = reflect.ValueOf(tm)
   706  			// err = c.CopyTo(cas.src, cas.tgt)
   707  			tgt, err := ftc.Transform(ctx, svv, cas.desiredType)
   708  			if err != nil {
   709  				t.Fatalf("err: %v", err)
   710  			}
   711  			if reflect.DeepEqual(tgt.Interface(), cas.expect) == false {
   712  				t.Fatalf("err transform: expect %v but got %v (%v)", cas.expect, tgt.Interface(), tool.Typfmt(tgt.Type()))
   713  			}
   714  			t.Logf("res #%d: %v (%v)", ix, tgt.Interface(), tool.Typfmt(tgt.Type()))
   715  		}
   716  
   717  	})
   718  
   719  	t.Run("toTimeConverter - normal test", func(t *testing.T) {
   720  
   721  		var tdc toTimeConverter
   722  		var tm time.Time
   723  		layout := "2006-01-02 15:04:05.999999999Z07:00"
   724  		tgtType := reflect.TypeOf((*time.Time)(nil)).Elem()
   725  
   726  		for ix, cas := range []struct {
   727  			src, tgt, expect interface{}
   728  		}{
   729  			{"2001-02-03 04:05:06.078912", &tm, "2001-02-03 04:05:06.078912Z"},
   730  			{"2001-02-03 04:05:06.078912345", &tm, "2001-02-03 04:05:06.078912345Z"},
   731  			{int(981173106), &tm, "2001-02-03 04:05:06Z"},
   732  			{int64(981173106), &tm, "2001-02-03 04:05:06Z"},
   733  			{float64(981173106.078912), &tm, "2001-02-03 04:05:06.078912019Z"},
   734  		} {
   735  			var c = newDeepCopier()
   736  			var ctx = newValueConverterContextForTest(c)
   737  			var svv = reflect.ValueOf(cas.src)
   738  			// err = c.CopyTo(cas.src, cas.tgt)
   739  			var tgt, err = tdc.Transform(ctx, svv, tgtType)
   740  			if err != nil {
   741  				t.Fatalf("err: %v", err)
   742  			}
   743  			got := tgt.Interface().(time.Time).UTC().Format(layout)
   744  			if reflect.DeepEqual(got, cas.expect) == false {
   745  				t.Fatalf("err transform: expect %v but got %v (%v)", cas.expect, got, tool.Typfmt(tgt.Type()))
   746  			}
   747  			t.Logf("res #%d: %v (%v)", ix, got, tool.Typfmt(tgt.Type()))
   748  		}
   749  
   750  	})
   751  }
   752  
   753  func TestFromStringConverter_defaultTypes(t *testing.T) {
   754  	var fss fromStringConverter
   755  	var src = "987"
   756  	var dst = 3.3
   757  	var svv = reflect.ValueOf(src)
   758  	var dvv = reflect.ValueOf(&dst)
   759  
   760  	ctx := newValueConverterContextForTest(newDeepCopier())
   761  	ret, err := fss.convertToOrZeroTarget(ctx, svv, dvv.Type().Elem())
   762  	if err != nil {
   763  		t.Fatalf("err: %v", err)
   764  	}
   765  	t.Logf("ret: %v (%v)", tool.Valfmt(&ret), tool.Typfmtv(&ret))
   766  }
   767  
   768  func TestFromStringConverter_postCopyTo(t *testing.T) {
   769  	var fss fromStringConverter
   770  
   771  	var src = "987"
   772  	var dst = 3.3
   773  	var svv = reflect.ValueOf(src)
   774  	var dvv = reflect.ValueOf(&dst)
   775  
   776  	c := newDeepCopier().withFlags(cms.ClearIfInvalid)
   777  	ctx := newValueConverterContextForTest(c)
   778  	err := fss.postCopyTo(ctx, svv, dvv.Elem())
   779  	if err != nil {
   780  		t.Fatalf("err: %v", err)
   781  	}
   782  	t.Logf("ret: %v (%v)", dst, tool.Typfmtv(&dvv))
   783  }
   784  
   785  func TestToStringConverter_postCopyTo(t *testing.T) {
   786  	var fss toStringConverter
   787  	var src = struct {
   788  		fval float64
   789  	}{3.3}
   790  	var dst = struct {
   791  		fval string
   792  	}{}
   793  	var svv = reflect.ValueOf(&src)
   794  	var dvv = reflect.ValueOf(&dst)
   795  	var sf1 = tool.Rindirect(svv).Field(0)
   796  	var df1 = tool.Rindirect(dvv).Field(0)
   797  	// var sft = reflect.TypeOf(src).Field(0)
   798  
   799  	ctx := &ValueConverterContext{
   800  		Params: &Params{
   801  			srcOwner: &svv,
   802  			dstOwner: &dvv,
   803  			// field:      &sft,
   804  			// fieldTags:  parseFieldTags(sft.Tag),
   805  			targetIterator: newStructIterator(dvv,
   806  				withStructPtrAutoExpand(true),
   807  				withStructFieldPtrAutoNew(true),
   808  				withStructSource(&svv, true),
   809  			),
   810  			controller: newDeepCopier(),
   811  		},
   812  	}
   813  
   814  	ctx.nextTargetField() // call ctx.targetIterator.Next() to locate the first field
   815  
   816  	sf2 := cl.GetUnexportedField(sf1)
   817  
   818  	err := fss.postCopyTo(ctx, sf2, df1)
   819  	if err != nil {
   820  		t.Fatalf("err: %v", err)
   821  	}
   822  	if dst.fval != "3.3" {
   823  		t.Fatalf("want '3.3' but got %v", dst.fval)
   824  	}
   825  	t.Logf("ret: %v (%v)", dst, tool.Typfmtv(&dvv))
   826  }
   827  
   828  type si1 struct{}
   829  type si2 struct{}
   830  
   831  func (*si2) String() string { return "i2" }
   832  
   833  func TestHasStringer(t *testing.T) {
   834  	var i1 si1
   835  	var i2 si2
   836  
   837  	v := reflect.ValueOf(i1)
   838  	t.Logf("si1: %v", tool.HasStringer(&v))
   839  	v = reflect.ValueOf(i2)
   840  	t.Logf("si2: %v", tool.HasStringer(&v))
   841  	v = reflect.ValueOf(&i2)
   842  	t.Logf("*si2: %v", tool.HasStringer(&v))
   843  }
   844  
   845  func TestNameToMapKey(t *testing.T) {
   846  	name := "9527"
   847  	// value := 789
   848  	mapslice := []interface{}{
   849  		map[int]interface{}{
   850  			111: 333,
   851  		},
   852  		map[int]interface{}{
   853  			9527: 333,
   854  		},
   855  		map[float32]interface{}{
   856  			9527: 333,
   857  		},
   858  		map[complex128]interface{}{
   859  			9527: 333,
   860  		},
   861  		map[string]interface{}{
   862  			"my": 12,
   863  		},
   864  		map[string]interface{}{
   865  			"9527": 33,
   866  		},
   867  	}
   868  
   869  	for _, m := range mapslice {
   870  		mv := reflect.ValueOf(&m) // nolint:gosec // G601: Implicit memory aliasing in for loop
   871  		mvind := tool.Rdecodesimple(mv)
   872  		t.Logf("    target map is %v", tool.Typfmtv(&mvind))
   873  		mt := tool.Rdecodetypesimple(mvind.Type())
   874  		key, err := nameToMapKey(name, mt)
   875  		if err != nil {
   876  			t.Errorf("nameToMapKey, has error: %v", err)
   877  		} else {
   878  			t.Logf("for target map %v, got key from nameToMapKey: %v %v", tool.Typfmt(mt), tool.Valfmt(&key), tool.Typfmt(key.Type()))
   879  		}
   880  	}
   881  }
   882  
   883  func TestFromFuncConverterAlongMainEntry(t *testing.T) {
   884  	type A1 struct {
   885  		Bv func() (int, error)
   886  	}
   887  	type B1 struct {
   888  		Bv int
   889  	}
   890  
   891  	var a1 = A1{func() (int, error) { return 3, nil }}
   892  	var b1 = B1{1}
   893  
   894  	// test for fromFuncConverter along Copy -> cpController.findConverters
   895  	Copy(&a1, &b1)
   896  
   897  	if b1.Bv != 3 {
   898  		t.Fatalf("expect %v but got %v", 3, b1.Bv)
   899  	}
   900  }
   901  
   902  func TestFromFuncConverter(t *testing.T) {
   903  	fn0 := func() string { return "hello" }
   904  
   905  	type C struct {
   906  		A int
   907  		B bool
   908  	}
   909  	type A struct {
   910  		A func() C
   911  		B func() bool
   912  	}
   913  	type B struct {
   914  		C *C
   915  		B bool
   916  	}
   917  	var a0 = A{
   918  		func() C { return C{7, true} },
   919  		func() bool { return false },
   920  	}
   921  	var b0 = B{nil, true}
   922  	var b1 = B{&C{7, true}, false}
   923  
   924  	var boolTgt bool
   925  	var intTgt = 1
   926  	var stringTgt = "world"
   927  
   928  	lazyInitRoutines()
   929  
   930  	for ix, fnCase := range []struct {
   931  		fn     interface{}
   932  		target interface{}
   933  		expect interface{}
   934  	}{
   935  		{func() ([]int, error) { return []int{2, 3}, nil }, &[]int{1}, []int{1, 2, 3}},
   936  
   937  		// {func() ([2]int, error) { return [2]int{2, 3}, nil }, &[2]int{1}, [2]int{2, 3}},
   938  
   939  		{func() A { return a0 },
   940  			&b0,
   941  			b1,
   942  		},
   943  
   944  		{func() map[string]interface{} { return map[string]interface{}{"hello": "world"} },
   945  			&map[string]interface{}{"k": 1, "hello": "bob"},
   946  			map[string]interface{}{"hello": "world", "k": 1},
   947  		},
   948  
   949  		{func() string { return "hello" }, &stringTgt, "hello"},
   950  		{func() string { return "hello" }, &intTgt, 1},
   951  		{func() string { return "789" }, &intTgt, 789},
   952  		{&fn0, &stringTgt, "hello"},
   953  
   954  		{func() ([2]int, error) { return [2]int{2, 3}, nil }, &[2]int{1}, [2]int{2, 3}},
   955  		{func() ([2]int, error) { return [2]int{2, 3}, nil }, &[3]int{1}, [3]int{2, 3}},
   956  		{func() ([3]int, error) { return [3]int{2, 3, 5}, nil }, &[2]int{1}, [2]int{2, 3}},
   957  		{func() ([]int, error) { return []int{2, 3}, nil }, &[]int{1}, []int{1, 2, 3}},
   958  
   959  		{func() bool { return true }, &boolTgt, true},
   960  		{func() int { return 3 }, &intTgt, 3},
   961  		{func() (int, error) { return 5, nil }, &intTgt, 5},
   962  	} {
   963  		if fnCase.fn != nil { //nolint:gocritic //nestingReduce: invert if cond, replace body with `continue`, move old body after the statement
   964  			fnv := reflect.ValueOf(&fnCase.fn)
   965  			tgtv := reflect.ValueOf(&fnCase.target)
   966  			ff, tt := tool.Rdecodesimple(fnv), tool.Rdecodesimple(tgtv)
   967  			dbglog.Log("---- CASE %d. %v -> %v", ix, tool.Typfmtv(&ff), tool.Typfmtv(&tt))
   968  
   969  			c := fromFuncConverter{}
   970  			ctx := newValueConverterContextForTest(nil)
   971  			err := c.CopyTo(ctx, fnv, tgtv)
   972  
   973  			if err != nil {
   974  				t.Fatalf("has error: %v", err)
   975  			} else if ret := tt.Interface(); reflect.DeepEqual(ret, fnCase.expect) == false {
   976  				t.Fatalf("unexpect result: expect %v but got %v", fnCase.expect, ret)
   977  			}
   978  		}
   979  	}
   980  }
   981  
   982  func newValueConverterContextForTest(c *cpController) *ValueConverterContext {
   983  	if c == nil {
   984  		c = newDeepCopier()
   985  	}
   986  	return &ValueConverterContext{newParams(withOwnersSimple(c, nil))}
   987  }