@@ -201,6 +201,58 @@ func TestDo_cancelContextSecond(t *testing.T) {
201201 }
202202}
203203
204+ func TestDo_callDoAfterCancellation (t * testing.T ) {
205+ done := make (chan struct {})
206+ defer close (done )
207+
208+ var g singleflight.Group
209+
210+ callCounter := new (atomic.Uint64 )
211+ fn := func (_ context.Context ) (interface {}, error ) {
212+ callCounter .Add (1 )
213+ select {
214+ case <- time .After (time .Second ):
215+ case <- done :
216+ }
217+ return "" , nil
218+ }
219+
220+ go func () {
221+ // keep the function call active for long period (1 second)
222+ if _ , _ , err := g .Do (context .Background (), "key" , fn ); err != nil {
223+ panic (err )
224+ }
225+ }()
226+
227+ { // make another call that is canceled shortly (100 milliseconds)
228+ ctx , cancel := context .WithTimeout (context .Background (), 200 * time .Millisecond )
229+ defer cancel ()
230+ _ , _ , err := g .Do (ctx , "key" , fn )
231+ if ! errors .Is (err , context .DeadlineExceeded ) {
232+ t .Fatal (err )
233+ }
234+ }
235+
236+ want := uint64 (1 )
237+
238+ if got := callCounter .Load (); got != want {
239+ t .Errorf ("got call counter %v, want %v" , got , want )
240+ }
241+
242+ { // make another call after the previous call cancellation
243+ ctx , cancel := context .WithTimeout (context .Background (), 200 * time .Millisecond )
244+ defer cancel ()
245+ _ , _ , err := g .Do (ctx , "key" , fn )
246+ if ! errors .Is (err , context .DeadlineExceeded ) {
247+ t .Fatal (err )
248+ }
249+ }
250+
251+ if got := callCounter .Load (); got != want {
252+ t .Errorf ("got call counter %v, want %v" , got , want )
253+ }
254+ }
255+
204256func TestForget (t * testing.T ) {
205257 done := make (chan struct {})
206258 defer close (done )
0 commit comments