1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59203 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-06-29 14:35:09 +00:00
parent 0a11abfc7e
commit d55cd34ba8
53 changed files with 263 additions and 210 deletions

View file

@ -114,6 +114,7 @@ class MSpecMain < MSpecScript
puts children.map { |child| child.gets }.uniq
formatter.start
last_files = {}
until @files.empty?
IO.select(children)[0].each { |io|
@ -127,22 +128,33 @@ class MSpecMain < MSpecScript
while chunk = (io.read_nonblock(4096) rescue nil)
reply += chunk
end
raise reply
reply.chomp!('.')
msg = "A child mspec-run process printed unexpected output on STDOUT"
if last_file = last_files[io]
msg += " while running #{last_file}"
end
abort "\n#{msg}: #{reply.inspect}"
end
unless @files.empty?
file = @files.shift
last_files[io] = file
io.puts file
end
io.puts @files.shift unless @files.empty?
}
end
ok = true
success = true
children.each { |child|
child.puts "QUIT"
Process.wait(child.pid)
ok &&= $?.success?
_pid, status = Process.wait2(child.pid)
success &&= status.success?
child.close
}
formatter.aggregate_results(output_files)
formatter.finish
ok
success
end
def run
@ -152,7 +164,7 @@ class MSpecMain < MSpecScript
argv.concat config[:flags]
argv.concat config[:loadpath]
argv.concat config[:requires]
argv << "#{MSPEC_HOME}/bin/mspec-#{ config[:command] || "run" }"
argv << "#{MSPEC_HOME}/bin/mspec-#{config[:command] || 'run'}"
argv.concat config[:options]
if config[:multi]

View file

@ -38,6 +38,14 @@ require 'mspec/helpers/tmp'
# If +nil+ is passed for the first argument, the command line
# will be built only from the options hash.
#
# If no arguments are passed to ruby_exe, it returns an Array
# containing the interpreter executable and the flags:
#
# spawn(*ruby_exe, "-e", "puts :hello")
#
# This avoids spawning an extra shell, and ensure the pid returned by spawn
# corresponds to the ruby process and not the shell.
#
# The RUBY_EXE constant is setup by mspec automatically
# and is used by ruby_exe and ruby_cmd. The mspec runner script
# will set ENV['RUBY_EXE'] to the name of the executable used
@ -121,11 +129,15 @@ def resolve_ruby_exe
raise Exception, "Unable to find a suitable ruby executable."
end
def ruby_exe(code, opts = {})
def ruby_exe(code = :not_given, opts = {})
if opts[:dir]
raise "ruby_exe(..., dir: dir) is no longer supported, use Dir.chdir"
end
if code == :not_given
return RUBY_EXE.split(' ')
end
env = opts[:env] || {}
saved_env = {}
env.each do |key, value|

View file

@ -1,3 +1,15 @@
module MSpecMatchers
end
class MSpecEnv
include MSpecMatchers
end
# Expactations are sometimes used in a module body
class Module
include MSpecMatchers
end
class SpecPositiveOperatorMatcher
def initialize(actual)
@actual = actual

View file

@ -19,8 +19,8 @@ class BeAnInstanceOfMatcher
end
end
class Object
def be_an_instance_of(expected)
module MSpecMatchers
private def be_an_instance_of(expected)
BeAnInstanceOfMatcher.new(expected)
end
end

View file

@ -17,8 +17,8 @@ class BeAncestorOfMatcher
end
end
class Object
def be_ancestor_of(expected)
module MSpecMatchers
private def be_ancestor_of(expected)
BeAncestorOfMatcher.new(expected)
end
end

View file

@ -20,8 +20,8 @@ class BeCloseMatcher
end
end
class Object
def be_close(expected, tolerance)
module MSpecMatchers
private def be_close(expected, tolerance)
BeCloseMatcher.new(expected, tolerance)
end
end

View file

@ -30,8 +30,8 @@ class BeComputedByMatcher
end
end
class Object
def be_computed_by(sym, *args)
module MSpecMatchers
private def be_computed_by(sym, *args)
BeComputedByMatcher.new(sym, *args)
end
end

View file

@ -13,8 +13,8 @@ class BeEmptyMatcher
end
end
class Object
def be_empty
module MSpecMatchers
private def be_empty
BeEmptyMatcher.new
end
end

View file

@ -13,8 +13,8 @@ class BeFalseMatcher
end
end
class Object
def be_false
module MSpecMatchers
private def be_false
BeFalseMatcher.new
end
end

View file

@ -17,8 +17,8 @@ class BeKindOfMatcher
end
end
class Object
def be_kind_of(expected)
module MSpecMatchers
private def be_kind_of(expected)
BeKindOfMatcher.new(expected)
end
end

View file

@ -13,8 +13,8 @@ class BeNaNMatcher
end
end
class Object
def be_nan
module MSpecMatchers
private def be_nan
BeNaNMatcher.new
end
end

View file

@ -13,8 +13,8 @@ class BeNilMatcher
end
end
class Object
def be_nil
module MSpecMatchers
private def be_nil
BeNilMatcher.new
end
end

View file

@ -13,8 +13,8 @@ class BeTrueMatcher
end
end
class Object
def be_true
module MSpecMatchers
private def be_true
BeTrueMatcher.new
end
end

View file

@ -13,8 +13,8 @@ class BeTrueOrFalseMatcher
end
end
class Object
def be_true_or_false
module MSpecMatchers
private def be_true_or_false
BeTrueOrFalseMatcher.new
end
end

View file

@ -28,8 +28,8 @@ class BlockingMatcher
end
end
class Object
def block_caller(timeout = 0.1)
module MSpecMatchers
private def block_caller(timeout = 0.1)
BlockingMatcher.new
end
end

View file

@ -49,8 +49,8 @@ class ComplainMatcher
end
end
class Object
def complain(complaint=nil)
module MSpecMatchers
private def complain(complaint=nil)
ComplainMatcher.new(complaint)
end
end

View file

@ -19,8 +19,8 @@ class EqlMatcher
end
end
class Object
def eql(expected)
module MSpecMatchers
private def eql(expected)
EqlMatcher.new(expected)
end
end

View file

@ -19,8 +19,8 @@ class EqualMatcher
end
end
class Object
def equal(expected)
module MSpecMatchers
private def equal(expected)
EqualMatcher.new(expected)
end
end

View file

@ -71,8 +71,8 @@ class EqualElementMatcher
end
end
class Object
def equal_element(*args)
module MSpecMatchers
private def equal_element(*args)
EqualElementMatcher.new(*args)
end
end

View file

@ -5,8 +5,8 @@ class HaveClassVariableMatcher < VariableMatcher
self.description = 'class variable'
end
class Object
def have_class_variable(variable)
module MSpecMatchers
private def have_class_variable(variable)
HaveClassVariableMatcher.new(variable)
end
end

View file

@ -5,8 +5,8 @@ class HaveConstantMatcher < VariableMatcher
self.description = 'constant'
end
class Object
def have_constant(variable)
module MSpecMatchers
private def have_constant(variable)
HaveConstantMatcher.new(variable)
end
end

View file

@ -17,8 +17,8 @@ class HaveInstanceMethodMatcher < MethodMatcher
end
end
class Object
def have_instance_method(method, include_super=true)
module MSpecMatchers
private def have_instance_method(method, include_super=true)
HaveInstanceMethodMatcher.new method, include_super
end
end

View file

@ -5,8 +5,8 @@ class HaveInstanceVariableMatcher < VariableMatcher
self.description = 'instance variable'
end
class Object
def have_instance_variable(variable)
module MSpecMatchers
private def have_instance_variable(variable)
HaveInstanceVariableMatcher.new(variable)
end
end

View file

@ -17,8 +17,8 @@ class HaveMethodMatcher < MethodMatcher
end
end
class Object
def have_method(method, include_super=true)
module MSpecMatchers
private def have_method(method, include_super=true)
HaveMethodMatcher.new method, include_super
end
end

View file

@ -17,8 +17,8 @@ class HavePrivateInstanceMethodMatcher < MethodMatcher
end
end
class Object
def have_private_instance_method(method, include_super=true)
module MSpecMatchers
private def have_private_instance_method(method, include_super=true)
HavePrivateInstanceMethodMatcher.new method, include_super
end
end

View file

@ -17,8 +17,8 @@ class HavePrivateMethodMatcher < MethodMatcher
end
end
class Object
def have_private_method(method, include_super=true)
module MSpecMatchers
private def have_private_method(method, include_super=true)
HavePrivateMethodMatcher.new method, include_super
end
end

View file

@ -17,8 +17,8 @@ class HaveProtectedInstanceMethodMatcher < MethodMatcher
end
end
class Object
def have_protected_instance_method(method, include_super=true)
module MSpecMatchers
private def have_protected_instance_method(method, include_super=true)
HaveProtectedInstanceMethodMatcher.new method, include_super
end
end

View file

@ -17,8 +17,8 @@ class HavePublicInstanceMethodMatcher < MethodMatcher
end
end
class Object
def have_public_instance_method(method, include_super=true)
module MSpecMatchers
private def have_public_instance_method(method, include_super=true)
HavePublicInstanceMethodMatcher.new method, include_super
end
end

View file

@ -17,8 +17,8 @@ class HaveSingletonMethodMatcher < MethodMatcher
end
end
class Object
def have_singleton_method(method, include_super=true)
module MSpecMatchers
private def have_singleton_method(method, include_super=true)
HaveSingletonMethodMatcher.new method, include_super
end
end

View file

@ -24,9 +24,8 @@ class IncludeMatcher
end
# Cannot override #include at the toplevel in MRI
module MSpec
def include(*expected)
module MSpecMatchers
private def include(*expected)
IncludeMatcher.new(*expected)
end
module_function :include
end

View file

@ -17,12 +17,12 @@ class InfinityMatcher
end
end
class Object
def be_positive_infinity
module MSpecMatchers
private def be_positive_infinity
InfinityMatcher.new(1)
end
def be_negative_infinity
private def be_negative_infinity
InfinityMatcher.new(-1)
end
end

View file

@ -39,9 +39,8 @@ class MatchYAMLMatcher
end
end
class Object
def match_yaml(expected)
module MSpecMatchers
private def match_yaml(expected)
MatchYAMLMatcher.new(expected)
end
end

View file

@ -60,8 +60,8 @@ class OutputMatcher
end
end
class Object
def output(stdout=nil, stderr=nil)
module MSpecMatchers
private def output(stdout=nil, stderr=nil)
OutputMatcher.new(stdout, stderr)
end
end

View file

@ -64,8 +64,8 @@ class OutputToFDMatcher
end
end
class Object
def output_to_fd(what, where = STDOUT)
module MSpecMatchers
private def output_to_fd(what, where = STDOUT)
OutputToFDMatcher.new what, where
end
end

View file

@ -72,8 +72,8 @@ class RaiseErrorMatcher
end
end
class Object
def raise_error(exception=Exception, message=nil, &block)
module MSpecMatchers
private def raise_error(exception=Exception, message=nil, &block)
RaiseErrorMatcher.new(exception, message, &block)
end
end

View file

@ -17,8 +17,8 @@ class RespondToMatcher
end
end
class Object
def respond_to(expected)
module MSpecMatchers
private def respond_to(expected)
RespondToMatcher.new(expected)
end
end

View file

@ -17,12 +17,12 @@ class SignedZeroMatcher
end
end
class Object
def be_positive_zero
module MSpecMatchers
private def be_positive_zero
SignedZeroMatcher.new(1)
end
def be_negative_zero
private def be_negative_zero
SignedZeroMatcher.new(-1)
end
end

View file

@ -1,9 +1,5 @@
require 'mspec/expectations/expectations'
class Object
alias_method :__mspec_object_id__, :object_id
end
module Mock
def self.reset
@mocks = @stubs = @objects = nil
@ -22,7 +18,7 @@ module Mock
end
def self.replaced_name(obj, sym)
:"__mspec_#{obj.__mspec_object_id__}_#{sym}__"
:"__mspec_#{obj.__id__}_#{sym}__"
end
def self.replaced_key(obj, sym)

View file

@ -1,10 +1,6 @@
require 'mspec/mocks/proxy'
class Object
def stub!(sym)
Mock.install_method self, sym, :stub
end
def should_receive(sym)
Mock.install_method self, sym
end
@ -14,15 +10,19 @@ class Object
proxy.exactly(0).times
end
def mock(name, options={})
MockObject.new name, options
end
def mock_int(val)
MockIntObject.new(val)
end
def mock_numeric(name, options={})
NumericMockObject.new name, options
def stub!(sym)
Mock.install_method self, sym, :stub
end
end
def mock(name, options={})
MockObject.new name, options
end
def mock_int(val)
MockIntObject.new(val)
end
def mock_numeric(name, options={})
NumericMockObject.new name, options
end

View file

@ -1,4 +1,6 @@
class SpecEvaluate
include MSpecMatchers
def self.desc=(desc)
@desc = desc
end
@ -47,8 +49,6 @@ class SpecEvaluate
end
end
class Object
def evaluate(str, desc=nil, &block)
SpecEvaluate.new(str, desc).define(&block)
end
def evaluate(str, desc=nil, &block)
SpecEvaluate.new(str, desc).define(&block)
end

View file

@ -2,6 +2,10 @@ require 'mspec/runner/context'
require 'mspec/runner/exception'
require 'mspec/runner/tag'
class MSpecEnv
include MSpec
end
module MSpec
@exit = nil
@ -53,11 +57,19 @@ module MSpec
if ENV["MSPEC_MULTI"]
STDOUT.print "."
STDOUT.flush
while (file = STDIN.gets.chomp) != "QUIT"
while file = STDIN.gets and file = file.chomp
return if file == "QUIT"
yield file
STDOUT.print "."
STDOUT.flush
begin
STDOUT.print "."
STDOUT.flush
rescue Errno::EPIPE
# The parent died
exit 1
end
end
# The parent closed the connection without QUIT
abort "the parent did not send QUIT"
else
return unless files = retrieve(:files)
shuffle files if randomize?
@ -76,8 +88,7 @@ module MSpec
end
def self.setup_env
@env = Object.new
@env.extend MSpec
@env = MSpecEnv.new
end
def self.actions(action, *args)

View file

@ -1,28 +1,26 @@
class Object
def before(at=:each, &block)
private def before(at=:each, &block)
MSpec.current.before at, &block
end
def after(at=:each, &block)
private def after(at=:each, &block)
MSpec.current.after at, &block
end
def describe(mod, msg=nil, options=nil, &block)
private def describe(mod, msg=nil, options=nil, &block)
MSpec.describe mod, msg, &block
end
def it(msg, &block)
private def it(msg, &block)
MSpec.current.it msg, &block
end
def it_should_behave_like(desc)
private def it_should_behave_like(desc)
MSpec.current.it_should_behave_like desc
end
# For ReadRuby compatiability
def doc(*a)
end
alias_method :context, :describe
private :context
alias_method :specify, :it
private :specify
end

View file

@ -1,12 +1,10 @@
require 'mspec/runner/mspec'
class Object
def it_behaves_like(desc, meth, obj=nil)
send :before, :all do
@method = meth
@object = obj
end
send :it_should_behave_like, desc.to_s
def it_behaves_like(desc, meth, obj=nil)
send :before, :all do
@method = meth
@object = obj
end
send :it_should_behave_like, desc.to_s
end

View file

@ -396,7 +396,7 @@ class MSpecOptions
end
def obj.load
file = MSpec.retrieve :file
print "\n#{file.ljust(@width)}"
STDERR.print "\n#{file.ljust(@width)}"
end
MSpec.register :start, obj
MSpec.register :load, obj
@ -407,7 +407,7 @@ class MSpecOptions
obj = Object.new
obj.instance_variable_set :@marker, o
def obj.load
print @marker
STDERR.print @marker
end
MSpec.register :load, obj
end

View file

@ -60,13 +60,13 @@ describe MSpecMain, "#run" do
end
it "uses exec to invoke the runner script" do
@script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run")
@script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
@script.options []
@script.run
end
it "shows the command line on stderr" do
@script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run")
@script.should_receive(:exec).with("ruby", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
@script.options []
@script.run
$stderr.to_s.should == "$ ruby #{Dir.pwd}/bin/mspec-run\n"
@ -74,7 +74,7 @@ describe MSpecMain, "#run" do
it "adds config[:launch] to the exec options" do
@script.should_receive(:exec).with("ruby",
"-Xlaunch.option", "#{MSPEC_HOME}/bin/mspec-run")
"-Xlaunch.option", "#{MSPEC_HOME}/bin/mspec-run", close_others: false)
@config[:launch] << "-Xlaunch.option"
@script.options []
@script.run

View file

@ -33,6 +33,7 @@ MSpec.register :finish, monitor
at_exit { MSpec.actions :finish }
MSpec.actions :start
MSpec.setup_env
# Specs
describe "MSpec expectation method #should" do

View file

@ -0,0 +1,8 @@
unless defined?(RSpec)
describe "Object" do
it ".public_instance_methods(false) is empty" do
Object.public_instance_methods(false).sort.should ==
[:should, :should_not, :should_not_receive, :should_receive, :stub!]
end
end
end

View file

@ -11,53 +11,42 @@ class RubyExeSpecs
end
describe "#ruby_exe_options" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@ruby_engine = Object.const_get :RUBY_ENGINE
@ruby_exe_env = ENV['RUBY_EXE']
@script = RubyExeSpecs.new
end
after :all do
Object.const_set :RUBY_ENGINE, @ruby_engine
ENV['RUBY_EXE'] = @ruby_exe_env
$VERBOSE = @verbose
end
before :each do
@ruby_exe_env = ENV['RUBY_EXE']
@script = RubyExeSpecs.new
end
after :each do
ENV['RUBY_EXE'] = @ruby_exe_env
end
it "returns ENV['RUBY_EXE'] when passed :env" do
ENV['RUBY_EXE'] = "kowabunga"
@script.ruby_exe_options(:env).should == "kowabunga"
end
it "returns 'bin/jruby' when passed :engine and RUBY_ENGINE is 'jruby'" do
Object.const_set :RUBY_ENGINE, 'jruby'
stub_const "RUBY_ENGINE", 'jruby'
@script.ruby_exe_options(:engine).should == 'bin/jruby'
end
it "returns 'bin/rbx' when passed :engine, RUBY_ENGINE is 'rbx'" do
Object.const_set :RUBY_ENGINE, 'rbx'
stub_const "RUBY_ENGINE", 'rbx'
@script.ruby_exe_options(:engine).should == 'bin/rbx'
end
it "returns 'ir' when passed :engine and RUBY_ENGINE is 'ironruby'" do
Object.const_set :RUBY_ENGINE, 'ironruby'
stub_const "RUBY_ENGINE", 'ironruby'
@script.ruby_exe_options(:engine).should == 'ir'
end
it "returns 'maglev-ruby' when passed :engine and RUBY_ENGINE is 'maglev'" do
Object.const_set :RUBY_ENGINE, 'maglev'
stub_const "RUBY_ENGINE", 'maglev'
@script.ruby_exe_options(:engine).should == 'maglev-ruby'
end
it "returns 'topaz' when passed :engine and RUBY_ENGINE is 'topaz'" do
Object.const_set :RUBY_ENGINE, 'topaz'
stub_const "RUBY_ENGINE", 'topaz'
@script.ruby_exe_options(:engine).should == 'topaz'
end
@ -75,21 +64,11 @@ describe "#ruby_exe_options" do
end
describe "#resolve_ruby_exe" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@name = "ruby_spec_exe"
end
before :each do
@name = "ruby_spec_exe"
@script = RubyExeSpecs.new
end
after :all do
$VERBOSE = @verbose
end
it "returns the value returned by #ruby_exe_options if it exists and is executable" do
@script.should_receive(:ruby_exe_options).and_return(@name)
File.should_receive(:file?).with(@name).and_return(true)
@ -126,12 +105,8 @@ describe "#resolve_ruby_exe" do
end
describe Object, "#ruby_cmd" do
before :all do
@verbose = $VERBOSE
$VERBOSE = nil
@ruby_exe = Object.const_get :RUBY_EXE
Object.const_set :RUBY_EXE, 'ruby_spec_exe -w -Q'
before :each do
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
@file = "some/ruby/file.rb"
@code = %(some "real" 'ruby' code)
@ -139,11 +114,6 @@ describe Object, "#ruby_cmd" do
@script = RubyExeSpecs.new
end
after :all do
Object.const_set :RUBY_EXE, @ruby_exe
$VERBOSE = @verbose
end
it "returns a command that runs the given file if it is a file that exists" do
File.should_receive(:exist?).with(@file).and_return(true)
@script.ruby_cmd(@file).should == "ruby_spec_exe -w -Q some/ruby/file.rb"
@ -168,12 +138,15 @@ describe Object, "#ruby_cmd" do
end
describe Object, "#ruby_exe" do
before :all do
before :each do
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
@script = RubyExeSpecs.new
@script.stub(:`)
end
before :each do
@script.stub(:`)
it "returns an Array containing the interpreter executable and flags when given no arguments" do
@script.ruby_exe.should == ['ruby_spec_exe', '-w', '-Q']
end
it "executes (using `) the result of calling #ruby_cmd with the given arguments" do

View file

@ -0,0 +1,18 @@
require 'spec_helper'
expected_output = <<EOS
RUBY_DESCRIPTION
.
Finished in D.DDDDDD seconds
1 file, 1 example, 1 expectation, 0 failures, 0 errors, 0 tagged
EOS
describe "MSpec" do
it "does not define public methods on Object" do
out, ret = run_mspec("run", "spec/fixtures/object_methods_spec.rb")
out.should == expected_output
ret.success?.should == true
end
end

View file

@ -5,38 +5,40 @@ require 'mspec/matchers'
describe OutputToFDMatcher do
# Figure out how in the hell to achieve this
it "matches when running the block produces the expected output to the given FD" do
output_to_fd("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" }).should == true
OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.print "Hi\n" }).should == true
end
it "does not match if running the block does not produce the expected output to the FD" do
output_to_fd("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") }).should == false
OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda { $stderr.puts("Hello\n") }).should == false
end
it "propagate the exception if one is thrown while matching" do
exc = RuntimeError.new("propagates")
lambda {
output_to_fd("Hi\n", STDERR).matches?(lambda {
OutputToFDMatcher.new("Hi\n", STDERR).matches?(lambda {
raise exc
}).should == false
}.should raise_error(exc)
end
it "defaults to matching against STDOUT" do
output_to_fd("Hi\n").matches?(lambda { $stdout.print "Hi\n" }).should == true
object = Object.new
object.extend MSpecMatchers
object.send(:output_to_fd, "Hi\n").matches?(lambda { $stdout.print "Hi\n" }).should == true
end
it "accepts any IO instance" do
io = IO.new STDOUT.fileno
output_to_fd("Hi\n", io).matches?(lambda { io.print "Hi\n" }).should == true
OutputToFDMatcher.new("Hi\n", io).matches?(lambda { io.print "Hi\n" }).should == true
end
it "allows matching with a Regexp" do
s = "Hi there\n"
output_to_fd(/Hi/, STDERR).matches?(lambda { $stderr.print s }).should == true
output_to_fd(/Hi?/, STDERR).matches?(lambda { $stderr.print s }).should == true
output_to_fd(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s }).should == true
output_to_fd(/.*/, STDERR).matches?(lambda { $stderr.print s }).should == true
output_to_fd(/H.*?here/, STDERR).matches?(lambda { $stderr.print s }).should == true
output_to_fd(/Ahoy/, STDERR).matches?(lambda { $stderr.print s }).should == false
OutputToFDMatcher.new(/Hi/, STDERR).matches?(lambda { $stderr.print s }).should == true
OutputToFDMatcher.new(/Hi?/, STDERR).matches?(lambda { $stderr.print s }).should == true
OutputToFDMatcher.new(/[hH]i?/, STDERR).matches?(lambda { $stderr.print s }).should == true
OutputToFDMatcher.new(/.*/, STDERR).matches?(lambda { $stderr.print s }).should == true
OutputToFDMatcher.new(/H.*?here/, STDERR).matches?(lambda { $stderr.print s }).should == true
OutputToFDMatcher.new(/Ahoy/, STDERR).matches?(lambda { $stderr.print s }).should == false
end
end

View file

@ -22,16 +22,14 @@ end
describe Mock, ".replaced_name" do
it "returns the name for a method that is being replaced by a mock method" do
m = double('a fake id')
m.stub(:__mspec_object_id__).and_return(42)
Mock.replaced_name(m, :method_call).should == :__mspec_42_method_call__
Mock.replaced_name(m, :method_call).should == :"__mspec_#{m.object_id}_method_call__"
end
end
describe Mock, ".replaced_key" do
it "returns a key used internally by Mock" do
m = double('a fake id')
m.stub(:__mspec_object_id__).and_return(42)
Mock.replaced_key(m, :method_call).should == [:__mspec_42_method_call__, :method_call]
Mock.replaced_key(m, :method_call).should == [:"__mspec_#{m.object_id}_method_call__", :method_call]
end
end

View file

@ -11,6 +11,7 @@ describe Object, "#it_behaves_like" do
@state = ContextState.new "Top level"
@state.instance_variable_set :@parsed, true
@state.singleton_class.send(:public, :it_behaves_like)
@shared = ContextState.new :shared_spec, :shared => true
MSpec.stub(:retrieve_shared).and_return(@shared)
@ -51,6 +52,7 @@ describe Object, "#it_behaves_like" do
@state2 = ContextState.new "Second top level"
@state2.instance_variable_set :@parsed, true
@state2.singleton_class.send(:public, :it_behaves_like)
end
it "ensures the shared spec state is distinct" do

View file

@ -18,10 +18,17 @@ IMPLS = {
},
}
MSPEC = ARGV.delete('--mspec')
# Assuming the rubyspec repo is a sibling of the mspec repo
RUBYSPEC_REPO = File.expand_path("../../../../rubyspec", __FILE__)
raise RUBYSPEC_REPO unless Dir.exist?(RUBYSPEC_REPO)
MSPEC_REPO = File.expand_path("../../../../mspec", __FILE__)
raise MSPEC_REPO if MSPEC && !Dir.exist?(MSPEC_REPO)
SOURCE_REPO = MSPEC ? MSPEC_REPO : RUBYSPEC_REPO
NOW = Time.now
BRIGHT_YELLOW = "\e[33;1m"
@ -57,10 +64,13 @@ class RubyImplementation
end
def last_merge_message
@data[:merge_message] || "Merge ruby/spec commit"
message = @data[:merge_message] || "Merge ruby/spec commit"
message.gsub!("ruby/spec", "ruby/mspec") if MSPEC
message
end
def prefix
return "spec/mspec" if MSPEC
@data[:prefix] || "spec/ruby"
end
@ -96,18 +106,18 @@ end
def filter_commits(impl)
Dir.chdir(impl.repo_name) do
date = NOW.strftime("%F")
branch = "specs-#{date}"
branch = "#{MSPEC ? :mspec : :specs}-#{date}"
unless branch?(branch)
sh "git", "checkout", "-b", branch
sh "git", "filter-branch", "-f", "--subdirectory-filter", impl.prefix, *impl.from_commit
sh "git", "push", "-f", RUBYSPEC_REPO, "#{branch}:#{impl.name}"
sh "git", "push", "-f", SOURCE_REPO, "#{branch}:#{impl.name}"
end
end
end
def rebase_commits(impl)
Dir.chdir(RUBYSPEC_REPO) do
Dir.chdir(SOURCE_REPO) do
sh "git", "checkout", "master"
sh "git", "pull"
@ -144,25 +154,29 @@ end
def test_new_specs
require "yaml"
Dir.chdir(RUBYSPEC_REPO) do
versions = YAML.load_file(".travis.yml")
versions = versions["matrix"]["include"].map { |job| job["rvm"] }
versions.delete "ruby-head"
min_version, max_version = versions.minmax
Dir.chdir(SOURCE_REPO) do
if MSPEC
sh "bundle", "exec", "rspec"
else
versions = YAML.load_file(".travis.yml")
versions = versions["matrix"]["include"].map { |job| job["rvm"] }
versions.delete "ruby-head"
min_version, max_version = versions.minmax
run_rubyspec = -> version {
command = "chruby #{version} && ../mspec/bin/mspec -j"
sh ENV["SHELL"], "-c", command
}
run_rubyspec[min_version]
run_rubyspec[max_version]
run_rubyspec["trunk"]
run_rubyspec = -> version {
command = "chruby #{version} && ../mspec/bin/mspec -j"
sh ENV["SHELL"], "-c", command
}
run_rubyspec[min_version]
run_rubyspec[max_version]
run_rubyspec["trunk"]
end
end
end
def verify_commits(impl)
puts
Dir.chdir(RUBYSPEC_REPO) do
Dir.chdir(SOURCE_REPO) do
history = `git log master...`
history.lines.slice_before(/^commit \h{40}$/).each do |commit, *message|
commit = commit.chomp.split.last
@ -182,7 +196,7 @@ def verify_commits(impl)
end
def fast_forward_master(impl)
Dir.chdir(RUBYSPEC_REPO) do
Dir.chdir(SOURCE_REPO) do
sh "git", "checkout", "master"
sh "git", "merge", "--ff-only", "#{impl.name}-rebased"
end
@ -192,7 +206,7 @@ def check_ci
puts
puts <<-EOS
Push to master, and check that the CI passes:
https://github.com/ruby/spec/commits/master
https://github.com/ruby/#{:m if MSPEC}spec/commits/master
EOS
end