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 }