Module: RSpec::Support::InSubProcess

Defined in:
lib/rspec/support/spec/in_sub_process.rb

Defined Under Namespace

Classes: UnmarshableObject

Instance Method Summary collapse

Instance Method Details

#in_sub_processObject

Useful as a way to isolate a global change to a subprocess.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rspec/support/spec/in_sub_process.rb', line 12

def in_sub_process(prevent_warnings=true) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  exception_reader, exception_writer = IO.pipe
  result_reader, result_writer = IO.pipe

  # Set binary mode to avoid errors surrounding ascii-8bit to utf-8 conversion
  # this happens with warnings on rspec-rails for example
  [exception_reader, exception_writer, result_reader, result_writer].each { |io| io.binmode }

  pid = Process.fork do
    warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr)

    begin
      result = yield
      warning_preventer.verify_no_warnings! if prevent_warnings
      # rubocop:disable Lint/HandleExceptions
    rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception
      # rubocop:enable Lint/HandleExceptions
    end

    exception_writer.write marshal_dump_with_unmarshable_object_handling(exception)
    exception_reader.close
    exception_writer.close

    result_writer.write marshal_dump_with_unmarshable_object_handling(result)
    result_reader.close
    result_writer.close

    exit! # prevent at_exit hooks from running (e.g. minitest)
  end

  exception_writer.close
  result_writer.close
  Process.waitpid(pid)

  exception = Marshal.load(exception_reader.read)
  exception_reader.close
  raise exception if exception

  result = Marshal.load(result_reader.read)
  result_reader.close
  result
end

#in_sub_process_if_possibleObject

Useful as a way to isolate a global change to a subprocess.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/rspec/support/spec/in_sub_process.rb', line 54

def in_sub_process(prevent_warnings=true) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  exception_reader, exception_writer = IO.pipe
  result_reader, result_writer = IO.pipe

  # Set binary mode to avoid errors surrounding ascii-8bit to utf-8 conversion
  # this happens with warnings on rspec-rails for example
  [exception_reader, exception_writer, result_reader, result_writer].each { |io| io.binmode }

  pid = Process.fork do
    warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr)

    begin
      result = yield
      warning_preventer.verify_no_warnings! if prevent_warnings
      # rubocop:disable Lint/HandleExceptions
    rescue Support::AllExceptionsExceptOnesWeMustNotRescue => exception
      # rubocop:enable Lint/HandleExceptions
    end

    exception_writer.write marshal_dump_with_unmarshable_object_handling(exception)
    exception_reader.close
    exception_writer.close

    result_writer.write marshal_dump_with_unmarshable_object_handling(result)
    result_reader.close
    result_writer.close

    exit! # prevent at_exit hooks from running (e.g. minitest)
  end

  exception_writer.close
  result_writer.close
  Process.waitpid(pid)

  exception = Marshal.load(exception_reader.read)
  exception_reader.close
  raise exception if exception

  result = Marshal.load(result_reader.read)
  result_reader.close
  result
end

#marshal_dump_with_unmarshable_object_handling(object) ⇒ Object



56
57
58
59
60
# File 'lib/rspec/support/spec/in_sub_process.rb', line 56

def marshal_dump_with_unmarshable_object_handling(object)
  Marshal.dump(object)
rescue TypeError => error
  Marshal.dump(UnmarshableObject.new(error))
end