From ac8e06f56725099f879b32aa2cfe8a0c29123e5d Mon Sep 17 00:00:00 2001 From: Ivo Anjo Date: Wed, 12 Jun 2024 14:00:31 +0100 Subject: [PATCH] [NO-TICKET] Minor: Use fiddle to simulate crash in spec **What does this PR do?** This PR adds an additional test case to the profiling crashtracker as discussed in https://github.com/DataDog/dd-trace-rb/pull/3384#discussion_r1595866807 (thanks @lloeki for the suggestion). **Motivation:** Improve test coverage for the feature. **Additional Notes:** The diff looks more noiser than it is because of whitespace changes, I recommend reviewing this PR without them. **How to test the change?** Check that the new test passes! --- spec/datadog/profiling/crashtracker_spec.rb | 49 ++++++++++++--------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/spec/datadog/profiling/crashtracker_spec.rb b/spec/datadog/profiling/crashtracker_spec.rb index 67f6258a970..59137e85efa 100644 --- a/spec/datadog/profiling/crashtracker_spec.rb +++ b/spec/datadog/profiling/crashtracker_spec.rb @@ -2,6 +2,7 @@ require 'datadog/profiling/crashtracker' require 'webrick' +require 'fiddle' RSpec.describe Datadog::Profiling::Crashtracker do before do @@ -175,33 +176,39 @@ let(:exporter_configuration) { [:agent, "http://#{hostname}:#{port}"] } - it 'reports crashes via http' do - fork_expectations = proc do |status:, stdout:, stderr:| - expect(Signal.signame(status.termsig)).to eq('SEGV').or eq('ABRT') - expect(stderr).to include('[BUG] Segmentation fault') - end + [:fiddle, :signal].each do |trigger| + it "reports crashes via http when app crashes with #{trigger}" do + fork_expectations = proc do |status:, stdout:, stderr:| + expect(Signal.signame(status.termsig)).to eq('SEGV').or eq('ABRT') + expect(stderr).to include('[BUG] Segmentation fault') + end - expect_in_fork(fork_expectations: fork_expectations) do - crashtracker.start + expect_in_fork(fork_expectations: fork_expectations) do + crashtracker.start - Process.kill('SEGV', Process.pid) - end + if trigger == :fiddle + Fiddle.free(42) + else + Process.kill('SEGV', Process.pid) + end + end - crash_report = JSON.parse(request.body, symbolize_names: true)[:payload].first + crash_report = JSON.parse(request.body, symbolize_names: true)[:payload].first - expect(crash_report[:stack_trace]).to_not be_empty - expect(crash_report[:tags]).to include('signum:11', 'signame:SIGSEGV') + expect(crash_report[:stack_trace]).to_not be_empty + expect(crash_report[:tags]).to include('signum:11', 'signame:SIGSEGV') - crash_report_message = JSON.parse(crash_report[:message], symbolize_names: true) + crash_report_message = JSON.parse(crash_report[:message], symbolize_names: true) - expect(crash_report_message[:metadata]).to include( - profiling_library_name: 'dd-trace-rb', - profiling_library_version: Datadog::VERSION::STRING, - family: 'ruby', - tags: ['tag1:value1', 'tag2:value2'], - ) - expect(crash_report_message[:files][:'/proc/self/maps']).to_not be_empty - expect(crash_report_message[:os_info]).to_not be_empty + expect(crash_report_message[:metadata]).to include( + profiling_library_name: 'dd-trace-rb', + profiling_library_version: Datadog::VERSION::STRING, + family: 'ruby', + tags: ['tag1:value1', 'tag2:value2'], + ) + expect(crash_report_message[:files][:'/proc/self/maps']).to_not be_empty + expect(crash_report_message[:os_info]).to_not be_empty + end end end end