diff --git a/spec/mspec/lib/mspec/commands/mspec-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb index 4d8f4d9984e8..064c177d69b9 100644 --- a/spec/mspec/lib/mspec/commands/mspec-run.rb +++ b/spec/mspec/lib/mspec/commands/mspec-run.rb @@ -32,6 +32,7 @@ def options(argv = ARGV) options.chdir options.prefix options.configure { |f| load f } + options.env options.randomize options.repeat options.pretend diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb index 3b5962dbe6e7..23cf915e66d2 100644 --- a/spec/mspec/lib/mspec/utils/options.rb +++ b/spec/mspec/lib/mspec/utils/options.rb @@ -204,6 +204,13 @@ def configure(&block) "Load FILE containing configuration options", &block) end + def env + on("--env", "KEY=VALUE", "Set environment variable") do |env| + key, value = env.split('=', 2) + ENV[key] = value + end + end + def targets on("-t", "--target", "TARGET", "Implementation to run the specs, where TARGET is:") do |t| @@ -484,6 +491,7 @@ def debug def all configure {} + env targets formatters filters diff --git a/spec/mspec/tool/sync/sync-rubyspec.rb b/spec/mspec/tool/sync/sync-rubyspec.rb index 13f1d8004dcb..effccc1567c1 100644 --- a/spec/mspec/tool/sync/sync-rubyspec.rb +++ b/spec/mspec/tool/sync/sync-rubyspec.rb @@ -23,6 +23,8 @@ CHECK_LAST_MERGE = !MSPEC && ENV['CHECK_LAST_MERGE'] != 'false' TEST_MASTER = ENV['TEST_MASTER'] != 'false' +ONLY_FILTER = ENV['ONLY_FILTER'] == 'true' + MSPEC_REPO = File.expand_path("../../..", __FILE__) raise MSPEC_REPO if !Dir.exist?(MSPEC_REPO) or !Dir.exist?("#{MSPEC_REPO}/.git") @@ -230,15 +232,17 @@ def main(impls) impl = RubyImplementation.new(impl, data) update_repo(impl) filter_commits(impl) - rebase_commits(impl) - if new_commits?(impl) - test_new_specs - verify_commits(impl) - fast_forward_master(impl) - check_ci - else - STDERR.puts "#{BRIGHT_YELLOW}No new commits#{RESET}" - fast_forward_master(impl) + unless ONLY_FILTER + rebase_commits(impl) + if new_commits?(impl) + test_new_specs + verify_commits(impl) + fast_forward_master(impl) + check_ci + else + STDERR.puts "#{BRIGHT_YELLOW}No new commits#{RESET}" + fast_forward_master(impl) + end end end end diff --git a/spec/ruby/command_line/dash_v_spec.rb b/spec/ruby/command_line/dash_v_spec.rb index 747db7f75588..d30efa37d68c 100644 --- a/spec/ruby/command_line/dash_v_spec.rb +++ b/spec/ruby/command_line/dash_v_spec.rb @@ -9,6 +9,7 @@ ruby_exe(nil, args: '-v').sub("+PRISM ", "").should include(RUBY_DESCRIPTION.sub("+PRISM ", "")) end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) || (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?) || + (ENV['RUBY_GC_LIBRARY'] && ENV['RUBY_GC_LIBRARY'].length > 0) || (ENV['RUBY_MN_THREADS'] == '1') end end diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb index 38e29c0d2145..e940f912af8f 100644 --- a/spec/ruby/command_line/rubyopt_spec.rb +++ b/spec/ruby/command_line/rubyopt_spec.rb @@ -25,12 +25,12 @@ guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do it "prints the version number for '-v'" do ENV["RUBYOPT"] = '-v' - ruby_exe("").sub("+PRISM ", "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "") + ruby_exe("").sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "") end it "ignores whitespace around the option" do ENV["RUBYOPT"] = ' -v ' - ruby_exe("").sub("+PRISM ", "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "") + ruby_exe("").sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "") end end diff --git a/spec/ruby/core/basicobject/equal_spec.rb b/spec/ruby/core/basicobject/equal_spec.rb index 3c1ad56d4ab5..ce28eaed9554 100644 --- a/spec/ruby/core/basicobject/equal_spec.rb +++ b/spec/ruby/core/basicobject/equal_spec.rb @@ -11,8 +11,10 @@ it "is unaffected by overriding __id__" do o1 = mock("object") o2 = mock("object") - def o1.__id__; 10; end - def o2.__id__; 10; end + suppress_warning { + def o1.__id__; 10; end + def o2.__id__; 10; end + } o1.equal?(o2).should be_false end diff --git a/spec/ruby/core/exception/system_call_error_spec.rb b/spec/ruby/core/exception/system_call_error_spec.rb index 7235aa9c268c..f6995d3c5ec3 100644 --- a/spec/ruby/core/exception/system_call_error_spec.rb +++ b/spec/ruby/core/exception/system_call_error_spec.rb @@ -96,11 +96,23 @@ def initialize end it "sets an 'unknown error' message when an unknown error number" do - SystemCallError.new(-1).message.should =~ /Unknown error(:)? -1/ + platform_is_not :windows do + SystemCallError.new(-1).message.should =~ /Unknown error(:)? -1/ + end + + platform_is :windows do + SystemCallError.new(-1).message.should == "The operation completed successfully." + end end it "adds a custom error message to an 'unknown error' message when an unknown error number and a custom message specified" do - SystemCallError.new("custom message", -1).message.should =~ /Unknown error(:)? -1 - custom message/ + platform_is_not :windows do + SystemCallError.new("custom message", -1).message.should =~ /Unknown error(:)? -1 - custom message/ + end + + platform_is :windows do + SystemCallError.new("custom message", -1).message.should == "The operation completed successfully. - custom message" + end end it "converts to Integer if errno is a Complex convertible to Integer" do diff --git a/spec/ruby/core/integer/shared/exponent.rb b/spec/ruby/core/integer/shared/exponent.rb index 15df518b7e49..5ef6d686d809 100644 --- a/spec/ruby/core/integer/shared/exponent.rb +++ b/spec/ruby/core/integer/shared/exponent.rb @@ -48,10 +48,18 @@ (-1).send(@method, 4611686018427387905).should eql(-1) end - it "returns Float::INFINITY when the number is too big" do - -> { - 2.send(@method, 427387904).should == Float::INFINITY - }.should complain(/warning: in a\*\*b, b may be too big/) + ruby_version_is ""..."3.4" do + it "returns Float::INFINITY when the number is too big" do + -> { + 2.send(@method, 427387904).should == Float::INFINITY + }.should complain(/warning: in a\*\*b, b may be too big/) + end + end + + ruby_version_is "3.4" do + it "raises an ArgumentError when the number is too big" do + -> { 100000000.send(@method, 1000000000) }.should raise_error(ArgumentError) + end end it "raises a ZeroDivisionError for 0 ** -1" do @@ -108,13 +116,23 @@ -> { @bignum.send(@method, :symbol) }.should raise_error(TypeError) end - it "switch to a Float when the values is too big" do - flt = nil - -> { - flt = @bignum.send(@method, @bignum) - }.should complain(/warning: in a\*\*b, b may be too big/) - flt.should be_kind_of(Float) - flt.infinite?.should == 1 + ruby_version_is ""..."3.4" do + it "switch to a Float when the values is too big" do + flt = nil + -> { + flt = @bignum.send(@method, @bignum) + }.should complain(/warning: in a\*\*b, b may be too big/) + flt.should be_kind_of(Float) + flt.infinite?.should == 1 + end + end + + ruby_version_is "3.4" do + it "does not switch to a Float when the values is too big" do + -> { + @bignum.send(@method, @bignum) + }.should raise_error(ArgumentError) + end end it "returns a complex number when negative and raised to a fractional power" do diff --git a/spec/ruby/core/kernel/sleep_spec.rb b/spec/ruby/core/kernel/sleep_spec.rb index 607764464fe3..4401e542563a 100644 --- a/spec/ruby/core/kernel/sleep_spec.rb +++ b/spec/ruby/core/kernel/sleep_spec.rb @@ -51,18 +51,15 @@ def o.divmod(*); [0, 0.001]; end t.value.should == 5 end - quarantine! do # fails transiently on at least linux & darwin - it "sleeps with nanosecond precision" do - start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - 100.times do - sleep(0.0001) - end - end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - - actual_duration = end_time - start_time - (actual_duration > 0.01).should == true # 100 * 0.0001 => 0.01 - (actual_duration < 0.03).should == true + it "sleeps with nanosecond precision" do + start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 100.times do + sleep(0.0001) end + end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + actual_duration = end_time - start_time + actual_duration.should > 0.01 # 100 * 0.0001 => 0.01 end ruby_version_is ""..."3.3" do diff --git a/spec/ruby/core/module/deprecate_constant_spec.rb b/spec/ruby/core/module/deprecate_constant_spec.rb index aabef934c4b5..ec0de6782ffa 100644 --- a/spec/ruby/core/module/deprecate_constant_spec.rb +++ b/spec/ruby/core/module/deprecate_constant_spec.rb @@ -44,6 +44,15 @@ end end + ruby_bug '#20900', ''...'3.4' do + describe "when removing the deprecated module" do + it "warns with a message" do + @module.deprecate_constant :PUBLIC1 + -> { @module.module_eval {remove_const :PUBLIC1} }.should complain(/warning: constant .+::PUBLIC1 is deprecated/) + end + end + end + it "accepts multiple symbols and strings as constant names" do @module.deprecate_constant "PUBLIC1", :PUBLIC2 diff --git a/spec/ruby/core/process/status/bit_and_spec.rb b/spec/ruby/core/process/status/bit_and_spec.rb index 97f768fdc1a9..f4a4328907d8 100644 --- a/spec/ruby/core/process/status/bit_and_spec.rb +++ b/spec/ruby/core/process/status/bit_and_spec.rb @@ -1,5 +1,35 @@ require_relative '../../../spec_helper' describe "Process::Status#&" do - it "needs to be reviewed for spec completeness" + it "returns a bitwise and of the integer status of an exited child" do + suppress_warning do + ruby_exe("exit(29)", exit_status: 29) + ($? & 0).should == 0 + ($? & $?.to_i).should == $?.to_i + + # Actual value is implementation specific + platform_is :linux do + # 29 == 0b11101 + ($? & 0b1011100000000).should == 0b1010100000000 + end + end + end + + ruby_version_is "3.3" do + it "raises an ArgumentError if mask is negative" do + suppress_warning do + ruby_exe("exit(0)") + -> { + $? & -1 + }.should raise_error(ArgumentError, 'negative mask value: -1') + end + end + + it "shows a deprecation warning" do + ruby_exe("exit(0)") + -> { + $? & 0 + }.should complain(/warning: Process::Status#& is deprecated and will be removed .*use other Process::Status predicates instead/) + end + end end diff --git a/spec/ruby/core/process/status/right_shift_spec.rb b/spec/ruby/core/process/status/right_shift_spec.rb index e9dda437e8b1..034ce348cbf9 100644 --- a/spec/ruby/core/process/status/right_shift_spec.rb +++ b/spec/ruby/core/process/status/right_shift_spec.rb @@ -1,5 +1,34 @@ require_relative '../../../spec_helper' describe "Process::Status#>>" do - it "needs to be reviewed for spec completeness" + it "returns a right shift of the integer status of an exited child" do + suppress_warning do + ruby_exe("exit(29)", exit_status: 29) + ($? >> 0).should == $?.to_i + ($? >> 1).should == $?.to_i >> 1 + + # Actual value is implementation specific + platform_is :linux do + ($? >> 8).should == 29 + end + end + end + + ruby_version_is "3.3" do + it "raises an ArgumentError if shift value is negative" do + suppress_warning do + ruby_exe("exit(0)") + -> { + $? >> -1 + }.should raise_error(ArgumentError, 'negative shift value: -1') + end + end + + it "shows a deprecation warning" do + ruby_exe("exit(0)") + -> { + $? >> 0 + }.should complain(/warning: Process::Status#>> is deprecated and will be removed .*use other Process::Status attributes instead/) + end + end end diff --git a/spec/ruby/core/range/reverse_each_spec.rb b/spec/ruby/core/range/reverse_each_spec.rb index b80f9eef5bb2..b51e04c3fff2 100644 --- a/spec/ruby/core/range/reverse_each_spec.rb +++ b/spec/ruby/core/range/reverse_each_spec.rb @@ -2,7 +2,7 @@ ruby_version_is "3.3" do describe "Range#reverse_each" do - it "traverses the Range in reverse order and pass each element to block" do + it "traverses the Range in reverse order and passes each element to block" do a = [] (1..3).reverse_each { |i| a << i } a.should == [3, 2, 1] @@ -88,8 +88,10 @@ (1..3).reverse_each.size.should == 3 end - it "returns Infinity when Range size is infinite" do - (..3).reverse_each.size.should == Float::INFINITY + ruby_bug "#20936", "3.4"..."3.5" do + it "returns Infinity when Range size is infinite" do + (..3).reverse_each.size.should == Float::INFINITY + end end it "returns nil when Range size is unknown" do @@ -98,4 +100,4 @@ end end end -end \ No newline at end of file +end diff --git a/spec/ruby/core/refinement/refined_class_spec.rb b/spec/ruby/core/refinement/refined_class_spec.rb index 00b65d08955a..acc6e2cb2bfc 100644 --- a/spec/ruby/core/refinement/refined_class_spec.rb +++ b/spec/ruby/core/refinement/refined_class_spec.rb @@ -1,8 +1,29 @@ -require_relative '../../spec_helper' +require_relative "../../spec_helper" +require_relative 'shared/target' describe "Refinement#refined_class" do ruby_version_is "3.2"..."3.3" do - it "returns the class refined by the receiver" do + it_behaves_like :refinement_target, :refined_class + end + + ruby_version_is "3.3"..."3.4" do + it "has been deprecated in favour of Refinement#target" do + refinement_int = nil + + Module.new do + refine Integer do + refinement_int = self + end + end + + -> { + refinement_int.refined_class + }.should complain(/warning: Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/) + end + end + + ruby_version_is "3.4" do + it "has been removed" do refinement_int = nil Module.new do @@ -11,7 +32,7 @@ end end - refinement_int.refined_class.should == Integer + refinement_int.should_not.respond_to?(:refined_class) end end end diff --git a/spec/ruby/core/refinement/shared/target.rb b/spec/ruby/core/refinement/shared/target.rb new file mode 100644 index 000000000000..79557bea0b96 --- /dev/null +++ b/spec/ruby/core/refinement/shared/target.rb @@ -0,0 +1,13 @@ +describe :refinement_target, shared: true do + it "returns the class refined by the receiver" do + refinement_int = nil + + Module.new do + refine Integer do + refinement_int = self + end + end + + refinement_int.send(@method).should == Integer + end +end diff --git a/spec/ruby/core/refinement/target_spec.rb b/spec/ruby/core/refinement/target_spec.rb new file mode 100644 index 000000000000..fee9588a96ed --- /dev/null +++ b/spec/ruby/core/refinement/target_spec.rb @@ -0,0 +1,8 @@ +require_relative "../../spec_helper" +require_relative 'shared/target' + +describe "Refinement#target" do + ruby_version_is "3.3" do + it_behaves_like :refinement_target, :target + end +end diff --git a/spec/ruby/core/string/chilled_string_spec.rb b/spec/ruby/core/string/chilled_string_spec.rb index 9f81b1af6d65..b8fb6eedc946 100644 --- a/spec/ruby/core/string/chilled_string_spec.rb +++ b/spec/ruby/core/string/chilled_string_spec.rb @@ -2,69 +2,141 @@ describe "chilled String" do guard -> { ruby_version_is "3.4" and !"test".equal?("test") } do - describe "#frozen?" do - it "returns false" do - "chilled".frozen?.should == false + describe "chilled string literals" do + + describe "#frozen?" do + it "returns false" do + "chilled".frozen?.should == false + end end - end - describe "#-@" do - it "returns a different instance" do - input = "chilled" - interned = (-input) - interned.frozen?.should == true - interned.object_id.should_not == input.object_id + describe "#-@" do + it "returns a different instance" do + input = "chilled" + interned = (-input) + interned.frozen?.should == true + interned.object_id.should_not == input.object_id + end end - end - describe "#+@" do - it "returns a different instance" do - input = "chilled" - duped = (+input) - duped.frozen?.should == false - duped.object_id.should_not == input.object_id + describe "#+@" do + it "returns a different instance" do + input = "chilled" + duped = (+input) + duped.frozen?.should == false + duped.object_id.should_not == input.object_id + end end - end - describe "#clone" do - it "preserves chilled status" do - input = "chilled".clone - -> { - input << "-mutated" - }.should complain(/literal string will be frozen in the future/) - input.should == "chilled-mutated" + describe "#clone" do + it "preserves chilled status" do + input = "chilled".clone + -> { + input << "-mutated" + }.should complain(/literal string will be frozen in the future/) + input.should == "chilled-mutated" + end + end + + describe "mutation" do + it "emits a warning" do + input = "chilled" + -> { + input << "-mutated" + }.should complain(/literal string will be frozen in the future/) + input.should == "chilled-mutated" + end + + it "emits a warning on singleton_class creation" do + -> { + "chilled".singleton_class + }.should complain(/literal string will be frozen in the future/) + end + + it "emits a warning on instance variable assignment" do + -> { + "chilled".instance_variable_set(:@ivar, 42) + }.should complain(/literal string will be frozen in the future/) + end + + it "raises FrozenError after the string was explicitly frozen" do + input = "chilled" + input.freeze + -> { + -> { + input << "mutated" + }.should raise_error(FrozenError) + }.should_not complain(/literal string will be frozen in the future/) + end end end - describe "mutation" do - it "emits a warning" do - input = "chilled" - -> { - input << "-mutated" - }.should complain(/literal string will be frozen in the future/) - input.should == "chilled-mutated" + describe "chilled strings returned by Symbol#to_s" do + + describe "#frozen?" do + it "returns false" do + :chilled.to_s.frozen?.should == false + end end - it "emits a warning on singleton_class creation" do - -> { - "chilled".singleton_class - }.should complain(/literal string will be frozen in the future/) + describe "#-@" do + it "returns a different instance" do + input = :chilled.to_s + interned = (-input) + interned.frozen?.should == true + interned.object_id.should_not == input.object_id + end end - it "emits a warning on instance variable assignment" do - -> { - "chilled".instance_variable_set(:@ivar, 42) - }.should complain(/literal string will be frozen in the future/) + describe "#+@" do + it "returns a different instance" do + input = :chilled.to_s + duped = (+input) + duped.frozen?.should == false + duped.object_id.should_not == input.object_id + end + end + + describe "#clone" do + it "preserves chilled status" do + input = :chilled.to_s.clone + -> { + input << "-mutated" + }.should complain(/string returned by :chilled\.to_s will be frozen in the future/) + input.should == "chilled-mutated" + end end - it "raises FrozenError after the string was explicitly frozen" do - input = "chilled" - input.freeze - -> { + describe "mutation" do + it "emits a warning" do + input = :chilled.to_s + -> { + input << "-mutated" + }.should complain(/string returned by :chilled\.to_s will be frozen in the future/) + input.should == "chilled-mutated" + end + + it "emits a warning on singleton_class creation" do + -> { + :chilled.to_s.singleton_class + }.should complain(/string returned by :chilled\.to_s will be frozen in the future/) + end + + it "emits a warning on instance variable assignment" do + -> { + :chilled.to_s.instance_variable_set(:@ivar, 42) + }.should complain(/string returned by :chilled\.to_s will be frozen in the future/) + end + + it "raises FrozenError after the string was explicitly frozen" do + input = :chilled.to_s + input.freeze -> { - input << "mutated" - }.should raise_error(FrozenError) - }.should_not complain(/literal string will be frozen in the future/) + -> { + input << "mutated" + }.should raise_error(FrozenError) + }.should_not complain(/string returned by :chilled\.to_s will be frozen in the future/) + end end end end diff --git a/spec/ruby/core/time/comparison_spec.rb b/spec/ruby/core/time/comparison_spec.rb index 5b53c9fb50de..866fbea72ef1 100644 --- a/spec/ruby/core/time/comparison_spec.rb +++ b/spec/ruby/core/time/comparison_spec.rb @@ -55,6 +55,32 @@ }.should_not complain end + context "given different timezones" do + it "returns 0 if time is the same as other" do + # three timezones, all at the same timestamp + time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0) + time_cet = Time.new(2000, 1, 1, 1, 0, 0, '+01:00') + time_brt = Time.new(1999, 12, 31, 21, 0, 0, '-03:00') + (time_utc <=> time_cet).should == 0 + (time_utc <=> time_brt).should == 0 + (time_cet <=> time_brt).should == 0 + end + + it "returns -1 if the first argument is before the second argument" do + # time_brt is later, even though the date is earlier + time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0) + time_brt = Time.new(1999, 12, 31, 23, 0, 0, '-03:00') + (time_utc <=> time_brt).should == -1 + end + + it "returns 1 if the first argument is before the second argument" do + # time_brt is later, even though the date is earlier + time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0) + time_brt = Time.new(1999, 12, 31, 23, 0, 0, '-03:00') + (time_brt <=> time_utc).should == 1 + end + end + describe "given a non-Time argument" do it "returns nil if argument <=> self returns nil" do t = Time.now diff --git a/spec/ruby/core/time/shared/gmtime.rb b/spec/ruby/core/time/shared/gmtime.rb index bae19da4624d..7b4f65f0b796 100644 --- a/spec/ruby/core/time/shared/gmtime.rb +++ b/spec/ruby/core/time/shared/gmtime.rb @@ -4,7 +4,14 @@ with_timezone("CST", -6) do t = Time.local(2007, 1, 9, 6, 0, 0) t.send(@method) - t.should == Time.gm(2007, 1, 9, 12, 0, 0) + # Time#== compensates for time zones, so check all parts separately + t.year.should == 2007 + t.month.should == 1 + t.mday.should == 9 + t.hour.should == 12 + t.min.should == 0 + t.sec.should == 0 + t.zone.should == "UTC" end end diff --git a/spec/ruby/core/tracepoint/raised_exception_spec.rb b/spec/ruby/core/tracepoint/raised_exception_spec.rb index ca2f50abb36f..5ac853184049 100644 --- a/spec/ruby/core/tracepoint/raised_exception_spec.rb +++ b/spec/ruby/core/tracepoint/raised_exception_spec.rb @@ -17,4 +17,22 @@ raised_exception.should equal(error_result) end end + + ruby_version_is "3.3" do + it 'returns value from exception rescued on the :rescue event' do + raised_exception, error_result = nil + trace = TracePoint.new(:rescue) { |tp| + next unless TracePointSpec.target_thread? + raised_exception = tp.raised_exception + } + trace.enable do + begin + raise StandardError + rescue => e + error_result = e + end + raised_exception.should equal(error_result) + end + end + end end diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb index a605a3619fdc..75c1e71bc2c0 100644 --- a/spec/ruby/language/block_spec.rb +++ b/spec/ruby/language/block_spec.rb @@ -999,6 +999,7 @@ def a; 1; end end end +# tested more thoroughly in language/delegation_spec.rb describe "Anonymous block forwarding" do ruby_version_is "3.1" do it "forwards blocks to other method that formally declares anonymous block" do diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb index 34408c019018..80ad1818b116 100644 --- a/spec/ruby/language/defined_spec.rb +++ b/spec/ruby/language/defined_spec.rb @@ -900,6 +900,10 @@ defined?(DefinedSpecs::Undefined).should be_nil end + it "returns nil when the constant is not defined and the outer module implements .const_missing" do + defined?(DefinedSpecs::ModuleWithConstMissing::Undefined).should be_nil + end + it "does not call .const_missing if the constant is not defined" do DefinedSpecs.should_not_receive(:const_missing) defined?(DefinedSpecs::UnknownChild).should be_nil diff --git a/spec/ruby/language/delegation_spec.rb b/spec/ruby/language/delegation_spec.rb index d780506421bd..b75f3f5f7cee 100644 --- a/spec/ruby/language/delegation_spec.rb +++ b/spec/ruby/language/delegation_spec.rb @@ -1,6 +1,7 @@ require_relative '../spec_helper' require_relative 'fixtures/delegation' +# Forwarding anonymous parameters describe "delegation with def(...)" do it "delegates rest and kwargs" do a = Class.new(DelegationSpecs::Target) @@ -10,10 +11,10 @@ def delegate(...) end RUBY - a.new.delegate(1, b: 2).should == [[1], {b: 2}] + a.new.delegate(1, b: 2).should == [[1], {b: 2}, nil] end - it "delegates block" do + it "delegates a block literal" do a = Class.new(DelegationSpecs::Target) a.class_eval(<<-RUBY) def delegate_block(...) @@ -24,6 +25,18 @@ def delegate_block(...) a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]] end + it "delegates a block argument" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate(...) + target(...) + end + RUBY + + block = proc {} + a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block] + end + it "parses as open endless Range when brackets are omitted" do a = Class.new(DelegationSpecs::Target) suppress_warning do @@ -34,7 +47,7 @@ def delegate(...) RUBY end - a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true) + a.new.delegate(1, b: 2).should == Range.new([[], {}, nil], nil, true) end end @@ -47,10 +60,10 @@ def delegate(x, ...) end RUBY - a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}] + a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}, nil] end - it "delegates block" do + it "delegates a block literal" do a = Class.new(DelegationSpecs::Target) a.class_eval(<<-RUBY) def delegate_block(x, ...) @@ -60,6 +73,18 @@ def delegate_block(x, ...) a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]] end + + it "delegates a block argument" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate(...) + target(...) + end + RUBY + + block = proc {} + a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block] + end end ruby_version_is "3.2" do @@ -70,9 +95,19 @@ def delegate_block(x, ...) def delegate(*) target(*) end - RUBY + RUBY - a.new.delegate(0, 1).should == [[0, 1], {}] + a.new.delegate(0, 1).should == [[0, 1], {}, nil] + end + + ruby_version_is "3.3" do + context "within a block that accepts anonymous rest within a method that accepts anonymous rest" do + it "does not allow delegating rest" do + -> { + eval "def m(*); proc { |*| n(*) } end" + }.should raise_error(SyntaxError, /anonymous rest parameter is also used within block/) + end + end end end end @@ -85,9 +120,45 @@ def delegate(*) def delegate(**) target(**) end - RUBY + RUBY + + a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}, nil] + end - a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}] + ruby_version_is "3.3" do + context "within a block that accepts anonymous kwargs within a method that accepts anonymous kwargs" do + it "does not allow delegating kwargs" do + -> { + eval "def m(**); proc { |**| n(**) } end" + }.should raise_error(SyntaxError, /anonymous keyword rest parameter is also used within block/) + end + end + end + end +end + +ruby_version_is "3.1" do + describe "delegation with def(&)" do + it "delegates an anonymous block parameter" do + a = Class.new(DelegationSpecs::Target) + a.class_eval(<<-RUBY) + def delegate(&) + target(&) + end + RUBY + + block = proc {} + a.new.delegate(&block).should == [[], {}, block] + end + + ruby_version_is "3.3" do + context "within a block that accepts anonymous block within a method that accepts anonymous block" do + it "does not allow delegating a block" do + -> { + eval "def m(&); proc { |&| n(&) } end" + }.should raise_error(SyntaxError, /anonymous block parameter is also used within block/) + end + end end end end diff --git a/spec/ruby/language/fixtures/defined.rb b/spec/ruby/language/fixtures/defined.rb index a9552619bf2a..3761cfa5bd40 100644 --- a/spec/ruby/language/fixtures/defined.rb +++ b/spec/ruby/language/fixtures/defined.rb @@ -285,6 +285,12 @@ def method_no_args end end + module ModuleWithConstMissing + def self.const_missing(const) + const + end + end + class SuperWithIntermediateModules include IntermediateModule1 include IntermediateModule2 diff --git a/spec/ruby/language/fixtures/delegation.rb b/spec/ruby/language/fixtures/delegation.rb index 527d92839027..da2b02479197 100644 --- a/spec/ruby/language/fixtures/delegation.rb +++ b/spec/ruby/language/fixtures/delegation.rb @@ -1,7 +1,7 @@ module DelegationSpecs class Target - def target(*args, **kwargs) - [args, kwargs] + def target(*args, **kwargs, &block) + [args, kwargs, block] end def target_block(*args, **kwargs) diff --git a/spec/ruby/library/io-wait/wait_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb index 5952f127f757..61356ff395cc 100644 --- a/spec/ruby/library/io-wait/wait_spec.rb +++ b/spec/ruby/library/io-wait/wait_spec.rb @@ -91,14 +91,17 @@ t.join # Thread#kill doesn't wait for the thread to end end - it "changes thread status to 'sleep' when waits for WRITABLE event" do - IOSpec.exhaust_write_buffer(@w) - - t = Thread.new { @w.wait(IO::WRITABLE, 10) } - sleep 1 - t.status.should == 'sleep' - t.kill - t.join # Thread#kill doesn't wait for the thread to end + # https://github.com/ruby/ruby/actions/runs/11948300522/job/33305664284?pr=12139 + platform_is_not :windows do + it "changes thread status to 'sleep' when waits for WRITABLE event" do + IOSpec.exhaust_write_buffer(@w) + + t = Thread.new { @w.wait(IO::WRITABLE, 10) } + sleep 1 + t.status.should == 'sleep' + t.kill + t.join # Thread#kill doesn't wait for the thread to end + end end it "can be interrupted when waiting for READABLE event" do diff --git a/spec/ruby/library/random/formatter/alphanumeric_spec.rb b/spec/ruby/library/random/formatter/alphanumeric_spec.rb new file mode 100644 index 000000000000..df14c29e2454 --- /dev/null +++ b/spec/ruby/library/random/formatter/alphanumeric_spec.rb @@ -0,0 +1,58 @@ +require_relative '../../../spec_helper' + +ruby_version_is "3.1" do + require 'random/formatter' + + describe "Random::Formatter#alphanumeric" do + before :each do + @object = Object.new + @object.extend(Random::Formatter) + @object.define_singleton_method(:bytes) do |n| + "\x00".b * n + end + end + + it "generates a random alphanumeric string" do + @object.alphanumeric.should =~ /\A[A-Za-z0-9]+\z/ + end + + it "has a default size of 16 characters" do + @object.alphanumeric.size.should == 16 + end + + it "accepts a 'size' argument" do + @object.alphanumeric(10).size.should == 10 + end + + it "uses the default size if 'nil' is given as size argument" do + @object.alphanumeric(nil).size.should == 16 + end + + it "raises an ArgumentError if the size is not numeric" do + -> { + @object.alphanumeric("10") + }.should raise_error(ArgumentError) + end + + it "does not coerce the size argument with #to_int" do + size = mock("size") + size.should_not_receive(:to_int) + -> { + @object.alphanumeric(size) + }.should raise_error(ArgumentError) + end + + ruby_version_is "3.3" do + it "accepts a 'chars' argument with the output alphabet" do + @object.alphanumeric(chars: ['a', 'b']).should =~ /\A[ab]+\z/ + end + + it "converts the elements of chars using #to_s" do + to_s = mock("to_s") + to_s.should_receive(:to_s).and_return("[mock to_s]") + # Using 1 value in chars results in an infinite loop + @object.alphanumeric(1, chars: [to_s, to_s]).should == "[mock to_s]" + end + end + end +end diff --git a/spec/ruby/library/securerandom/random_number_spec.rb b/spec/ruby/library/securerandom/random_number_spec.rb index 03781f49019c..bb25bc496ed9 100644 --- a/spec/ruby/library/securerandom/random_number_spec.rb +++ b/spec/ruby/library/securerandom/random_number_spec.rb @@ -11,8 +11,8 @@ (1..64).each do |idx| num = SecureRandom.random_number(idx) num.should be_kind_of(Integer) - (0 <= num).should == true - (num < idx).should == true + 0.should <= num + num.should < idx end end @@ -21,8 +21,8 @@ 11.times do num = SecureRandom.random_number max num.should be_kind_of(Integer) - (0 <= num).should == true - (num < max).should == true + 0.should <= num + num.should < max end end @@ -30,8 +30,8 @@ 64.times do num = SecureRandom.random_number num.should be_kind_of(Float) - (0.0 <= num).should == true - (num < 1.0).should == true + 0.0.should <= num + num.should < 1.0 end end @@ -39,8 +39,8 @@ 64.times do num = SecureRandom.random_number 11...13 num.should be_kind_of(Integer) - (11 <= num).should == true - (num < 13).should == true + 11.should <= num + num.should < 13 end end @@ -50,8 +50,8 @@ 32.times do num = SecureRandom.random_number lower..upper num.should be_kind_of(Integer) - (lower <= num).should == true - (num <= upper).should == true + lower.should <= num + num.should <= upper end end @@ -59,23 +59,23 @@ 64.times do num = SecureRandom.random_number 0.6..0.9 num.should be_kind_of(Float) - (0.6 <= num).should == true - (num <= 0.9).should == true + 0.6.should <= num + num.should <= 0.9 end end it "generates a random float number between 0.0 and 1.0 if argument is negative" do num = SecureRandom.random_number(-10) num.should be_kind_of(Float) - (0.0 <= num).should == true - (num < 1.0).should == true + 0.0.should <= num + num.should < 1.0 end it "generates a random float number between 0.0 and 1.0 if argument is negative float" do num = SecureRandom.random_number(-11.1) num.should be_kind_of(Float) - (0.0 <= num).should == true - (num < 1.0).should == true + 0.0.should <= num + num.should < 1.0 end it "generates different float numbers with subsequent invocations" do @@ -84,7 +84,7 @@ 256.times do val = SecureRandom.random_number # make sure the random values are not repeating - values.include?(val).should == false + values.should_not include(val) values << val end end diff --git a/spec/ruby/library/socket/socket/connect_spec.rb b/spec/ruby/library/socket/socket/connect_spec.rb index 175c9942bcd6..7fceb47b009f 100644 --- a/spec/ruby/library/socket/socket/connect_spec.rb +++ b/spec/ruby/library/socket/socket/connect_spec.rb @@ -63,7 +63,11 @@ client.timeout = 0 -> { - client.connect(address) + begin + client.connect(address) + rescue Errno::ECONNREFUSED + skip "Outgoing packets may be filtered" + end }.should raise_error(IO::TimeoutError) end end diff --git a/spec/ruby/optional/capi/ext/hash_spec.c b/spec/ruby/optional/capi/ext/hash_spec.c index e7fdbb10f474..0e5b3d1c0aa6 100644 --- a/spec/ruby/optional/capi/ext/hash_spec.c +++ b/spec/ruby/optional/capi/ext/hash_spec.c @@ -136,7 +136,7 @@ VALUE hash_spec_compute_a_hash_code(VALUE self, VALUE seed) { VALUE hash_spec_rb_hash_bulk_insert(VALUE self, VALUE array_len, VALUE array, VALUE hash) { VALUE* ptr; - + if (array == Qnil) { ptr = NULL; } else { diff --git a/spec/ruby/optional/capi/io_spec.rb b/spec/ruby/optional/capi/io_spec.rb index a34b3a4ff051..dbfaf556f6a7 100644 --- a/spec/ruby/optional/capi/io_spec.rb +++ b/spec/ruby/optional/capi/io_spec.rb @@ -531,123 +531,135 @@ end end - describe "rb_io_open_descriptor" do - it "creates a new IO instance" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.should.is_a?(IO) - end + quarantine! do # "Errno::EBADF: Bad file descriptor" at closing @r_io, @rw_io etc in the after :each hook + describe "rb_io_open_descriptor" do + it "creates a new IO instance" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.should.is_a?(IO) + end - it "return an instance of the specified class" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.class.should == File + it "return an instance of the specified class" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.class.should == File - io = @o.rb_io_open_descriptor(IO, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.class.should == IO - end + io = @o.rb_io_open_descriptor(IO, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.class.should == IO + end - it "sets the specified file descriptor" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.fileno.should == @r_io.fileno - end + it "sets the specified file descriptor" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.fileno.should == @r_io.fileno + end - it "sets the specified path" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.path.should == "a.txt" - end + it "sets the specified path" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.path.should == "a.txt" + end - it "sets the specified mode" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_BINMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.should.binmode? + it "sets the specified mode" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_BINMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.should.binmode? - io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_TEXTMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.should_not.binmode? - end + io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_TEXTMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.should_not.binmode? + end - it "sets the specified timeout" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.timeout.should == 60 - end + it "sets the specified timeout" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.timeout.should == 60 + end - it "sets the specified internal encoding" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.internal_encoding.should == Encoding::US_ASCII - end + it "sets the specified internal encoding" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.internal_encoding.should == Encoding::US_ASCII + end - it "sets the specified external encoding" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.external_encoding.should == Encoding::UTF_8 - end + it "sets the specified external encoding" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.external_encoding.should == Encoding::UTF_8 + end - it "does not apply the specified encoding flags" do - File.write("a.txt", "123\r\n456\n89") - file = File.open("a.txt", "r") + it "does not apply the specified encoding flags" do + name = tmp("rb_io_open_descriptor_specs") + File.write(name, "123\r\n456\n89") + file = File.open(name, "r") - io = @o.rb_io_open_descriptor(File, file.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", CApiIOSpecs::ECONV_UNIVERSAL_NEWLINE_DECORATOR, {}) - io.read_nonblock(20).should == "123\r\n456\n89" - end + io = @o.rb_io_open_descriptor(File, file.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", CApiIOSpecs::ECONV_UNIVERSAL_NEWLINE_DECORATOR, {}) + io.read_nonblock(20).should == "123\r\n456\n89" + ensure + file.close + rm_r name + end - it "ignores the IO open options" do - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {external_encoding: "windows-1251"}) - io.external_encoding.should == Encoding::UTF_8 + it "ignores the IO open options" do + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {external_encoding: "windows-1251"}) + io.external_encoding.should == Encoding::UTF_8 - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {internal_encoding: "windows-1251"}) - io.internal_encoding.should == Encoding::US_ASCII + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {internal_encoding: "windows-1251"}) + io.internal_encoding.should == Encoding::US_ASCII - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {encoding: "windows-1251:binary"}) - io.external_encoding.should == Encoding::UTF_8 - io.internal_encoding.should == Encoding::US_ASCII + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {encoding: "windows-1251:binary"}) + io.external_encoding.should == Encoding::UTF_8 + io.internal_encoding.should == Encoding::US_ASCII - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {textmode: false}) - io.should_not.binmode? + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {textmode: false}) + io.should_not.binmode? - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {binmode: true}) - io.should_not.binmode? + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {binmode: true}) + io.should_not.binmode? - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {autoclose: false}) - io.should.autoclose? + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {autoclose: false}) + io.should.autoclose? - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {path: "a.txt"}) - io.path.should == "a.txt" - end + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {path: "a.txt"}) + io.path.should == "a.txt" + end - it "ignores the IO encoding options" do - io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_WRITABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {crlf_newline: true}) + it "ignores the IO encoding options" do + io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_WRITABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {crlf_newline: true}) - io.write("123\r\n456\n89") - io.flush + io.write("123\r\n456\n89") + io.flush - @r_io.read_nonblock(20).should == "123\r\n456\n89" - end + @r_io.read_nonblock(20).should == "123\r\n456\n89" + end - it "allows wrong mode" do - io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) - io.should.is_a?(File) + it "allows wrong mode" do + io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {}) + io.should.is_a?(File) - -> { io.read_nonblock(1) }.should raise_error(Errno::EBADF) - end + platform_is_not :windows do + -> { io.read_nonblock(1) }.should raise_error(Errno::EBADF) + end - it "tolerates NULL as rb_io_encoding *encoding parameter" do - io = @o.rb_io_open_descriptor_without_encoding(File, @r_io.fileno, 0, "a.txt", 60) - io.should.is_a?(File) - end + platform_is :windows do + -> { io.read_nonblock(1) }.should raise_error(IO::EWOULDBLOCKWaitReadable) + end + end + + it "tolerates NULL as rb_io_encoding *encoding parameter" do + io = @o.rb_io_open_descriptor_without_encoding(File, @r_io.fileno, 0, "a.txt", 60) + io.should.is_a?(File) + end - it "deduplicates path String" do - path = "a.txt".dup - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {}) - io.path.should_not equal(path) + it "deduplicates path String" do + path = "a.txt".dup + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {}) + io.path.should_not equal(path) - path = "a.txt".freeze - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {}) - io.path.should_not equal(path) - end + path = "a.txt".freeze + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {}) + io.path.should_not equal(path) + end - it "calls #to_str to convert a path to a String" do - path = Object.new - def path.to_str; "a.txt"; end + it "calls #to_str to convert a path to a String" do + path = Object.new + def path.to_str; "a.txt"; end - io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {}) + io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {}) - io.path.should == "a.txt" + io.path.should == "a.txt" + end end end end diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb index 96d61ee003c4..c90e50f1db9c 100644 --- a/spec/ruby/optional/capi/kernel_spec.rb +++ b/spec/ruby/optional/capi/kernel_spec.rb @@ -197,9 +197,13 @@ class CApiKernelSpecs::Exc < StandardError end it "uses an 'unknown error' message when errno is unknown" do - -> do - @s.rb_syserr_fail(-10, nil) - end.should raise_error(SystemCallError, /Unknown error(:)? -1/) # a new class Errno::E-01 is generated on the fly + platform_is_not :windows do + -> { @s.rb_syserr_fail(-10, nil) }.should raise_error(SystemCallError, /Unknown error(:)? -10/) + end + + platform_is :windows do + -> { @s.rb_syserr_fail(-1, nil) }.should raise_error(SystemCallError, "The operation completed successfully.") + end end end @@ -217,9 +221,13 @@ class CApiKernelSpecs::Exc < StandardError end it "uses an 'unknown error' message when errno is unknown" do - -> do - @s.rb_syserr_fail_str(-1, nil) - end.should raise_error(SystemCallError, /Unknown error(:)? -1/) # a new class Errno::E-01 is generated on the fly + platform_is_not :windows do + -> { @s.rb_syserr_fail_str(-10, nil) }.should raise_error(SystemCallError, /Unknown error(:)? -10/) + end + + platform_is :windows do + -> { @s.rb_syserr_fail_str(-1, nil) }.should raise_error(SystemCallError, "The operation completed successfully.") + end end end diff --git a/spec/ruby/shared/process/fork.rb b/spec/ruby/shared/process/fork.rb index 11e18d7b1cef..8dbb3d0da43d 100644 --- a/spec/ruby/shared/process/fork.rb +++ b/spec/ruby/shared/process/fork.rb @@ -23,31 +23,31 @@ end it "returns status zero" do - pid = Process.fork { exit! 0 } + pid = @object.fork { exit! 0 } _, result = Process.wait2(pid) result.exitstatus.should == 0 end it "returns status zero" do - pid = Process.fork { exit 0 } + pid = @object.fork { exit 0 } _, result = Process.wait2(pid) result.exitstatus.should == 0 end it "returns status zero" do - pid = Process.fork {} + pid = @object.fork {} _, result = Process.wait2(pid) result.exitstatus.should == 0 end it "returns status non-zero" do - pid = Process.fork { exit! 42 } + pid = @object.fork { exit! 42 } _, result = Process.wait2(pid) result.exitstatus.should == 42 end it "returns status non-zero" do - pid = Process.fork { exit 42 } + pid = @object.fork { exit 42 } _, result = Process.wait2(pid) result.exitstatus.should == 42 end diff --git a/spec/ruby/shared/rational/exponent.rb b/spec/ruby/shared/rational/exponent.rb index b0e9b2357416..2145d6baceae 100644 --- a/spec/ruby/shared/rational/exponent.rb +++ b/spec/ruby/shared/rational/exponent.rb @@ -84,47 +84,91 @@ (Rational(-1) ** bignum_value(3)).should eql(Rational(-1)) end - it "returns positive Infinity when self is > 1" do - -> { - (Rational(2) ** bignum_value).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_max) ** bignum_value).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - end - - it "returns 0.0 when self is > 1 and the exponent is negative" do - -> { - (Rational(2) ** -bignum_value).should eql(0.0) - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_max) ** -bignum_value).should eql(0.0) - }.should complain(/warning: in a\*\*b, b may be too big/) - end - - # Fails on linux due to pow() bugs in glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=3866 - platform_is_not :linux do - it "returns positive Infinity when self < -1" do + ruby_version_is ""..."3.4" do + it "returns positive Infinity when self is > 1" do -> { - (Rational(-2) ** bignum_value).infinite?.should == 1 + (Rational(2) ** bignum_value).infinite?.should == 1 }.should complain(/warning: in a\*\*b, b may be too big/) -> { - (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_min) ** bignum_value).infinite?.should == 1 + (Rational(fixnum_max) ** bignum_value).infinite?.should == 1 }.should complain(/warning: in a\*\*b, b may be too big/) end - it "returns 0.0 when self is < -1 and the exponent is negative" do + it "returns 0.0 when self is > 1 and the exponent is negative" do -> { - (Rational(-2) ** -bignum_value).should eql(0.0) + (Rational(2) ** -bignum_value).should eql(0.0) }.should complain(/warning: in a\*\*b, b may be too big/) -> { - (Rational(fixnum_min) ** -bignum_value).should eql(0.0) + (Rational(fixnum_max) ** -bignum_value).should eql(0.0) }.should complain(/warning: in a\*\*b, b may be too big/) end end + + ruby_version_is "3.4" do + it "raises an ArgumentError when self is > 1" do + -> { + (Rational(2) ** bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_max) ** bignum_value) + }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when self is > 1 and the exponent is negative" do + -> { + (Rational(2) ** -bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_max) ** -bignum_value) + }.should raise_error(ArgumentError) + end + end + + # Fails on linux due to pow() bugs in glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=3866 + platform_is_not :linux do + ruby_version_is ""..."3.4" do + it "returns positive Infinity when self < -1" do + -> { + (Rational(-2) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_min) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + end + + it "returns 0.0 when self is < -1 and the exponent is negative" do + -> { + (Rational(-2) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_min) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + end + end + + ruby_version_is "3.4" do + it "returns positive Infinity when self < -1" do + -> { + (Rational(-2) ** bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_min) ** bignum_value) + }.should raise_error(ArgumentError) + end + + it "returns 0.0 when self is < -1 and the exponent is negative" do + -> { + (Rational(-2) ** -bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_min) ** -bignum_value) + }.should raise_error(ArgumentError) + end + end + end end describe "when passed Float" do diff --git a/spec/tags/core/module/deprecate_constant_tags.txt b/spec/tags/core/module/deprecate_constant_tags.txt new file mode 100644 index 000000000000..d165b14f15ef --- /dev/null +++ b/spec/tags/core/module/deprecate_constant_tags.txt @@ -0,0 +1 @@ +fails:Module#deprecate_constant when removing the deprecated module warns with a message diff --git a/spec/tags/core/process/status/bit_and_tags.txt b/spec/tags/core/process/status/bit_and_tags.txt new file mode 100644 index 000000000000..d882c7260d62 --- /dev/null +++ b/spec/tags/core/process/status/bit_and_tags.txt @@ -0,0 +1,6 @@ +slow:Process::Status#& returns a bitwise and of the integer status of an exited child +slow:Process::Status#& raises an ArgumentError if mask is negative +slow:Process::Status#& shows a deprecation warning +fails:Process::Status#& returns a bitwise and of the integer status of an exited child +fails:Process::Status#& raises an ArgumentError if mask is negative +fails:Process::Status#& shows a deprecation warning diff --git a/spec/tags/core/process/status/right_shift_tags.txt b/spec/tags/core/process/status/right_shift_tags.txt new file mode 100644 index 000000000000..57fb6489236c --- /dev/null +++ b/spec/tags/core/process/status/right_shift_tags.txt @@ -0,0 +1,5 @@ +slow:Process::Status#>> returns a right shift of the integer status of an exited child +slow:Process::Status#>> raises an ArgumentError if shift value is negative +slow:Process::Status#>> shows a deprecation warning +fails:Process::Status#>> raises an ArgumentError if shift value is negative +fails:Process::Status#>> shows a deprecation warning diff --git a/spec/tags/core/refinement/refined_class_tags.txt b/spec/tags/core/refinement/refined_class_tags.txt new file mode 100644 index 000000000000..117517584109 --- /dev/null +++ b/spec/tags/core/refinement/refined_class_tags.txt @@ -0,0 +1 @@ +fails:Refinement#refined_class has been deprecated in favour of Refinement#target diff --git a/spec/tags/core/refinement/target_tags.txt b/spec/tags/core/refinement/target_tags.txt new file mode 100644 index 000000000000..09b279765c95 --- /dev/null +++ b/spec/tags/core/refinement/target_tags.txt @@ -0,0 +1 @@ +fails:Refinement#target returns the class refined by the receiver diff --git a/spec/tags/core/tracepoint/raised_exception_tags.txt b/spec/tags/core/tracepoint/raised_exception_tags.txt index 3a32ffe6c5b1..d3fd91512314 100644 --- a/spec/tags/core/tracepoint/raised_exception_tags.txt +++ b/spec/tags/core/tracepoint/raised_exception_tags.txt @@ -1 +1,2 @@ fails:TracePoint#raised_exception returns value from exception raised on the :raise event +fails:TracePoint#raised_exception returns value from exception rescued on the :rescue event