package thread import ( "context" "github.com/stretchr/testify/assert" "strconv" "sync" "sync/atomic" "testing" "time" ) type report struct { rw sync.Mutex text string } func (r *report) log(text string) { r.rw.Lock() defer r.rw.Unlock() r.text += text } func (r *report) String() string { return r.text } func Test_checkManager(t *testing.T) { var count atomic.Int32 var r report var wg sync.WaitGroup ctx, cancel := context.WithCancel(context.Background()) wg.Add(1) go func() { defer wg.Done() r.log("Start manger\n") manager := Manager{Count: 3} go manager.Start(func() { number := count.Add(1) r.log("Start " + strconv.Itoa(int(number)) + "\n") switch number { case 1: <-ctx.Done() time.Sleep(100 * time.Millisecond) case 2: time.Sleep(100 * time.Millisecond) case 3: time.Sleep(200 * time.Millisecond) case 4: time.Sleep(200 * time.Millisecond) case 5: <-ctx.Done() time.Sleep(200 * time.Millisecond) case 6: <-ctx.Done() time.Sleep(300 * time.Millisecond) default: <-ctx.Done() time.Sleep(400 * time.Millisecond) } r.log("Finish " + strconv.Itoa(int(number)) + "\n") }) r.log("Wait cancel\n") manager.Wait(ctx) r.log("Finish manger\n") }() time.Sleep(1 * time.Second) cancel() wg.Wait() assert.Equal(t, int32(6), count.Load()) assert.Equal(t, "Start manger\nWait cancel\nStart 1\nStart 2\nStart 3\nFinish 2\nStart 4\nFinish 3\nStart 5\nFinish 4\nStart 6\nFinish 1\nFinish 5\nFinish 6\nFinish manger\n", r.String()) }