package daemon import ( "testing" "time" "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" eventtypes "github.com/docker/docker/api/types/events" "github.com/docker/docker/container" "github.com/docker/docker/daemon/events" ) func reset(c *container.Container) { c.State = &container.State{} c.State.Health = &container.Health{} c.State.Health.SetStatus(types.Starting) } func TestNoneHealthcheck(t *testing.T) { c := &container.Container{ ID: "container_id", Name: "container_name", Config: &containertypes.Config{ Image: "image_name", Healthcheck: &containertypes.HealthConfig{ Test: []string{"NONE"}, }, }, State: &container.State{}, } store, err := container.NewViewDB() if err != nil { t.Fatal(err) } daemon := &Daemon{ containersReplica: store, } daemon.initHealthMonitor(c) if c.State.Health != nil { t.Error("Expecting Health to be nil, but was not") } } // FIXME(vdemeester) This takes around 3s… This is *way* too long func TestHealthStates(t *testing.T) { e := events.New() _, l, _ := e.Subscribe() defer e.Evict(l) expect := func(expected string) { select { case event := <-l: ev := event.(eventtypes.Message) if ev.Status != expected { t.Errorf("Expecting event %#v, but got %#v\n", expected, ev.Status) } case <-time.After(1 * time.Second): t.Errorf("Expecting event %#v, but got nothing\n", expected) } } c := &container.Container{ ID: "container_id", Name: "container_name", Config: &containertypes.Config{ Image: "image_name", }, } store, err := container.NewViewDB() if err != nil { t.Fatal(err) } daemon := &Daemon{ EventsService: e, containersReplica: store, } c.Config.Healthcheck = &containertypes.HealthConfig{ Retries: 1, } reset(c) handleResult := func(startTime time.Time, exitCode int) { handleProbeResult(daemon, c, &types.HealthcheckResult{ Start: startTime, End: startTime, ExitCode: exitCode, }, nil) } // starting -> failed -> success -> failed handleResult(c.State.StartedAt.Add(1*time.Second), 1) expect("health_status: unhealthy") handleResult(c.State.StartedAt.Add(2*time.Second), 0) expect("health_status: healthy") handleResult(c.State.StartedAt.Add(3*time.Second), 1) expect("health_status: unhealthy") // Test retries reset(c) c.Config.Healthcheck.Retries = 3 handleResult(c.State.StartedAt.Add(20*time.Second), 1) handleResult(c.State.StartedAt.Add(40*time.Second), 1) if status := c.State.Health.Status(); status != types.Starting { t.Errorf("Expecting starting, but got %#v\n", status) } if c.State.Health.FailingStreak != 2 { t.Errorf("Expecting FailingStreak=2, but got %d\n", c.State.Health.FailingStreak) } handleResult(c.State.StartedAt.Add(60*time.Second), 1) expect("health_status: unhealthy") handleResult(c.State.StartedAt.Add(80*time.Second), 0) expect("health_status: healthy") if c.State.Health.FailingStreak != 0 { t.Errorf("Expecting FailingStreak=0, but got %d\n", c.State.Health.FailingStreak) } // Test start period reset(c) c.Config.Healthcheck.Retries = 2 c.Config.Healthcheck.StartPeriod = 30 * time.Second handleResult(c.State.StartedAt.Add(20*time.Second), 1) if status := c.State.Health.Status(); status != types.Starting { t.Errorf("Expecting starting, but got %#v\n", status) } if c.State.Health.FailingStreak != 0 { t.Errorf("Expecting FailingStreak=0, but got %d\n", c.State.Health.FailingStreak) } handleResult(c.State.StartedAt.Add(50*time.Second), 1) if status := c.State.Health.Status(); status != types.Starting { t.Errorf("Expecting starting, but got %#v\n", status) } if c.State.Health.FailingStreak != 1 { t.Errorf("Expecting FailingStreak=1, but got %d\n", c.State.Health.FailingStreak) } handleResult(c.State.StartedAt.Add(80*time.Second), 0) expect("health_status: healthy") if c.State.Health.FailingStreak != 0 { t.Errorf("Expecting FailingStreak=0, but got %d\n", c.State.Health.FailingStreak) } }