Skip to content

Commit

Permalink
add DD_CIVISIBILITY_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE env va…
Browse files Browse the repository at this point in the history
…riable to switch to single threaded code coverage mode if needed
  • Loading branch information
anmarchenko committed Jun 10, 2024
1 parent caa3fb5 commit 8c3bf11
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 5 deletions.
3 changes: 2 additions & 1 deletion lib/datadog/ci/configuration/components.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ def activate_ci!(settings)
config_tags: custom_configuration_tags,
coverage_writer: coverage_writer,
enabled: settings.ci.enabled && settings.ci.itr_enabled,
bundle_location: settings.ci.itr_code_coverage_excluded_bundle_path
bundle_location: settings.ci.itr_code_coverage_excluded_bundle_path,
use_single_threaded_coverage: settings.ci.itr_code_coverage_use_single_threaded_mode
)

git_tree_uploader = Git::TreeUploader.new(api: test_visibility_api)
Expand Down
6 changes: 6 additions & 0 deletions lib/datadog/ci/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ def self.add_settings!(base)
end
end

option :itr_code_coverage_use_single_threaded_mode do |o|
o.type :bool
o.env CI::Ext::Settings::ENV_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE
o.default false
end

define_method(:instrument) do |integration_name, options = {}, &block|
return unless enabled

Expand Down
1 change: 1 addition & 0 deletions lib/datadog/ci/ext/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module Settings
ENV_ITR_ENABLED = "DD_CIVISIBILITY_ITR_ENABLED"
ENV_GIT_METADATA_UPLOAD_ENABLED = "DD_CIVISIBILITY_GIT_METADATA_UPLOAD_ENABLED"
ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH"
ENV_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE = "DD_CIVISIBILITY_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE"

# Source: https://docs.datadoghq.com/getting_started/site/
DD_SITE_ALLOWLIST = %w[
Expand Down
13 changes: 11 additions & 2 deletions lib/datadog/ci/itr/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def initialize(
api: nil,
coverage_writer: nil,
enabled: false,
bundle_location: nil
bundle_location: nil,
use_single_threaded_coverage: false
)
@enabled = enabled
@api = api
Expand All @@ -43,6 +44,7 @@ def initialize(
else
bundle_location
end
@use_single_threaded_coverage = use_single_threaded_coverage

@test_skipping_enabled = false
@code_coverage_enabled = false
Expand Down Expand Up @@ -186,12 +188,15 @@ def write(event)
def coverage_collector
Thread.current[:dd_coverage_collector] ||= Coverage::DDCov.new(
root: Git::LocalRepository.root,
ignored_path: @bundle_location
ignored_path: @bundle_location,
threading_mode: code_coverage_mode
)
end

def load_datadog_cov!
require "datadog_cov.#{RUBY_VERSION}_#{RUBY_PLATFORM}"

Datadog.logger.debug("Loaded Datadog code coverage collector, using coverage mode: #{code_coverage_mode}")
rescue LoadError => e
Datadog.logger.error("Failed to load coverage collector: #{e}. Code coverage will not be collected.")

Expand Down Expand Up @@ -222,6 +227,10 @@ def fetch_skippable_tests(test_session:, git_tree_upload_worker:)
Datadog.logger.debug { "Found #{@skippable_tests.count} skippable tests." }
Datadog.logger.debug { "ITR correlation ID: #{@correlation_id}" }
end

def code_coverage_mode
@use_single_threaded_coverage ? :single : :multi
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions sig/datadog/ci/ext/settings.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module Datadog
ENV_ITR_ENABLED: String
ENV_GIT_METADATA_UPLOAD_ENABLED: String
ENV_ITR_CODE_COVERAGE_EXCLUDED_BUNDLE_PATH: String
ENV_ITR_CODE_COVERAGE_USE_SINGLE_THREADED_MODE: String

DD_SITE_ALLOWLIST: Array[String]
end
Expand Down
5 changes: 4 additions & 1 deletion sig/datadog/ci/itr/runner.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module Datadog
@dd_env: String?
@config_tags: Hash[String, String]
@bundle_location: String?
@use_single_threaded_coverage: bool

@skipped_tests_count: Integer
@mutex: Thread::Mutex
Expand All @@ -23,7 +24,7 @@ module Datadog
attr_reader skipped_tests_count: Integer
attr_reader correlation_id: String?

def initialize: (dd_env: String?, ?enabled: bool, ?coverage_writer: Datadog::CI::ITR::Coverage::Writer?, ?api: Datadog::CI::Transport::Api::Base?, ?config_tags: Hash[String, String]?, ?bundle_location: String?) -> void
def initialize: (dd_env: String?, ?enabled: bool, ?coverage_writer: Datadog::CI::ITR::Coverage::Writer?, ?api: Datadog::CI::Transport::Api::Base?, ?config_tags: Hash[String, String]?, ?bundle_location: String?, ?use_single_threaded_coverage: bool) -> void

def configure: (Hash[String, untyped] remote_configuration, test_session: Datadog::CI::TestSession, git_tree_upload_worker: Datadog::CI::Worker) -> void

Expand Down Expand Up @@ -58,6 +59,8 @@ module Datadog
def fetch_skippable_tests: (test_session: Datadog::CI::TestSession, git_tree_upload_worker: Datadog::CI::Worker) -> void

def increment_skipped_tests_counter: () -> void

def code_coverage_mode: () -> Datadog::CI::ITR::Coverage::DDCov::threading_mode
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions spec/datadog/ci/contrib/minitest/helpers/addition_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module AdditionHelper
def self.add(a, b)
a + b
end
end
60 changes: 59 additions & 1 deletion spec/datadog/ci/contrib/minitest/instrumentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_foo
end
end

context "with service name configured" do
context "with service name configured and code coverage enabled" do
include_context "CI mode activated" do
let(:integration_name) { :minitest }
let(:integration_options) { {service_name: "ltest"} }
Expand Down Expand Up @@ -402,12 +402,18 @@ def test_foo
before(:context) do
Minitest::Runnable.reset

require_relative "helpers/addition_helper"
class SomeTest < Minitest::Test
def test_pass
assert true
end

def test_pass_other
# add thread to test that code coverage is collected
t = Thread.new do
AdditionHelper.add(1, 2)
end
t.join
assert true
end
end
Expand Down Expand Up @@ -494,6 +500,13 @@ def test_pass_other
expect_coverage_events_belong_to_suite(first_test_suite_span)
expect_coverage_events_belong_to_tests(test_spans)
expect_non_empty_coverages

# expect that background thread is covered
test_span = test_spans.find { |span| span.get_tag("test.name") == "test_pass_other" }
cov_event = find_coverage_for_test(test_span)
expect(cov_event.coverage.keys).to include(
File.expand_path(File.join(__dir__, "helpers/addition_helper.rb"))
)
end

context "when ITR skips tests" do
Expand Down Expand Up @@ -881,4 +894,49 @@ class SomeUnskippableSpec < Minitest::Spec
end
end
end

context "when using single threaded code coverage" do
include_context "CI mode activated" do
let(:integration_name) { :minitest }

let(:itr_enabled) { true }
let(:code_coverage_enabled) { true }
let(:use_single_threaded_coverage) { true }
end

before do
Minitest.run([])
end

before(:context) do
Thread.current[:dd_coverage_collector] = nil

Minitest::Runnable.reset

require_relative "helpers/addition_helper"
class SomeTestWithThreads < Minitest::Test
def test_with_background_thread
# add thread to test that code coverage is collected
t = Thread.new do
AdditionHelper.add(1, 2)
end
t.join
assert true
end
end
end

it "does not cover the background thread" do
skip if PlatformHelpers.jruby?

expect(test_spans).to have(1).item
expect(coverage_events).to have(1).item

# expect that background thread is not covered
cov_event = find_coverage_for_test(first_test_span)
expect(cov_event.coverage.keys).not_to include(
File.expand_path(File.join(__dir__, "helpers/addition_helper.rb"))
)
end
end
end
2 changes: 2 additions & 0 deletions spec/support/contexts/ci_mode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
let(:git_metadata_upload_enabled) { false }
let(:require_git) { false }
let(:bundle_path) { nil }
let(:use_single_threaded_coverage) { false }

let(:itr_correlation_id) { "itr_correlation_id" }
let(:itr_skippable_tests) { [] }
Expand Down Expand Up @@ -77,6 +78,7 @@
c.ci.itr_enabled = itr_enabled
c.ci.git_metadata_upload_enabled = git_metadata_upload_enabled
c.ci.itr_code_coverage_excluded_bundle_path = bundle_path
c.ci.itr_code_coverage_use_single_threaded_mode = use_single_threaded_coverage
unless integration_name == :no_instrument
c.ci.instrument integration_name, integration_options
end
Expand Down

0 comments on commit 8c3bf11

Please sign in to comment.