Class: Mutest::Isolation::Fork Private

Inherits:
Mutest::Isolation show all
Defined in:
lib/mutest/isolation/fork.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Isolation via the fork(2) systemcall.

We do inject so many globals and common patterns to make this unit specifiable without mocking the globals and more important: Not having mutations that bypass mocks into a real world side effect.

Constant Summary

Constants inherited from Mutest::Isolation

Error

Instance Method Summary collapse

Instance Method Details

#call(&block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Call block in isolation

Returns:

  • (Object)

    returns block execution result

Raises:

  • (Error)

    if block terminates abnormal



21
22
23
24
25
26
27
# File 'lib/mutest/isolation/fork.rb', line 21

def call(&block)
  io.pipe(binmode: true) do |pipes|
    parent(*pipes, &block)
  end
rescue => exception
  raise Error, exception
end

#child(reader, writer, &block) ⇒ undefined

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handle child process

Parameters:

  • reader (IO)
  • writer (IO)

Returns:

  • (undefined)


53
54
55
56
57
58
# File 'lib/mutest/isolation/fork.rb', line 53

def child(reader, writer, &block)
  reader.close
  writer.binmode
  writer.syswrite(marshal.dump(result(&block)))
  writer.close
end

#parent(reader, writer, &block) ⇒ undefined

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handle parent process

Parameters:

  • reader (IO)
  • writer (IO)

Returns:

  • (undefined)


35
36
37
38
39
40
41
42
43
44
45
# File 'lib/mutest/isolation/fork.rb', line 35

def parent(reader, writer, &block)
  pid =
    process.fork do
      child(reader, writer, &block)
    end

  writer.close
  marshal.load(reader)
ensure
  process.waitpid(pid) if pid
end

#resultObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The block result computed under silencing

Returns:

  • (Object)


63
64
65
66
67
68
69
# File 'lib/mutest/isolation/fork.rb', line 63

def result
  devnull.call do |null|
    stderr.reopen(null)
    stdout.reopen(null)
    yield
  end
end