diff --git a/app.go b/app.go index 82b4a32..7c0cdc1 100644 --- a/app.go +++ b/app.go @@ -142,11 +142,13 @@ func (a *App) runShutdownHooks(ctx context.Context) error { return nil } +var background = context.Background() + // Run will start the App, running the startup Hooks, then the Processes. // It will wait for any signals before shutting down first the Processes then the shutdown Hooks. // This behaviour can be customised by using Launch, WaitForShutdown, and Shutdown. func (a *App) Run() int { - ac := NewAppContext(context.Background()) + ac := NewAppContext(background) defer ac.Stop() defer a.cleanup(ac.TerminationContext) diff --git a/app_internal_test.go b/app_internal_test.go new file mode 100644 index 0000000..f948d4d --- /dev/null +++ b/app_internal_test.go @@ -0,0 +1,12 @@ +package lu + +import ( + "context" + "testing" +) + +func SetBackgroundContextForTesting(t *testing.T, ctx context.Context) { + old := background + t.Cleanup(func() { background = old }) + background = ctx +} diff --git a/app_test.go b/app_test.go index 40f55f3..c6310b5 100644 --- a/app_test.go +++ b/app_test.go @@ -2,11 +2,14 @@ package lu_test import ( "context" + "io" + "os" "testing" "time" "github.com/luno/jettison/jtest" "github.com/luno/jettison/log" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/luno/lu" @@ -237,3 +240,66 @@ func TestRunningProcesses(t *testing.T) { }) } } + +func TestPIDRemoved(t *testing.T) { + tests := []struct { + name string + app func(t *testing.T) *lu.App + expExit int + }{ + { + name: "not using pid", + app: func(t *testing.T) *lu.App { + var a lu.App + a.AddProcess(process.NoOp()) + return &a + }, + expExit: 1, + }, + { + name: "normal app", + app: func(t *testing.T) *lu.App { + a := lu.App{UseProcessFile: true} + a.AddProcess(process.NoOp()) + return &a + }, + expExit: 1, + }, + { + name: "app fails to start", + app: func(t *testing.T) *lu.App { + a := lu.App{UseProcessFile: true} + a.OnStartUp(func(ctx context.Context) error { + return io.ErrUnexpectedEOF + }) + a.AddProcess(process.NoOp()) + return &a + }, + expExit: 1, + }, + { + name: "app fails to shutdown", + app: func(t *testing.T) *lu.App { + a := lu.App{UseProcessFile: true} + a.OnShutdown(func(ctx context.Context) error { + return io.ErrUnexpectedEOF + }) + a.AddProcess(process.NoOp()) + return &a + }, + expExit: 1, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + t.Cleanup(cancel) + lu.SetBackgroundContextForTesting(t, ctx) + + exit := tc.app(t).Run() + assert.Equal(t, tc.expExit, exit) + _, err := os.Open("/tmp/lu.pid") + assert.True(t, os.IsNotExist(err)) + }) + } +}