blob: b29baa632daacf539ea95448680ac000a5495827 [file] [log] [blame]
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -08001package rt_test
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "syscall"
8 "testing"
9 "time"
10
Jiri Simsa764efb72014-12-25 20:57:03 -080011 "v.io/core/veyron2"
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080012
Jiri Simsa764efb72014-12-25 20:57:03 -080013 "v.io/core/veyron/lib/expect"
14 "v.io/core/veyron/lib/modules"
15 "v.io/core/veyron/lib/signals"
16 "v.io/core/veyron/lib/testutil"
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080017)
18
19var cstderr io.Writer
20
21func init() {
22 testutil.Init()
23 if testing.Verbose() {
24 cstderr = os.Stderr
25 }
26}
27
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -080028func newShell(t *testing.T) *modules.Shell {
29 sh, err := modules.NewShell(nil)
30 if err != nil {
31 t.Fatalf("unexpected error: %s", err)
32 }
33 return sh
34}
35
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080036// TestSimpleServerSignal verifies that sending a signal to the simple server
37// causes it to exit cleanly.
38func TestSimpleServerSignal(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -080039 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080040 defer sh.Cleanup(os.Stdout, cstderr)
41 h, _ := sh.Start("simpleServerProgram", nil)
42 s := expect.NewSession(t, h.Stdout(), time.Minute)
43 s.Expect("Ready")
44 syscall.Kill(h.Pid(), syscall.SIGINT)
45 s.Expect("Received signal interrupt")
46 s.Expect("Interruptible cleanup")
47 s.Expect("Deferred cleanup")
48 fmt.Fprintln(h.Stdin(), "close")
49 s.ExpectEOF()
50}
51
52// TestSimpleServerLocalStop verifies that sending a local stop command to the
53// simple server causes it to exit cleanly.
54func TestSimpleServerLocalStop(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -080055 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080056 defer sh.Cleanup(os.Stdout, cstderr)
57 h, _ := sh.Start("simpleServerProgram", nil)
58 s := expect.NewSession(t, h.Stdout(), time.Minute)
59 s.Expect("Ready")
60 fmt.Fprintln(h.Stdin(), "stop")
61 s.Expect(fmt.Sprintf("Received signal %s", veyron2.LocalStop))
62 s.Expect("Interruptible cleanup")
63 s.Expect("Deferred cleanup")
64 fmt.Fprintln(h.Stdin(), "close")
65 s.ExpectEOF()
66}
67
68// TestSimpleServerDoubleSignal verifies that sending a succession of two
69// signals to the simple server causes it to initiate the cleanup sequence on
70// the first signal and then exit immediately on the second signal.
71func TestSimpleServerDoubleSignal(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -080072 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080073 defer sh.Cleanup(os.Stdout, cstderr)
74 h, _ := sh.Start("simpleServerProgram", nil)
75 s := expect.NewSession(t, h.Stdout(), time.Minute)
76 s.Expect("Ready")
77 syscall.Kill(h.Pid(), syscall.SIGINT)
78 s.Expect("Received signal interrupt")
79 syscall.Kill(h.Pid(), syscall.SIGINT)
80 err := h.Shutdown(os.Stdout, cstderr)
81 if err == nil {
82 t.Fatalf("expected an error")
83 }
84 if got, want := err.Error(), fmt.Sprintf("exit status %d", signals.DoubleStopExitCode); got != want {
85 t.Errorf("got %q, want %q", got, want)
86 }
87}
88
89// TestSimpleServerLocalForceStop verifies that sending a local ForceStop
90// command to the simple server causes it to exit immediately.
91func TestSimpleServerLocalForceStop(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -080092 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -080093 defer sh.Cleanup(os.Stdout, cstderr)
94 h, _ := sh.Start("simpleServerProgram", nil)
95 s := expect.NewSession(t, h.Stdout(), time.Minute)
96 s.Expect("Ready")
97 fmt.Fprintln(h.Stdin(), "forcestop")
98 s.Expect("straight exit")
99 err := h.Shutdown(os.Stdout, cstderr)
100 if err == nil {
101 t.Fatalf("expected an error")
102 }
103 if got, want := err.Error(), fmt.Sprintf("exit status %d", veyron2.ForceStopExitCode); got != want {
104 t.Errorf("got %q, want %q", got, want)
105 }
106}
107
108// TestSimpleServerKill demonstrates that a SIGKILL still forces the server
109// to exit regardless of our signal handling.
110func TestSimpleServerKill(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800111 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -0800112 defer sh.Cleanup(os.Stdout, cstderr)
113 h, _ := sh.Start("simpleServerProgram", nil)
114 s := expect.NewSession(t, h.Stdout(), time.Minute)
115 s.Expect("Ready")
116 syscall.Kill(h.Pid(), syscall.SIGKILL)
117 err := h.Shutdown(os.Stdout, cstderr)
118 if err == nil {
119 t.Fatalf("expected an error")
120 }
121 if got, want := err.Error(), "signal: killed"; got != want {
122 t.Errorf("got %q, want %q", got, want)
123 }
124}
125
126// TestComplexServerSignal verifies that sending a signal to the complex server
127// initiates the cleanup sequence in that server (we observe the printouts
128// corresponding to all the simulated sequential/parallel and
129// blocking/interruptible shutdown steps), and then exits cleanly.
130func TestComplexServerSignal(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800131 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -0800132 defer sh.Cleanup(os.Stdout, cstderr)
133 h, _ := sh.Start("complexServerProgram", nil)
134 s := expect.NewSession(t, h.Stdout(), time.Minute)
135 s.Expect("Ready")
136 syscall.Kill(h.Pid(), syscall.SIGINT)
137 s.Expect("Received signal interrupt")
138 s.ExpectSetRE("Sequential blocking cleanup",
139 "Sequential interruptible cleanup",
140 "Parallel blocking cleanup1",
141 "Parallel blocking cleanup2",
142 "Parallel interruptible cleanup1",
143 "Parallel interruptible cleanup2")
144 fmt.Fprintln(h.Stdin(), "close")
145 s.ExpectEOF()
146}
147
148// TestComplexServerLocalStop verifies that sending a local stop command to the
149// complex server initiates the cleanup sequence in that server (we observe the
150// printouts corresponding to all the simulated sequential/parallel and
151// blocking/interruptible shutdown steps), and then exits cleanly.
152func TestComplexServerLocalStop(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800153 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -0800154 defer sh.Cleanup(os.Stdout, cstderr)
155 h, _ := sh.Start("complexServerProgram", nil)
156 s := expect.NewSession(t, h.Stdout(), time.Minute)
157 s.Expect("Ready")
158
159 fmt.Fprintln(h.Stdin(), "stop")
160 s.Expect(fmt.Sprintf("Stop %s", veyron2.LocalStop))
161 s.ExpectSetRE(
162 "Sequential blocking cleanup",
163 "Sequential interruptible cleanup",
164 "Parallel blocking cleanup1",
165 "Parallel blocking cleanup2",
166 "Parallel interruptible cleanup1",
167 "Parallel interruptible cleanup2",
168 )
169 fmt.Fprintln(h.Stdin(), "close")
170 s.ExpectEOF()
171}
172
173// TestComplexServerDoubleSignal verifies that sending a succession of two
174// signals to the complex server has the expected effect: the first signal
175// initiates the cleanup steps and the second signal kills the process, but only
176// after the blocking shutdown steps were allowed to complete (as observed by
177// the corresponding printouts from the server). Note that we have no
178// expectations on whether or not the interruptible shutdown steps execute.
179func TestComplexServerDoubleSignal(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800180 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -0800181 defer sh.Cleanup(os.Stdout, cstderr)
182 h, _ := sh.Start("complexServerProgram", nil)
183 s := expect.NewSession(t, h.Stdout(), time.Minute)
184 s.Expect("Ready")
185 syscall.Kill(h.Pid(), syscall.SIGINT)
186 s.Expect("Received signal interrupt")
187 syscall.Kill(h.Pid(), syscall.SIGINT)
188 s.ExpectSetEventuallyRE(
189 "Sequential blocking cleanup",
190 "Parallel blocking cleanup1",
191 "Parallel blocking cleanup2")
192 err := h.Shutdown(os.Stdout, cstderr)
193 if err == nil {
194 t.Fatalf("expected an error")
195 }
196 if got, want := err.Error(), fmt.Sprintf("exit status %d", signals.DoubleStopExitCode); got != want {
197 t.Errorf("got %q, want %q", got, want)
198 }
199}
200
201// TestComplexServerLocalForceStop verifies that sending a local ForceStop
202// command to the complex server forces it to exit immediately.
203func TestComplexServerLocalForceStop(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800204 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -0800205 defer sh.Cleanup(os.Stdout, cstderr)
206 h, _ := sh.Start("complexServerProgram", nil)
207 s := expect.NewSession(t, h.Stdout(), time.Minute)
208 s.Expect("Ready")
209 fmt.Fprintln(h.Stdin(), "forcestop")
210 s.Expect("straight exit")
211 err := h.Shutdown(os.Stdout, cstderr)
212 if err == nil {
213 t.Fatalf("expected an error")
214 }
215 if got, want := err.Error(), fmt.Sprintf("exit status %d", veyron2.ForceStopExitCode); got != want {
216 t.Errorf("got %q, want %q", got, want)
217 }
218}
219
220// TestComplexServerKill demonstrates that a SIGKILL still forces the server to
221// exit regardless of our signal handling.
222func TestComplexServerKill(t *testing.T) {
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800223 sh := newShell(t)
Cosmos Nicolaoua429eff2014-11-19 14:02:34 -0800224 defer sh.Cleanup(os.Stdout, cstderr)
225 h, _ := sh.Start("complexServerProgram", nil)
226 s := expect.NewSession(t, h.Stdout(), time.Minute)
227 s.Expect("Ready")
228 syscall.Kill(h.Pid(), syscall.SIGKILL)
229 err := h.Shutdown(os.Stdout, cstderr)
230 if err == nil {
231 t.Fatalf("expected an error")
232 }
233 if got, want := err.Error(), "signal: killed"; got != want {
234 t.Errorf("got %q, want %q", got, want)
235 }
236}