Tizen_4.0 base
[platform/upstream/docker-engine.git] / container / state_test.go
1 package container
2
3 import (
4         "context"
5         "testing"
6         "time"
7
8         "github.com/docker/docker/api/types"
9 )
10
11 func TestIsValidHealthString(t *testing.T) {
12         contexts := []struct {
13                 Health   string
14                 Expected bool
15         }{
16                 {types.Healthy, true},
17                 {types.Unhealthy, true},
18                 {types.Starting, true},
19                 {types.NoHealthcheck, true},
20                 {"fail", false},
21         }
22
23         for _, c := range contexts {
24                 v := IsValidHealthString(c.Health)
25                 if v != c.Expected {
26                         t.Fatalf("Expected %t, but got %t", c.Expected, v)
27                 }
28         }
29 }
30
31 func TestStateRunStop(t *testing.T) {
32         s := NewState()
33
34         // Begin another wait with WaitConditionRemoved. It should complete
35         // within 200 milliseconds.
36         ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
37         defer cancel()
38         removalWait := s.Wait(ctx, WaitConditionRemoved)
39
40         // Full lifecycle two times.
41         for i := 1; i <= 2; i++ {
42                 // A wait with WaitConditionNotRunning should return
43                 // immediately since the state is now either "created" (on the
44                 // first iteration) or "exited" (on the second iteration). It
45                 // shouldn't take more than 50 milliseconds.
46                 ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
47                 defer cancel()
48                 // Expectx exit code to be i-1 since it should be the exit
49                 // code from the previous loop or 0 for the created state.
50                 if status := <-s.Wait(ctx, WaitConditionNotRunning); status.ExitCode() != i-1 {
51                         t.Fatalf("ExitCode %v, expected %v, err %q", status.ExitCode(), i-1, status.Err())
52                 }
53
54                 // A wait with WaitConditionNextExit should block until the
55                 // container has started and exited. It shouldn't take more
56                 // than 100 milliseconds.
57                 ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
58                 defer cancel()
59                 initialWait := s.Wait(ctx, WaitConditionNextExit)
60
61                 // Set the state to "Running".
62                 s.Lock()
63                 s.SetRunning(i, true)
64                 s.Unlock()
65
66                 // Assert desired state.
67                 if !s.IsRunning() {
68                         t.Fatal("State not running")
69                 }
70                 if s.Pid != i {
71                         t.Fatalf("Pid %v, expected %v", s.Pid, i)
72                 }
73                 if s.ExitCode() != 0 {
74                         t.Fatalf("ExitCode %v, expected 0", s.ExitCode())
75                 }
76
77                 // Now that it's running, a wait with WaitConditionNotRunning
78                 // should block until we stop the container. It shouldn't take
79                 // more than 100 milliseconds.
80                 ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
81                 defer cancel()
82                 exitWait := s.Wait(ctx, WaitConditionNotRunning)
83
84                 // Set the state to "Exited".
85                 s.Lock()
86                 s.SetStopped(&ExitStatus{ExitCode: i})
87                 s.Unlock()
88
89                 // Assert desired state.
90                 if s.IsRunning() {
91                         t.Fatal("State is running")
92                 }
93                 if s.ExitCode() != i {
94                         t.Fatalf("ExitCode %v, expected %v", s.ExitCode(), i)
95                 }
96                 if s.Pid != 0 {
97                         t.Fatalf("Pid %v, expected 0", s.Pid)
98                 }
99
100                 // Receive the initialWait result.
101                 if status := <-initialWait; status.ExitCode() != i {
102                         t.Fatalf("ExitCode %v, expected %v, err %q", status.ExitCode(), i, status.Err())
103                 }
104
105                 // Receive the exitWait result.
106                 if status := <-exitWait; status.ExitCode() != i {
107                         t.Fatalf("ExitCode %v, expected %v, err %q", status.ExitCode(), i, status.Err())
108                 }
109         }
110
111         // Set the state to dead and removed.
112         s.SetDead()
113         s.SetRemoved()
114
115         // Wait for removed status or timeout.
116         if status := <-removalWait; status.ExitCode() != 2 {
117                 // Should have the final exit code from the loop.
118                 t.Fatalf("Removal wait exitCode %v, expected %v, err %q", status.ExitCode(), 2, status.Err())
119         }
120 }
121
122 func TestStateTimeoutWait(t *testing.T) {
123         s := NewState()
124
125         s.Lock()
126         s.SetRunning(0, true)
127         s.Unlock()
128
129         // Start a wait with a timeout.
130         ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
131         defer cancel()
132         waitC := s.Wait(ctx, WaitConditionNotRunning)
133
134         // It should timeout *before* this 200ms timer does.
135         select {
136         case <-time.After(200 * time.Millisecond):
137                 t.Fatal("Stop callback doesn't fire in 200 milliseconds")
138         case status := <-waitC:
139                 t.Log("Stop callback fired")
140                 // Should be a timeout error.
141                 if status.Err() == nil {
142                         t.Fatal("expected timeout error, got nil")
143                 }
144                 if status.ExitCode() != -1 {
145                         t.Fatalf("expected exit code %v, got %v", -1, status.ExitCode())
146                 }
147         }
148
149         s.Lock()
150         s.SetStopped(&ExitStatus{ExitCode: 0})
151         s.Unlock()
152
153         // Start another wait with a timeout. This one should return
154         // immediately.
155         ctx, cancel = context.WithTimeout(context.Background(), 100*time.Millisecond)
156         defer cancel()
157         waitC = s.Wait(ctx, WaitConditionNotRunning)
158
159         select {
160         case <-time.After(200 * time.Millisecond):
161                 t.Fatal("Stop callback doesn't fire in 200 milliseconds")
162         case status := <-waitC:
163                 t.Log("Stop callback fired")
164                 if status.ExitCode() != 0 {
165                         t.Fatalf("expected exit code %v, got %v, err %q", 0, status.ExitCode(), status.Err())
166                 }
167         }
168 }