|
|
@@ -555,6 +555,122 @@ func TestJobWithZeroTimeDoesNotRun(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func TestStopAndWait(t *testing.T) {
|
|
|
+ t.Run("nothing running, returns immediately", func(t *testing.T) {
|
|
|
+ cron := newWithSeconds()
|
|
|
+ cron.Start()
|
|
|
+ ctx := cron.Stop()
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ case <-time.After(time.Millisecond):
|
|
|
+ t.Error("context was not done immediately")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("repeated calls to Stop", func(t *testing.T) {
|
|
|
+ cron := newWithSeconds()
|
|
|
+ cron.Start()
|
|
|
+ _ = cron.Stop()
|
|
|
+ time.Sleep(time.Millisecond)
|
|
|
+ ctx := cron.Stop()
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ case <-time.After(time.Millisecond):
|
|
|
+ t.Error("context was not done immediately")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("a couple fast jobs added, still returns immediately", func(t *testing.T) {
|
|
|
+ cron := newWithSeconds()
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ cron.Start()
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ time.Sleep(time.Second)
|
|
|
+ ctx := cron.Stop()
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ case <-time.After(time.Millisecond):
|
|
|
+ t.Error("context was not done immediately")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("a couple fast jobs and a slow job added, waits for slow job", func(t *testing.T) {
|
|
|
+ cron := newWithSeconds()
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ cron.Start()
|
|
|
+ cron.AddFunc("* * * * * *", func() { time.Sleep(2 * time.Second) })
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ time.Sleep(time.Second)
|
|
|
+
|
|
|
+ ctx := cron.Stop()
|
|
|
+
|
|
|
+ // Verify that it is not done for at least 750ms
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ t.Error("context was done too quickly immediately")
|
|
|
+ case <-time.After(750 * time.Millisecond):
|
|
|
+ // expected, because the job sleeping for 1 second is still running
|
|
|
+ }
|
|
|
+
|
|
|
+ // Verify that it IS done in the next 500ms (giving 250ms buffer)
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ // expected
|
|
|
+ case <-time.After(1500 * time.Millisecond):
|
|
|
+ t.Error("context not done after job should have completed")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("repeated calls to stop, waiting for completion and after", func(t *testing.T) {
|
|
|
+ cron := newWithSeconds()
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ cron.AddFunc("* * * * * *", func() { time.Sleep(2 * time.Second) })
|
|
|
+ cron.Start()
|
|
|
+ cron.AddFunc("* * * * * *", func() {})
|
|
|
+ time.Sleep(time.Second)
|
|
|
+ ctx := cron.Stop()
|
|
|
+ ctx2 := cron.Stop()
|
|
|
+
|
|
|
+ // Verify that it is not done for at least 1500ms
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ t.Error("context was done too quickly immediately")
|
|
|
+ case <-ctx2.Done():
|
|
|
+ t.Error("context2 was done too quickly immediately")
|
|
|
+ case <-time.After(1500 * time.Millisecond):
|
|
|
+ // expected, because the job sleeping for 2 seconds is still running
|
|
|
+ }
|
|
|
+
|
|
|
+ // Verify that it IS done in the next 1s (giving 500ms buffer)
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ // expected
|
|
|
+ case <-time.After(time.Second):
|
|
|
+ t.Error("context not done after job should have completed")
|
|
|
+ }
|
|
|
+
|
|
|
+ // Verify that ctx2 is also done.
|
|
|
+ select {
|
|
|
+ case <-ctx2.Done():
|
|
|
+ // expected
|
|
|
+ case <-time.After(time.Millisecond):
|
|
|
+ t.Error("context2 not done even though context1 is")
|
|
|
+ }
|
|
|
+
|
|
|
+ // Verify that a new context retrieved from stop is immediately done.
|
|
|
+ ctx3 := cron.Stop()
|
|
|
+ select {
|
|
|
+ case <-ctx3.Done():
|
|
|
+ // expected
|
|
|
+ case <-time.After(time.Millisecond):
|
|
|
+ t.Error("context not done even when cron Stop is completed")
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
func wait(wg *sync.WaitGroup) chan bool {
|
|
|
ch := make(chan bool)
|
|
|
go func() {
|