Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

app: Add internal option to override os.Exit #792

Merged
merged 1 commit into from
Sep 17, 2021
Merged

Conversation

abhinav
Copy link
Collaborator

@abhinav abhinav commented Sep 17, 2021

Add an option exposed only to tests in the go.uber.org/fx package that
allows overriding how os.Exit behaves.

The way the new option works is,

  • App gets a new osExit func(int) field which defaults to os.Exit
  • app_internal_test.go uses package fx and therefore, it can access
    internal fields of the App. We define a new exported option in this
    package that sets osExit. Because this option is defined in a test
    file, though, it is not made part of the public API of the package.
  • app_test.go uses package fx_test so it's an external test--it cannot
    access unexported fields, but it can access the exported option
    defined in app_internal_test.go.

This will allow testing the app.Run function directly.

Copy link
Contributor

@sywhang sywhang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM other than maybe adding a comment for the osExit field

app.go Outdated Show resolved Hide resolved
Add an option exposed only to tests in the go.uber.org/fx package that
allows overriding how `os.Exit` behaves.

The way the new option works is,

- `App` gets a new `osExit func(int)` field which defaults to `os.Exit`
- app_internal_test.go uses `package fx` and therefore, it can access
  internal fields of the `App`. We define a new exported option in this
  package that sets `osExit`. Because this option is defined in a test
  file, though, it is not made part of the public API of the package.
- app_test.go uses `package fx_test` so it's an external test--it cannot
  access unexported fields, but it can access the exported option
  defined in app_internal_test.go.

This will allow testing the `app.Run` function directly.
Base automatically changed from abg/reorder to master September 17, 2021 21:05
@abhinav abhinav merged commit 14f0965 into master Sep 17, 2021
@abhinav abhinav deleted the abg/os-exit-option branch September 17, 2021 21:05
abhinav added a commit that referenced this pull request Sep 17, 2021
As reported in #782, `App.Run` had a bug so that
if an application using it failed to start up because of a timeout
no event would be logged to indicate this.
The system would silently exit with a non-zero status code.

This PR resolves this by ensuring that even for timeouts,
we log `Started` or `Stopped` events with non-nil `Err` values.
This matches the behavior for other startup or shutdown failures.

To test this, I wanted to use `App.Run` directly so
I added an internal test-only option `WithExit`
that lets us override the behavior of `os.Exit`
without a global variable. (#792)

The issue resolution was pretty straightforward:

- Start: `defer LogEvent(..)` in Start instead of
  the wrapped `start` method which runs inside a separate gorotuine.
- Stop: Apply `defer LogEvent(..)` in Stop instead of `App.Run`.
  This actually exposed a bug too: we did not previously log `Stopped`
  if `App.Stop` was called. This resulted in some test changes.

There was a small non-determinism in `withTimeout`:
What if the context times out at the same time as the callback finishing?
`select` will pick one of the `case`s randomly.
I resolved this non-determinism by checking `ctx.Err()` in the success case again.

I also moved `App.start` next to `App.Start`, and `App.run` next to `App.Run`
to aid in readability. The move is in #791.

Resolves #782
Resolves GO-866
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants