-
Notifications
You must be signed in to change notification settings - Fork 290
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
fix: Only register signal handlers if user intends to use them #1215
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,8 +21,10 @@ | |
package fx | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"sync" | ||
"testing" | ||
|
||
|
@@ -115,3 +117,24 @@ func TestAnnotationError(t *testing.T) { | |
assert.ErrorIs(t, err, wantErr) | ||
assert.Contains(t, err.Error(), wantErr.Error()) | ||
} | ||
|
||
// TestStartDoesNotRegisterSignals verifies that signal.Notify is not called | ||
// when a user starts an app. signal.Notify should only be called when the | ||
// .Wait/.Done are called. Note that app.Run calls .Wait() implicitly. | ||
func TestStartDoesNotRegisterSignals(t *testing.T) { | ||
app := New() | ||
calledNotify := false | ||
|
||
// Mock notify function to spy when this is called. | ||
app.receivers.notify = func(c chan<- os.Signal, sig ...os.Signal) { | ||
calledNotify = true | ||
} | ||
app.receivers.stopNotify = func(c chan<- os.Signal) {} | ||
|
||
app.Start(context.Background()) | ||
defer app.Stop(context.Background()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are not testing it then I think. I mean the test code is not doing what you expect When defer is called it's too late, no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Stop should be after the wait. Or you use a t.Cleanup(func() { |
||
assert.False(t, calledNotify, "notify should not be called when app starts") | ||
|
||
_ = app.Wait() // User signals intent have fx listen for signals. This should call notify | ||
assert.True(t, calledNotify, "notify should be called after Wait") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2331,7 +2331,9 @@ func TestHookConstructors(t *testing.T) { | |
func TestDone(t *testing.T) { | ||
t.Parallel() | ||
|
||
done := fxtest.New(t).Done() | ||
app := fxtest.New(t) | ||
defer app.RequireStop() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In test t.Cleanup is preferred over defer |
||
done := app.Done() | ||
require.NotNil(t, done, "Got a nil channel.") | ||
select { | ||
case sig := <-done: | ||
|
@@ -2340,6 +2342,28 @@ func TestDone(t *testing.T) { | |
} | ||
} | ||
|
||
// TestShutdownThenWait tests that if we call .Shutdown before waiting, the wait | ||
// will still return the last shutdown signal. | ||
func TestShutdownThenWait(t *testing.T) { | ||
t.Parallel() | ||
|
||
var ( | ||
s Shutdowner | ||
) | ||
MarcoPolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
app := fxtest.New( | ||
t, | ||
Populate(&s), | ||
) | ||
MarcoPolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer app.RequireStop() | ||
assert.NotNil(t, s) | ||
|
||
err := s.Shutdown(ExitCode(1337)) | ||
MarcoPolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
require.NoError(t, err) | ||
|
||
shutdownSig := <-app.Wait() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because of GitHub workflow, I cannot comment the Wait method, so I'm commenting here. I would expect to use the context as argument This way It's useless in the unit tests, but meaningful in the real app There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unsure but I would expect the same from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Last remark, I'm surprised that code in Stop are not closing the channels when leaving on ctx.Done() |
||
require.Equal(t, 1337, shutdownSig.ExitCode) | ||
MarcoPolo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func TestReplaceLogger(t *testing.T) { | ||
t.Parallel() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,7 +102,7 @@ func (recv *signalReceivers) running() bool { | |
return recv.shutdown != nil && recv.finished != nil | ||
} | ||
|
||
func (recv *signalReceivers) Start(ctx context.Context) { | ||
func (recv *signalReceivers) Start() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the context was not used ? |
||
recv.m.Lock() | ||
defer recv.m.Unlock() | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should define a variable
stopCalled bool
and set it to true when called.And then test its value after calling
Stop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is relevant for this test. #1198 already includes testing that
stopNotify
gets called when an app stops. I think this is testing thatnotify
does not get called when an app starts.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. The only reason I'm setting
.stopNotify
is because I consider it bad form to call the defaultsignal.Stop
func with a channel that was never registered in the first place.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK noted