blob: ae779e66e7871999ad6646cb5cf3d274f46cc92e [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Jiri Simsa5293dcb2014-05-10 09:56:38 -07005package signals
6
7import (
Cosmos Nicolaoucc581722014-10-07 12:45:39 -07008 "bufio"
Jiri Simsa5293dcb2014-05-10 09:56:38 -07009 "fmt"
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070010 "io"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070011 "os"
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070012 "path/filepath"
13 "runtime"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070014 "syscall"
15 "testing"
16
Jiri Simsa6ac95222015-02-23 16:11:49 -080017 "v.io/v23"
18 "v.io/v23/context"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070019 "v.io/v23/rpc"
Todd Wang94c9d0b2015-04-01 14:27:00 -070020 "v.io/v23/services/appcycle"
Jiri Simsa6ac95222015-02-23 16:11:49 -080021 "v.io/v23/vtrace"
Todd Wang712eeef2015-04-03 17:13:50 -070022 "v.io/x/ref/lib/mgmt"
Todd Wangb3511492015-04-07 23:32:34 -070023 "v.io/x/ref/lib/security/securityflag"
Todd Wangcd4b3cc2015-04-06 16:42:02 -070024 "v.io/x/ref/services/device"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070025 "v.io/x/ref/test"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070026 "v.io/x/ref/test/modules"
Todd Wangb3511492015-04-07 23:32:34 -070027
Suharsh Sivakumardcc11d72015-05-11 12:19:20 -070028 _ "v.io/x/ref/runtime/factories/generic"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070029)
30
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080031//go:generate v23 test generate
Jiri Simsa5293dcb2014-05-10 09:56:38 -070032
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080033func stopLoop(stop func(), stdin io.Reader, ch chan<- struct{}) {
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070034 scanner := bufio.NewScanner(stdin)
35 for scanner.Scan() {
36 switch scanner.Text() {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070037 case "close":
38 close(ch)
39 return
40 case "stop":
Suharsh Sivakumard68949c2015-01-26 10:32:23 -080041 stop()
Jiri Simsa5293dcb2014-05-10 09:56:38 -070042 }
43 }
44}
45
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070046func program(stdin io.Reader, stdout io.Writer, signals ...os.Signal) {
Todd Wang60052d82015-05-22 15:00:10 -070047 ctx, shutdown := test.V23Init()
Jiri Simsa5293dcb2014-05-10 09:56:38 -070048 closeStopLoop := make(chan struct{})
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070049 // obtain ac here since stopLoop may execute after shutdown is called below
50 ac := v23.GetAppCycle(ctx)
51 go stopLoop(func() { ac.Stop(ctx) }, stdin, closeStopLoop)
Suharsh Sivakumar946f64d2015-01-08 10:48:13 -080052 wait := ShutdownOnSignals(ctx, signals...)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070053 fmt.Fprintf(stdout, "ready\n")
54 fmt.Fprintf(stdout, "received signal %s\n", <-wait)
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080055 shutdown()
Jiri Simsa5293dcb2014-05-10 09:56:38 -070056 <-closeStopLoop
57}
58
Todd Wang95873902015-05-22 14:21:30 -070059var handleDefaults = modules.Register(func(env *modules.Env, args ...string) error {
60 program(env.Stdin, env.Stdout)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070061 return nil
Todd Wang95873902015-05-22 14:21:30 -070062}, "handleDefaults")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070063
Todd Wang95873902015-05-22 14:21:30 -070064var handleCustom = modules.Register(func(env *modules.Env, args ...string) error {
65 program(env.Stdin, env.Stdout, syscall.SIGABRT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070066 return nil
Todd Wang95873902015-05-22 14:21:30 -070067}, "handleCustom")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070068
Todd Wang95873902015-05-22 14:21:30 -070069var handleCustomWithStop = modules.Register(func(env *modules.Env, args ...string) error {
70 program(env.Stdin, env.Stdout, STOP, syscall.SIGABRT, syscall.SIGHUP)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070071 return nil
Todd Wang95873902015-05-22 14:21:30 -070072}, "handleCustomWithStop")
Bogdan Caprita1002ba42014-06-06 19:24:40 -070073
Todd Wang95873902015-05-22 14:21:30 -070074var handleDefaultsIgnoreChan = modules.Register(func(env *modules.Env, args ...string) error {
Todd Wang60052d82015-05-22 15:00:10 -070075 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080076 defer shutdown()
Jiri Simsa5293dcb2014-05-10 09:56:38 -070077 closeStopLoop := make(chan struct{})
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070078 // obtain ac here since stopLoop may execute after shutdown is called below
79 ac := v23.GetAppCycle(ctx)
80 go stopLoop(func() { ac.Stop(ctx) }, env.Stdin, closeStopLoop)
Suharsh Sivakumar946f64d2015-01-08 10:48:13 -080081 ShutdownOnSignals(ctx)
Todd Wang95873902015-05-22 14:21:30 -070082 fmt.Fprintf(env.Stdout, "ready\n")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070083 <-closeStopLoop
Cosmos Nicolaoucc581722014-10-07 12:45:39 -070084 return nil
Todd Wang95873902015-05-22 14:21:30 -070085}, "handleDefaultsIgnoreChan")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070086
87func isSignalInSet(sig os.Signal, set []os.Signal) bool {
88 for _, s := range set {
89 if sig == s {
90 return true
91 }
92 }
93 return false
94}
95
96func checkSignalIsDefault(t *testing.T, sig os.Signal) {
97 if !isSignalInSet(sig, defaultSignals()) {
98 t.Errorf("signal %s not in default signal set, as expected", sig)
99 }
100}
101
102func checkSignalIsNotDefault(t *testing.T, sig os.Signal) {
103 if isSignalInSet(sig, defaultSignals()) {
104 t.Errorf("signal %s unexpectedly in default signal set", sig)
105 }
106}
107
Todd Wang95873902015-05-22 14:21:30 -0700108func newShell(t *testing.T, ctx *context.T, prog modules.Program) (*modules.Shell, modules.Handle) {
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700109 sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800110 if err != nil {
111 t.Fatalf("unexpected error: %s", err)
112 }
Todd Wang95873902015-05-22 14:21:30 -0700113 handle, err := sh.Start(nil, prog)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700114 if err != nil {
115 sh.Cleanup(os.Stderr, os.Stderr)
116 t.Fatalf("unexpected error: %s", err)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700117 return nil, nil
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700118 }
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700119 return sh, handle
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700120}
121
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700122// TestCleanShutdownSignal verifies that sending a signal to a child that
123// handles it by default causes the child to shut down cleanly.
124func TestCleanShutdownSignal(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700125 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800126 defer shutdown()
127
Todd Wang95873902015-05-22 14:21:30 -0700128 sh, h := newShell(t, ctx, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700129 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700130 h.Expect("ready")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700131 checkSignalIsDefault(t, syscall.SIGINT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700132 syscall.Kill(h.Pid(), syscall.SIGINT)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700133 h.Expectf("received signal %s", syscall.SIGINT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700134 fmt.Fprintf(h.Stdin(), "close\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700135 h.ExpectEOF()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700136}
137
138// TestCleanShutdownStop verifies that sending a stop comamnd to a child that
139// handles stop commands by default causes the child to shut down cleanly.
140func TestCleanShutdownStop(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700141 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800142 defer shutdown()
143
Todd Wang95873902015-05-22 14:21:30 -0700144 sh, h := newShell(t, ctx, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700145 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700146 h.Expect("ready")
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700147 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700148 h.Expectf("received signal %s", v23.LocalStop)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700149 fmt.Fprintf(h.Stdin(), "close\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700150 h.ExpectEOF()
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700151
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700152}
153
Bogdan Caprita1002ba42014-06-06 19:24:40 -0700154// TestCleanShutdownStopCustom verifies that sending a stop comamnd to a child
155// that handles stop command as part of a custom set of signals handled, causes
156// the child to shut down cleanly.
157func TestCleanShutdownStopCustom(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700158 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800159 defer shutdown()
160
Todd Wang95873902015-05-22 14:21:30 -0700161 sh, h := newShell(t, ctx, handleCustomWithStop)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700162 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700163 h.Expect("ready")
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700164 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700165 h.Expectf("received signal %s", v23.LocalStop)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700166 fmt.Fprintf(h.Stdin(), "close\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700167 h.ExpectEOF()
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700168}
169
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700170func testExitStatus(t *testing.T, h modules.Handle, code int) {
171 h.ExpectEOF()
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700172 _, file, line, _ := runtime.Caller(1)
173 file = filepath.Base(file)
174 if got, want := h.Shutdown(os.Stdout, os.Stderr), fmt.Errorf("exit status %d", code); got.Error() != want.Error() {
175 t.Errorf("%s:%d: got %q, want %q", file, line, got, want)
176 }
Bogdan Caprita1002ba42014-06-06 19:24:40 -0700177}
178
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700179// TestStopNoHandler verifies that sending a stop command to a child that does
180// not handle stop commands causes the child to exit immediately.
181func TestStopNoHandler(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700182 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800183 defer shutdown()
184
Todd Wang95873902015-05-22 14:21:30 -0700185 sh, h := newShell(t, ctx, handleCustom)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700186 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700187 h.Expect("ready")
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700188 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700189 testExitStatus(t, h, v23.UnhandledStopExitCode)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700190}
191
192// TestDoubleSignal verifies that sending a succession of two signals to a child
193// that handles these signals by default causes the child to exit immediately
194// upon receiving the second signal.
195func TestDoubleSignal(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700196 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800197 defer shutdown()
198
Todd Wang95873902015-05-22 14:21:30 -0700199 sh, h := newShell(t, ctx, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700200 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700201 h.Expect("ready")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700202 checkSignalIsDefault(t, syscall.SIGTERM)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700203 syscall.Kill(h.Pid(), syscall.SIGTERM)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700204 h.Expectf("received signal %s", syscall.SIGTERM)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700205 checkSignalIsDefault(t, syscall.SIGINT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700206 syscall.Kill(h.Pid(), syscall.SIGINT)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700207 testExitStatus(t, h, DoubleStopExitCode)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700208}
209
210// TestSignalAndStop verifies that sending a signal followed by a stop command
211// to a child that handles these by default causes the child to exit immediately
212// upon receiving the stop command.
213func TestSignalAndStop(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700214 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800215 defer shutdown()
216
Todd Wang95873902015-05-22 14:21:30 -0700217 sh, h := newShell(t, ctx, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700218 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700219 h.Expect("ready")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700220 checkSignalIsDefault(t, syscall.SIGTERM)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700221 syscall.Kill(h.Pid(), syscall.SIGTERM)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700222 h.Expectf("received signal %s", syscall.SIGTERM)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700223 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700224 testExitStatus(t, h, DoubleStopExitCode)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700225}
226
227// TestDoubleStop verifies that sending a succession of stop commands to a child
228// that handles stop commands by default causes the child to exit immediately
229// upon receiving the second stop command.
230func TestDoubleStop(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700231 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800232 defer shutdown()
233
Todd Wang95873902015-05-22 14:21:30 -0700234 sh, h := newShell(t, ctx, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700235 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700236 h.Expect("ready")
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700237 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700238 h.Expectf("received signal %s", v23.LocalStop)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700239 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700240 testExitStatus(t, h, DoubleStopExitCode)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700241}
242
243// TestSendUnhandledSignal verifies that sending a signal that the child does
244// not handle causes the child to exit as per the signal being sent.
245func TestSendUnhandledSignal(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700246 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800247 defer shutdown()
248
Todd Wang95873902015-05-22 14:21:30 -0700249 sh, h := newShell(t, ctx, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700250 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700251 h.Expect("ready")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700252 checkSignalIsNotDefault(t, syscall.SIGABRT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700253 syscall.Kill(h.Pid(), syscall.SIGABRT)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700254 testExitStatus(t, h, 2)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700255}
256
257// TestDoubleSignalIgnoreChan verifies that, even if we ignore the channel that
258// ShutdownOnSignals returns, sending two signals should still cause the
259// process to exit (ensures that there is no dependency in ShutdownOnSignals
260// on having a goroutine read from the returned channel).
261func TestDoubleSignalIgnoreChan(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700262 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800263 defer shutdown()
264
Todd Wang95873902015-05-22 14:21:30 -0700265 sh, h := newShell(t, ctx, handleDefaultsIgnoreChan)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700266 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700267 h.Expect("ready")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700268 // Even if we ignore the channel that ShutdownOnSignals returns,
269 // sending two signals should still cause the process to exit.
270 checkSignalIsDefault(t, syscall.SIGTERM)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700271 syscall.Kill(h.Pid(), syscall.SIGTERM)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700272 checkSignalIsDefault(t, syscall.SIGINT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700273 syscall.Kill(h.Pid(), syscall.SIGINT)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700274 testExitStatus(t, h, DoubleStopExitCode)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700275}
276
277// TestHandlerCustomSignal verifies that sending a non-default signal to a
278// server that listens for that signal causes the server to shut down cleanly.
279func TestHandlerCustomSignal(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700280 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800281 defer shutdown()
282
Todd Wang95873902015-05-22 14:21:30 -0700283 sh, h := newShell(t, ctx, handleCustom)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700284 defer sh.Cleanup(os.Stderr, os.Stderr)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700285 h.Expect("ready")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700286 checkSignalIsNotDefault(t, syscall.SIGABRT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700287 syscall.Kill(h.Pid(), syscall.SIGABRT)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700288 h.Expectf("received signal %s", syscall.SIGABRT)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700289 fmt.Fprintf(h.Stdin(), "stop\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700290 h.ExpectEOF()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700291}
Bogdan Caprita1002ba42014-06-06 19:24:40 -0700292
293// TestHandlerCustomSignalWithStop verifies that sending a custom stop signal
294// to a server that listens for that signal causes the server to shut down
295// cleanly, even when a STOP signal is also among the handled signals.
296func TestHandlerCustomSignalWithStop(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700297 rootCtx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800298 defer shutdown()
299
Jiri Simsa7fc6e872014-06-09 09:22:53 -0700300 for _, signal := range []syscall.Signal{syscall.SIGABRT, syscall.SIGHUP} {
Todd Wangad492042015-04-17 15:58:40 -0700301 ctx, _ := vtrace.WithNewTrace(rootCtx)
Todd Wang95873902015-05-22 14:21:30 -0700302 sh, h := newShell(t, ctx, handleCustomWithStop)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700303 h.Expect("ready")
Bogdan Caprita1002ba42014-06-06 19:24:40 -0700304 checkSignalIsNotDefault(t, signal)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700305 syscall.Kill(h.Pid(), signal)
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700306 h.Expectf("received signal %s", signal)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700307 fmt.Fprintf(h.Stdin(), "close\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700308 h.ExpectEOF()
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700309 sh.Cleanup(os.Stderr, os.Stderr)
Bogdan Caprita1002ba42014-06-06 19:24:40 -0700310 }
311}
312
313// TestParseSignalsList verifies that ShutdownOnSignals correctly interprets
314// the input list of signals.
315func TestParseSignalsList(t *testing.T) {
316 list := []os.Signal{STOP, syscall.SIGTERM}
Matt Rosencrantzc7fecf12014-11-27 19:58:43 -0800317 ShutdownOnSignals(nil, list...)
Bogdan Caprita1002ba42014-06-06 19:24:40 -0700318 if !isSignalInSet(syscall.SIGTERM, list) {
319 t.Errorf("signal %s not in signal set, as expected: %v", syscall.SIGTERM, list)
320 }
321 if !isSignalInSet(STOP, list) {
322 t.Errorf("signal %s not in signal set, as expected: %v", STOP, list)
323 }
324}
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700325
326type configServer struct {
327 ch chan<- string
328}
329
Todd Wang54feabe2015-04-15 23:38:26 -0700330func (c *configServer) Set(_ *context.T, _ rpc.ServerCall, key, value string) error {
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700331 if key != mgmt.AppCycleManagerConfigKey {
332 return fmt.Errorf("Unexpected key: %v", key)
333 }
334 c.ch <- value
335 return nil
336
337}
338
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700339// TestCleanRemoteShutdown verifies that remote shutdown works correctly.
340func TestCleanRemoteShutdown(t *testing.T) {
Todd Wang60052d82015-05-22 15:00:10 -0700341 ctx, shutdown := test.V23Init()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800342 defer shutdown()
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700343
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700344 sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800345 if err != nil {
346 t.Fatalf("unexpected error: %s", err)
347 }
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700348 defer sh.Cleanup(os.Stderr, os.Stderr)
349
Matt Rosencrantzbb6295d2015-06-19 15:13:58 -0700350 ch := make(chan string)
Matt Rosencrantz53ac5852015-09-04 15:14:54 -0700351 ctx, server, err := v23.WithNewServer(ctx, "", device.ConfigServer(&configServer{ch}), securityflag.NewAuthorizerOrDie())
Matt Rosencrantzbb6295d2015-06-19 15:13:58 -0700352 if err != nil {
353 t.Fatalf("Got error: %v", err)
354 }
355 configServiceName := server.Status().Endpoints[0].Name()
356
Jiri Simsa37893392014-11-07 10:55:45 -0800357 sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
358 sh.SetConfigKey(mgmt.ProtocolConfigKey, "tcp")
359 sh.SetConfigKey(mgmt.AddressConfigKey, "127.0.0.1:0")
Todd Wang95873902015-05-22 14:21:30 -0700360 h, err := sh.Start(nil, handleDefaults)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700361 if err != nil {
362 t.Fatalf("unexpected error: %s", err)
363 }
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700364 appCycleName := <-ch
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700365 h.Expect("ready")
Todd Wang702385a2014-11-07 01:54:08 -0800366 appCycle := appcycle.AppCycleClient(appCycleName)
Matt Rosencrantzf541b772015-01-13 07:58:59 -0800367 stream, err := appCycle.Stop(ctx)
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700368 if err != nil {
369 t.Fatalf("Got error: %v", err)
370 }
Shyam Jayaraman97b9dca2014-07-31 13:30:46 -0700371 rStream := stream.RecvStream()
372 if rStream.Advance() || rStream.Err() != nil {
373 t.Errorf("Expected EOF, got (%v, %v) instead: ", rStream.Value(), rStream.Err())
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700374 }
375 if err := stream.Finish(); err != nil {
376 t.Fatalf("Got error: %v", err)
377 }
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700378 h.Expectf("received signal %s", v23.RemoteStop)
Cosmos Nicolaoucc581722014-10-07 12:45:39 -0700379 fmt.Fprintf(h.Stdin(), "close\n")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700380 h.ExpectEOF()
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -0700381}