Class: Pinspec::Runner::Sandbox

Inherits:
Object
  • Object
show all
Defined in:
lib/pinspec/runner/sandbox.rb

Defined Under Namespace

Classes: Result

Constant Summary collapse

PROBE_DIR =
"tmp/pinspec"
DEFAULT_TIMEOUT =
600
FORCED_ENV =
{
  "DISABLE_SPRING" => "1",
  "TZ" => "UTC",
  "RAILS_ENV" => "test"
}.freeze
SCRUBBED_ENV =
Runtime::BUNDLER_VARS.to_h { |name| [name, nil] }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app_root:, probe_source:, timeout: DEFAULT_TIMEOUT, runner: nil, env: {}) ⇒ Sandbox

Returns a new instance of Sandbox.



39
40
41
42
43
44
45
# File 'lib/pinspec/runner/sandbox.rb', line 39

def initialize(app_root:, probe_source:, timeout: DEFAULT_TIMEOUT, runner: nil, env: {})
  @app_root = app_root
  @probe_source = probe_source
  @timeout = timeout
  @runner = runner
  @env = env
end

Class Method Details

.probe_filename(pid: Process.pid, object_id: nil) ⇒ Object

One probe file per run. A fixed path means two pinspec runs against the same application overwrite each other's probe between boots, and the result is not an error: the stability filter compares one target's observations against another's and reports the target as unstable, or crashes looking up a case id that belongs to a different corpus. Silent and wrong, which is worse than a lock. pinspec pin app/services is sequential, but a developer with two terminals or a CI that fans out is not.



19
20
21
# File 'lib/pinspec/runner/sandbox.rb', line 19

def self.probe_filename(pid: Process.pid, object_id: nil)
  "probe-#{pid}-#{object_id || rand(1 << 24)}.rb"
end

Instance Method Details

#capture(boots: 2) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/pinspec/runner/sandbox.rb', line 57

def capture(boots: 2)
  write_probe!

  results = (1..boots).map { |run| execute(run: run, seed: 40 + run) }

  # Removed only on success. A probe left behind after a failure is the
  # evidence; one left behind after every run just fills tmp/ with files a
  # reader cannot tell apart.
  FileUtils.rm_f(probe_path)
  results
end

#probe_pathObject



47
48
49
# File 'lib/pinspec/runner/sandbox.rb', line 47

def probe_path
  @probe_path ||= File.join(@app_root, PROBE_DIR, self.class.probe_filename(object_id: object_id))
end

#runtimeObject



69
70
71
# File 'lib/pinspec/runner/sandbox.rb', line 69

def runtime
  @runtime ||= Runtime.for(@app_root)
end

#write_probe!Object



51
52
53
54
55
# File 'lib/pinspec/runner/sandbox.rb', line 51

def write_probe!
  FileUtils.mkdir_p(File.dirname(probe_path))
  File.write(probe_path, @probe_source)
  probe_path
end