222 lines
7.0 KiB
Ruby
222 lines
7.0 KiB
Ruby
begin
|
|
require "bundler/gem_tasks"
|
|
rescue LoadError
|
|
# bundler not installed
|
|
end
|
|
|
|
require 'rake/testtask'
|
|
Rake::TestTask.new(:test) do |test|
|
|
test.libs << 'lib' << 'test'
|
|
test.pattern = 'test/**/*_test.rb'
|
|
test.verbose = false
|
|
end
|
|
|
|
class SpecRunner
|
|
STATS = [:files, :examples, :expectations, :failures, :errors]
|
|
attr_reader :stats, :not_found
|
|
|
|
def initialize
|
|
@counts = [0] * 5
|
|
@not_found = []
|
|
end
|
|
|
|
def run(cmd, path)
|
|
result = `#{cmd}`
|
|
match = result.match(/(\d+) files?, (\d+) examples?, (\d+) expectations?, (\d+) failures?, (\d+) errors?/)
|
|
if match.nil?
|
|
puts "*** mspec returned with unexpected results:"
|
|
puts result
|
|
puts "Command was:", cmd
|
|
exit 1
|
|
end
|
|
_, ex, p, f, e = data = match.captures.map{|x| x.to_i}
|
|
not_found << path if ex == 0
|
|
STATS.each_with_index do |_, i|
|
|
@counts[i] += data[i]
|
|
end
|
|
if f + e > 0
|
|
puts cmd
|
|
puts result
|
|
else
|
|
print "."
|
|
STDOUT.flush
|
|
end
|
|
end
|
|
|
|
def stats
|
|
h = {}
|
|
STATS.zip(@counts).each{|k, v| h[k]=v}
|
|
h
|
|
end
|
|
|
|
def report
|
|
puts "*** Overall:", stats.map{|a| a.join(' ')}.join(', ')
|
|
puts "No spec found for #{@not_found.join(', ')}" unless @not_found.empty?
|
|
end
|
|
|
|
def success?
|
|
stats[:failures] == 0 && stats[:errors] == 0
|
|
end
|
|
end
|
|
|
|
desc "Run specs, where path can be '*/*' (default), 'class/*' or 'class/method'."
|
|
task :spec, :path, :action do |t, args|
|
|
args.with_defaults(:path => '*/*', :action => 'ci')
|
|
specs = SpecRunner.new
|
|
|
|
# Avoid unclear error message by checking if at least one spec exists in the old specs
|
|
has_frozen_spec = !Dir.glob('frozen_old_spec/rubyspec/core/#{path}_spec.rb')
|
|
if has_frozen_spec || RUBY_VERSION < '1.9'
|
|
mspec_cmds(args[:path], 'frozen_old_spec', args[:action]) do |cmd, path|
|
|
specs.run(cmd, path)
|
|
end
|
|
end
|
|
|
|
unless RUBY_VERSION < '1.9' # Give up entirely on running new specs in 1.8.x, mainly because of {hash: 'syntax'}
|
|
mspec_cmds(args[:path], 'spec', args[:action]) do |cmd, path|
|
|
specs.run(cmd, path)
|
|
end
|
|
end
|
|
specs.report
|
|
fail unless specs.success?
|
|
end
|
|
|
|
task :all_spec do # Necessary because of argument passing bug in 1.8.7
|
|
Rake::Task[:spec].invoke
|
|
end
|
|
|
|
desc "Same as spec, but creating tags for failures"
|
|
task :spec_tag, :path do |t, args|
|
|
Rake::Task[:spec].invoke(args[:path], 'tag -G fails')
|
|
end
|
|
|
|
if RUBY_VERSION >= '2.4.0'
|
|
require 'rubocop/rake_task'
|
|
RuboCop::RakeTask.new
|
|
task :default => [:rubocop, :test, :all_spec]
|
|
else
|
|
task :default => [:test, :all_spec]
|
|
end
|
|
|
|
DEPENDENCIES = Hash.new([]).merge!(
|
|
'1.8.7/argf/chars' => 'backports/1.8.7/string/each_char',
|
|
'1.8.7/argf/each_char' => 'backports/1.8.7/string/each_char',
|
|
'1.8.7/array/cycle' => 'backports/1.8.7/stop_iteration',
|
|
'1.8.7/enumerable/entries' => ['backports/1.8.7/enumerable/each_with_index', 'backports/1.8.7/enumerable/to_a'],
|
|
'1.8.7/enumerator/rewind' => 'backports/1.8.7/enumerator/next',
|
|
'1.8.7/hash/reject' => 'backports/1.8.7/integer/even',
|
|
'1.9.1/hash/rassoc' => 'backports/1.9.1/hash/key',
|
|
'1.9.1/proc/lambda' => 'backports/1.9.1/proc/curry',
|
|
'1.9.2/complex/to_r' => 'complex',
|
|
'1.9.2/array/select' => 'backports/1.8.7/array/select',
|
|
'1.9.2/hash/select' => 'backports/1.8.7/hash/select',
|
|
'1.9.2/enumerable/each_entry' => 'backports/1.8.7/enumerable/each_with_index',
|
|
'2.0.0/hash/to_h' => 'backports/1.9.1/hash/default_proc',
|
|
'2.2.0/float/next_float' => 'backports/2.2.0/float/prev_float',
|
|
'2.2.0/float/prev_float' => 'backports/2.2.0/float/next_float',
|
|
'2.3.0/array/bsearch_index' => ['backports/2.3.0/array/dig', 'backports/2.3.0/hash/dig'],
|
|
'2.3.0/array/dig' => ['backports/2.3.0/hash/dig', 'backports/2.3.0/struct/dig'],
|
|
'2.3.0/hash/dig' => ['backports/2.3.0/array/dig', 'backports/2.3.0/struct/dig'],
|
|
'2.3.0/struct/dig' => ['backports/2.3.0/array/dig', 'backports/2.3.0/hash/dig'],
|
|
'2.4.0/fixnum/dup' => ['backports/2.4.0/bignum/dup'],
|
|
'2.4.0/bignum/dup' => ['backports/2.4.0/fixnum/dup'],
|
|
'2.7.0/enumerable/tally' => ['backports/2.4.0/hash/transform_values', 'backports/2.2.0/kernel/itself'],
|
|
)
|
|
{
|
|
:each_with_index => %w[enumerable/detect enumerable/find enumerable/find_all enumerable/select enumerable/to_a],
|
|
:first => %w[enumerable/cycle io/bytes io/chars io/each_byte io/each_char io/lines io/each_line]
|
|
}.each do |req, libs|
|
|
libs.each{|l| DEPENDENCIES["1.8.7/#{l}"] = "backports/1.8.7/enumerable/#{req}" }
|
|
end
|
|
|
|
# These **old** specs cause actual errors while loading in 1.8:
|
|
OLD_IGNORE_IN_18 = %w[
|
|
1.9.1/symbol/length
|
|
1.9.1/symbol/size
|
|
1.9.3/string/byteslice
|
|
1.8.7/proc/yield
|
|
1.9.1/proc/case_compare
|
|
2.4.0/string/match
|
|
2.4.0/regexp/match
|
|
2.5.0/module/define_method
|
|
]
|
|
# These **new** specs cause actual errors while loading in 1.9:
|
|
IGNORE_IN_19 = %w[
|
|
2.1.0/enumerable/to_h
|
|
2.1.0/array/to_h
|
|
2.1.0/module/include
|
|
2.2.0/kernel/itself
|
|
2.5.0/module/define_method
|
|
2.5.0/module/alias_method
|
|
2.5.0/module/undef_method
|
|
2.5.0/module/remove_method
|
|
2.5.0/module/attr
|
|
2.5.0/module/attr_reader
|
|
2.5.0/module/attr_writer
|
|
2.5.0/module/attr_accessor
|
|
2.5.0/struct/new
|
|
]
|
|
# These **new** specs cause actual errors while loading in 2.0.0:
|
|
IGNORE_IN_200 = %w[
|
|
2.4.0/enumerable/sum
|
|
]
|
|
|
|
IGNORE = %w[
|
|
3.0.0/ractor/ractor
|
|
3.1.0/enumerable/compact
|
|
3.1.0/struct/keyword_init
|
|
]
|
|
|
|
CLASS_MAP = Hash.new{|k, v| k[v] = v}.merge!(
|
|
'match_data' => 'matchdata', # don't ask me why RubySpec uses matchdata instead of match_data
|
|
'true_class' => 'true',
|
|
'false_class' => 'false',
|
|
'nil_class' => 'nil'
|
|
)
|
|
|
|
EXTRA_SPECS = {
|
|
'queue/close' => %w[queue/pop queue/push queue/closed],
|
|
'enumerable/chain' => %w[enumerator/chain/*]
|
|
}
|
|
|
|
USE_MSPEC_GEM = RUBY_VERSION < '2.1'
|
|
|
|
def mspec_cmds(pattern, spec_folder, action='ci')
|
|
pattern = "lib/backports/*.*.*/#{pattern}.rb"
|
|
Dir.glob(pattern) do |lib_path|
|
|
_match, version, path = lib_path.match(/backports\/(\d\.\d\.\d)\/(.*)\.rb/).to_a
|
|
next if path =~ /stdlib/
|
|
next if version <= RUBY_VERSION
|
|
version_path = "#{version}/#{path}"
|
|
if RUBY_VERSION < '2.0.0'
|
|
next if OLD_IGNORE_IN_18.include? version_path if RUBY_VERSION < '1.9'
|
|
next if IGNORE_IN_19.include? version_path
|
|
next if spec_folder != 'frozen_old_spec' && version <= '2.0.0' # Don't run new specs for pre 2.0 features & ruby
|
|
end
|
|
next if RUBY_VERSION < '2.1.0' && IGNORE_IN_200.include?(version_path)
|
|
next if IGNORE.include?(version_path)
|
|
deps = [*DEPENDENCIES[version_path]].map{|p| "-r #{p}"}.join(' ')
|
|
klass, method = path.split('/')
|
|
path = [CLASS_MAP[klass], method].join('/')
|
|
spec_paths = [path, *EXTRA_SPECS[path]].map do |p|
|
|
p.gsub! /fixnum|bignum/, 'integer'
|
|
"#{spec_folder}/rubyspec/core/#{p}_spec.rb"
|
|
end
|
|
if USE_MSPEC_GEM
|
|
cmd = "mspec #{action}"
|
|
else
|
|
cmd = 'ruby'
|
|
main = "spec/mspec/bin/mspec-#{action}"
|
|
end
|
|
|
|
yield %W[ #{cmd}
|
|
-I lib
|
|
-r ./set_version/#{version}
|
|
#{deps}
|
|
-r backports/#{version_path}
|
|
#{main}
|
|
#{spec_paths.join(' ')}
|
|
].join(' '), path
|
|
end
|
|
end
|