summaryrefslogtreecommitdiff
path: root/spec/mspec/lib/mspec/commands/mspec.rb
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-05-07 12:04:49 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-05-07 12:04:49 +0000
commit95e8c48dd3348503a8c7db5d0498894a1b676395 (patch)
tree9eef7f720314ebaff56845a74e203770e62284e4 /spec/mspec/lib/mspec/commands/mspec.rb
parented7d803500de38186c74bce94d233e85ef51e503 (diff)
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
Diffstat (limited to 'spec/mspec/lib/mspec/commands/mspec.rb')
-rwxr-xr-xspec/mspec/lib/mspec/commands/mspec.rb163
1 files changed, 163 insertions, 0 deletions
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