@@ -83,3 +83,114 @@ func TestDoDupSuppress(t *testing.T) {
8383 t .Errorf ("number of calls = %d; want 1" , got )
8484 }
8585}
86+
87+ func TestDoCalledTwice (t * testing.T ) {
88+ var g Group
89+ c := make (chan string )
90+ var calls int32
91+ fn := func () (interface {}, error ) {
92+ atomic .AddInt32 (& calls , 1 )
93+ return <- c , nil
94+ }
95+
96+ const n = 10
97+ var wg sync.WaitGroup
98+ for i := 0 ; i < n ; i ++ {
99+ wg .Add (1 )
100+ go func () {
101+ v , err := g .Do ("key" , fn )
102+ if err != nil {
103+ t .Errorf ("Do error: %v" , err )
104+ }
105+ if v .(string ) != "bar" {
106+ t .Errorf ("got %q; want %q" , v , "bar" )
107+ }
108+ wg .Done ()
109+ }()
110+ }
111+ time .Sleep (100 * time .Millisecond ) // let goroutines above block
112+ c <- "bar"
113+ wg .Wait ()
114+ go func () {
115+ // call one more time; fn() should get called a second time
116+ v , err := g .Do ("key" , fn )
117+ if err != nil {
118+ t .Errorf ("Do error: %v" , err )
119+ }
120+ if v .(string ) != "bar" {
121+ t .Errorf ("got %q; want %q" , v , "bar" )
122+ }
123+ }()
124+ c <- "bar"
125+ if got := atomic .LoadInt32 (& calls ); got != 2 {
126+ t .Errorf ("number of calls = %d; want 2" , got )
127+ }
128+ }
129+
130+ func TestOnceDo (t * testing.T ) {
131+ var g OnceGroup
132+ v , err := g .Do ("key" , func () (interface {}, error ) {
133+ return "bar" , nil
134+ })
135+ if got , want := fmt .Sprintf ("%v (%T)" , v , v ), "bar (string)" ; got != want {
136+ t .Errorf ("Do = %v; want %v" , got , want )
137+ }
138+ if err != nil {
139+ t .Errorf ("Do error = %v" , err )
140+ }
141+ }
142+
143+ func TestOnceDoErr (t * testing.T ) {
144+ var g OnceGroup
145+ someErr := errors .New ("Some error" )
146+ v , err := g .Do ("key" , func () (interface {}, error ) {
147+ return nil , someErr
148+ })
149+ if err != someErr {
150+ t .Errorf ("Do error = %v; want someErr" , err )
151+ }
152+ if v != nil {
153+ t .Errorf ("unexpected non-nil value %#v" , v )
154+ }
155+ }
156+
157+ func TestOnceDoDupSuppress (t * testing.T ) {
158+ var g OnceGroup
159+ c := make (chan string )
160+ var calls int32
161+ fn := func () (interface {}, error ) {
162+ atomic .AddInt32 (& calls , 1 )
163+ return <- c , nil
164+ }
165+
166+ const n = 10
167+ var wg sync.WaitGroup
168+ for i := 0 ; i < n ; i ++ {
169+ wg .Add (1 )
170+ go func () {
171+ v , err := g .Do ("key" , fn )
172+ if err != nil {
173+ t .Errorf ("Do error: %v" , err )
174+ }
175+ if v .(string ) != "bar" {
176+ t .Errorf ("got %q; want %q" , v , "bar" )
177+ }
178+ wg .Done ()
179+ }()
180+ }
181+ time .Sleep (100 * time .Millisecond ) // let goroutines above block
182+ c <- "bar"
183+ wg .Wait ()
184+ // one more time after every goroutine has completed - should return the
185+ // same result instantly.
186+ v , err := g .Do ("key" , fn )
187+ if err != nil {
188+ t .Errorf ("Do error: %v" , err )
189+ }
190+ if v .(string ) != "bar" {
191+ t .Errorf ("got %q; want %q" , v , "bar" )
192+ }
193+ if got := atomic .LoadInt32 (& calls ); got != 1 {
194+ t .Errorf ("number of calls = %d; want 1" , got )
195+ }
196+ }
0 commit comments