github.com/Aoi-hosizora/ahlib@v1.5.1-0.20230404072829-241b93cf91c7/xmodule/xmodule_test.go (about) 1 package xmodule 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/Aoi-hosizora/ahlib/xtesting" 7 "reflect" 8 "strconv" 9 "strings" 10 "testing" 11 ) 12 13 func TestSimpleTypes(t *testing.T) { 14 xtesting.Equal(t, ModuleName("").String(), "") 15 xtesting.Equal(t, ModuleName("-").String(), "-") 16 xtesting.Equal(t, ModuleName("~").String(), "~") 17 xtesting.Equal(t, ModuleName("test").String(), "test") 18 19 xtesting.Equal(t, nameKey("").String(), "<invalid>") 20 xtesting.Equal(t, nameKey("-").String(), "name:-") 21 xtesting.Equal(t, nameKey("~").String(), "name:~") 22 xtesting.Equal(t, nameKey("name").String(), "name:name") 23 24 xtesting.Equal(t, typeKey(nil).String(), "<invalid>") 25 xtesting.Equal(t, typeKey(reflect.TypeOf("s")).String(), "type:string") 26 xtesting.Equal(t, typeKey(reflect.TypeOf(&strconv.NumError{})).String(), "type:*strconv.NumError") 27 xtesting.Equal(t, typeKey(reflect.TypeOf(new(fmt.Stringer)).Elem()).String(), "type:fmt.Stringer") 28 } 29 30 func TestProvideByName(t *testing.T) { 31 defer func() { _mc = NewModuleContainer() }() 32 SetLogger(DefaultLogger(LogSilent, nil, nil)) 33 for _, tc := range []struct { 34 giveName ModuleName 35 giveModule interface{} 36 wantPanicP bool 37 wantPanicR bool 38 }{ 39 {ModuleName(""), 0, true, true}, 40 {ModuleName("-"), 0, true, true}, 41 {ModuleName("~"), 0, true, true}, 42 {ModuleName("0"), nil, true, false}, 43 {ModuleName("int"), 12, false, false}, // int 44 {ModuleName("uint"), uint(12), false, false}, // uint 45 {ModuleName("float"), 12.5, false, false}, // float 46 {ModuleName("bool"), true, false, false}, // bool 47 {ModuleName("string"), "a", false, false}, // string 48 {ModuleName("array"), [2]string{"1", "2"}, false, false}, // array 49 {ModuleName("slice"), []string{"1", "2"}, false, false}, // slice 50 {ModuleName("pointer"), &struct{}{}, false, false}, // pointer 51 {ModuleName("struct"), struct{ int }{1}, false, false}, // struct 52 } { 53 if tc.wantPanicP { 54 xtesting.Panic(t, func() { ProvideByName(tc.giveName, tc.giveModule) }) 55 } 56 if tc.wantPanicR { 57 xtesting.Panic(t, func() { RemoveByName(tc.giveName) }) 58 } 59 if !tc.wantPanicP && !tc.wantPanicR { 60 ProvideByName(tc.giveName, tc.giveModule) 61 xtesting.Equal(t, _mc.modules[nameKey(tc.giveName)], tc.giveModule) 62 xtesting.True(t, RemoveByName(tc.giveName)) 63 _, ok := _mc.modules[nameKey(tc.giveName)] 64 xtesting.False(t, ok) 65 xtesting.False(t, RemoveByName(tc.giveName)) 66 } 67 } 68 } 69 70 func TestProvideByType(t *testing.T) { 71 defer func() { _mc = NewModuleContainer() }() 72 SetLogger(DefaultLogger(LogSilent, nil, nil)) 73 for _, tc := range []struct { 74 giveModule interface{} 75 wantPanicP bool 76 wantPanicR bool 77 }{ 78 {nil, true, true}, 79 {12, false, false}, // int 80 {uint(12), false, false}, // uint 81 {12.5, false, false}, // float 82 {true, false, false}, // bool 83 {"a", false, false}, // string 84 {[2]string{"1", "2"}, false, false}, // array 85 {[]string{"1", "2"}, false, false}, // slice 86 {&struct{}{}, false, false}, // pointer 87 {struct{ int }{1}, false, false}, // struct 88 } { 89 if tc.wantPanicP { 90 xtesting.Panic(t, func() { ProvideByType(tc.giveModule) }) 91 } 92 if tc.wantPanicR { 93 xtesting.Panic(t, func() { RemoveByType(tc.giveModule) }) 94 } 95 if !tc.wantPanicP && !tc.wantPanicR { 96 ProvideByType(tc.giveModule) 97 xtesting.Equal(t, _mc.modules[typeKey(reflect.TypeOf(tc.giveModule))], tc.giveModule) 98 xtesting.True(t, RemoveByType(tc.giveModule)) 99 _, ok := _mc.modules[typeKey(reflect.TypeOf(tc.giveModule))] 100 xtesting.False(t, ok) 101 xtesting.False(t, RemoveByType(tc.giveModule)) 102 } 103 } 104 } 105 106 func TestProvideByIntf(t *testing.T) { 107 defer func() { _mc = NewModuleContainer() }() 108 SetLogger(DefaultLogger(LogSilent, nil, nil)) 109 for _, tc := range []struct { 110 givePtr interface{} 111 giveImpl interface{} 112 wantPanicP bool 113 wantPanicR bool 114 }{ 115 {nil, 0, true, false}, 116 {0, nil, true, true}, 117 {0, errors.New(""), true, true}, // non ptr 118 {t, "", true, true}, // non itf 119 {(*error)(nil), "", true, false}, // non impl 120 {(*error)(nil), errors.New("test"), false, false}, 121 {(*fmt.Stringer)(nil), &strings.Builder{}, false, false}, 122 } { 123 if tc.wantPanicP { 124 xtesting.Panic(t, func() { ProvideByIntf(tc.givePtr, tc.giveImpl) }) 125 } 126 if tc.wantPanicR { 127 xtesting.Panic(t, func() { RemoveByIntf(tc.givePtr) }) 128 } 129 if !tc.wantPanicP && !tc.wantPanicR { 130 ProvideByIntf(tc.givePtr, tc.giveImpl) 131 xtesting.Equal(t, _mc.modules[typeKey(reflect.TypeOf(tc.givePtr).Elem())], tc.giveImpl) 132 xtesting.True(t, RemoveByIntf(tc.givePtr)) 133 _, ok := _mc.modules[typeKey(reflect.TypeOf(tc.givePtr).Elem())] 134 xtesting.False(t, ok) 135 xtesting.False(t, RemoveByIntf(tc.givePtr)) 136 } 137 } 138 } 139 140 func TestGetByName(t *testing.T) { 141 defer func() { _mc = NewModuleContainer() }() 142 SetLogger(DefaultLogger(LogSilent, nil, nil)) 143 ProvideByName("int", 12) 144 ProvideByName("uint", uint(12)) 145 ProvideByName("float", 12.5) 146 ProvideByName("bool", true) 147 ProvideByName("string", "a") 148 ProvideByName("array", [2]string{"1", "2"}) 149 ProvideByName("slice", []string{"1", "2"}) 150 ProvideByName("pointer", &struct{}{}) 151 ProvideByName("struct", struct{ int }{1}) 152 153 for _, tc := range []struct { 154 giveName ModuleName 155 wantModule interface{} 156 wantPanic bool 157 }{ 158 {ModuleName(""), nil, true}, 159 {ModuleName("~"), nil, true}, 160 {ModuleName("-"), nil, true}, 161 {ModuleName("int"), 12, false}, // int 162 {ModuleName("uint"), uint(12), false}, // uint 163 {ModuleName("float"), 12.5, false}, // float 164 {ModuleName("bool"), true, false}, // bool 165 {ModuleName("string"), "a", false}, // string 166 {ModuleName("array"), [2]string{"1", "2"}, false}, // array 167 {ModuleName("slice"), []string{"1", "2"}, false}, // slice 168 {ModuleName("pointer"), &struct{}{}, false}, // pointer 169 {ModuleName("struct"), struct{ int }{1}, false}, // struct 170 } { 171 if tc.wantPanic { 172 xtesting.Panic(t, func() { GetByName(tc.giveName) }) 173 } else { 174 module, ok := GetByName(tc.giveName) 175 xtesting.Equal(t, module, tc.wantModule) 176 xtesting.True(t, ok) 177 xtesting.Equal(t, MustGetByName(tc.giveName), tc.wantModule) 178 } 179 } 180 181 xtesting.Panic(t, func() { MustGetByName("") }) 182 xtesting.Panic(t, func() { MustGetByName("~") }) 183 xtesting.Panic(t, func() { MustGetByName("-") }) 184 xtesting.Panic(t, func() { MustGetByName("not exist") }) 185 } 186 187 func TestGetByType(t *testing.T) { 188 defer func() { _mc = NewModuleContainer() }() 189 SetLogger(DefaultLogger(LogSilent, nil, nil)) 190 ProvideByType(12) 191 ProvideByType(uint(12)) 192 ProvideByType(12.5) 193 ProvideByType(true) 194 ProvideByType("a") 195 ProvideByType([2]string{"1", "2"}) 196 ProvideByType([]string{"1", "2"}) 197 ProvideByType(&struct{}{}) 198 ProvideByType(struct{ int }{1}) 199 200 for _, tc := range []struct { 201 wantModule interface{} 202 wantPanic bool 203 }{ 204 {nil, true}, 205 {nil, true}, 206 {nil, true}, 207 {12, false}, // int 208 {uint(12), false}, // uint 209 {12.5, false}, // float 210 {true, false}, // bool 211 {"a", false}, // string 212 {[2]string{"1", "2"}, false}, // array 213 {[]string{"1", "2"}, false}, // slice 214 {&struct{}{}, false}, // pointer 215 {struct{ int }{1}, false}, // struct 216 } { 217 if tc.wantPanic { 218 xtesting.Panic(t, func() { GetByType(tc.wantModule) }) 219 } else { 220 module, ok := GetByType(tc.wantModule) 221 xtesting.Equal(t, module, tc.wantModule) 222 xtesting.True(t, ok) 223 xtesting.Equal(t, MustGetByType(tc.wantModule), tc.wantModule) 224 } 225 } 226 227 xtesting.Panic(t, func() { MustGetByType(struct{}{}) }) 228 } 229 230 func TestGetByIntf(t *testing.T) { 231 defer func() { _mc = NewModuleContainer() }() 232 SetLogger(DefaultLogger(LogSilent, nil, nil)) 233 ProvideByIntf((*error)(nil), errors.New("test")) 234 ProvideByIntf((*fmt.Stringer)(nil), &strings.Builder{}) 235 236 for _, tc := range []struct { 237 givePtr interface{} 238 wantModule interface{} 239 wantPanic bool 240 }{ 241 {nil, 0, true}, 242 {0, errors.New(""), true}, // non ptr 243 {t, "", true}, // non itf 244 {(*error)(nil), errors.New("test"), false}, 245 {(*fmt.Stringer)(nil), &strings.Builder{}, false}, 246 } { 247 if tc.wantPanic { 248 xtesting.Panic(t, func() { GetByIntf(tc.givePtr) }) 249 } else { 250 module, ok := GetByIntf(tc.givePtr) 251 xtesting.Equal(t, module, tc.wantModule) 252 xtesting.True(t, ok) 253 xtesting.Equal(t, MustGetByIntf(tc.givePtr), tc.wantModule) 254 } 255 } 256 257 xtesting.Panic(t, func() { MustGetByIntf((*fmt.GoStringer)(nil)) }) 258 } 259 260 func TestInject(t *testing.T) { 261 defer func() { _mc = NewModuleContainer() }() 262 SetLogger(DefaultLogger(LogSilent, nil, nil)) 263 264 t.Run("abnormal", func(t *testing.T) { 265 type allIgnored struct { 266 unexportedField string 267 ExportedField1 string 268 ExportedField2 string `module:""` 269 ExportedField3 string `module:"-"` 270 } 271 test1 := &allIgnored{} 272 273 for _, tc := range []struct { 274 giveCtrl interface{} 275 wantErr bool 276 wantPanic bool 277 }{ 278 {nil, false, true}, // nil 279 {struct{}{}, false, true}, // struct 280 {new(int), true, true}, // *int 281 {test1, false, false}, // *struct 282 } { 283 if tc.wantPanic { 284 xtesting.Panic(t, func() { _ = Inject(tc.giveCtrl) }) 285 } else { 286 xtesting.Equal(t, Inject(tc.giveCtrl) != nil, tc.wantErr) 287 } 288 } 289 for _, tc := range []struct { 290 give interface{} 291 want interface{} 292 }{ 293 {test1.unexportedField, ""}, 294 {test1.ExportedField1, ""}, 295 {test1.ExportedField2, ""}, 296 {test1.ExportedField3, ""}, 297 } { 298 xtesting.Equal(t, tc.give, tc.want) 299 } 300 }) 301 302 type testStruct struct { 303 Int1 int `module:"int"` 304 Uint1 uint `module:"uint"` 305 Float1 float64 `module:"float"` 306 Bool1 bool `module:"bool"` 307 String1 string `module:"string"` 308 Array1 [2]string `module:"array"` 309 Slice1 []string `module:"slice"` 310 Pointer1 *struct{} `module:"pointer"` 311 Struct1 struct{ int } `module:"struct"` 312 Int2 int `module:"~"` 313 Uint2 uint `module:"~"` 314 Float2 float64 `module:"~"` 315 Bool2 bool `module:"~"` 316 String2 string `module:"~"` 317 Array2 [2]string `module:"~"` 318 Slice2 []string `module:"~"` 319 Pointer2 *struct{} `module:"~"` 320 Struct2 struct{ int } `module:"~"` 321 Err error `module:"~"` 322 Sb fmt.Stringer `module:"~"` 323 } 324 ProvideByName("int", 12) 325 ProvideByName("uint", uint(12)) 326 ProvideByName("float", 12.5) 327 ProvideByName("bool", true) 328 ProvideByName("string", "a") 329 ProvideByName("array", [2]string{"1", "2"}) 330 ProvideByName("slice", []string{"1", "2"}) 331 ProvideByName("pointer", &struct{}{}) 332 ProvideByName("struct", struct{ int }{1}) 333 ProvideByType(12) 334 ProvideByType(uint(12)) 335 ProvideByType(12.5) 336 ProvideByType(true) 337 ProvideByType("a") 338 ProvideByType([2]string{"1", "2"}) 339 ProvideByType([]string{"1", "2"}) 340 ProvideByType(&struct{}{}) 341 ProvideByType(struct{ int }{1}) 342 ProvideByIntf((*error)(nil), errors.New("test")) 343 ProvideByIntf((*fmt.Stringer)(nil), &strings.Builder{}) 344 345 t.Run("normal", func(t *testing.T) { 346 test2 := &testStruct{} 347 xtesting.Nil(t, Inject(test2)) 348 xtesting.NotPanic(t, func() { MustInject(test2) }) 349 for _, tc := range []struct { 350 give interface{} 351 want interface{} 352 }{ 353 {test2.Int1, 12}, 354 {test2.Uint1, uint(12)}, 355 {test2.Float1, 12.5}, 356 {test2.Bool1, true}, 357 {test2.String1, "a"}, 358 {test2.Array1, [2]string{"1", "2"}}, 359 {test2.Slice1, []string{"1", "2"}}, 360 {test2.Pointer1, &struct{}{}}, 361 {test2.Struct1, struct{ int }{1}}, 362 {test2.Int2, 12}, 363 {test2.Uint2, uint(12)}, 364 {test2.Float2, 12.5}, 365 {test2.Bool2, true}, 366 {test2.String2, "a"}, 367 {test2.Array2, [2]string{"1", "2"}}, 368 {test2.Slice2, []string{"1", "2"}}, 369 {test2.Pointer2, &struct{}{}}, 370 {test2.Struct2, struct{ int }{1}}, 371 {test2.Err, errors.New("test")}, 372 {test2.Sb, &strings.Builder{}}, 373 } { 374 xtesting.Equal(t, tc.give, tc.want) 375 } 376 }) 377 378 t.Run("some errors", func(t *testing.T) { 379 // type mismatch 380 ProvideByName("uint", 12) 381 test := &testStruct{} 382 xtesting.NotNil(t, Inject(test)) 383 xtesting.Panic(t, func() { MustInject(test) }) 384 385 // module not found 386 ProvideByName("uint", uint(12)) 387 _mc.modules = map[mkey]interface{}{} 388 test = &testStruct{} 389 xtesting.NotNil(t, Inject(test)) 390 xtesting.Panic(t, func() { MustInject(test) }) 391 }) 392 } 393 394 func TestAutoProvide(t *testing.T) { 395 t.Run("providers", func(t *testing.T) { 396 xtesting.Panic(t, func() { NameProvider("", 0) }) 397 xtesting.Panic(t, func() { NameProvider("~", struct{}{}) }) 398 xtesting.Panic(t, func() { NameProvider("xxx", nil) }) 399 xtesting.NotPanic(t, func() { NameProvider("xxx", "module") }) 400 xtesting.Panic(t, func() { TypeProvider(nil) }) 401 xtesting.NotPanic(t, func() { TypeProvider("module") }) 402 xtesting.Panic(t, func() { IntfProvider(0, struct{}{}) }) 403 xtesting.Panic(t, func() { IntfProvider(fmt.Stringer(nil), ModuleName("x")) }) 404 xtesting.NotPanic(t, func() { IntfProvider((*fmt.Stringer)(nil), ModuleName("x")) }) 405 406 _mc = NewModuleContainer() 407 _mc.SetLogger(DefaultLogger(LogSilent, nil, nil)) 408 xtesting.Panic(t, func() { _ = _mc.AutoProvide(&ModuleProvider{}) }) 409 xtesting.NotPanic(t, func() { _ = _mc.AutoProvide(nil, NameProvider("xxx", 0)) }) 410 xtesting.NotPanic(t, func() { _mc.MustAutoProvide(nil, nil, nil) }) 411 }) 412 413 t.Run("simple", func(t *testing.T) { 414 defer func() { _mc = NewModuleContainer() }() 415 SetLogger(DefaultLogger(LogSilent, nil, nil)) 416 417 repository := []int{1, 2, 3, 4} 418 type DBer interface { 419 GetData() interface{} 420 } 421 type DB struct { 422 DBer // embed directly 423 Flag int8 424 } 425 type Service struct { 426 Repository []int `module:"repo"` 427 DB DBer `module:"~"` 428 Variable string 429 } 430 type Controller struct { 431 Service *Service `module:"~"` 432 } 433 434 providers := []*ModuleProvider{ 435 TypeProvider(&Service{Variable: "hello world"}), 436 NameProvider("repo", repository), 437 IntfProvider((*DBer)(nil), &DB{Flag: 3}), 438 } 439 xtesting.Nil(t, AutoProvide(providers...)) 440 ctrl := &Controller{Service: MustGetByType(&Service{}).(*Service)} 441 xtesting.Equal(t, ctrl.Service.Variable, "hello world") 442 xtesting.Equal(t, ctrl.Service.Repository, []int{1, 2, 3, 4}) 443 xtesting.Equal(t, ctrl.Service.DB.(*DB).Flag, int8(3)) 444 445 _mc.modules = map[mkey]interface{}{} 446 xtesting.NotPanic(t, func() { _mc.MustAutoProvide(providers...) }) 447 ctrl = &Controller{Service: MustGetByType(&Service{}).(*Service)} 448 xtesting.Equal(t, ctrl.Service.DB.(*DB).Flag, int8(3)) 449 }) 450 451 t.Run("complex", func(t *testing.T) { 452 defer func() { _mc = NewModuleContainer() }() 453 SetLogger(DefaultLogger(LogSilent, nil, nil)) 454 455 type ( 456 IE interface{ EEE() } 457 ID interface{ DDD() } 458 F struct{} 459 E struct { 460 IE 461 F *F `module:"fff"` 462 X string `module:"str1"` 463 Y string `module:"str2"` 464 Z string `module:"~"` 465 } 466 C struct { 467 E IE `module:"~"` 468 F *F `module:"fff"` 469 X string `module:"str2"` 470 Y string `module:"~"` 471 Z uint64 `module:"~"` 472 } 473 D struct { 474 ID 475 C *C `module:"~"` 476 X int32 `module:"int1"` 477 Y int64 `module:"int2"` 478 Z string 479 } 480 B struct { 481 C *C `module:"~"` 482 D ID `module:"~"` 483 X int64 `module:"int2"` 484 Y int8 485 } 486 A struct { 487 B *B `module:"bbb"` 488 C *C `module:"~"` 489 D *D `module:"ddd"` 490 E IE `module:"~"` 491 X string `module:"str1"` 492 Y string `module:"str2"` 493 Z int32 `module:"int1"` 494 W int64 `module:"int2"` 495 } 496 O struct { 497 A *A `module:"~"` 498 F *F `module:"~"` 499 X string 500 Y int64 `module:"int2"` 501 } 502 ) 503 providers := []*ModuleProvider{ 504 TypeProvider(&O{X: "xxx"}), 505 TypeProvider(&A{}), 506 NameProvider("bbb", &B{Y: 127}), 507 TypeProvider(&C{}), 508 IntfProvider((*ID)(nil), &D{Z: "zzz"}), NameProvider("ddd", &D{Z: "zzz2"}), 509 IntfProvider((*IE)(nil), &E{}), 510 NameProvider("fff", &F{}), TypeProvider(&F{}), 511 TypeProvider("abc"), TypeProvider(uint64(789)), 512 NameProvider("int1", int32(111)), NameProvider("int2", int64(222)), 513 NameProvider("str1", "sss"), NameProvider("str2", "ttt"), 514 } 515 _mc = NewModuleContainer() 516 _mc.SetLogger(DefaultLogger(LogPrvName|LogPrvType|LogPrvIntf|LogInjFinish, nil, nil)) 517 xtesting.Nil(t, AutoProvide(providers...)) 518 fmt.Println("==============") 519 _mc = NewModuleContainer() 520 _mc.SetLogger(DefaultLogger(LogInjField|LogInjFinish, nil, nil)) 521 xtesting.NotPanic(t, func() { MustAutoProvide(providers...) }) 522 523 o := _mc.MustGetByType(&O{}).(*O) 524 xtesting.Equal(t, o.X, "xxx") 525 xtesting.Equal(t, o.Y, int64(222)) 526 xtesting.Equal(t, *o.F, F{}) 527 xtesting.Equal(t, o.A.X, "sss") 528 xtesting.Equal(t, o.A.Y, "ttt") 529 xtesting.Equal(t, o.A.Z, int32(111)) 530 xtesting.Equal(t, o.A.W, int64(222)) 531 xtesting.Equal(t, o.A.B.X, int64(222)) 532 xtesting.Equal(t, o.A.B.Y, int8(127)) 533 xtesting.Equal(t, o.A.B.C, o.A.C) 534 xtesting.Equal(t, o.A.B.D.(*D).Y, int64(222)) 535 xtesting.Equal(t, o.A.B.D.(*D).Z, "zzz") 536 xtesting.Equal(t, o.A.C.X, "ttt") 537 xtesting.Equal(t, o.A.C.Y, "abc") 538 xtesting.Equal(t, o.A.C.Z, uint64(789)) 539 xtesting.Equal(t, o.A.C.E, o.A.E) 540 xtesting.Equal(t, *o.A.C.F, F{}) 541 xtesting.Equal(t, o.A.D.X, int32(111)) 542 xtesting.Equal(t, o.A.D.Y, int64(222)) 543 xtesting.Equal(t, o.A.D.Z, "zzz2") 544 xtesting.Equal(t, o.A.D.C, o.A.C) 545 xtesting.Equal(t, o.A.E.(*E).X, "sss") 546 xtesting.Equal(t, o.A.E.(*E).Y, "ttt") 547 xtesting.Equal(t, o.A.E.(*E).Z, "abc") 548 xtesting.Equal(t, *o.A.E.(*E).F, F{}) 549 }) 550 551 t.Run("errors", func(t *testing.T) { 552 defer func() { _mc = NewModuleContainer() }() 553 SetLogger(DefaultLogger(LogSilent, nil, nil)) 554 restore := func() { _mc.modules = map[mkey]interface{}{} } 555 556 type Dep1 struct { 557 X string `module:"x"` 558 Y string `module:"y"` 559 } 560 type Dep2 struct { 561 D *Dep2 `module:"~"` 562 } 563 type Dep3 struct { 564 D interface{} `module:"dep4"` 565 } 566 type Dep4 struct { 567 D *Dep3 `module:"~"` 568 } 569 570 restore() 571 xtesting.NotNil(t, AutoProvide(TypeProvider(&Dep1{}))) // module not found 572 restore() 573 xtesting.NotNil(t, AutoProvide(NameProvider("x", &Dep2{}))) // module not found 574 restore() 575 xtesting.NotNil(t, AutoProvide(TypeProvider(&Dep1{}), NameProvider("x", 0))) // type mismatch 576 restore() 577 xtesting.NotNil(t, AutoProvide(TypeProvider(&Dep1{}), NameProvider("x", 0), NameProvider("y", false))) // type mismatch, multi error 578 restore() 579 xtesting.NotNil(t, AutoProvide(TypeProvider(&Dep2{}))) // dependency cycle 580 restore() 581 xtesting.NotNil(t, AutoProvide(TypeProvider(&Dep3{}), NameProvider("dep4", &Dep4{}))) // dependency cycle 582 583 restore() 584 xtesting.Panic(t, func() { MustAutoProvide(TypeProvider(&Dep1{})) }) 585 restore() 586 xtesting.Panic(t, func() { MustAutoProvide(NameProvider("x", &Dep2{})) }) 587 restore() 588 xtesting.Panic(t, func() { MustAutoProvide(TypeProvider(&Dep1{}), NameProvider("x", 0)) }) 589 restore() 590 xtesting.Panic(t, func() { MustAutoProvide(TypeProvider(&Dep1{}), NameProvider("x", 0), NameProvider("y", false)) }) 591 restore() 592 xtesting.Panic(t, func() { MustAutoProvide(TypeProvider(&Dep2{})) }) 593 restore() 594 xtesting.Panic(t, func() { MustAutoProvide(TypeProvider(&Dep3{}), NameProvider("dep4", &Dep4{})) }) 595 }) 596 } 597 598 func TestLogger(t *testing.T) { 599 xtesting.EqualValue(t, LogPrvName, 1) // 00001 600 xtesting.EqualValue(t, LogPrvType, 2) // 00010 601 xtesting.EqualValue(t, LogPrvIntf, 4) // 00100 602 xtesting.EqualValue(t, LogInjField, 8) // 01000 603 xtesting.EqualValue(t, LogInjFinish, 16) // 10000 604 xtesting.EqualValue(t, LogSilent, 0) // 00000 605 xtesting.EqualValue(t, LogPrv, 7) // 00111 606 xtesting.EqualValue(t, LogAll, 31) // 11111 607 608 type testStruct struct { 609 unexported bool 610 WithoutTag bool 611 EmptyTag bool `module:""` 612 IgnoreTag bool `module:"-"` 613 614 Int int `module:"int"` 615 Uint uint `module:"uint"` 616 Float float64 `module:"~"` 617 String string `module:"~"` 618 Itf interface{} `module:"~"` 619 Error error `module:"~"` 620 } 621 622 for _, tc := range []struct { 623 name string 624 giveLevel LogLevel 625 giveIgnore bool 626 giveMismatch bool 627 giveCustom bool 628 }{ 629 {"LogSilent", LogSilent, false, false, false}, 630 {"LogPrvName", LogPrvName, false, false, false}, 631 {"LogPrvType", LogPrvType, false, false, false}, 632 {"LogPrvIntf", LogPrvIntf, false, false, false}, 633 {"LogPrvName | LogPrvType", LogPrvName | LogPrvType, false, false, false}, 634 {"LogPrvType | LogPrvIntf", LogPrvType | LogPrvIntf, false, false, false}, 635 {"LogPrvName | LogPrvIntf", LogPrvIntf | LogPrvName, false, false, false}, 636 {"LogPrv", LogPrv, false, false, false}, 637 {"LogInjField", LogInjField, false, false, false}, 638 {"LogInjFinish with module not found", LogInjFinish, true, false, false}, 639 {"LogInjFinish with cannot assign", LogInjFinish, false, true, false}, 640 {"LogInjField | LogInjFinish", LogInjField | LogInjFinish, false, false, false}, 641 {"LogAll", LogAll, false, false, false}, 642 {"LogAll with custom function", LogAll, false, false, true}, 643 } { 644 t.Run(tc.name, func(t *testing.T) { 645 mc := NewModuleContainer() 646 if !tc.giveCustom { 647 mc.SetLogger(DefaultLogger(tc.giveLevel, nil, nil)) 648 } else { 649 mc.SetLogger(DefaultLogger(tc.giveLevel, func(moduleName, moduleType string) { 650 fmt.Printf("[Xmodule] Prv: %s <-- %s\n", moduleName, moduleType) 651 }, func(moduleName string, structName string, additional string) { 652 fmt.Printf("[Xmodule] Inj: %s --> %s %s\n", moduleName, structName, additional) 653 })) 654 } 655 656 // prv 657 if !tc.giveMismatch { 658 mc.ProvideByName("int", 1) 659 } else { 660 mc.ProvideByName("int", "1") 661 } 662 if !tc.giveIgnore { 663 mc.ProvideByName("uint", uint(1)) 664 mc.ProvideByType(1.0) 665 } 666 mc.ProvideByType("test") 667 mc.ProvideByIntf((*interface{})(nil), struct{}{}) 668 mc.ProvideByIntf((*error)(nil), errors.New("test")) 669 670 // inj 671 _ = mc.Inject(&testStruct{}) 672 }) 673 } 674 }