Class: Evilution::Integration::RSpec::StateGuard::ConfigurationState

Inherits:
Object
  • Object
show all
Defined in:
lib/evilution/integration/rspec/state_guard/configuration_state.rb

Overview

Restores the RSpec.configuration state that ::RSpec::Core::Runner.run mutates on the shared singleton during an in-process mutation run (EV-dwqw / GH #1343).

The visible symptom was every SUBSEQUENT host example rendering its progress dots without color (white instead of green). Root cause: the run’s args carry “–no-color”, and ConfigurationOptions#configure applies it via Configuration#force, which does ‘@preferred_options.merge!(:color_mode => :off)` IN PLACE. `Configuration#color_mode` reads `@preferred_options.fetch(:color_mode)` first, so the host’s color setting stays :off for the rest of the process. Separately, Runner#setup points ‘output_stream`/`error_stream` (attr_writers, i.e. the @output_stream/@error_stream ivars) at the run’s throwaway StringIOs.

Forked runs never leak these (the mutation happens in a child that dies); only the in-process isolation path mutates the host’s own configuration.

back by replacing the ivar; the stream ivars are reassigned during the run, so capturing the original references is enough.

Constant Summary collapse

PREFERRED_OPTIONS =
:@preferred_options
STREAM_IVARS =
%i[@output_stream @error_stream].freeze
ALL_IVARS =
[PREFERRED_OPTIONS, *STREAM_IVARS].freeze

Instance Method Summary collapse

Constructor Details

#initialize(configuration: nil) ⇒ ConfigurationState

configuration is injectable for isolated unit testing; production uses the shared RSpec.configuration singleton.



30
31
32
# File 'lib/evilution/integration/rspec/state_guard/configuration_state.rb', line 30

def initialize(configuration: nil)
  @configuration = configuration
end

Instance Method Details

#release(captured) ⇒ Object

Restore exactly the pre-run state: ivars present at snapshot get their value back; ivars created by the run but absent before are removed, so nothing the run introduced can leak into the host either.



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/evilution/integration/rspec/state_guard/configuration_state.rb', line 47

def release(captured)
  return unless captured

  config = configuration
  ALL_IVARS.each do |ivar|
    if captured.key?(ivar)
      config.instance_variable_set(ivar, captured[ivar])
    elsif config.instance_variable_defined?(ivar)
      config.remove_instance_variable(ivar)
    end
  end
end

#snapshotObject



34
35
36
37
38
39
40
41
42
# File 'lib/evilution/integration/rspec/state_guard/configuration_state.rb', line 34

def snapshot
  config = configuration
  state = {}
  capture_preferred_options(config, state)
  STREAM_IVARS.each do |ivar|
    state[ivar] = config.instance_variable_get(ivar) if config.instance_variable_defined?(ivar)
  end
  state
end