Sha256: f6ffc25fc6d8f254b3d8443ec056f4889b4bd11f9a581db2e4cde2ce06ec5d59

Contents?: true

Size: 1.76 KB

Versions: 8

Compression:

Stored size: 1.76 KB

Contents

module Mutest
  class Isolation
    # 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.
    class Fork < self
      include Anima.new(:process, :stderr, :stdout, :io, :devnull, :marshal)

      # Prevent mutation from `process.fork` to `fork` to call Kernel#fork
      undef_method :fork

      # Call block in isolation
      #
      # @return [Object]
      #   returns block execution result
      #
      # @raise [Error]
      #   if block terminates abnormal
      def call(&block)
        io.pipe(binmode: true) do |pipes|
          parent(*pipes, &block)
        end
      rescue => exception
        raise Error, exception
      end

      # Handle parent process
      #
      # @param [IO] reader
      # @param [IO] writer
      #
      # @return [undefined]
      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

      # Handle child process
      #
      # @param [IO] reader
      # @param [IO] writer
      #
      # @return [undefined]
      def child(reader, writer, &block)
        reader.close
        writer.binmode
        writer.syswrite(marshal.dump(result(&block)))
        writer.close
      end

      # The block result computed under silencing
      #
      # @return [Object]
      def result
        devnull.call do |null|
          stderr.reopen(null)
          stdout.reopen(null)
          yield
        end
      end
    end # Fork
  end # Isolation
end # Mutest

Version data entries

8 entries across 8 versions & 1 rubygems

Version Path
mutest-0.0.9 lib/mutest/isolation/fork.rb
mutest-0.0.8 lib/mutest/isolation/fork.rb
mutest-0.0.7 lib/mutest/isolation/fork.rb
mutest-0.0.6 lib/mutest/isolation/fork.rb
mutest-0.0.5 lib/mutest/isolation/fork.rb
mutest-0.0.4 lib/mutest/isolation/fork.rb
mutest-0.0.3 lib/mutest/isolation/fork.rb
mutest-0.0.2 lib/mutest/isolation/fork.rb