class ParallelTests

def self.bundler_enabled?

copied from http://github.com/carlhuda/bundler Bundler::SharedHelpers#find_gemfile
def self.bundler_enabled?
  return true if Object.const_defined?(:Bundler) 
  previous = nil
  current = File.expand_path(Dir.pwd)
  until !File.directory?(current) || current == previous
    filename = File.join(current, "Gemfile")
    return true if File.exists?(filename)
    current, previous = File.expand_path("..", current), current
  end
  false
end

def self.execute_command(cmd, process_number)

def self.execute_command(cmd, process_number)
  cmd = "TEST_ENV_NUMBER=#{test_env_number(process_number)} ; export TEST_ENV_NUMBER; #{cmd}"
  f = open("|#{cmd}", 'r')
  all = ''
  while char = f.getc
    char = (char.is_a?(Fixnum) ? char.chr : char) # 1.8 <-> 1.9
    all << char
    print char
    STDOUT.flush
  end
  f.close
  {:stdout => all, :exit_status => $?.exitstatus}
end

def self.find_results(test_output)

def self.find_results(test_output)
  test_output.split("\n").map {|line|
    line = line.gsub(/\.|F|\*/,'')
    next unless line_is_result?(line)
    line
  }.compact
end

def self.find_tests(root)

def self.find_tests(root)
  if root.is_a?(Array)
    root
  else
    Dir["#{root}**/**/*#{self.test_suffix}"]
  end
end

def self.line_is_result?(line)

def self.line_is_result?(line)
  line =~ /\d+ failure/
end

def self.parse_rake_args(args)

parallel:spec[2,controller] <-> parallel:spec[controller]
def self.parse_rake_args(args)
  num_processes = Parallel.processor_count
  options = ""
  if args[:count].to_s =~ /^\d*$/ # number or empty
    num_processes = args[:count] unless args[:count].to_s.empty?
    prefix = args[:path_prefix]
    options = args[:options] if args[:options]
  else # something stringy
    prefix = args[:count]
  end
  [num_processes.to_i, prefix.to_s, options]
end

def self.run_tests(test_files, process_number, options)

def self.run_tests(test_files, process_number, options)
  require_list = test_files.map { |filename| "\"#{filename}\"" }.join(",")
  cmd = "ruby -Itest #{options} -e '[#{require_list}].each {|f| require f }'"
  execute_command(cmd, process_number)
end

def self.test_env_number(process_number)

def self.test_env_number(process_number)
  process_number == 0 ? '' : process_number + 1
end

def self.test_suffix

def self.test_suffix
  "_test.rb"
end

def self.tests_in_groups(root, num_groups, options={})

finds all tests and partitions them into groups
def self.tests_in_groups(root, num_groups, options={})
  if options[:no_sort] == true
    Grouper.in_groups(find_tests(root), num_groups)
  else
    Grouper.in_even_groups_by_size(tests_with_runtime(root), num_groups)
  end
end

def self.tests_with_runtime(root)

def self.tests_with_runtime(root)
  tests = find_tests(root)
  lines = File.read('tmp/parallel_profile.log').split("\n") rescue []
  # use recorded test runtime if we got enough data
  if lines.size * 1.5 > tests.size
    puts "Using recorded test runtime"
    times = Hash.new(1)
    lines.each do |line|
      test, time = line.split(":")
      times[test] = time.to_f
    end
    tests.sort.map{|test| [test, times[test]] }
  else # use file sizes
    tests.sort.map{|test| [test, File.stat(test).size] }
  end
end