| package engine |
| |
| import ( |
| "testing" |
| "time" |
| ) |
| |
| func TestShutdownEmpty(t *testing.T) { |
| eng := New() |
| if eng.IsShutdown() { |
| t.Fatalf("IsShutdown should be false") |
| } |
| eng.Shutdown() |
| if !eng.IsShutdown() { |
| t.Fatalf("IsShutdown should be true") |
| } |
| } |
| |
| func TestShutdownAfterRun(t *testing.T) { |
| eng := New() |
| var called bool |
| eng.Register("foo", func(job *Job) Status { |
| called = true |
| return StatusOK |
| }) |
| if err := eng.Job("foo").Run(); err != nil { |
| t.Fatal(err) |
| } |
| eng.Shutdown() |
| if err := eng.Job("foo").Run(); err == nil { |
| t.Fatalf("%#v", *eng) |
| } |
| } |
| |
| // An approximate and racy, but better-than-nothing test that |
| // |
| func TestShutdownDuringRun(t *testing.T) { |
| var ( |
| jobDelay time.Duration = 500 * time.Millisecond |
| jobDelayLow time.Duration = 100 * time.Millisecond |
| jobDelayHigh time.Duration = 700 * time.Millisecond |
| ) |
| eng := New() |
| var completed bool |
| eng.Register("foo", func(job *Job) Status { |
| time.Sleep(jobDelay) |
| completed = true |
| return StatusOK |
| }) |
| go eng.Job("foo").Run() |
| time.Sleep(50 * time.Millisecond) |
| done := make(chan struct{}) |
| var startShutdown time.Time |
| go func() { |
| startShutdown = time.Now() |
| eng.Shutdown() |
| close(done) |
| }() |
| time.Sleep(50 * time.Millisecond) |
| if err := eng.Job("foo").Run(); err == nil { |
| t.Fatalf("run on shutdown should fail: %#v", *eng) |
| } |
| <-done |
| // Verify that Shutdown() blocks for roughly 500ms, instead |
| // of returning almost instantly. |
| // |
| // We use >100ms to leave ample margin for race conditions between |
| // goroutines. It's possible (but unlikely in reasonable testing |
| // conditions), that this test will cause a false positive or false |
| // negative. But it's probably better than not having any test |
| // for the 99.999% of time where testing conditions are reasonable. |
| if d := time.Since(startShutdown); d.Nanoseconds() < jobDelayLow.Nanoseconds() { |
| t.Fatalf("shutdown did not block long enough: %v", d) |
| } else if d.Nanoseconds() > jobDelayHigh.Nanoseconds() { |
| t.Fatalf("shutdown blocked too long: %v", d) |
| } |
| if !completed { |
| t.Fatalf("job did not complete") |
| } |
| } |