daemon/health_test.go
b6c7becb
 package daemon
 
 import (
 	"testing"
 	"time"
 
91e197d6
 	"github.com/docker/docker/api/types"
 	containertypes "github.com/docker/docker/api/types/container"
 	eventtypes "github.com/docker/docker/api/types/events"
b6c7becb
 	"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{}
7db30ab0
 	c.State.Health.SetStatus(types.Starting)
b6c7becb
 }
 
4016038b
 func TestNoneHealthcheck(t *testing.T) {
 	c := &container.Container{
55f8828e
 		ID:   "container_id",
 		Name: "container_name",
 		Config: &containertypes.Config{
 			Image: "image_name",
 			Healthcheck: &containertypes.HealthConfig{
 				Test: []string{"NONE"},
4016038b
 			},
 		},
55f8828e
 		State: &container.State{},
4016038b
 	}
aacddda8
 	store, err := container.NewViewDB()
eed4c7b7
 	if err != nil {
 		t.Fatal(err)
 	}
 	daemon := &Daemon{
 		containersReplica: store,
 	}
4016038b
 
 	daemon.initHealthMonitor(c)
 	if c.State.Health != nil {
f78f7de9
 		t.Error("Expecting Health to be nil, but was not")
4016038b
 	}
 }
 
522bfd92
 // FIXME(vdemeester) This takes around 3s… This is *way* too long
b6c7becb
 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{
55f8828e
 		ID:   "container_id",
 		Name: "container_name",
 		Config: &containertypes.Config{
 			Image: "image_name",
b6c7becb
 		},
 	}
eed4c7b7
 
aacddda8
 	store, err := container.NewViewDB()
eed4c7b7
 	if err != nil {
 		t.Fatal(err)
 	}
 
b6c7becb
 	daemon := &Daemon{
eed4c7b7
 		EventsService:     e,
 		containersReplica: store,
b6c7becb
 	}
 
 	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,
89b12347
 		}, nil)
b6c7becb
 	}
 
 	// 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)
7db30ab0
 	if status := c.State.Health.Status(); status != types.Starting {
 		t.Errorf("Expecting starting, but got %#v\n", status)
b6c7becb
 	}
 	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)
 	}
e401f637
 
 	// 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)
7db30ab0
 	if status := c.State.Health.Status(); status != types.Starting {
 		t.Errorf("Expecting starting, but got %#v\n", status)
e401f637
 	}
 	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)
7db30ab0
 	if status := c.State.Health.Status(); status != types.Starting {
 		t.Errorf("Expecting starting, but got %#v\n", status)
e401f637
 	}
 	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)
 	}
b6c7becb
 }