Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2679139492 |
No files matched your search
+5
-4
@@ -4,6 +4,7 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
@@ -78,7 +79,7 @@ func run(_ *cobra.Command, _ []string) {
|
||||
),
|
||||
)
|
||||
|
||||
exitCode := runApp(app)
|
||||
exitCode := runApp(app, os.Stderr)
|
||||
if exitCode != 0 {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
@@ -88,13 +89,13 @@ func run(_ *cobra.Command, _ []string) {
|
||||
// and returns the status pixad exits with, as fx.App.Run does. It prints
|
||||
// a start or stop error to stderr, once, as the error that caused it:
|
||||
// dig.RootCause drops the frames fx and dig wrap around it.
|
||||
func runApp(app *fx.App) int {
|
||||
func runApp(app *fx.App, stderr io.Writer) int {
|
||||
startCtx, cancelStart := context.WithTimeout(context.Background(), app.StartTimeout())
|
||||
defer cancelStart()
|
||||
|
||||
err := app.Start(startCtx)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, dig.RootCause(err))
|
||||
_, _ = fmt.Fprintln(stderr, dig.RootCause(err))
|
||||
|
||||
return 1
|
||||
}
|
||||
@@ -106,7 +107,7 @@ func runApp(app *fx.App) int {
|
||||
|
||||
err = app.Stop(stopCtx)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, dig.RootCause(err))
|
||||
_, _ = fmt.Fprintln(stderr, dig.RootCause(err))
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
var errTestStopFailed = errors.New("test stop hook failed")
|
||||
|
||||
// TestRunAppPrintsStopErrorOnce checks that when a stop hook fails, runApp
|
||||
// prints the hook's error once and returns exit status 1.
|
||||
func TestRunAppPrintsStopErrorOnce(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := fx.New(
|
||||
fx.NopLogger,
|
||||
fx.Invoke(func(lifecycle fx.Lifecycle, shutdowner fx.Shutdowner) {
|
||||
lifecycle.Append(fx.Hook{
|
||||
// Ask to shut down as soon as the app has started, so
|
||||
// that runApp goes on to stop it.
|
||||
OnStart: func(context.Context) error { return shutdowner.Shutdown() },
|
||||
OnStop: func(context.Context) error { return errTestStopFailed },
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
|
||||
exitCode := runApp(app, &stderr)
|
||||
if exitCode != 1 {
|
||||
t.Errorf("runApp() = %d, want 1", exitCode)
|
||||
}
|
||||
|
||||
want := errTestStopFailed.Error() + "\n"
|
||||
if stderr.String() != want {
|
||||
t.Errorf("stderr = %q, want %q", stderr.String(), want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunAppReturnsShutdownExitCode checks that runApp returns the exit
|
||||
// code a shutdown request names.
|
||||
func TestRunAppReturnsShutdownExitCode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := fx.New(
|
||||
fx.NopLogger,
|
||||
fx.Invoke(func(lifecycle fx.Lifecycle, shutdowner fx.Shutdowner) {
|
||||
lifecycle.Append(fx.Hook{
|
||||
OnStart: func(context.Context) error {
|
||||
return shutdowner.Shutdown(fx.ExitCode(3))
|
||||
},
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
exitCode := runApp(app, io.Discard)
|
||||
if exitCode != 3 {
|
||||
t.Errorf("runApp() = %d, want 3", exitCode)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user