class RubyQC::Modifier

Public Class Methods

new(args, &block) click to toggle source
Calls superclass method
# File lib/rubyqc/modifier.rb, line 6
def initialize args, &block
  super(args, [], RubyQC.default_times, RubyQC.default_parallel)
  run(&block)
end

Public Instance Methods

parallel(t, &block) click to toggle source
# File lib/rubyqc/modifier.rb, line 18
def parallel t, &block
  raise ArgumentError.new(
    "Must have at least 1 thread, but got: #{t}") if t <= 0
  self.threads = t
  run(&block)
end
times(t, &block) click to toggle source
# File lib/rubyqc/modifier.rb, line 11
def times t, &block
  raise ArgumentError.new(
    "Must run at least once, but got: #{t}") if t <= 0
  self.cases = t
  run(&block)
end

Private Instance Methods

mutex() click to toggle source
# File lib/rubyqc/modifier.rb, line 26
def mutex
  @mutex ||= Mutex.new
end
run(&block) click to toggle source
# File lib/rubyqc/modifier.rb, line 30
def run &block
  if !block_given?
    # waiting for block to be given
  elsif threads == 1
    run_thread(cases, &block)
  else
    divided = cases / threads
    mod     = cases % threads

    ts = (threads - 1).times.map{
      Thread.new{ run_thread(divided, &block) }
    } + [Thread.new{ run_thread(divided + mod, &block) }]
    ts.each(&:join)

    raise Error.new(cases, errors) unless errors.empty?
  end

  self
end
run_thread(t) { |*map(&:rubyqc)| ... } click to toggle source
# File lib/rubyqc/modifier.rb, line 50
def run_thread t
  t.times do
    if Thread.current == Thread.main
      # we raise errors immediately if we're not running in parallels
      yield(*args.map(&:rubyqc))
    else
      begin
        yield(*args.map(&:rubyqc))
      rescue Exception => e
        mutex.synchronize{ errors << e }
      end
    end
  end
end