@@ -796,6 +796,53 @@ func TestEndToEndSuccess(t *testing.T) {
796796 assert .ElementsMatch (t , actualStrs , expectedStrs , "list of strings provided must match" )
797797 })
798798
799+ t .Run ("multiple As with Group and Name" , func (t * testing.T ) {
800+ c := digtest .New (t )
801+ expectedNames := []string {"inst1" , "inst2" }
802+ expectedStrs := []string {"foo" , "bar" }
803+ for i , s := range expectedStrs {
804+ s := s
805+ c .RequireProvide (func () * bytes.Buffer {
806+ return bytes .NewBufferString (s )
807+ }, dig .Group ("buffs" ), dig .Name (expectedNames [i ]),
808+ dig .As (new (io.Reader ), new (io.Writer )))
809+ }
810+
811+ type in struct {
812+ dig.In
813+
814+ Reader1 io.Reader `name:"inst1"`
815+ Reader2 io.Reader `name:"inst2"`
816+ Readers []io.Reader `group:"buffs"`
817+ Writers []io.Writer `group:"buffs"`
818+ }
819+
820+ var actualStrs []string
821+ var actualStrsName []string
822+
823+ c .RequireInvoke (func (got in ) {
824+ require .Len (t , got .Readers , 2 )
825+ buf := make ([]byte , 3 )
826+ for i , r := range got .Readers {
827+ _ , err := r .Read (buf )
828+ require .NoError (t , err )
829+ actualStrs = append (actualStrs , string (buf ))
830+ // put the text back
831+ got .Writers [i ].Write (buf )
832+ }
833+ _ , err := got .Reader1 .Read (buf )
834+ require .NoError (t , err )
835+ actualStrsName = append (actualStrsName , string (buf ))
836+ _ , err = got .Reader2 .Read (buf )
837+ require .NoError (t , err )
838+ actualStrsName = append (actualStrsName , string (buf ))
839+ require .Len (t , got .Writers , 2 )
840+ })
841+
842+ assert .ElementsMatch (t , actualStrs , expectedStrs , "list of strings provided must match" )
843+ assert .ElementsMatch (t , actualStrsName , expectedStrs , "names: list of strings provided must match" )
844+ })
845+
799846 t .Run ("As same interface" , func (t * testing.T ) {
800847 c := digtest .New (t )
801848 c .RequireProvide (func () io.Reader {
@@ -1145,6 +1192,48 @@ func TestGroups(t *testing.T) {
11451192 })
11461193 })
11471194
1195+ t .Run ("values are provided; coexist with name" , func (t * testing.T ) {
1196+ c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
1197+
1198+ type out struct {
1199+ dig.Out
1200+
1201+ Value int `group:"val"`
1202+ }
1203+
1204+ type out2 struct {
1205+ dig.Out
1206+
1207+ Value int `name:"inst1" group:"val"`
1208+ }
1209+
1210+ provide := func (i int ) {
1211+ c .RequireProvide (func () out {
1212+ return out {Value : i }
1213+ })
1214+ }
1215+
1216+ provide (1 )
1217+ provide (2 )
1218+ provide (3 )
1219+
1220+ c .RequireProvide (func () out2 {
1221+ return out2 {Value : 4 }
1222+ })
1223+
1224+ type in struct {
1225+ dig.In
1226+
1227+ SingleValue int `name:"inst1"`
1228+ Values []int `group:"val"`
1229+ }
1230+
1231+ c .RequireInvoke (func (i in ) {
1232+ assert .Equal (t , []int {1 , 2 , 3 , 4 }, i .Values )
1233+ assert .Equal (t , 4 , i .SingleValue )
1234+ })
1235+ })
1236+
11481237 t .Run ("groups are provided via option" , func (t * testing.T ) {
11491238 c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
11501239
@@ -1169,6 +1258,36 @@ func TestGroups(t *testing.T) {
11691258 })
11701259 })
11711260
1261+ t .Run ("groups are provided via option; coexist with name" , func (t * testing.T ) {
1262+ c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
1263+
1264+ provide := func (i int ) {
1265+ c .RequireProvide (func () int {
1266+ return i
1267+ }, dig .Group ("val" ))
1268+ }
1269+
1270+ provide (1 )
1271+ provide (2 )
1272+ provide (3 )
1273+
1274+ c .RequireProvide (func () int {
1275+ return 4
1276+ }, dig .Group ("val" ), dig .Name ("inst1" ))
1277+
1278+ type in struct {
1279+ dig.In
1280+
1281+ SingleValue int `name:"inst1"`
1282+ Values []int `group:"val"`
1283+ }
1284+
1285+ c .RequireInvoke (func (i in ) {
1286+ assert .Equal (t , []int {1 , 2 , 3 , 4 }, i .Values )
1287+ assert .Equal (t , 4 , i .SingleValue )
1288+ })
1289+ })
1290+
11721291 t .Run ("different types may be grouped" , func (t * testing.T ) {
11731292 c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
11741293
@@ -1476,6 +1595,44 @@ func TestGroups(t *testing.T) {
14761595 })
14771596 })
14781597
1598+ t .Run ("flatten collects slices but also handles name" , func (t * testing.T ) {
1599+ c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
1600+
1601+ type out1 struct {
1602+ dig.Out
1603+
1604+ Value []int `name:"foo1" group:"val,flatten"`
1605+ }
1606+
1607+ type out2 struct {
1608+ dig.Out
1609+
1610+ Value []int `name:"foo2" group:"val,flatten"`
1611+ }
1612+
1613+ c .RequireProvide (func () out1 {
1614+ return out1 {Value : []int {1 , 2 }}
1615+ })
1616+
1617+ c .RequireProvide (func () out2 {
1618+ return out2 {Value : []int {3 , 4 }}
1619+ })
1620+
1621+ type in struct {
1622+ dig.In
1623+
1624+ NotFlattenedSlice1 []int `name:"foo1"`
1625+ NotFlattenedSlice2 []int `name:"foo2"`
1626+ Values []int `group:"val"`
1627+ }
1628+
1629+ c .RequireInvoke (func (i in ) {
1630+ assert .Equal (t , []int {2 , 3 , 4 , 1 }, i .Values )
1631+ assert .Equal (t , []int {1 , 2 }, i .NotFlattenedSlice1 )
1632+ assert .Equal (t , []int {3 , 4 }, i .NotFlattenedSlice2 )
1633+ })
1634+ })
1635+
14791636 t .Run ("flatten via option" , func (t * testing.T ) {
14801637 c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
14811638 c .RequireProvide (func () []int {
@@ -1493,6 +1650,31 @@ func TestGroups(t *testing.T) {
14931650 })
14941651 })
14951652
1653+ t .Run ("flatten via option also handles name" , func (t * testing.T ) {
1654+ c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
1655+ c .RequireProvide (func () []int {
1656+ return []int {1 , 2 }
1657+ }, dig .Group ("val,flatten" ), dig .Name ("foo1" ))
1658+
1659+ c .RequireProvide (func () []int {
1660+ return []int {3 }
1661+ }, dig .Group ("val,flatten" ), dig .Name ("foo2" ))
1662+
1663+ type in struct {
1664+ dig.In
1665+
1666+ NotFlattenedSlice1 []int `name:"foo1"`
1667+ NotFlattenedSlice2 []int `name:"foo2"`
1668+ Values []int `group:"val"`
1669+ }
1670+
1671+ c .RequireInvoke (func (i in ) {
1672+ assert .Equal (t , []int {2 , 3 , 1 }, i .Values )
1673+ assert .Equal (t , []int {1 , 2 }, i .NotFlattenedSlice1 )
1674+ assert .Equal (t , []int {3 }, i .NotFlattenedSlice2 )
1675+ })
1676+ })
1677+
14961678 t .Run ("flatten via option error if not a slice" , func (t * testing.T ) {
14971679 c := digtest .New (t , dig .SetRand (rand .New (rand .NewSource (0 ))))
14981680 err := c .Provide (func () int { return 1 }, dig .Group ("val,flatten" ))
@@ -2219,21 +2401,6 @@ func TestAsExpectingOriginalType(t *testing.T) {
22192401 })
22202402}
22212403
2222- func TestProvideIncompatibleOptions (t * testing.T ) {
2223- t .Parallel ()
2224-
2225- t .Run ("group and name" , func (t * testing.T ) {
2226- c := digtest .New (t )
2227- err := c .Provide (func () io.Reader {
2228- t .Fatal ("this function must not be called" )
2229- return nil
2230- }, dig .Group ("foo" ), dig .Name ("bar" ))
2231- require .Error (t , err )
2232- assert .Contains (t , err .Error (), "cannot use named values with value groups: " +
2233- `name:"bar" provided with group:"foo"` )
2234- })
2235- }
2236-
22372404type testStruct struct {}
22382405
22392406func (testStruct ) TestMethod (x int ) float64 { return float64 (x ) }
@@ -2780,6 +2947,60 @@ func testProvideFailures(t *testing.T, dryRun bool) {
27802947 )
27812948 })
27822949
2950+ t .Run ("provide multiple instances with the same name and same group" , func (t * testing.T ) {
2951+ c := digtest .New (t , dig .DryRun (dryRun ))
2952+ type A struct {}
2953+ type ret1 struct {
2954+ dig.Out
2955+ * A `name:"foo" group:"foos"`
2956+ }
2957+ type ret2 struct {
2958+ dig.Out
2959+ * A `name:"foo" group:"foos"`
2960+ }
2961+ c .RequireProvide (func () ret1 {
2962+ return ret1 {A : & A {}}
2963+ })
2964+
2965+ err := c .Provide (func () ret2 {
2966+ return ret2 {A : & A {}}
2967+ })
2968+ require .Error (t , err , "expected error on the second provide" )
2969+ dig .AssertErrorMatches (t , err ,
2970+ `cannot provide function "go.uber.org/dig_test".testProvideFailures\S+` ,
2971+ `dig_test.go:\d+` , // file:line
2972+ `cannot provide \*dig_test.A\[name="foo"\] from \[0\].A:` ,
2973+ `already provided by "go.uber.org/dig_test".testProvideFailures\S+` ,
2974+ )
2975+ })
2976+
2977+ t .Run ("provide multiple instances with the same name but different group" , func (t * testing.T ) {
2978+ c := digtest .New (t , dig .DryRun (dryRun ))
2979+ type A struct {}
2980+ type ret1 struct {
2981+ dig.Out
2982+ * A `name:"foo" group:"foos"`
2983+ }
2984+ type ret2 struct {
2985+ dig.Out
2986+ * A `name:"foo" group:"foosss"`
2987+ }
2988+ c .RequireProvide (func () ret1 {
2989+ return ret1 {A : & A {}}
2990+ })
2991+
2992+ err := c .Provide (func () ret2 {
2993+ return ret2 {A : & A {}}
2994+ })
2995+ require .Error (t , err , "expected error on the second provide" )
2996+ dig .AssertErrorMatches (t , err ,
2997+ `cannot provide function "go.uber.org/dig_test".testProvideFailures\S+` ,
2998+ `dig_test.go:\d+` , // file:line
2999+ `cannot provide \*dig_test.A\[name="foo"\] from \[0\].A:` ,
3000+ `already provided by "go.uber.org/dig_test".testProvideFailures\S+` ,
3001+ )
3002+ })
3003+
27833004 t .Run ("out with unexported field should error" , func (t * testing.T ) {
27843005 c := digtest .New (t , dig .DryRun (dryRun ))
27853006
0 commit comments