From 95e8c48dd3348503a8c7db5d0498894a1b676395 Mon Sep 17 00:00:00 2001 From: eregon Date: Sun, 7 May 2017 12:04:49 +0000 Subject: Add in-tree mspec and ruby/spec * For easier modifications of ruby/spec by MRI developers. * .gitignore: track changes under spec. * spec/mspec, spec/rubyspec: add in-tree mspec and ruby/spec. These files can therefore be updated like any other file in MRI. Instructions are provided in spec/README. [Feature #13156] [ruby-core:79246] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- spec/mspec/lib/mspec/commands/mspec.rb | 163 +++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100755 spec/mspec/lib/mspec/commands/mspec.rb (limited to 'spec/mspec/lib/mspec/commands/mspec.rb') diff --git a/spec/mspec/lib/mspec/commands/mspec.rb b/spec/mspec/lib/mspec/commands/mspec.rb new file mode 100755 index 0000000000..6f1ae8cb6e --- /dev/null +++ b/spec/mspec/lib/mspec/commands/mspec.rb @@ -0,0 +1,163 @@ +#!/usr/bin/env ruby + +require 'mspec/version' +require 'mspec/utils/options' +require 'mspec/utils/script' +require 'mspec/helpers/tmp' +require 'mspec/runner/actions/filter' +require 'mspec/runner/actions/timer' + + +class MSpecMain < MSpecScript + def initialize + super + + config[:loadpath] = [] + config[:requires] = [] + config[:target] = ENV['RUBY'] || 'ruby' + config[:flags] = [] + config[:command] = nil + config[:options] = [] + config[:launch] = [] + end + + def options(argv=ARGV) + config[:command] = argv.shift if ["ci", "run", "tag"].include?(argv[0]) + + options = MSpecOptions.new "mspec [COMMAND] [options] (FILE|DIRECTORY|GLOB)+", 30, config + + options.doc " The mspec command sets up and invokes the sub-commands" + options.doc " (see below) to enable, for instance, running the specs" + options.doc " with different implementations like ruby, jruby, rbx, etc.\n" + + options.configure do |f| + load f + config[:options] << '-B' << f + end + + options.targets + + options.on("--warnings", "Don't supress warnings") do + config[:flags] << '-w' + ENV['OUTPUT_WARNINGS'] = '1' + end + + options.on("-j", "--multi", "Run multiple (possibly parallel) subprocesses") do + config[:multi] = true + config[:options] << "-fy" + end + + options.version MSpec::VERSION do + if config[:command] + config[:options] << "-v" + else + puts "#{File.basename $0} #{MSpec::VERSION}" + exit + end + end + + options.help do + if config[:command] + config[:options] << "-h" + else + puts options + exit 1 + end + end + + options.doc "\n Custom options" + custom_options options + + # The rest of the help output + options.doc "\n where COMMAND is one of:\n" + options.doc " run - Run the specified specs (default)" + options.doc " ci - Run the known good specs" + options.doc " tag - Add or remove tags\n" + options.doc " mspec COMMAND -h for more options\n" + options.doc " example: $ mspec run -h\n" + + options.on_extra { |o| config[:options] << o } + options.parse(argv) + + if config[:multi] + options = MSpecOptions.new "mspec", 30, config + options.all + patterns = options.parse(config[:options]) + @files = files_from_patterns(patterns) + end + end + + def register; end + + def multi_exec(argv) + MSpec.register_files @files + + require 'mspec/runner/formatters/multi' + formatter = MultiFormatter.new + + output_files = [] + processes = [cores, @files.size].min + children = processes.times.map { |i| + name = tmp "mspec-multi-#{i}" + output_files << name + + env = { + "SPEC_TEMP_DIR" => "rubyspec_temp_#{i}", + "MSPEC_MULTI" => i.to_s + } + command = argv + ["-o", name] + $stderr.puts "$ #{command.join(' ')}" if $MSPEC_DEBUG + IO.popen([env, *command], "rb+") + } + + puts children.map { |child| child.gets }.uniq + formatter.start + + until @files.empty? + IO.select(children)[0].each { |io| + reply = io.read(1) + case reply + when '.' + formatter.unload + when nil + raise "Worker died!" + else + while chunk = (io.read_nonblock(4096) rescue nil) + reply += chunk + end + raise reply + end + io.puts @files.shift unless @files.empty? + } + end + + ok = true + children.each { |child| + child.puts "QUIT" + Process.wait(child.pid) + ok &&= $?.success? + } + + formatter.aggregate_results(output_files) + formatter.finish + ok + end + + def run + argv = config[:target].split(/\s+/) + + argv.concat config[:launch] + argv.concat config[:flags] + argv.concat config[:loadpath] + argv.concat config[:requires] + argv << "#{MSPEC_HOME}/bin/mspec-#{ config[:command] || "run" }" + argv.concat config[:options] + + if config[:multi] + exit multi_exec(argv) + else + $stderr.puts "$ #{argv.join(' ')}" + exec(*argv) + end + end +end -- cgit v1.2.3