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

Fix some thread-leaking tests #1541

Closed
wants to merge 1 commit into from
Closed

Conversation

marcotc
Copy link
Member

@marcotc marcotc commented Jun 3, 2021

While trying to debug leaking threads associated with dogstatsd-ruby, I noticed that some of our tests are leaking threads, which makes it hard to use our test suite to help us debug the issue.

This PR addresses leaky threads associated with spec:main tests.

A run of spec:main won't be 100% clean yet, as the dreaded ./spec/ddtrace/workers/* tests are still leaking, but they are pretty hard to clean, so have to be addressed separately.

@marcotc marcotc added the dev/testing Involves testing processes (e.g. RSpec) label Jun 3, 2021
@marcotc marcotc self-assigned this Jun 3, 2021
@marcotc marcotc requested a review from a team June 3, 2021 21:50
@@ -225,6 +226,8 @@
test_class.configure do |c|
c.runtime_metrics.statsd = new_statsd
end

expect(old_statsd).to_not have_received(:close)
Copy link
Member Author

Choose a reason for hiding this comment

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

I've finally found a case where expect(...).to receive(...) is not equivalent to expect(...).to have_received(...).

In this specific case, old_statsd.close is invoked in an after block, which trips expect(...).to receive(...), but not expect(...).to have_received(...).

Copy link
Member

Choose a reason for hiding this comment

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

Good point, I had never considered that the have_received has a temporal component, it's "this thing has/hasn't happened so far -- doesn't say anything about the future". (But to be honest I never use it so maybe that's why I hadn't run into this before :P)

Although -- may I suggest moving the expectation to the it? It's a bit weird to have it in the before, since the it specifically states "...but does not close the old Statsd".

@codecov-commenter
Copy link

Codecov Report

Merging #1541 (5be8149) into master (a801f69) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1541   +/-   ##
=======================================
  Coverage   98.23%   98.23%           
=======================================
  Files         878      878           
  Lines       42269    42279   +10     
=======================================
+ Hits        41523    41534   +11     
+ Misses        746      745    -1     
Impacted Files Coverage Δ
spec/ddtrace/configuration_spec.rb 100.00% <100.00%> (ø)
spec/ddtrace/context_provider_spec.rb 95.34% <100.00%> (+0.05%) ⬆️
spec/ddtrace/diagnostics/health_spec.rb 100.00% <100.00%> (ø)
spec/ddtrace/runtime/metrics_spec.rb 96.61% <100.00%> (+0.02%) ⬆️
spec/ddtrace/profiling/ext/forking_spec.rb 100.00% <0.00%> (+0.61%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a801f69...5be8149. Read the comment docs.

Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

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

To be honest, the messiness in the configuration_spec betrays how this weird mix of semi-integration-semi-unit test that says it's testing Configuration but it's actually testing Components half of the time is not a good place to be in.

I think getting a sane configuration_spec will be a good indicator for the success of your plans to refactor the component initialization :)

@@ -225,6 +226,8 @@
test_class.configure do |c|
c.runtime_metrics.statsd = new_statsd
end

expect(old_statsd).to_not have_received(:close)
Copy link
Member

Choose a reason for hiding this comment

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

Good point, I had never considered that the have_received has a temporal component, it's "this thing has/hasn't happened so far -- doesn't say anything about the future". (But to be honest I never use it so maybe that's why I hadn't run into this before :P)

Although -- may I suggest moving the expectation to the it? It's a bit weird to have it in the before, since the it specifically states "...but does not close the old Statsd".

Comment on lines +214 to +219
let(:old_statsd) { instance_double(Datadog::Statsd, close: nil) }
let(:new_statsd) { instance_double(Datadog::Statsd, close: nil) }

before do
# Since its being reused, it should not be closed.
expect(old_statsd).to_not receive(:close)
allow(old_statsd).to receive(:close)
Copy link
Member

Choose a reason for hiding this comment

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

I believe the allow can be removed, since adding close: nil to the double implicitly states that it is allowed.

Comment on lines 264 to +267
let(:statsd) { instance_double(Datadog::Statsd) }

before do
expect(statsd).to_not receive(:close)
allow(statsd).to receive(:close)
Copy link
Member

Choose a reason for hiding this comment

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

Minor: Maybe move the allow to be part of the double setup, like the previous test?


test_class.configure do |c|
c.runtime_metrics.statsd = statsd
c.diagnostics.health_metrics.statsd = statsd
end

test_class.configure { |_c| }

expect(statsd).to_not have_received(:close)
Copy link
Member

Choose a reason for hiding this comment

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

I think this should also be part of the it, since this is the behavior we're after in this test (reusing and not closing).

Comment on lines 303 to +306
let(:tracer) { Datadog::Tracer.new }

before do
expect(tracer).to_not receive(:shutdown!)
allow(tracer).to receive(:shutdown!)
Copy link
Member

Choose a reason for hiding this comment

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

Could we use a double of the tracer here, like we do for the statsd above?

@marcotc marcotc closed this Oct 26, 2023
@GustavoCaso GustavoCaso deleted the fix-a-few-leaky-tests branch October 27, 2023 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dev/testing Involves testing processes (e.g. RSpec)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants