-
Notifications
You must be signed in to change notification settings - Fork 905
GODRIVER-3340 Add a test for goroutine leaks. #1874
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
GODRIVER-3340 Add a test for goroutine leaks. #1874
Conversation
API Change ReportNo changes found! |
c8d11ec
to
e81225e
Compare
e81225e
to
e339231
Compare
internal/test/goleak/goleak_test.go
Outdated
}{ | ||
{ | ||
desc: "base", | ||
opts: options.Client().ApplyURI(uri), |
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.
ApplyURI
is used in every test and if it's empty will default to localhost:27017
. Suggest applying this value in the test runner:
opts := tc.opts
if u := os.Getenv("MONGODB_URI"); u != "" {
opts.ApplyURI(u)
}
client, err := mongo.Connect(context.Background(), opts)
require.NoError(t, err)
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.
My concern with that approach is that ApplyURI
will overwrite the explicitly configured values if it's called after. However, I believe I can get the same effect using something like
base := options.Client()
if u := os.Getenv("MONGODB_URI"); u != "" {
base.ApplyURI(u)
}
client, err := mongo.Connect(context.Background(), base, t.opts)
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.
Updated.
// These can't be run in parallel because goleak currently can't filter | ||
// out goroutines from other parallel subtests. | ||
t.Run(tc.desc, func(t *testing.T) { | ||
defer goleak.VerifyNone(t) |
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.
The uber-go/goleak documentation implies that we don't have to make this check both in the subtest and at the TestMain()
level: https://github.com/uber-go/goleak#quick-start . If that's true, suggest removing TestMain()
.
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.
Good idea. I added it to catch goroutine leaks that I didn't know I was looking for, but it's never caught a goroutine leak that goleak.VerifyNone
didn't catch, so I'm fine removing it.
We should definitely prioritize using goleak.VerifyNone
in specific test cases because it both indicates which scenario(s) caused a goroutine leak and the output shows up clearly in the Evergreen test logs. goleak.VerifyTestMain
does neither.
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.
Removed TestMain
.
internal/test/goleak/goleak_test.go
Outdated
_, err = coll.InsertOne(context.Background(), bson.M{"x": 123}) | ||
require.NoError(t, err) | ||
|
||
for i := 0; i < 20; i++ { |
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.
What is the significance of 20? Should we constantize this value to give it context?
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.
20 is "enough to cause a noticeable problem", so it doesn't have any special significance. However, note that we've only detected one type of goroutine leak with this test so far, so it's possible that we'll need to change the test scenario, duration, etc to catch future goroutine leaks. I'll leave a comment about the significance and limitations of the overall test loop related to detecting goroutine leaks. Ideally, we should actually be testing for goroutine leaks in our existing test suites, but that has proved somewhat difficult to implement.
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 ended up removing the sleep, increased the iterations to 50, moved the InsertOne
into the loop, added a ChangeStream
simulated workload, and added some operations that intentionally time out. I added a comment describing the intent of the different operations.
internal/test/goleak/goleak_test.go
Outdated
var res bson.D | ||
err = coll.FindOne(context.Background(), bson.D{}).Decode(&res) | ||
require.NoError(t, err) | ||
time.Sleep(50 * time.Millisecond) |
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.
Could we add a comment to describe what we are awaiting?
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.
For some reason, adding the sleep increases the number of goroutines that leak when using "zstd" compression. I will add a comment describing the current purpose for sleeping there.
drivers-pr-bot please backport to master |
Sorry, unable to cherry-pick to master, please backport manually. Here are approximate instructions:
|
(cherry picked from commit c3448e6)
* commit '0dc2e05e': (184 commits) GODRIVER-3448 Limit GOMAXPROCS for fuzz tests (#1939) [v1] (#1943) GODRIVER-3470 Correct BSON unmarshaling logic for null values (#1924) GODRIVER-3370 Add bypassEmptyTsReplacement option. (#1927) BUMP v1.17.2 GODRIVER-3436 Avoid initializing null data given custom decoder (#1902) GODRIVER-3340 Add a test for goroutine leaks. (#1874) Update reviewers.txt (#1855) [v1] (#1883) Fix data race in 'discard connections' pool test. [v1] (#1877) Bump golangci-lint for 1.23 compatibility [v1] (#1875) GODRIVER-3340 Bump github.com/klauspost/compress from 1.13.6 to 1.16.7 [v1] (#1869) GODRIVER-3374 Add ReadCompressedCompressedMessage back to wiremessage API (#1870) GODRIVER-3156 Detect and discard closed idle connections. (#1815) GODRIVER-3358 Do not override authSource from TXT record (#1830) DEVPROD-10453 Use assume_role for s3 uploads [v1] (#1824) GODRIVER-2589 Clarify `*Cursor.All()` behavior in comment. (#1804) GODRIVER-3313 Skip CSOT spec tests on Windows and macOS. (#1818) BUMP v1.17.0 GODRIVER-3302 Handle malformatted message length properly. (#1758) GODRIVER-3312 Use remaining test secrets from the vault [v1] (#1811) Remove GCP from supplied callback example (#1809) ...
…41094483929 * release/2.0: (203 commits) Use different credentials for merge-up PRs (#1968) Add GitHub Actions workflow for merge ups (#1962) BUMP v1.17.3 GODRIVER-3448 Limit GOMAXPROCS for fuzz tests (#1939) [v1] (#1943) [release/1.17] (#1957) Update reviewers.txt (#1855) [v1] (#1883) [release/1.17] (#1958) Cherry pick 1.17.2 work to release/1.17 (#1956) GODRIVER-3470 Correct BSON unmarshaling logic for null values (#1924) (#1955) GODRIVER-3370 Add bypassEmptyTsReplacement option. (#1927) [release/1.17] (#1954) GODRIVER-3448 Limit GOMAXPROCS for fuzz tests (#1939) [v1] (#1943) GODRIVER-3470 Correct BSON unmarshaling logic for null values (#1924) GODRIVER-3370 Add bypassEmptyTsReplacement option. (#1927) BUMP v1.17.2 GODRIVER-3436 Avoid initializing null data given custom decoder (#1902) GODRIVER-3340 Add a test for goroutine leaks. (#1874) Update reviewers.txt (#1855) [v1] (#1883) GODRIVER-3340 Bump github.com/klauspost/compress from 1.13.6 to 1.16.7 [release/1.17] (#1880) GODRIVER-3374 Add ReadCompressedCompressedMessage back to wiremessage API (#1870) Fix data race in 'discard connections' pool test. [v1] (#1877) Bump golangci-lint for 1.23 compatibility [v1] (#1875) Fix data race in 'discard connections' pool test. [v1] (#1877) ...
GODRIVER-3340
Summary
internal/test/goleak
that tests for goroutine leaks.Background & Motivation
Our usage of the
zstd.Decoder
pooled with async.Pool
created the possibility of a gorutine leak when using the "zstd" compressor. We didn't catch it because we currently don't have any way to detect goroutine leaks. Add a test that uses github.com/uber-go/goleak to check for goroutine leaks.