@@ -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