-
Notifications
You must be signed in to change notification settings - Fork 375
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3036 from DataDog/non-monitor-detection
- Loading branch information
Showing
4 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# frozen_string_literal: true | ||
|
||
module Datadog | ||
module Core | ||
module Environment | ||
# Provides information about the execution environment on the current process. | ||
module Execution | ||
class << self | ||
# Is this process running in a development environment? | ||
# This can be used to make decisions about when to enable | ||
# background systems like worker threads or telemetry. | ||
def development? | ||
!!(repl? || test?) | ||
end | ||
|
||
private | ||
|
||
# Is this process running a test? | ||
def test? | ||
rspec? || minitest? | ||
end | ||
|
||
# Is this process running inside on a Read–eval–print loop? | ||
# DEV: REPLs always set the program name to the exact REPL name. | ||
def repl? | ||
REPL_PROGRAM_NAMES.include?($PROGRAM_NAME) | ||
end | ||
|
||
REPL_PROGRAM_NAMES = %w[irb pry].freeze | ||
private_constant :REPL_PROGRAM_NAMES | ||
|
||
# RSpec always runs using the `rspec` file https://github.com/rspec/rspec-core/blob/main/exe/rspec | ||
def rspec? | ||
$PROGRAM_NAME.end_with?(RSPEC_PROGRAM_NAME) | ||
end | ||
|
||
RSPEC_PROGRAM_NAME = '/rspec' | ||
private_constant :RSPEC_PROGRAM_NAME | ||
|
||
# Check if Minitest is present and installed to run. | ||
def minitest? | ||
# Minitest >= 5 | ||
(defined?(::Minitest) && | ||
::Minitest.class_variable_defined?(:@@installed_at_exit) && | ||
::Minitest.class_variable_get(:@@installed_at_exit)) || | ||
# Minitest < 5 | ||
(defined?(::Minitest::Unit) && | ||
::Minitest::Unit.class_variable_defined?(:@@installed_at_exit) && | ||
::Minitest::Unit.class_variable_get(:@@installed_at_exit)) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module Datadog | ||
module Core | ||
module Environment | ||
module Execution | ||
def self.development?: () -> bool | ||
|
||
private | ||
def self.test?: () -> bool | ||
def self.repl?: () -> bool | ||
|
||
REPL_PROGRAM_NAMES: ::Array[::String] | ||
def self.rspec?: () -> bool | ||
|
||
RSPEC_PROGRAM_NAME: ::String | ||
def self.minitest?: () -> bool | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
require 'datadog/core/environment/execution' | ||
|
||
RSpec.describe Datadog::Core::Environment::Execution do | ||
describe '#development?' do | ||
subject(:development?) { described_class.development? } | ||
|
||
context 'when in an RSpec test' do | ||
it { is_expected.to eq(true) } | ||
end | ||
|
||
context 'when not in an RSpec test' do | ||
# RSpec is detected through the $PROGRAM_NAME. | ||
# Changing it will make RSpec detection to return false. | ||
# | ||
# We change the $PROGRAM_NAME instead of stubbing | ||
# `Datadog::Core::Environment::Execution.rspec?` because | ||
# otherwise we'll have no real test for non-RSpec cases. | ||
around do |example| | ||
begin | ||
original = $PROGRAM_NAME | ||
$PROGRAM_NAME = 'not-rspec' | ||
example.run | ||
ensure | ||
$PROGRAM_NAME = original | ||
end | ||
end | ||
|
||
let(:repl_script) do | ||
<<-RUBY | ||
# Load the working directory version of `ddtrace` | ||
lib = File.expand_path('lib', __dir__) | ||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | ||
require 'datadog/core/environment/execution' | ||
# Print actual value to STDERR, as STDOUT tends to have more noise in REPL sessions. | ||
STDERR.print Datadog::Core::Environment::Execution.development? | ||
RUBY | ||
end | ||
|
||
it 'ensure RSpec detection returns false' do | ||
is_expected.to eq(false) | ||
end | ||
|
||
context 'when in an IRB session' do | ||
it 'returns true' do | ||
_, err = Bundler.with_clean_env do # Ruby 2.6 does not have irb by default in a bundle, but has it outside of it. | ||
Open3.capture3('irb', '--noprompt', '--noverbose', stdin_data: repl_script) | ||
end | ||
expect(err).to end_with('true') | ||
end | ||
end | ||
|
||
context 'when in a Pry session' do | ||
it 'returns true' do | ||
Tempfile.create('test') do |f| | ||
f.write(repl_script) | ||
f.close | ||
|
||
out, = Open3.capture2e('pry', '-f', '--noprompt', f.path) | ||
expect(out).to eq('true') | ||
end | ||
end | ||
end | ||
|
||
context 'when in a Minitest test' do | ||
before { skip('Minitest not in bundle') unless Gem.loaded_specs['minitest'] } | ||
|
||
it 'returns true' do | ||
expect_in_fork do | ||
# Minitest reads CLI arguments, but the current process has RSpec | ||
# arguments that are not relevant (nor compatible) with Minitest. | ||
# This happens inside a fork, thus we don't have to reset it. | ||
Object.const_set('ARGV', []) | ||
|
||
require 'minitest/autorun' | ||
|
||
is_expected.to eq(true) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |