diff options
author | Andrew Konchin <[email protected]> | 2025-05-07 13:08:11 +0300 |
---|---|---|
committer | Benoit Daloze <[email protected]> | 2025-05-09 23:22:15 +0200 |
commit | 269ad29de95e41cc8a4eede84b98a81a6ff4f7b6 () | |
tree | 150acf5f6d6c2d401dd46b84b942af26b3699cc9 | |
parent | 3135eddb4e8c6975b6fa5345f15fdaa55257851a (diff) |
Update to ruby/spec@d8bacef
Notes: Merged: https://.com/ruby/ruby/pull/13265
261 files changed, 4150 insertions, 4921 deletions
@@ -1,7 +1,7 @@ inherit_from: .rubocop_todo.yml AllCops: - TargetRubyVersion: 3.1 DisplayCopNames: true Exclude: - command_line/fixtures/bad_syntax.rb @@ -30,8 +30,8 @@ ruby/spec is known to be tested in these implementations for every commit: * [Opal](https://.com/opal/opal/tree/master/spec) * [Artichoke](https://.com/artichoke/spec/tree/artichoke-vendor) -ruby/spec describes the behavior of Ruby 3.1 and more recent Ruby versions. -More precisely, every latest stable MRI release should [pass](https://.com/ruby/spec/actions/workflows/ci.yml) all specs of ruby/spec (3.1.x, 3.2.x, etc), and those are tested in CI. ### Synchronization with Ruby Implementations @@ -63,6 +63,7 @@ For older specs try these commits: * Ruby 2.6.10 - [Suite](https://.com/ruby/spec/commit/aaf998fb8c92c4e63ad423a2e7ca6e6921818c6e) using [MSpec](https://.com/ruby/mspec/commit/5e36c684e9e2b92b1187589bba1df22c640a8661) * Ruby 2.7.8 - [Suite](https://.com/ruby/spec/commit/93787e6035c925b593a9c0c6fb0e7e07a6f1df1f) using [MSpec](https://.com/ruby/mspec/commit/1d8cf64722d8a7529f7cd205be5f16a89b7a67fd) * Ruby 3.0.7 - [Suite](https://.com/ruby/spec/commit/affef93d9940f615e4836f64b011da211f570913) using [MSpec](https://.com/ruby/mspec/commit/0aabb3e548eb5ea6cad0125f8f46cee34542b6b7) ### Running the specs @@ -27,7 +27,7 @@ describe "Array#pack with format 'A'" do ["abc"].pack("A*").should == "abc" end - it "padds the output with spaces when the count exceeds the size of the String" do ["abc"].pack("A6").should == "abc " end @@ -55,7 +55,7 @@ describe "Array#pack with format 'a'" do ["abc"].pack("a*").should == "abc" end - it "padds the output with NULL bytes when the count exceeds the size of the String" do ["abc"].pack("a6").should == "abc\x00\x00\x00" end @@ -32,16 +32,7 @@ describe :array_pack_basic_non_float, shared: true do [@obj, @obj, @obj, @obj].pack("aa #{pack_format} # some comment \n#{pack_format}").should be_an_instance_of(String) end - ruby_version_is ""..."3.2" do - it "warns in verbose mode that a directive is unknown" do - # additional directive ('a') is required for the X directive - -> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/, verbose: true) - -> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/, verbose: true) - -> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/, verbose: true) - end - end - - ruby_version_is "3.2"..."3.3" do # https://bugs.ruby-lang.org/issues/19150 # NOTE: it's just a plan of the Ruby core team it "warns that a directive is unknown" do @@ -26,7 +26,7 @@ describe "Array#pack with format 'Z'" do ["abc"].pack("Z*").should == "abc\x00" end - it "padds the output with NULL bytes when the count exceeds the size of the String" do ["abc"].pack("Z6").should == "abc\x00\x00\x00" end @@ -754,99 +754,97 @@ describe :array_slice, shared: true do a.send(@method, (...-9)).should == [] end - ruby_version_is "3.2" do - describe "can be sliced with Enumerator::ArithmeticSequence" do - it "with infinite/inverted ranges and negative steps" do - @array = [0, 1, 2, 3, 4, 5] - @array.send(@method, (2..).step(-1)).should == [2, 1, 0] - @array.send(@method, (2..).step(-2)).should == [2, 0] - @array.send(@method, (2..).step(-3)).should == [2] - @array.send(@method, (2..).step(-4)).should == [2] - - @array.send(@method, (-3..).step(-1)).should == [3, 2, 1, 0] - @array.send(@method, (-3..).step(-2)).should == [3, 1] - @array.send(@method, (-3..).step(-3)).should == [3, 0] - @array.send(@method, (-3..).step(-4)).should == [3] - @array.send(@method, (-3..).step(-5)).should == [3] - - @array.send(@method, (..0).step(-1)).should == [5, 4, 3, 2, 1, 0] - @array.send(@method, (..0).step(-2)).should == [5, 3, 1] - @array.send(@method, (..0).step(-3)).should == [5, 2] - @array.send(@method, (..0).step(-4)).should == [5, 1] - @array.send(@method, (..0).step(-5)).should == [5, 0] - @array.send(@method, (..0).step(-6)).should == [5] - @array.send(@method, (..0).step(-7)).should == [5] - - @array.send(@method, (...0).step(-1)).should == [5, 4, 3, 2, 1] - @array.send(@method, (...0).step(-2)).should == [5, 3, 1] - @array.send(@method, (...0).step(-3)).should == [5, 2] - @array.send(@method, (...0).step(-4)).should == [5, 1] - @array.send(@method, (...0).step(-5)).should == [5] - @array.send(@method, (...0).step(-6)).should == [5] - - @array.send(@method, (...1).step(-1)).should == [5, 4, 3, 2] - @array.send(@method, (...1).step(-2)).should == [5, 3] - @array.send(@method, (...1).step(-3)).should == [5, 2] - @array.send(@method, (...1).step(-4)).should == [5] - @array.send(@method, (...1).step(-5)).should == [5] - - @array.send(@method, (..-5).step(-1)).should == [5, 4, 3, 2, 1] - @array.send(@method, (..-5).step(-2)).should == [5, 3, 1] - @array.send(@method, (..-5).step(-3)).should == [5, 2] - @array.send(@method, (..-5).step(-4)).should == [5, 1] - @array.send(@method, (..-5).step(-5)).should == [5] - @array.send(@method, (..-5).step(-6)).should == [5] - - @array.send(@method, (...-5).step(-1)).should == [5, 4, 3, 2] - @array.send(@method, (...-5).step(-2)).should == [5, 3] - @array.send(@method, (...-5).step(-3)).should == [5, 2] - @array.send(@method, (...-5).step(-4)).should == [5] - @array.send(@method, (...-5).step(-5)).should == [5] - - @array.send(@method, (4..1).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (4..1).step(-2)).should == [4, 2] - @array.send(@method, (4..1).step(-3)).should == [4, 1] - @array.send(@method, (4..1).step(-4)).should == [4] - @array.send(@method, (4..1).step(-5)).should == [4] - - @array.send(@method, (4...1).step(-1)).should == [4, 3, 2] - @array.send(@method, (4...1).step(-2)).should == [4, 2] - @array.send(@method, (4...1).step(-3)).should == [4] - @array.send(@method, (4...1).step(-4)).should == [4] - - @array.send(@method, (-2..1).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (-2..1).step(-2)).should == [4, 2] - @array.send(@method, (-2..1).step(-3)).should == [4, 1] - @array.send(@method, (-2..1).step(-4)).should == [4] - @array.send(@method, (-2..1).step(-5)).should == [4] - - @array.send(@method, (-2...1).step(-1)).should == [4, 3, 2] - @array.send(@method, (-2...1).step(-2)).should == [4, 2] - @array.send(@method, (-2...1).step(-3)).should == [4] - @array.send(@method, (-2...1).step(-4)).should == [4] - - @array.send(@method, (4..-5).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (4..-5).step(-2)).should == [4, 2] - @array.send(@method, (4..-5).step(-3)).should == [4, 1] - @array.send(@method, (4..-5).step(-4)).should == [4] - @array.send(@method, (4..-5).step(-5)).should == [4] - - @array.send(@method, (4...-5).step(-1)).should == [4, 3, 2] - @array.send(@method, (4...-5).step(-2)).should == [4, 2] - @array.send(@method, (4...-5).step(-3)).should == [4] - @array.send(@method, (4...-5).step(-4)).should == [4] - - @array.send(@method, (-2..-5).step(-1)).should == [4, 3, 2, 1] - @array.send(@method, (-2..-5).step(-2)).should == [4, 2] - @array.send(@method, (-2..-5).step(-3)).should == [4, 1] - @array.send(@method, (-2..-5).step(-4)).should == [4] - @array.send(@method, (-2..-5).step(-5)).should == [4] - - @array.send(@method, (-2...-5).step(-1)).should == [4, 3, 2] - @array.send(@method, (-2...-5).step(-2)).should == [4, 2] - @array.send(@method, (-2...-5).step(-3)).should == [4] - @array.send(@method, (-2...-5).step(-4)).should == [4] - end end end @@ -1,31 +1,29 @@ require_relative '../../spec_helper' -ruby_version_is '3.2' do - describe "Class#attached_object" do - it "returns the object that is attached to a singleton class" do - a = Class.new - a_obj = a.new - a_obj.singleton_class.attached_object.should == a_obj - end - it "returns the class object that is attached to a class's singleton class" do - a = Class.new - singleton_class = (class << a; self; end) - singleton_class.attached_object.should == a - end - it "raises TypeError if the class is not a singleton class" do - a = Class.new - -> { a.attached_object }.should raise_error(TypeError, /is not a singleton class/) - end - it "raises TypeError for special singleton classes" do - -> { nil.singleton_class.attached_object }.should raise_error(TypeError, /[`']NilClass' is not a singleton class/) - -> { true.singleton_class.attached_object }.should raise_error(TypeError, /[`']TrueClass' is not a singleton class/) - -> { false.singleton_class.attached_object }.should raise_error(TypeError, /[`']FalseClass' is not a singleton class/) - end end end @@ -11,20 +11,18 @@ describe "Complex.polar" do ->{ Complex.polar(nil, nil) }.should raise_error(TypeError) end - ruby_bug "#19004", ""..."3.2" do - it "computes the real values of the real & imaginary parts from the polar form" do - a = Complex.polar(1.0+0.0i, Math::PI/2+0.0i) - a.real.should be_close(0.0, TOLERANCE) - a.imag.should be_close(1.0, TOLERANCE) - a.real.real?.should be_true - a.imag.real?.should be_true - b = Complex.polar(1+0.0i) - b.real.should be_close(1.0, TOLERANCE) - b.imag.should be_close(0.0, TOLERANCE) - b.real.real?.should be_true - b.imag.real?.should be_true - end end end @@ -1,21 +1,11 @@ require_relative '../../spec_helper' -ruby_version_is ''...'3.2' do - describe "Data" do - it "does not exist anymore" do - Object.should_not have_constant(:Data) - end end -end - -ruby_version_is '3.2' do - describe "Data" do - it "is a new constant" do - Data.superclass.should == Object - end - it "is not deprecated" do - -> { Data }.should_not complain - end end end @@ -1,107 +1,105 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#deconstruct" do - it "returns a hash of attributes" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2} - end - - it "requires one argument" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - -> { - d.deconstruct_keys - }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/) - end - - it "returns only specified keys" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2} - d.deconstruct_keys([:x] ).should == {x: 1} - d.deconstruct_keys([] ).should == {} - end - - it "accepts string attribute names" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - d.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2} - end - - it "accepts argument position number as well but returns them as keys" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys([0, 1]).should == {0 => 1, 1 => 2} - d.deconstruct_keys([0] ).should == {0 => 1} - d.deconstruct_keys([-1] ).should == {-1 => 2} - end - - it "ignores incorrect position numbers" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys([0, 3]).should == {0 => 1} - end - - it "support mixing attribute names and argument position numbers" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1} - end - - it "returns an empty hash when there are more keys than attributes" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - d.deconstruct_keys([:x, :y, :x]).should == {} - end - - it "returns at first not existing attribute name" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys([:a, :x]).should == {} - d.deconstruct_keys([:x, :a]).should == {x: 1} - end - - it "returns at first not existing argument position number" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys([3, 0]).should == {} - d.deconstruct_keys([0, 3]).should == {0 => 1} - end - - it "accepts nil argument and return all the attributes" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - d.deconstruct_keys(nil).should == {x: 1, y: 2} - end - - it "raises TypeError if index is not a String, a Symbol and not convertible to Integer " do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - -> { - d.deconstruct_keys([0, []]) - }.should raise_error(TypeError, "no implicit conversion of Array into Integer") - end - - it "raise TypeError if passed anything except nil or array" do - klass = Data.define(:x, :y) - d = klass.new(1, 2) - - -> { d.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/) - -> { d.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/) - -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/) - -> { d.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/) - end end end @@ -1,10 +1,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#deconstruct" do - it "returns an array of attribute values" do - DataSpecs::Measure.new(42, "km").deconstruct.should == [42, "km"] - end end end @@ -1,36 +1,34 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data.define" do - it "accepts no arguments" do - empty_data = Data.define - empty_data.members.should == [] - end - it "accepts symbols" do - movie = Data.define(:title, :year) - movie.members.should == [:title, :year] - end - it "accepts strings" do - movie = Data.define("title", "year") - movie.members.should == [:title, :year] - end - it "accepts a mix of strings and symbols" do - movie = Data.define("title", :year, "genre") - movie.members.should == [:title, :year, :genre] - end - it "accepts a block" do - movie = Data.define(:title, :year) do - def title_with_year - "#{title} (#{year})" - end end - movie.members.should == [:title, :year] - movie.new("Matrix", 1999).title_with_year.should == "Matrix (1999)" end end end @@ -1,65 +1,63 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#eql?" do - it "returns true if the other is the same object" do - a = DataSpecs::Measure.new(42, "km") - a.should.eql?(a) - end - it "returns true if the other has all the same fields" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42, "km") - a.should.eql?(b) - end - it "returns false if the other is a different object or has different fields" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42, "mi") - a.should_not.eql?(b) - end - it "returns false if other is of a different class" do - a = DataSpecs::Measure.new(42, "km") - klass = Data.define(*DataSpecs::Measure.members) - b = klass.new(42, "km") - a.should_not.eql?(b) - end - it "returns false if any corresponding elements are not equal with #eql?" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42.0, "mi") - a.should_not.eql?(b) - end - context "recursive structure" do - it "returns true the other is the same object" do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: 42, unit: a) - a.should.eql?(a) - end - it "returns true if the other has all the same fields" do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: 42, unit: a) - b = DataSpecs::Measure.allocate - b.send(:initialize, amount: 42, unit: b) - a.should.eql?(b) - end - it "returns false if any corresponding elements are not equal with #eql?" do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: a, unit: "km") - b = DataSpecs::Measure.allocate - b.send(:initialize, amount: b, unit: "mi") - a.should_not.eql?(b) - end end end end @@ -1,65 +1,63 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#==" do - it "returns true if the other is the same object" do - a = DataSpecs::Measure.new(42, "km") - a.should == a - end - it "returns true if the other has all the same fields" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42, "km") - a.should == b - end - it "returns false if the other is a different object or has different fields" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42, "mi") - a.should_not == b - end - it "returns false if other is of a different class" do - a = DataSpecs::Measure.new(42, "km") - klass = Data.define(*DataSpecs::Measure.members) - b = klass.new(42, "km") - a.should_not == b - end - it "returns false if any corresponding elements are not equal with #==" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42.0, "mi") - a.should_not == b - end - context "recursive structure" do - it "returns true the other is the same object" do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: 42, unit: a) - a.should == a - end - it "returns true if the other has all the same fields" do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: 42, unit: a) - b = DataSpecs::Measure.allocate - b.send(:initialize, amount: 42, unit: b) - a.should == b - end - it "returns false if any corresponding elements are not equal with #==" do - a = DataSpecs::Measure.allocate - a.send(:initialize, amount: a, unit: "km") - b = DataSpecs::Measure.allocate - b.send(:initialize, amount: b, unit: "mi") - a.should_not == b - end end end end @@ -1,5 +1,5 @@ module DataSpecs - guard -> { ruby_version_is "3.2" and Data.respond_to?(:define) } do Measure = Data.define(:amount, :unit) class MeasureWithOverriddenName < Measure @@ -1,27 +1,25 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#hash" do - it "returns the same integer for objects with the same content" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42, "km") - a.hash.should == b.hash - a.hash.should be_an_instance_of(Integer) - end - it "returns different hashes for objects with different values" do - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(42, "ml") - a.hash.should_not == b.hash - a = DataSpecs::Measure.new(42, "km") - b = DataSpecs::Measure.new(13, "km") - a.hash.should_not == b.hash - end - it "returns different hashes for different classes" do - Data.define(:x).new(1).hash.should != Data.define(:x).new(1).hash - end end end @@ -1,65 +1,63 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#initialize" do - it "accepts positional arguments" do - data = DataSpecs::Measure.new(42, "km") - data.amount.should == 42 - data.unit.should == "km" - end - it "accepts alternative positional arguments" do - data = DataSpecs::Measure[42, "km"] - data.amount.should == 42 - data.unit.should == "km" - end - it "accepts keyword arguments" do - data = DataSpecs::Measure.new(amount: 42, unit: "km") - data.amount.should == 42 - data.unit.should == "km" - end - it "accepts alternative keyword arguments" do - data = DataSpecs::Measure[amount: 42, unit: "km"] - data.amount.should == 42 - data.unit.should == "km" - end - it "accepts String keyword arguments" do - data = DataSpecs::Measure.new("amount" => 42, "unit" => "km") - data.amount.should == 42 - data.unit.should == "km" - end - it "raises ArgumentError if no arguments are given" do - -> { - DataSpecs::Measure.new - }.should raise_error(ArgumentError) { |e| - e.message.should.include?("missing keywords: :amount, :unit") - } - end - it "raises ArgumentError if at least one argument is missing" do - -> { - DataSpecs::Measure.new(unit: "km") - }.should raise_error(ArgumentError) { |e| - e.message.should.include?("missing keyword: :amount") - } - end - it "raises ArgumentError if unknown keyword is given" do - -> { - DataSpecs::Measure.new(amount: 42, unit: "km", system: "metric") - }.should raise_error(ArgumentError) { |e| - e.message.should.include?("unknown keyword: :system") - } - end end end @@ -1,8 +1,6 @@ require_relative '../../spec_helper' require_relative 'shared/inspect' -ruby_version_is "3.2" do - describe "Data#inspect" do - it_behaves_like :data_inspect, :inspect - end end @@ -1,23 +1,21 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#members" do - it "returns an array of attribute names" do - measure = DataSpecs::Measure.new(amount: 42, unit: 'km') - measure.members.should == [:amount, :unit] - end end - describe "DataClass#members" do - it "returns an array of attribute names" do - DataSpecs::Measure.members.should == [:amount, :unit] - end - context "class inheriting Data" do - it "isn't available in a subclass" do - DataSpecs::DataSubclass.should_not.respond_to?(:members) - end end end end @@ -1,65 +1,63 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#to_h" do - it "transforms the data object into a hash" do data = DataSpecs::Measure.new(amount: 42, unit: 'km') - data.to_h.should == { amount: 42, unit: 'km' } end - context "with block" do - it "transforms [key, value] pairs returned by the block into a hash" do - data = DataSpecs::Measure.new(amount: 42, unit: 'km') - data.to_h { |key, value| [value, key] }.should == { 42 => :amount, 'km' => :unit } - end - - it "passes to a block each pair's key and value as separate arguments" do - ScratchPad.record [] - data = DataSpecs::Measure.new(amount: 42, unit: 'km') - data.to_h { |k, v| ScratchPad << [k, v]; [k, v] } - ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']] - ScratchPad.record [] - data.to_h { |*args| ScratchPad << args; [args[0], args[1]] } - ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']] - end - it "raises ArgumentError if block returns longer or shorter array" do - data = DataSpecs::Measure.new(amount: 42, unit: 'km') - -> do - data.to_h { |k, v| [k.to_s, v*v, 1] } - end.should raise_error(ArgumentError, /element has wrong array length/) - -> do - data.to_h { |k, v| [k] } - end.should raise_error(ArgumentError, /element has wrong array length/) - end - it "raises TypeError if block returns something other than Array" do - data = DataSpecs::Measure.new(amount: 42, unit: 'km') - -> do - data.to_h { |k, v| "not-array" } - end.should raise_error(TypeError, /wrong element type String/) - end - it "coerces returned pair to Array with #to_ary" do - x = mock('x') - x.stub!(:to_ary).and_return([:b, 'b']) - data = DataSpecs::Measure.new(amount: 42, unit: 'km') - data.to_h { |k| x }.should == { :b => 'b' } - end - it "does not coerce returned pair to Array with #to_a" do - x = mock('x') - x.stub!(:to_a).and_return([:b, 'b']) - data = DataSpecs::Measure.new(amount: 42, unit: 'km') - -> do - data.to_h { |k| x } - end.should raise_error(TypeError, /wrong element type MockObject/) - end end end end @@ -1,8 +1,6 @@ require_relative '../../spec_helper' require_relative 'shared/inspect' -ruby_version_is "3.2" do - describe "Data#to_s" do - it_behaves_like :data_inspect, :to_s - end end @@ -1,35 +1,33 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Data#with" do - it "returns self if given no arguments" do - data = DataSpecs::Measure.new(amount: 42, unit: "km") - data = data.with.should.equal?(data) - end - it "accepts keyword arguments" do - data = DataSpecs::Measure.new(amount: 42, unit: "km") - data = data.with(amount: 4, unit: "m") - data.amount.should == 4 - data.unit.should == "m" - end - it "accepts String keyword arguments" do - data = DataSpecs::Measure.new(amount: 42, unit: "km") - data = data.with("amount" => 4, "unit" => "m") - data.amount.should == 4 - data.unit.should == "m" - end - it "raises ArgumentError if no keyword arguments are given" do - data = DataSpecs::Measure.new(amount: 42, unit: "km") - -> { - data.with(4, "m") - }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)") - end end end @@ -177,7 +177,7 @@ ruby_version_is '3.3' do dir.close end - guard -> { Dir.respond_to? :fchdir } do it "does not raise an Errno::ENOENT if the original directory no longer exists" do dir_name1 = tmp('testdir1') dir_name2 = tmp('testdir2') @@ -14,7 +14,7 @@ describe "Dir#close" do dir.close.should == nil dir.close.should == nil - guard -> { dir.respond_to? :fileno } do -> { dir.fileno }.should raise_error(IOError, /closed directory/) end end @@ -25,7 +25,7 @@ describe "Dir#close" do end ruby_version_is '3.3'...'3.4' do - guard -> { Dir.respond_to? :for_fd } do it "does not raise an error even if the file descriptor is closed with another Dir instance" do dir = Dir.open DirSpecs.mock_dir dir_new = Dir.for_fd(dir.fileno) @@ -40,7 +40,7 @@ describe "Dir#close" do end ruby_version_is '3.4' do - guard -> { Dir.respond_to? :for_fd } do it "raises an error if the file descriptor is closed with another Dir instance" do dir = Dir.open DirSpecs.mock_dir dir_new = Dir.for_fd(dir.fileno) @@ -14,10 +14,8 @@ describe "Dir.exist?" do it_behaves_like :dir_exist, :exist? end -ruby_version_is "3.2" do - describe "Dir.exists?" do - it "has been removed" do - Dir.should_not.respond_to?(:exists?) - end end end @@ -2,7 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' ruby_version_is '3.3' do - guard -> { Dir.respond_to? :fchdir } do describe "Dir.fchdir" do before :all do DirSpecs.create_mock_dirs @@ -62,7 +62,7 @@ ruby_version_is '3.3' do end end - guard_not -> { Dir.respond_to? :fchdir } do describe "Dir.fchdir" do it "raises NotImplementedError" do -> { Dir.fchdir 1 }.should raise_error(NotImplementedError) @@ -192,13 +192,7 @@ module DirSpecs ] end - if RUBY_VERSION > '3.1' - def self.expected_glob_paths - expected_paths - ['..'] - end - else - def self.expected_glob_paths - expected_paths - end end end @@ -3,7 +3,7 @@ require_relative 'fixtures/common' quarantine! do # leads to "Errno::EBADF: Bad file descriptor - closedir" in DirSpecs.delete_mock_dirs ruby_version_is '3.3' do - guard -> { Dir.respond_to? :for_fd } do describe "Dir.for_fd" do before :all do DirSpecs.create_mock_dirs @@ -68,7 +68,7 @@ ruby_version_is '3.3' do end end - guard_not -> { Dir.respond_to? :for_fd } do describe "Dir.for_fd" do it "raises NotImplementedError" do -> { Dir.for_fd 1 }.should raise_error(NotImplementedError) @@ -33,28 +33,26 @@ describe "Dir.home" do end platform_is :windows do - ruby_version_is "3.2" do - it "returns the home directory with forward slashs and as UTF-8" do - ENV['HOME'] = "C:\\rubyspäc\\home" - home = Dir.home - home.should == "C:/rubyspäc/home" - home.encoding.should == Encoding::UTF_8 - end - it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do - old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')] - Dir.home.should == old_dirs[1].gsub("\\", "/") - ENV['HOMEDRIVE'] = "C:" - ENV['HOMEPATH'] = "\\rubyspec\\home1" - Dir.home.should == "C:/rubyspec/home1" - ENV['USERPROFILE'] = "C:\\rubyspec\\home2" - Dir.home.should == "C:/rubyspec/home2" - ENV['HOME'] = "C:\\rubyspec\\home3" - Dir.home.should == "C:/rubyspec/home3" - ensure - ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs - end end end end @@ -67,7 +67,7 @@ describe "Encoding#replicate" do end end - ruby_version_is "3.2"..."3.3" do it "warns about deprecation" do -> { Encoding::US_ASCII.replicate('MY-US-ASCII') @@ -343,9 +343,6 @@ module EnumerableSpecs end end - # Set is a core class since Ruby 3.2 - ruby_version_is '3.2' do - class SetSubclass < Set - end end end # EnumerableSpecs utility classes @@ -135,10 +135,8 @@ describe :enumerable_inject, shared: true do actual.sort_by(&:to_s).should == expected.sort_by(&:to_s) end - ruby_bug '#18635', ''...'3.2' do - it "raises an ArgumentError when no parameters or block is given" do - -> { [1,2].send(@method) }.should raise_error(ArgumentError) - -> { {one: 1, two: 2}.send(@method) }.should raise_error(ArgumentError) - end end end @@ -1,29 +1,27 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -ruby_version_is "3.2" do - describe "Enumerable#to_set" do - it "returns a new Set created from self" do - [1, 2, 3].to_set.should == Set[1, 2, 3] - {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]] - end - it "passes down passed blocks" do - [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9] - end - it "instantiates an object of provided as the first argument set class" do - set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass) - set.should be_kind_of(EnumerableSpecs::SetSubclass) - set.to_a.sort.should == [1, 2, 3] - end - it "does not need explicit `require 'set'`" do - output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1') - puts [1, 2, 3].to_set - RUBY - output.chomp.should == "#<Set: {1, 2, 3}>" - end end end @@ -1,73 +1,71 @@ require_relative '../../../spec_helper' require_relative '../../enumerable/shared/enumeratorized' -ruby_version_is "3.2" do - describe "Enumerator::Product#each" do - it_behaves_like :enumeratorized_with_origin_size, :each, Enumerator::Product.new([1, 2], [:a, :b]) - it "yields each element of Cartesian product of enumerators" do - enum = Enumerator::Product.new([1, 2], [:a, :b]) - acc = [] - enum.each { |e| acc << e } - acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - end - - it "calls #each_entry method on enumerators" do - object1 = Object.new - def object1.each_entry - yield 1 - yield 2 - end - - object2 = Object.new - def object2.each_entry - yield :a - yield :b - end - enum = Enumerator::Product.new(object1, object2) - acc = [] - enum.each { |e| acc << e } - acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]] end - it "raises a NoMethodError if the object doesn't respond to #each_entry" do - -> { - Enumerator::Product.new(Object.new).each {} - }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/) end - it "returns enumerator if not given a block" do - enum = Enumerator::Product.new([1, 2], [:a, :b]) - enum.each.should.kind_of?(Enumerator) - enum = Enumerator::Product.new([1, 2], [:a, :b]) - enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - end - it "returns self if given a block" do - enum = Enumerator::Product.new([1, 2], [:a, :b]) - enum.each {}.should.equal?(enum) - end - it "doesn't accept arguments" do - Enumerator::Product.instance_method(:each).arity.should == 0 - end - it "yields each element to a block that takes multiple arguments" do - enum = Enumerator::Product.new([1, 2], [:a, :b]) - acc = [] - enum.each { |x, y| acc << x } - acc.should == [1, 1, 2, 2] - acc = [] - enum.each { |x, y| acc << y } - acc.should == [:a, :b, :a, :b] - acc = [] - enum.each { |x, y, z| acc << z } - acc.should == [nil, nil, nil, nil] - end end end @@ -1,54 +1,52 @@ require_relative '../../../spec_helper' -ruby_version_is "3.2" do - describe "Enumerator::Product#initialize_copy" do - it "replaces content of the receiver with content of the other object" do - enum = Enumerator::Product.new([true, false]) - enum2 = Enumerator::Product.new([1, 2], [:a, :b]) - enum.send(:initialize_copy, enum2) - enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - end - it "returns self" do - enum = Enumerator::Product.new([true, false]) - enum2 = Enumerator::Product.new([1, 2], [:a, :b]) - enum.send(:initialize_copy, enum2).should.equal?(enum) - end - it "is a private method" do - Enumerator::Product.should have_private_instance_method(:initialize_copy, false) - end - it "does nothing if the argument is the same as the receiver" do - enum = Enumerator::Product.new(1..2) - enum.send(:initialize_copy, enum).should.equal?(enum) - enum.freeze - enum.send(:initialize_copy, enum).should.equal?(enum) - end - it "raises FrozenError if the receiver is frozen" do - enum = Enumerator::Product.new(1..2) - enum2 = Enumerator::Product.new(3..4) - -> { enum.freeze.send(:initialize_copy, enum2) }.should raise_error(FrozenError) - end - it "raises TypeError if the objects are of different class" do - enum = Enumerator::Product.new(1..2) - enum2 = Class.new(Enumerator::Product).new(3..4) - -> { enum.send(:initialize_copy, enum2) }.should raise_error(TypeError, 'initialize_copy should take same class object') - -> { enum2.send(:initialize_copy, enum) }.should raise_error(TypeError, 'initialize_copy should take same class object') - end - it "raises ArgumentError if the argument is not initialized yet" do - enum = Enumerator::Product.new(1..2) - enum2 = Enumerator::Product.allocate - -> { enum.send(:initialize_copy, enum2) }.should raise_error(ArgumentError, 'uninitialized product') - end end end @@ -1,33 +1,31 @@ require_relative '../../../spec_helper' -ruby_version_is "3.2" do - describe "Enumerator::Product#initialize" do - before :each do - @uninitialized = Enumerator::Product.allocate - end - it "is a private method" do - Enumerator::Product.should have_private_instance_method(:initialize, false) - end - it "returns self" do - @uninitialized.send(:initialize).should equal(@uninitialized) - end - it "accepts many arguments" do - @uninitialized.send(:initialize, 0..1, 2..3, 4..5).should equal(@uninitialized) - end - it "accepts arguments that are not Enumerable nor responding to :each_entry" do - @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) - end - describe "on frozen instance" do - it "raises a FrozenError" do - -> { - @uninitialized.freeze.send(:initialize, 0..1) - }.should raise_error(FrozenError) - end end end end @@ -1,22 +1,20 @@ require_relative '../../../spec_helper' -ruby_version_is "3.2" do - describe "Enumerator::Product#inspect" do - it "returns a String including enumerators" do - enum = Enumerator::Product.new([1, 2], [:a, :b]) - enum.inspect.should == "#<Enumerator::Product: [[1, 2], [:a, :b]]>" - end - it "represents a recursive element with '[...]'" do - enum = [1, 2] - enum_recursive = Enumerator::Product.new(enum) - enum << enum_recursive - enum_recursive.inspect.should == "#<Enumerator::Product: [[1, 2, #<Enumerator::Product: ...>]]>" - end - it "returns a not initialized representation if #initialized is not called yet" do - Enumerator::Product.allocate.inspect.should == "#<Enumerator::Product: uninitialized>" - end end end @@ -1,64 +1,62 @@ require_relative '../../../spec_helper' -ruby_version_is "3.2" do - describe "Enumerator::Product#rewind" do - before :each do - @enum = Enumerator::Product.new([1, 2].each.to_enum, [:a, :b].each.to_enum) - end - it "resets the enumerator to its initial state" do - @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - @enum.rewind - @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - end - it "returns self" do - @enum.rewind.should.equal? @enum - end - it "has no effect on a new enumerator" do - @enum.rewind - @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - end - it "has no effect if called multiple, consecutive times" do - @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - @enum.rewind - @enum.rewind - @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]] - end - it "calls the enclosed object's rewind method if one exists" do - obj = mock('rewinder') - enum = Enumerator::Product.new(obj.to_enum) - obj.should_receive(:rewind) - enum.rewind - end - it "does nothing if the object doesn't have a #rewind method" do - obj = mock('rewinder') - enum = Enumerator::Product.new(obj.to_enum) - enum.rewind.should == enum - end - it "calls a rewind method on each enumerable in direct order" do - ScratchPad.record [] - object1 = Object.new - def object1.rewind; ScratchPad << :object1; end - object2 = Object.new - def object2.rewind; ScratchPad << :object2; end - object3 = Object.new - def object3.rewind; ScratchPad << :object3; end - enum = Enumerator::Product.new(object1, object2, object3) - enum.rewind - ScratchPad.recorded.should == [:object1, :object2, :object3] - end end end @@ -1,56 +1,54 @@ require_relative '../../../spec_helper' -ruby_version_is "3.2" do - describe "Enumerator::Product#size" do - it "returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product" do - product = Enumerator::Product.new(1..2, 1..3, 1..4) - product.size.should == 24 # 2 * 3 * 4 - end - - it "returns nil if any enumerable reports its size as nil" do - enum = Object.new - def enum.size; nil; end - - product = Enumerator::Product.new(1..2, enum) - product.size.should == nil - end - - it "returns Float::INFINITY if any enumerable reports its size as Float::INFINITY" do - enum = Object.new - def enum.size; Float::INFINITY; end - - product = Enumerator::Product.new(1..2, enum) - product.size.should == Float::INFINITY - end - - it "returns nil if any enumerable reports its size as Float::NAN" do - enum = Object.new - def enum.size; Float::NAN; end - - product = Enumerator::Product.new(1..2, enum) - product.size.should == nil - end - - it "returns nil if any enumerable doesn't respond to #size" do - enum = Object.new - product = Enumerator::Product.new(1..2, enum) - product.size.should == nil - end - - it "returns nil if any enumerable reports a not-convertible to Integer" do - enum = Object.new - def enum.size; :symbol; end - - product = Enumerator::Product.new(1..2, enum) - product.size.should == nil - end - - it "returns nil if any enumerable reports a non-Integer but convertible to Integer size" do - enum = Object.new - def enum.size; 1.0; end - - product = Enumerator::Product.new(1..2, enum) - product.size.should == nil - end end end @@ -1,93 +1,91 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "Enumerator.product" do - it "returns a Cartesian product of enumerators" do - enum = Enumerator.product(1..2, ["A", "B"]) - enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]] - end - - it "accepts a list of enumerators of any length" do - enum = Enumerator.product(1..2) - enum.to_a.should == [[1], [2]] - enum = Enumerator.product(1..2, ["A"]) - enum.to_a.should == [[1, "A"], [2, "A"]] - enum = Enumerator.product(1..2, ["A"], ["B"]) - enum.to_a.should == [[1, "A", "B"], [2, "A", "B"]] - enum = Enumerator.product(2..3, ["A"], ["B"], ["C"]) - enum.to_a.should == [[2, "A", "B", "C"], [3, "A", "B", "C"]] - end - it "returns an enumerator with an empty array when no arguments passed" do - enum = Enumerator.product - enum.to_a.should == [[]] - end - it "returns an instance of Enumerator::Product" do - enum = Enumerator.product - enum.class.should == Enumerator::Product - end - it "accepts infinite enumerators and returns infinite enumerator" do - enum = Enumerator.product(1.., ["A", "B"]) - enum.take(5).should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"]] - enum.size.should == Float::INFINITY - end - it "accepts a block" do - elems = [] - enum = Enumerator.product(1..2, ["X", "Y"]) { elems << _1 } - elems.should == [[1, "X"], [1, "Y"], [2, "X"], [2, "Y"]] - end - it "returns nil when a block passed" do - Enumerator.product(1..2) {}.should == nil - end - # https://bugs.ruby-lang.org/issues/19829 - it "reject keyword arguments" do - -> { - Enumerator.product(1..3, foo: 1, bar: 2) - }.should raise_error(ArgumentError, "unknown keywords: :foo, :bar") - end - it "calls only #each_entry method on arguments" do - object = Object.new - def object.each_entry - yield 1 - yield 2 - end - enum = Enumerator.product(object, ["A", "B"]) - enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]] end - it "raises NoMethodError when argument doesn't respond to #each_entry" do - -> { - Enumerator.product(Object.new).to_a - }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/) - end - it "calls #each_entry lazily" do - Enumerator.product(Object.new).should be_kind_of(Enumerator) - end - it "iterates through consuming enumerator elements only once" do - a = [1, 2, 3] - i = 0 - enum = Enumerator.new do |y| - while i < a.size - y << a[i] - i += 1 - end end - - Enumerator.product(['a', 'b'], enum).to_a.should == [["a", 1], ["a", 2], ["a", 3]] end end end @@ -13,11 +13,9 @@ describe "ENV#clone" do }.should raise_error(ArgumentError) end - ruby_version_is "3.2" do - it "raises TypeError" do - -> { - ENV.clone - }.should raise_error(TypeError, /Cannot clone ENV, use ENV.to_h to get a copy of ENV as a hash/) - end end end @@ -15,12 +15,10 @@ describe :env_update, shared: true do ENV["bar"].should == "1" end - ruby_version_is "3.2" do - it "adds the multiple parameter hashes to ENV, returning ENV" do - ENV.send(@method, {"foo" => "multi1"}, {"bar" => "multi2"}).should equal(ENV) - ENV["foo"].should == "multi1" - ENV["bar"].should == "multi2" - end end it "returns ENV when no block given" do @@ -2,51 +2,49 @@ require_relative '../../spec_helper' require_relative 'fixtures/common' describe "Exception#detailed_message" do - ruby_version_is "3.2" do - it "returns decorated message" do - RuntimeError.new("new error").detailed_message.should == "new error (RuntimeError)" - end - it "is called by #full_message to allow message customization" do - exception = Exception.new("new error") - def exception.detailed_message(**) - "<prefix>#{message}<suffix>" - end - exception.full_message(highlight: false).should.include? "<prefix>new error<suffix>" end - it "returns just a message if exception class is anonymous" do - Class.new(RuntimeError).new("message").detailed_message.should == "message" - end - it "returns 'unhandled exception' for an instance of RuntimeError with empty message" do - RuntimeError.new("").detailed_message.should == "unhandled exception" - end - it "returns just class name for an instance other than RuntimeError with empty message" do - DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C" - StandardError.new("").detailed_message.should == "StandardError" - end - it "returns a generated class name for an instance of RuntimeError anonymous subclass with empty message" do - klass = Class.new(RuntimeError) - klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/ - end - it "accepts highlight keyword argument and adds escape control sequences" do - RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m" - end - it "accepts highlight keyword argument and adds escape control sequences for an instance of RuntimeError with empty message" do - RuntimeError.new("").detailed_message(highlight: true).should == "\e[1;4munhandled exception\e[m" - end - it "accepts highlight keyword argument and adds escape control sequences for an instance other than RuntimeError with empty message" do - StandardError.new("").detailed_message(highlight: true).should == "\e[1;4mStandardError\e[m" - end - it "allows and ignores other keyword arguments" do - RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)" - end end end @@ -165,52 +165,50 @@ describe "Exception#full_message" do exception.full_message.should include "origin exception" end - ruby_version_is "3.2" do - it "relies on #detailed_message" do - e = RuntimeError.new("new error") - e.define_singleton_method(:detailed_message) { |**| "DETAILED MESSAGE" } - e.full_message.lines.first.should =~ /DETAILED MESSAGE/ - end - - it "passes all its own keyword arguments (with :highlight default value and without :order default value) to #detailed_message" do - e = RuntimeError.new("new error") - options_passed = nil - e.define_singleton_method(:detailed_message) do |**options| - options_passed = options - "DETAILED MESSAGE" - end - e.full_message(foo: "bar") - options_passed.should == { foo: "bar", highlight: Exception.to_tty? } end - it "converts #detailed_message returned value to String if it isn't a String" do - message = Object.new - def message.to_str; "DETAILED MESSAGE"; end - e = RuntimeError.new("new error") - e.define_singleton_method(:detailed_message) { |**| message } - e.full_message.lines.first.should =~ /DETAILED MESSAGE/ - end - it "uses class name if #detailed_message returns nil" do - e = RuntimeError.new("new error") - e.define_singleton_method(:detailed_message) { |**| nil } - e.full_message(highlight: false).lines.first.should =~ /RuntimeError/ - e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/ - end - it "uses class name if exception object doesn't respond to #detailed_message" do - e = RuntimeError.new("new error") - class << e - undef :detailed_message - end - e.full_message(highlight: false).lines.first.should =~ /RuntimeError/ - e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/ end end end @@ -1,27 +1,25 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "SyntaxError#path" do - it "returns the file path provided to eval" do - filename = "speccing.rb" - -> { - eval("if true", TOPLEVEL_BINDING, filename) - }.should raise_error(SyntaxError) { |e| - e.path.should == filename - } - end - it "returns the file path that raised an exception" do - expected_path = fixture(__FILE__, "syntax_error.rb") - -> { - require_relative "fixtures/syntax_error" - }.should raise_error(SyntaxError) { |e| e.path.should == expected_path } - end - it "returns nil when constructed directly" do - SyntaxError.new.path.should == nil - end end end @@ -57,19 +57,17 @@ describe "Fiber#blocking?" do end end -ruby_version_is "3.2" do - describe "Fiber.blocking" do - context "when fiber is non-blocking" do - it "can become blocking" do - fiber = Fiber.new(blocking: false) do - Fiber.blocking do |f| - f.blocking? ? :blocking : :non_blocking - end end - - blocking = fiber.resume - blocking.should == :blocking end end end end @@ -1,183 +1,179 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "Fiber.new(storage:)" do - it "creates a Fiber with the given storage" do - storage = {life: 42} - fiber = Fiber.new(storage: storage) { Fiber.current.storage } - fiber.resume.should == storage - end - it "creates a fiber with lazily initialized storage" do - Fiber.new(storage: nil) { Fiber[:x] = 10; Fiber.current.storage }.resume.should == {x: 10} - end - it "creates a fiber by inheriting the storage of the parent fiber" do - fiber = Fiber.new(storage: {life: 42}) do - Fiber.new { Fiber.current.storage }.resume - end - fiber.resume.should == {life: 42} end - it "cannot create a fiber with non-hash storage" do - -> { Fiber.new(storage: 42) {} }.should raise_error(TypeError) - end - it "cannot create a fiber with a frozen hash as storage" do - -> { Fiber.new(storage: {life: 43}.freeze) {} }.should raise_error(FrozenError) - end - it "cannot create a fiber with a storage hash with non-symbol keys" do - -> { Fiber.new(storage: {life: 43, Object.new => 44}) {} }.should raise_error(TypeError) - end end - describe "Fiber#storage" do - it "cannot be accessed from a different fiber" do - f = Fiber.new(storage: {life: 42}) { nil } - -> { - f.storage - }.should raise_error(ArgumentError, /Fiber storage can only be accessed from the Fiber it belongs to/) - end end - describe "Fiber#storage=" do - it "can clear the storage of the fiber" do - fiber = Fiber.new(storage: {life: 42}) do - Fiber.current.storage = nil - Fiber[:x] = 10 - Fiber.current.storage - end - fiber.resume.should == {x: 10} end - it "can set the storage of the fiber" do - fiber = Fiber.new(storage: {life: 42}) do - Fiber.current.storage = {life: 43} - Fiber.current.storage - end - fiber.resume.should == {life: 43} end - it "can't set the storage of the fiber to non-hash" do - -> { Fiber.current.storage = 42 }.should raise_error(TypeError) - end - it "can't set the storage of the fiber to a frozen hash" do - -> { Fiber.current.storage = {life: 43}.freeze }.should raise_error(FrozenError) - end - it "can't set the storage of the fiber to a hash with non-symbol keys" do - -> { Fiber.current.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError) - end end - describe "Fiber.[]" do - it "returns the value of the given key in the storage of the current fiber" do - Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42 - end - it "returns nil if the key is not present in the storage of the current fiber" do - Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should be_nil - end - it "returns nil if the current fiber has no storage" do - Fiber.new { Fiber[:life] }.resume.should be_nil end - ruby_version_is "3.2.3" do - it "can use dynamically defined keys" do - key = :"#{self.class.name}#.#{self.object_id}" - Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42 - end - - it "can't use invalid keys" do - invalid_keys = [Object.new, 12] - invalid_keys.each do |key| - -> { Fiber[key] }.should raise_error(TypeError) - end - end end - ruby_bug "#20978", "3.2"..."3.4" do - it "can use keys as strings" do - key = Object.new - def key.to_str; "Foo"; end - Fiber.new { Fiber[key] = 42; Fiber["Foo"] }.resume.should == 42 - end - - it "converts a String key into a Symbol" do - Fiber.new { Fiber["key"] = 42; Fiber[:key] }.resume.should == 42 - Fiber.new { Fiber[:key] = 42; Fiber["key"] }.resume.should == 42 - end - - it "can use any object that responds to #to_str as a key" do - key = mock("key") - key.should_receive(:to_str).twice.and_return("key") - Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42 - end end - it "does not call #to_sym on the key" do key = mock("key") - key.should_not_receive(:to_sym) - -> { Fiber[key] }.should raise_error(TypeError) end - it "can access the storage of the parent fiber" do - f = Fiber.new(storage: {life: 42}) do - Fiber.new { Fiber[:life] }.resume - end - f.resume.should == 42 - end - it "can't access the storage of the fiber with non-symbol keys" do - -> { Fiber[Object.new] }.should raise_error(TypeError) end end - describe "Fiber.[]=" do - it "sets the value of the given key in the storage of the current fiber" do - Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43 - end - it "sets the value of the given key in the storage of the current fiber" do - Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43 - end - it "sets the value of the given key in the storage of the current fiber" do - Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43 - end - it "does not overwrite the storage of the parent fiber" do - f = Fiber.new(storage: {life: 42}) do - Fiber.yield Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume - Fiber[:life] - end - f.resume.should == 43 # Value of the inner fiber - f.resume.should == 42 # Value of the outer fiber - end - it "can't access the storage of the fiber with non-symbol keys" do - -> { Fiber[Object.new] = 44 }.should raise_error(TypeError) end - ruby_version_is "3.3" do - it "deletes the fiber storage key when assigning nil" do - Fiber.new(storage: {life: 42}) { - Fiber[:life] = nil - Fiber.current.storage - }.resume.should == {} - end end end - describe "Thread.new" do - it "creates a thread with the storage of the current fiber" do - fiber = Fiber.new(storage: {life: 42}) do - Thread.new { Fiber.current.storage }.value - end - fiber.resume.should == {life: 42} end end end @@ -5,10 +5,8 @@ describe "File.exist?" do it_behaves_like :file_exist, :exist?, File end -ruby_version_is "3.2" do - describe "File.exists?" do - it "has been removed" do - File.should_not.respond_to?(:exists?) - end end end @@ -5,10 +5,8 @@ describe "FileTest.exist?" do it_behaves_like :file_exist, :exist?, FileTest end -ruby_version_is "3.2" do - describe "FileTest.exists?" do - it "has been removed" do - FileTest.should_not.respond_to?(:exists?) - end end end @@ -84,4 +84,10 @@ describe :hash_to_s, shared: true do expected = ruby_version_is("3.4") ? "{true => false}" : "{true=>false}" { true => false }.to_s.should == expected end end @@ -30,45 +30,22 @@ describe "Hash#shift" do h.should == {} end - ruby_version_is '3.2' do - it "returns nil if the Hash is empty" do - h = {} - def h.default(key) - raise - end - h.shift.should == nil - end - end - - ruby_version_is ''...'3.2' do - it "calls #default with nil if the Hash is empty" do - h = {} - def h.default(key) - key.should == nil - :foo - end - h.shift.should == :foo end end it "returns nil from an empty hash" do {}.shift.should == nil end - ruby_version_is '3.2' do - it "returns nil for empty hashes with defaults and default procs" do - Hash.new(5).shift.should == nil - h = Hash.new { |*args| args } - h.shift.should == nil - end - end - - ruby_version_is ''...'3.2' do - it "returns (computed) default for empty hashes" do - Hash.new(5).shift.should == 5 - h = Hash.new { |*args| args } - h.shift.should == [h, nil] - end end it "preserves Hash invariants when removing the last item" do @@ -1,22 +1,20 @@ require_relative '../../spec_helper' describe "Integer#ceildiv" do - ruby_version_is '3.2' do - it "returns a quotient of division which is rounded up to the nearest integer" do - 0.ceildiv(3).should eql(0) - 1.ceildiv(3).should eql(1) - 3.ceildiv(3).should eql(1) - 4.ceildiv(3).should eql(2) - 4.ceildiv(-3).should eql(-1) - -4.ceildiv(3).should eql(-1) - -4.ceildiv(-3).should eql(2) - 3.ceildiv(1.2).should eql(3) - 3.ceildiv(6/5r).should eql(3) - (10**100-11).ceildiv(10**99-1).should eql(10) - (10**100-9).ceildiv(10**99-1).should eql(11) - end end end @@ -1,41 +1,13 @@ require_relative '../../spec_helper' describe "Fixnum" do - ruby_version_is ""..."3.2" do - it "is unified into Integer" do - suppress_warning do - Fixnum.should equal(Integer) - end - end - - it "is deprecated" do - -> { Fixnum }.should complain(/constant ::Fixnum is deprecated/) - end - end - - ruby_version_is "3.2" do - it "is no longer defined" do - Object.should_not.const_defined?(:Fixnum) - end end end describe "Bignum" do - ruby_version_is ""..."3.2" do - it "is unified into Integer" do - suppress_warning do - Bignum.should equal(Integer) - end - end - - it "is deprecated" do - -> { Bignum }.should complain(/constant ::Bignum is deprecated/) - end - end - - ruby_version_is "3.2" do - it "is no longer defined" do - Object.should_not.const_defined?(:Bignum) - end end end @@ -181,10 +181,8 @@ describe "Integer#<< (with n << m)" do (bignum_value << -(2**40)).should == 0 end - ruby_bug "#18517", ""..."3.2" do - it "returns 0 when m > 0 long and n == 0" do - (0 << (2**40)).should == 0 - end end it "returns 0 when m > 0 bignum and n == 0" do @@ -203,10 +203,8 @@ describe "Integer#>> (with n >> m)" do (bignum_value >> (2**40)).should == 0 end - ruby_bug "#18517", ""..."3.2" do - it "returns 0 when m < 0 long and n == 0" do - (0 >> -(2**40)).should == 0 - end end it "returns 0 when m < 0 bignum and n == 0" do @@ -1,14 +1,12 @@ require_relative '../../spec_helper' describe "IO#path" do - ruby_version_is "3.2" do - it "returns the path of the file associated with the IO object" do - path = tmp("io_path.txt") - File.open(path, "w") do |file| - IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path - end - ensure - File.unlink(path) end end end @@ -202,20 +202,10 @@ describe :io_each, shared: true do end describe "when passed chomp and nil as a separator" do - ruby_version_is "3.2" do - it "yields self's content" do - @io.pos = 100 - @io.send(@method, nil, chomp: true) { |s| ScratchPad << s } - ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"] - end - end - - ruby_version_is ""..."3.2" do - it "yields self's content without trailing new line character" do - @io.pos = 100 - @io.send(@method, nil, chomp: true) { |s| ScratchPad << s } - ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six."] - end end end @@ -131,9 +131,7 @@ describe "IO#sysread" do @read.sysread(3).should == "ab" end - guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do # https://bugs.ruby-lang.org/issues/18880 - it "raises ArgumentError when length is less than 0" do - -> { @read.sysread(-1) }.should raise_error(ArgumentError) - end end end @@ -1,30 +1,7 @@ require_relative '../../spec_helper' describe "Kernel#=~" do - ruby_version_is ''...'3.2' do - it "returns nil matching any object" do - o = Object.new - - suppress_warning do - (o =~ /Object/).should be_nil - (o =~ 'Object').should be_nil - (o =~ Object).should be_nil - (o =~ Object.new).should be_nil - (o =~ nil).should be_nil - (o =~ true).should be_nil - end - end - - it "is deprecated" do - -> do - Object.new =~ /regexp/ - end.should complain(/deprecated Object#=~ is called on Object/, verbose: true) - end - end - - ruby_version_is '3.2' do - it "is no longer defined" do - Object.new.should_not.respond_to?(:=~) - end end end @@ -14,18 +14,8 @@ describe "Kernel#!~" do (obj !~ :foo).should == false end - ruby_version_is ""..."3.2" do - it "returns true if self does not respond to #=~" do - suppress_warning do - (Object.new !~ :foo).should == true - end - end - end - - ruby_version_is "3.2" do - it "raises NoMethodError if self does not respond to #=~" do - -> { Object.new !~ :foo }.should raise_error(NoMethodError) - end end it 'can be overridden in subclasses' do @@ -106,7 +106,7 @@ describe "Kernel#open" do ScratchPad.clear end - it "calls #to_path to covert the argument to a String before calling #to_str" do obj = mock("open to_path") obj.should_receive(:to_path).at_least(1).times.and_return(@name) obj.should_not_receive(:to_str) @@ -296,6 +296,16 @@ describe :kernel_require, shared: true do $LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR] @object.require("load_fixture").should be_false end end describe "(file extensions)" do @@ -815,4 +825,24 @@ describe :kernel_require, shared: true do e.path.should == path } end end @@ -22,6 +22,7 @@ describe :kernel_sprintf, shared: true do @method.call("%d", "112").should == "112" @method.call("%d", "0127").should == "87" @method.call("%d", "0xc4").should == "196" end it "raises TypeError exception if cannot convert to Integer" do @@ -57,6 +58,11 @@ describe :kernel_sprintf, shared: true do it "works well with large numbers" do @method.call("%#{f}", 1234567890987654321).should == "1234567890987654321" end end end @@ -289,28 +295,12 @@ describe :kernel_sprintf, shared: true do @method.call("%c", "a").should == "a" end - ruby_version_is ""..."3.2" do - it "raises ArgumentError if argument is a string of several characters" do - -> { - @method.call("%c", "abc") - }.should raise_error(ArgumentError, /%c requires a character/) - end - - it "raises ArgumentError if argument is an empty string" do - -> { - @method.call("%c", "") - }.should raise_error(ArgumentError, /%c requires a character/) - end end - ruby_version_is "3.2" do - it "displays only the first character if argument is a string of several characters" do - @method.call("%c", "abc").should == "a" - end - - it "displays no characters if argument is an empty string" do - @method.call("%c", "").should == "" - end end it "raises TypeError if argument is not String or Integer and cannot be converted to them" do @@ -2,26 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#taint" do - ruby_version_is ""..."3.2" do - it "is a no-op" do - suppress_warning do - o = Object.new - o.taint - o.should_not.tainted? - end - end - - it "warns in verbose mode" do - -> { - obj = mock("tainted") - obj.taint - }.should complain(/Object#taint is deprecated and will be removed in Ruby 3.2/, verbose: true) - end - end - - ruby_version_is "3.2" do - it "has been removed" do - Object.new.should_not.respond_to?(:taint) - end end end @@ -2,28 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#tainted?" do - ruby_version_is ""..."3.2" do - it "is a no-op" do - suppress_warning do - o = mock('o') - p = mock('p') - p.taint - o.should_not.tainted? - p.should_not.tainted? - end - end - - it "warns in verbose mode" do - -> { - o = mock('o') - o.tainted? - }.should complain(/Object#tainted\? is deprecated and will be removed in Ruby 3.2/, verbose: true) - end - end - - ruby_version_is "3.2" do - it "has been removed" do - Object.new.should_not.respond_to?(:tainted?) - end end end @@ -2,27 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#trust" do - ruby_version_is ""..."3.2" do - it "is a no-op" do - suppress_warning do - o = Object.new.untrust - o.should_not.untrusted? - o.trust - o.should_not.untrusted? - end - end - - it "warns in verbose mode" do - -> { - o = Object.new.untrust - o.trust - }.should complain(/Object#trust is deprecated and will be removed in Ruby 3.2/, verbose: true) - end - end - - ruby_version_is "3.2" do - it "has been removed" do - Object.new.should_not.respond_to?(:trust) - end end end @@ -2,27 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#untaint" do - ruby_version_is ""..."3.2" do - it "is a no-op" do - suppress_warning do - o = Object.new.taint - o.should_not.tainted? - o.untaint - o.should_not.tainted? - end - end - - it "warns in verbose mode" do - -> { - o = Object.new.taint - o.untaint - }.should complain(/Object#untaint is deprecated and will be removed in Ruby 3.2/, verbose: true) - end - end - - ruby_version_is "3.2" do - it "has been removed" do - Object.new.should_not.respond_to?(:untaint) - end end end @@ -2,26 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#untrust" do - ruby_version_is ""..."3.2" do - it "is a no-op" do - suppress_warning do - o = Object.new - o.untrust - o.should_not.untrusted? - end - end - - it "warns in verbose mode" do - -> { - o = Object.new - o.untrust - }.should complain(/Object#untrust is deprecated and will be removed in Ruby 3.2/, verbose: true) - end - end - - ruby_version_is "3.2" do - it "has been removed" do - Object.new.should_not.respond_to?(:untrust) - end end end @@ -2,27 +2,7 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Kernel#untrusted?" do - ruby_version_is ""..."3.2" do - it "is a no-op" do - suppress_warning do - o = mock('o') - o.should_not.untrusted? - o.untrust - o.should_not.untrusted? - end - end - - it "warns in verbose mode" do - -> { - o = mock('o') - o.untrusted? - }.should complain(/Object#untrusted\? is deprecated and will be removed in Ruby 3.2/, verbose: true) - end - end - - ruby_version_is "3.2" do - it "has been removed" do - Object.new.should_not.respond_to?(:untrusted?) - end end end @@ -142,11 +142,9 @@ describe "main.using" do end.should raise_error(RuntimeError) end - ruby_version_is "3.2" do - it "does not raise error when wrapped with module" do - -> do - load File.expand_path('../fixtures/using.rb', __FILE__), true - end.should_not raise_error - end end end @@ -361,30 +361,28 @@ describe "Marshal.dump" do end end - ruby_version_is "3.2" do - describe "with a Data" do - it "dumps a Data" do - Marshal.dump(MarshalSpec::DataSpec::Measure.new(100, 'km')).should == "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm" - end - it "dumps an extended Data" do - obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km") - Marshal.dump(obj).should == "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm" - end - it "ignores overridden name method" do - obj = MarshalSpec::DataSpec::MeasureWithOverriddenName.new(100, "km") - Marshal.dump(obj).should == "\x04\bS:5MarshalSpec::DataSpec::MeasureWithOverriddenName\a:\vamountii:\tunit\"\akm" - end - it "uses object links for objects repeatedly dumped" do - d = MarshalSpec::DataSpec::Measure.new(100, 'km') - Marshal.dump([d, d]).should == "\x04\b[\aS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm@\x06" # @\x06 is a link to the object - end - it "raises TypeError with an anonymous Struct" do - -> { Marshal.dump(Data.define(:a).new(1)) }.should raise_error(TypeError, /can't dump anonymous class/) - end end end @@ -532,18 +532,16 @@ module MarshalSpec "Random" => random_data, } - if defined? Data # TODO: remove the condition when minimal supported version is 3.2 - module DataSpec - Measure = Data.define(:amount, :unit) - Empty = Data.define - - MeasureExtended = Class.new(Measure) - MeasureExtended.extend(Enumerable) - - class MeasureWithOverriddenName < Measure - def self.name - "Foo" - end end end end @@ -139,7 +139,7 @@ describe :marshal_load, shared: true do end end - ruby_bug "#19427", "3.1"..."3.3" do it "returns frozen object having #_dump method" do object = Marshal.send(@method, Marshal.dump(UserDefined.new), freeze: true) object.should.frozen? @@ -739,31 +739,29 @@ describe :marshal_load, shared: true do end end - ruby_version_is "3.2" do - describe "for a Data" do - it "loads a Data" do - obj = MarshalSpec::DataSpec::Measure.new(100, 'km') - dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm" - Marshal.dump(obj).should == dumped - Marshal.send(@method, dumped).should == obj - end - it "loads an extended Data" do - obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km") - dumped = "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm" - Marshal.dump(obj).should == dumped - Marshal.send(@method, dumped).should == obj - end - it "returns a frozen object" do - obj = MarshalSpec::DataSpec::Measure.new(100, 'km') - dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm" - Marshal.dump(obj).should == dumped - Marshal.send(@method, dumped).should.frozen? - end end end @@ -1,95 +1,93 @@ require_relative '../../spec_helper' describe "MatchData#byteoffset" do - ruby_version_is "3.2" do - it "returns beginning and ending byte-based offset of whole matched substring for 0 element" do - m = /(.)(.)(\d+)(\d)/.match("THX1138.") - m.byteoffset(0).should == [1, 7] - end - it "returns beginning and ending byte-based offset of n-th match, all the subsequent elements are capturing groups" do - m = /(.)(.)(\d+)(\d)/.match("THX1138.") - m.byteoffset(2).should == [2, 3] - m.byteoffset(3).should == [3, 6] - m.byteoffset(4).should == [6, 7] - end - it "accepts String as a reference to a named capture" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - m.byteoffset("f").should == [0, 3] - m.byteoffset("b").should == [3, 6] - end - it "accepts Symbol as a reference to a named capture" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - m.byteoffset(:f).should == [0, 3] - m.byteoffset(:b).should == [3, 6] - end - it "returns [nil, nil] if a capturing group is optional and doesn't match" do - m = /(?<x>q..)?/.match("foobarbaz") - m.byteoffset("x").should == [nil, nil] - m.byteoffset(1).should == [nil, nil] - end - it "returns correct beginning and ending byte-based offset for multi-byte strings" do - m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044") - m.byteoffset(1).should == [3, 6] - m.byteoffset(3).should == [6, 9] - end - it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do - m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044") - m.byteoffset(2).should == [nil, nil] - end - it "converts argument into integer if is not String nor Symbol" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - obj = Object.new - def obj.to_int; 2; end - m.byteoffset(1r).should == [0, 3] - m.byteoffset(1.1).should == [0, 3] - m.byteoffset(obj).should == [3, 6] - end - it "raises IndexError if there is no group with the provided name" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - -> { - m.byteoffset("y") - }.should raise_error(IndexError, "undefined group name reference: y") - -> { - m.byteoffset(:y) - }.should raise_error(IndexError, "undefined group name reference: y") - end - it "raises IndexError if index is out of bounds" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - -> { - m.byteoffset(-1) - }.should raise_error(IndexError, "index -1 out of matches") - -> { - m.byteoffset(3) - }.should raise_error(IndexError, "index 3 out of matches") - end - it "raises TypeError if can't convert argument into Integer" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - -> { - m.byteoffset([]) - }.should raise_error(TypeError, "no implicit conversion of Array into Integer") - end end end @@ -1,65 +1,63 @@ require_relative '../../spec_helper' describe "MatchData#deconstruct_keys" do - ruby_version_is "3.2" do - it "returns whole hash for nil as an argument" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - m.deconstruct_keys(nil).should == { f: "foo", b: "bar" } - end - it "returns only specified keys" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - m.deconstruct_keys([:f]).should == { f: "foo" } - end - it "requires one argument" do - m = /l/.match("l") - -> { - m.deconstruct_keys - }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1)") - end - it "it raises error when argument is neither nil nor array" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - -> { m.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array)") - -> { m.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array)") - -> { m.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array)") - -> { m.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array)") - end - it "returns {} when passed []" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - m.deconstruct_keys([]).should == {} - end - it "does not accept non-Symbol keys" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - -> { - m.deconstruct_keys(['year', :foo]) - }.should raise_error(TypeError, "wrong argument type String (expected Symbol)") - end - it "process keys till the first non-existing one" do - m = /(?<f>foo)(?<b>bar)(?<c>baz)/.match("foobarbaz") - m.deconstruct_keys([:f, :a, :b]).should == { f: "foo" } - end - it "returns {} when there are no named captured groups at all" do - m = /foo.+/.match("foobar") - m.deconstruct_keys(nil).should == {} - end - it "returns {} when passed more keys than named captured groups" do - m = /(?<f>foo)(?<b>bar)/.match("foobar") - m.deconstruct_keys([:f, :b, :c]).should == {} - end end end @@ -2,7 +2,5 @@ require_relative '../../spec_helper' require_relative 'shared/captures' describe "MatchData#deconstruct" do - ruby_version_is "3.2" do - it_behaves_like :matchdata_captures, :deconstruct - end end @@ -24,9 +24,7 @@ describe "Method#owner" do end end - ruby_version_is "3.2" do - it "returns the class on which public was called for a private method in ancestor" do - MethodSpecs::InheritedMethods::C.new.method(:derp).owner.should == MethodSpecs::InheritedMethods::C - end end end @@ -233,28 +233,14 @@ describe "Method#parameters" do m.method(:handled_via_method_missing).parameters.should == [[:rest]] end - ruby_version_is '3.2' do - it "adds rest arg with name * for \"star\" argument" do - m = MethodSpecs::Methods.new - m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]] - end - - it "adds keyrest arg with ** as a name for \"double star\" argument" do - m = MethodSpecs::Methods.new - m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest, :**]] - end end - ruby_version_is ''...'3.2' do - it "adds nameless rest arg for \"star\" argument" do - m = MethodSpecs::Methods.new - m.method(:one_unnamed_splat).parameters.should == [[:rest]] - end - - it "adds nameless keyrest arg for \"double star\" argument" do - m = MethodSpecs::Methods.new - m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest]] - end end it "adds block arg with name & for anonymous block argument" do @@ -2,27 +2,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Method#private?" do - ruby_version_is ""..."3.2" do - it "returns false when the method is public" do - obj = MethodSpecs::Methods.new - obj.method(:my_public_method).private?.should == false - end - - it "returns false when the method is protected" do - obj = MethodSpecs::Methods.new - obj.method(:my_protected_method).private?.should == false - end - - it "returns true when the method is private" do - obj = MethodSpecs::Methods.new - obj.method(:my_private_method).private?.should == true - end - end - - ruby_version_is "3.2" do - it "has been removed" do - obj = MethodSpecs::Methods.new - obj.method(:my_private_method).should_not.respond_to?(:private?) - end end end @@ -2,27 +2,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Method#protected?" do - ruby_version_is ""..."3.2" do - it "returns false when the method is public" do - obj = MethodSpecs::Methods.new - obj.method(:my_public_method).protected?.should == false - end - - it "returns true when the method is protected" do - obj = MethodSpecs::Methods.new - obj.method(:my_protected_method).protected?.should == true - end - - it "returns false when the method is private" do - obj = MethodSpecs::Methods.new - obj.method(:my_private_method).protected?.should == false - end - end - - ruby_version_is "3.2" do - it "has been removed" do - obj = MethodSpecs::Methods.new - obj.method(:my_protected_method).should_not.respond_to?(:protected?) - end end end @@ -2,27 +2,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Method#public?" do - ruby_version_is ""..."3.2" do - it "returns true when the method is public" do - obj = MethodSpecs::Methods.new - obj.method(:my_public_method).public?.should == true - end - - it "returns false when the method is protected" do - obj = MethodSpecs::Methods.new - obj.method(:my_protected_method).public?.should == false - end - - it "returns false when the method is private" do - obj = MethodSpecs::Methods.new - obj.method(:my_private_method).public?.should == false - end - end - - ruby_version_is "3.2" do - it "has been removed" do - obj = MethodSpecs::Methods.new - obj.method(:my_public_method).should_not.respond_to?(:public?) - end end end @@ -27,16 +27,8 @@ describe "Method#unbind" do @string.should =~ /MethodSpecs::MyMod/ end - ruby_version_is ""..."3.2" do - it "returns a String containing the Module the method is referenced from" do - @string.should =~ /MethodSpecs::MySub/ - end - end - - ruby_version_is "3.2" do - it "returns a String containing the Module the method is referenced from" do - @string.should =~ /MethodSpecs::MyMod/ - end end end @@ -603,32 +603,30 @@ describe "Module#autoload" do end end - ruby_version_is "3.2" do - it "warns once in verbose mode if the constant was defined in a parent scope" do - ScratchPad.record -> { - ModuleSpecs::DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent - } - module ModuleSpecs - module Autoload - autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb") - self.autoload?(:DeclaredInCurrentDefinedInParent).should == fixture(__FILE__, "autoload_callback.rb") - const_defined?(:DeclaredInCurrentDefinedInParent).should == true - - -> { - DeclaredInCurrentDefinedInParent - }.should complain( - /Expected .*autoload_callback.rb to define ModuleSpecs::Autoload::DeclaredInCurrentDefinedInParent but it didn't/, - verbose: true, - ) - - -> { - DeclaredInCurrentDefinedInParent - }.should_not complain(/.*/, verbose: true) - self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil - const_defined?(:DeclaredInCurrentDefinedInParent).should == false - ModuleSpecs.const_defined?(:DeclaredInCurrentDefinedInParent).should == true - end end end end @@ -3,236 +3,234 @@ require_relative 'fixtures/classes' require_relative 'fixtures/const_added' describe "Module#const_added" do - ruby_version_is "3.2" do - it "is a private instance method" do - Module.should have_private_instance_method(:const_added) end - it "returns nil in the default implementation" do - Module.new do - const_added(:TEST).should == nil end end - it "is called when a new constant is assigned on self" do - ScratchPad.record [] - - mod = Module.new do - def self.const_added(name) - ScratchPad << name - end end - mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1) - TEST = 1 - RUBY - ScratchPad.recorded.should == [:TEST] - end - it "is called when a new constant is assigned on self through const_set" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(name) - ScratchPad << name - end end - mod.const_set(:TEST, 1) - ScratchPad.recorded.should == [:TEST] - end - it "is called when a new module is defined under self" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(name) - ScratchPad << name - end end - mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1) - module SubModule - end - module SubModule - end - RUBY - ScratchPad.recorded.should == [:SubModule] end - it "is called when a new module is defined under a named module (assigned to a constant)" do - ScratchPad.record [] - ModuleSpecs::ConstAddedSpecs::NamedModule = Module.new do - def self.const_added(name) - ScratchPad << name - end - module self::A - def self.const_added(name) - ScratchPad << name - end - module self::B - end - end end - - ScratchPad.recorded.should == [:A, :B] end - it "is called when a new class is defined under self" do - ScratchPad.record [] - - mod = Module.new do - def self.const_added(name) - ScratchPad << name - end end - mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1) - class SubClass - end - class SubClass - end - RUBY - ScratchPad.recorded.should == [:SubClass] - end - it "is called when a new class is defined under a named module (assigned to a constant)" do - ScratchPad.record [] - ModuleSpecs::ConstAddedSpecs::NamedModuleB = Module.new do def self.const_added(name) ScratchPad << name end - class self::A - def self.const_added(name) - ScratchPad << name - end - - class self::B - end end end - - ScratchPad.recorded.should == [:A, :B] end - it "is called when an autoload is defined" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(name) - ScratchPad << name - end - end - mod.autoload :Autoload, "foo" - ScratchPad.recorded.should == [:Autoload] end - it "is called with a precise caller location with the line of definition" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(name) - location = caller_locations(1, 1)[0] - ScratchPad << location.lineno - end end - line = __LINE__ - mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1) - TEST = 1 - module SubModule - end - class SubClass - end - RUBY - mod.const_set(:CONST_SET, 1) - ScratchPad.recorded.should == [line + 2, line + 4, line + 7, line + 11] end - it "is called when the constant is already assigned a value" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(name) - ScratchPad.record const_get(name) - end end - mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1) - TEST = 123 - RUBY - ScratchPad.recorded.should == 123 end - it "records re-definition of existing constants" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(name) - ScratchPad << const_get(name) - end end - -> { - mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1) - TEST = 123 - TEST = 456 - RUBY - }.should complain(/warning: already initialized constant .+::TEST/) - ScratchPad.recorded.should == [123, 456] - end - it "for a class defined with the `class` keyword, const_added runs before inherited" do - ScratchPad.record [] - mod = Module.new do - def self.const_added(_) - ScratchPad << :const_added - end - end - parent = Class.new do - def self.inherited(_) - ScratchPad << :inherited - end end - class mod::C < parent; end - ScratchPad.recorded.should == [:const_added, :inherited] - end - it "the superclass of a class assigned to a constant is set before const_added is called" do - ScratchPad.record [] - parent = Class.new do - def self.const_added(name) - ScratchPad << name - ScratchPad << const_get(name).superclass - end end - class parent::C < parent; end - ScratchPad.recorded.should == [:C, parent] - end end end @@ -51,32 +51,16 @@ describe "Module#include" do ModuleSpecs::SubclassSpec.send(:remove_const, :AClass) end - ruby_version_is ""..."3.2" do - it "raises ArgumentError when the argument is a refinement" do - refinement = nil - Module.new do - refine String do - refinement = self - end end - - -> { ModuleSpecs::Basic.include(refinement) }.should raise_error(ArgumentError, "refinement module is not allowed") end - end - - ruby_version_is "3.2" do - it "raises a TypeError when the argument is a refinement" do - refinement = nil - Module.new do - refine String do - refinement = self - end - end - - -> { ModuleSpecs::Basic.include(refinement) }.should raise_error(TypeError, "Cannot include refinement") - end end it "imports constants to modules and classes" do @@ -48,11 +48,6 @@ describe "Module#instance_method" do @mod_um.inspect.should =~ /\bbar\b/ @mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethMod\b/ - - ruby_version_is ""..."3.2" do - @child_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/ - @mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/ - end end it "raises a TypeError if the given name is not a String/Symbol" do @@ -153,45 +153,43 @@ describe "Module#name" do ModuleSpecs::Anonymous.send(:remove_const, :StoredInMultiplePlaces) end - ruby_version_is "3.2" do - it "is set in #const_added callback when a module defined in the top-level scope" do - ruby_exe(<<~RUBY, args: "2>&1").chomp.should == "TEST1\nTEST2" - class Module - def const_added(name) - puts const_get(name).name - end end - # module with name - module TEST1 - end - # anonymous module - TEST2 = Module.new - RUBY - end - it "is set in #const_added callback for a nested module when an outer module defined in the top-level scope" do - ScratchPad.record [] - ModuleSpecs::NameSpecs::NamedModule = Module.new do def self.const_added(name) ScratchPad << const_get(name).name end - module self::A - def self.const_added(name) - ScratchPad << const_get(name).name - end - - module self::B - end end end - - ScratchPad.recorded.should.one?(/#<Module.+>::A$/) - ScratchPad.recorded.should.one?(/#<Module.+>::A::B$/) end end it "returns a frozen String" do @@ -455,32 +455,16 @@ describe "Module#prepend" do ModuleSpecs::SubclassSpec.send(:remove_const, :AClass) end - ruby_version_is ""..."3.2" do - it "raises ArgumentError when the argument is a refinement" do - refinement = nil - Module.new do - refine String do - refinement = self - end end - - -> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(ArgumentError, "refinement module is not allowed") end - end - - ruby_version_is "3.2" do - it "raises a TypeError when the argument is a refinement" do - refinement = nil - Module.new do - refine String do - refinement = self - end - end - - -> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(TypeError, "Cannot prepend refinement") - end end it "imports constants" do @@ -243,32 +243,6 @@ describe "Module#refine" do result.should == "foo from singleton class" end - ruby_version_is ""..."3.2" do - it "looks in the included modules for builtin methods" do - result = ruby_exe(<<-RUBY) - a = Module.new do - def /(other) quo(other) end - end - - refinement = Module.new do - refine Integer do - include a - end - end - - result = nil - Module.new do - using refinement - result = 1 / 2 - end - - print result.class - RUBY - - result.should == 'Rational' - end - end - it "looks in later included modules of the refined module first" do a = Module.new do def foo @@ -1,45 +1,43 @@ require_relative '../../spec_helper' describe "Module#refinements" do - ruby_version_is "3.2" do - it "returns refinements defined in a module" do - ScratchPad.record [] - - m = Module.new do - refine String do - ScratchPad << self - end - - refine Array do - ScratchPad << self - end end - m.refinements.sort_by(&:object_id).should == ScratchPad.recorded.sort_by(&:object_id) end - it "does not return refinements defined in the included module" do - ScratchPad.record [] - m1 = Module.new do - refine Integer do - nil - end end - m2 = Module.new do - include m1 - refine String do - ScratchPad << self - end end - - m2.refinements.should == ScratchPad.recorded end - it "returns an empty array if no refinements defined in a module" do - Module.new.refinements.should == [] - end end end @@ -76,122 +76,60 @@ describe "Module#ruby2_keywords" do Hash.ruby2_keywords_hash?(marked).should == true end - ruby_version_is "3.2" do - it "makes a copy and unmark the Hash when calling a method taking (*args)" do - obj = Object.new - obj.singleton_class.class_exec do - def splat(*args) - args.last - end - - def splat1(arg, *args) - args.last - end - def proc_call(*args) - -> *a { a.last }.call(*args) - end end - h = { a: 1 } - args = mark(**h) - marked = args.last - Hash.ruby2_keywords_hash?(marked).should == true - - after_usage = obj.splat(*args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should_not.equal?(marked) - Hash.ruby2_keywords_hash?(after_usage).should == false - Hash.ruby2_keywords_hash?(marked).should == true - - args = mark(1, **h) - marked = args.last - after_usage = obj.splat1(*args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should_not.equal?(marked) - Hash.ruby2_keywords_hash?(after_usage).should == false - Hash.ruby2_keywords_hash?(marked).should == true - - args = mark(**h) - marked = args.last - after_usage = obj.proc_call(*args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should_not.equal?(marked) - Hash.ruby2_keywords_hash?(after_usage).should == false - Hash.ruby2_keywords_hash?(marked).should == true - - args = mark(**h) - marked = args.last - after_usage = obj.send(:splat, *args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should_not.equal?(marked) - Hash.ruby2_keywords_hash?(after_usage).should == false - Hash.ruby2_keywords_hash?(marked).should == true end - end - ruby_version_is ""..."3.2" do - # https://bugs.ruby-lang.org/issues/18625 - it "does NOT copy the Hash when calling a method taking (*args)" do - obj = Object.new - obj.singleton_class.class_exec do - def splat(*args) - args.last - end - def splat1(arg, *args) - args.last - end - def proc_call(*args) - -> *a { a.last }.call(*args) - end - end - h = { a: 1 } - args = mark(**h) - marked = args.last - Hash.ruby2_keywords_hash?(marked).should == true - - after_usage = obj.splat(*args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625 - Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625 - Hash.ruby2_keywords_hash?(marked).should == true - - args = mark(1, **h) - marked = args.last - after_usage = obj.splat1(*args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625 - Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625 - Hash.ruby2_keywords_hash?(marked).should == true - - args = mark(**h) - marked = args.last - after_usage = obj.proc_call(*args) - after_usage.should == h - after_usage.should_not.equal?(h) - after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625 - Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625 - Hash.ruby2_keywords_hash?(marked).should == true - - args = mark(**h) - marked = args.last - after_usage = obj.send(:splat, *args) - after_usage.should == h - after_usage.should_not.equal?(h) - send_copies = RUBY_ENGINE == "ruby" # inconsistent with Proc#call above for CRuby - after_usage.equal?(marked).should == !send_copies - Hash.ruby2_keywords_hash?(after_usage).should == !send_copies - Hash.ruby2_keywords_hash?(marked).should == true - end end it "applies to the underlying method and applies across aliasing" do @@ -2,25 +2,23 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "Module#undefined_instance_methods" do - ruby_version_is "3.2" do - it "returns methods undefined in the class" do - methods = ModuleSpecs::UndefinedInstanceMethods::Parent.undefined_instance_methods - methods.should == [:undefed_method] - end - it "returns inherited methods undefined in the class" do - methods = ModuleSpecs::UndefinedInstanceMethods::Child.undefined_instance_methods - methods.should include(:parent_method, :another_parent_method) - end - it "returns methods from an included module that are undefined in the class" do - methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods - methods.should include(:super_included_method) - end - it "does not returns ancestors undefined methods" do - methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods - methods.should_not include(:parent_method, :another_parent_method) - end end end @@ -1,87 +1,85 @@ require_relative '../../spec_helper' describe "Module.used_refinements" do - ruby_version_is "3.2" do - it "returns list of all refinements imported in the current scope" do - refinement_int = nil - refinement_str = nil - ScratchPad.record [] - - m1 = Module.new do - refine Integer do - refinement_int = self - end end - m2 = Module.new do - refine String do - refinement_str = self - end end - Module.new do - using m1 - using m2 - Module.used_refinements.each { |r| ScratchPad << r } - end - - ScratchPad.recorded.sort_by(&:object_id).should == [refinement_int, refinement_str].sort_by(&:object_id) end - it "returns empty array if does not have any refinements imported" do - used_refinements = nil - Module.new do - used_refinements = Module.used_refinements - end - used_refinements.should == [] end - it "ignores refinements imported in a module that is included into the current one" do - used_refinements = nil - m1 = Module.new do - refine Integer do - nil - end - end - m2 = Module.new do - using m1 end - Module.new do - include m2 - used_refinements = Module.used_refinements - end - used_refinements.should == [] end - it "returns refinements even not defined directly in a module refinements are imported from" do - used_refinements = nil - ScratchPad.record [] - m1 = Module.new do - refine Integer do - ScratchPad << self - end - end - m2 = Module.new do - include m1 end - Module.new do - using m2 - used_refinements = Module.used_refinements - end - used_refinements.should == ScratchPad.recorded end end end @@ -20,29 +20,27 @@ describe "Proc#parameters" do proc {|x| }.parameters.first.first.should == :opt end - ruby_version_is "3.2" do - it "sets the first element of each sub-Array to :req for required argument if lambda keyword used" do - proc {|x| }.parameters(lambda: true).first.first.should == :req - proc {|y,*x| }.parameters(lambda: true).first.first.should == :req - end - it "regards named parameters in procs as required if lambda keyword used" do - proc {|x| }.parameters(lambda: true).first.first.should == :req - end - it "regards named parameters in lambda as optional if lambda: false keyword used" do - -> x { }.parameters(lambda: false).first.first.should == :opt - end - it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do - proc {|x| }.parameters(lambda: 123).first.first.should == :req - -> x { }.parameters(lambda: 123).first.first.should == :req - end - it "ignores the lambda keyword if it is nil" do - proc {|x|}.parameters(lambda: nil).first.first.should == :opt - -> x { }.parameters(lambda: nil).first.first.should == :req - end end it "regards optional keyword parameters in procs as optional" do @@ -110,24 +108,12 @@ describe "Proc#parameters" do -> x { }.parameters.should == [[:req, :x]] end - ruby_version_is '3.2' do - it "adds rest arg with name * for \"star\" argument" do - -> * {}.parameters.should == [[:rest, :*]] - end - - it "adds keyrest arg with ** as a name for \"double star\" argument" do - -> ** {}.parameters.should == [[:keyrest, :**]] - end end - ruby_version_is ''...'3.2' do - it "adds nameless rest arg for \"star\" argument" do - -> * {}.parameters.should == [[:rest]] - end - - it "adds nameless keyrest arg for \"double star\" argument" do - -> ** {}.parameters.should == [[:keyrest]] - end end it "adds block arg with name & for anonymous block argument" do @@ -8,12 +8,10 @@ describe :proc_dup, shared: true do a.call.should == b.call end - ruby_version_is "3.2" do - it "returns an instance of subclass" do - cl = Class.new(Proc) - cl.new{}.send(@method).class.should == cl - end end ruby_version_is "3.4" do @@ -5,6 +5,8 @@ describe "Process._fork" do Process.respond_to?(:_fork).should == Process.respond_to?(:fork) end guard_not -> { Process.respond_to?(:fork) } do it "raises a NotImplementedError when called" do -> { Process._fork }.should raise_error(NotImplementedError) @@ -7,7 +7,5 @@ describe "Queue#deq" do end describe "Queue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.deq(timeout: v) } - end end @@ -7,7 +7,5 @@ describe "Queue#pop" do end describe "Queue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.pop(timeout: v) } - end end @@ -7,7 +7,5 @@ describe "Queue#shift" do end describe "Queue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.shift(timeout: v) } - end end @@ -1,35 +1,7 @@ require_relative '../../spec_helper' describe "Random::DEFAULT" do - ruby_version_is ''...'3.2' do - it "returns a random number generator" do - suppress_warning do - Random::DEFAULT.should respond_to(:rand) - end - end - - it "changes seed on reboot" do - seed1 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems') - seed2 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems') - seed1.should != seed2 - end - - it "refers to the Random class" do - suppress_warning do - Random::DEFAULT.should.equal?(Random) - end - end - - it "is deprecated" do - -> { - Random::DEFAULT.should.equal?(Random) - }.should complain(/constant Random::DEFAULT is deprecated/) - end - end - - ruby_version_is '3.2' do - it "is no longer defined" do - Random.should_not.const_defined?(:DEFAULT) - end end end @@ -11,7 +11,7 @@ describe "Range#===" do it_behaves_like :range_cover_and_include, :=== it_behaves_like :range_cover, :=== - ruby_bug "#19533", "3.2"..."3.3" do it "returns true on any value if begin and end are both nil" do (nil..nil).should === 1 end @@ -8,10 +8,8 @@ describe "Range#last" do (1..5).last(3).should == [3, 4, 5] end - ruby_bug '#18994', '2.7'...'3.2' do - it "returns the specified number if elements for single element inclusive range" do - (1..1).last(1).should == [1] - end end it "returns an empty array for an empty Range" do @@ -22,16 +22,7 @@ describe "Range#size" do eval("('z'..)").size.should == nil end - ruby_version_is ""..."3.2" do - it 'returns Float::INFINITY for all beginless ranges' do - (..1).size.should == Float::INFINITY - (...0.5).size.should == Float::INFINITY - (..nil).size.should == Float::INFINITY - (...'o').size.should == Float::INFINITY - end - end - - ruby_version_is "3.2"..."3.4" do it 'returns Float::INFINITY for all beginless ranges if the end is numeric' do (..1).size.should == Float::INFINITY (...0.5).size.should == Float::INFINITY @@ -1,20 +1,18 @@ require_relative '../../spec_helper' describe "Refinement#append_features" do - ruby_version_is "3.2" do - it "is not defined" do - Refinement.should_not have_private_instance_method(:append_features) - end - it "is not called by Module#include" do - c = Class.new - Module.new do - refine c do - called = false - define_method(:append_features){called = true} - proc{c.include(self)}.should raise_error(TypeError) - called.should == false - end end end end @@ -1,22 +1,20 @@ require_relative '../../spec_helper' describe "Refinement#extend_object" do - ruby_version_is "3.2" do - it "is not defined" do - Refinement.should_not have_private_instance_method(:extend_object) - end - it "is not called by Object#extend" do - c = Class.new - Module.new do - refine c do - called = false - define_method(:extend_object) { called = true } - -> { - c.extend(self) - }.should raise_error(TypeError) - called.should == false - end end end end @@ -1,26 +1,12 @@ require_relative '../../spec_helper' describe "Refinement#include" do - ruby_version_is ""..."3.2" do - it "warns about deprecation" do - Module.new do - refine String do - -> { - include Module.new - }.should complain(/warning: Refinement#include is deprecated and will be removed in Ruby 3.2/) - end - end - end - end - - ruby_version_is "3.2" do - it "raises a TypeError" do - Module.new do - refine String do - -> { - include Module.new - }.should raise_error(TypeError, "Refinement#include has been removed") - end end end end @@ -1,20 +1,18 @@ require_relative '../../spec_helper' describe "Refinement#prepend_features" do - ruby_version_is "3.2" do - it "is not defined" do - Refinement.should_not have_private_instance_method(:prepend_features) - end - it "is not called by Module#prepend" do - c = Class.new - Module.new do - refine c do - called = false - define_method(:prepend_features){called = true} - proc{c.prepend(self)}.should raise_error(TypeError) - called.should == false - end end end end @@ -1,26 +1,12 @@ require_relative '../../spec_helper' describe "Refinement#prepend" do - ruby_version_is ""..."3.2" do - it "warns about deprecation" do - Module.new do - refine String do - -> { - prepend Module.new - }.should complain(/warning: Refinement#prepend is deprecated and will be removed in Ruby 3.2/) - end - end - end - end - - ruby_version_is "3.2" do - it "raises a TypeError" do - Module.new do - refine String do - -> { - prepend Module.new - }.should raise_error(TypeError, "Refinement#prepend has been removed") - end end end end @@ -2,7 +2,7 @@ require_relative "../../spec_helper" require_relative 'shared/target' describe "Refinement#refined_class" do - ruby_version_is "3.2"..."3.3" do it_behaves_like :refinement_target, :refined_class end @@ -1,25 +1,23 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "Regexp.linear_time?" do - it "returns true if matching can be done in linear time" do - Regexp.linear_time?(/a/).should == true - Regexp.linear_time?('a').should == true - end - it "return false if matching can't be done in linear time" do - Regexp.linear_time?(/(a)\1/).should == false - Regexp.linear_time?("(a)\\1").should == false - end - it "accepts flags for string argument" do - Regexp.linear_time?('a', Regexp::IGNORECASE).should == true - end - it "warns about flags being ignored for regexp arguments" do - -> { - Regexp.linear_time?(/a/, Regexp::IGNORECASE) - }.should complain(/warning: flags ignored/) - end end end @@ -123,140 +123,67 @@ describe :regexp_new_string, shared: true do (r.options & Regexp::EXTENDED).should_not == 0 end - ruby_version_is ""..."3.2" do - it "does not try to convert the second argument to Integer with #to_int method call" do - ScratchPad.clear - obj = Object.new - def obj.to_int() ScratchPad.record(:called) end Regexp.send(@method, "Hi", obj) - ScratchPad.recorded.should == nil - end - end - - ruby_version_is "3.2" do - it "does not try to convert the second argument to Integer with #to_int method call" do - ScratchPad.clear - obj = Object.new - def obj.to_int() ScratchPad.record(:called) end - - -> { - Regexp.send(@method, "Hi", obj) - }.should complain(/expected true or false as ignorecase/, {verbose: true}) - - ScratchPad.recorded.should == nil - end end - ruby_version_is ""..."3.2" do - it "treats any non-Integer, non-nil, non-false second argument as IGNORECASE" do r = Regexp.send(@method, 'Hi', Object.new) - (r.options & Regexp::IGNORECASE).should_not == 0 - (r.options & Regexp::MULTILINE).should == 0 - not_supported_on :opal do - (r.options & Regexp::EXTENDED).should == 0 - end - end - end - - ruby_version_is "3.2" do - it "warns any non-Integer, non-nil, non-false second argument" do - r = nil - -> { - r = Regexp.send(@method, 'Hi', Object.new) - }.should complain(/expected true or false as ignorecase/, {verbose: true}) - (r.options & Regexp::IGNORECASE).should_not == 0 - (r.options & Regexp::MULTILINE).should == 0 - not_supported_on :opal do - (r.options & Regexp::EXTENDED).should == 0 - end - end - - it "accepts a String of supported flags as the second argument" do - r = Regexp.send(@method, 'Hi', 'i') - (r.options & Regexp::IGNORECASE).should_not == 0 - (r.options & Regexp::MULTILINE).should == 0 - not_supported_on :opal do - (r.options & Regexp::EXTENDED).should == 0 - end - - r = Regexp.send(@method, 'Hi', 'imx') - (r.options & Regexp::IGNORECASE).should_not == 0 - (r.options & Regexp::MULTILINE).should_not == 0 - not_supported_on :opal do - (r.options & Regexp::EXTENDED).should_not == 0 - end - - r = Regexp.send(@method, 'Hi', 'mimi') - (r.options & Regexp::IGNORECASE).should_not == 0 - (r.options & Regexp::MULTILINE).should_not == 0 - not_supported_on :opal do - (r.options & Regexp::EXTENDED).should == 0 - end - - r = Regexp.send(@method, 'Hi', '') - (r.options & Regexp::IGNORECASE).should == 0 - (r.options & Regexp::MULTILINE).should == 0 - not_supported_on :opal do - (r.options & Regexp::EXTENDED).should == 0 - end - end - - it "raises an Argument error if the second argument contains unsupported chars" do - -> { Regexp.send(@method, 'Hi', 'e') }.should raise_error(ArgumentError, "unknown regexp option: e") - -> { Regexp.send(@method, 'Hi', 'n') }.should raise_error(ArgumentError, "unknown regexp option: n") - -> { Regexp.send(@method, 'Hi', 's') }.should raise_error(ArgumentError, "unknown regexp option: s") - -> { Regexp.send(@method, 'Hi', 'u') }.should raise_error(ArgumentError, "unknown regexp option: u") - -> { Regexp.send(@method, 'Hi', 'j') }.should raise_error(ArgumentError, "unknown regexp option: j") - -> { Regexp.send(@method, 'Hi', 'mjx') }.should raise_error(ArgumentError, /unknown regexp option: mjx\b/) end end - ruby_version_is ""..."3.2" do - it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do - -> { - Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII - }.should complain(/encoding option is ignored/) end - it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do - -> { - Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII - }.should complain(/encoding option is ignored/) end - it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do - -> { - Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII - }.should complain(/encoding option is ignored/) end - it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do - Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII - Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII end - it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do - a = "(?:[\x8E\xA1-\xFE])" - str = "\A(?:#{a}|x*)\z" - - Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::BINARY - Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::BINARY - Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::BINARY - Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::BINARY - end end describe "with escaped characters" do @@ -623,11 +550,5 @@ describe :regexp_new_regexp, shared: true do it "sets the encoding to US-ASCII if the Regexp literal has the 'n' option and the source String is ASCII only" do Regexp.send(@method, /Hi/n).encoding.should == Encoding::US_ASCII end - - ruby_version_is ''...'3.2' do - it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do - Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::BINARY - end - end end end @@ -1,35 +1,33 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "Regexp.timeout" do - after :each do - Regexp.timeout = nil - end - it "returns global timeout" do - Regexp.timeout = 3 - Regexp.timeout.should == 3 - end - it "raises Regexp::TimeoutError after global timeout elapsed" do - Regexp.timeout = 0.001 - Regexp.timeout.should == 0.001 - -> { - # A typical ReDoS case - /^(a*)*$/ =~ "a" * 1000000 + "x" - }.should raise_error(Regexp::TimeoutError, "regexp match timeout") - end - it "raises Regexp::TimeoutError after timeout keyword value elapsed" do - Regexp.timeout = 3 # This should be ignored - Regexp.timeout.should == 3 - re = Regexp.new("^a*b?a*$", timeout: 0.001) - -> { - re =~ "a" * 1000000 + "x" - }.should raise_error(Regexp::TimeoutError, "regexp match timeout") - end end end @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' require_relative 'shared/add' describe "Set#add" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' require_relative 'shared/add' describe "Set#<<" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/include' -require 'set' describe "Set#===" do it_behaves_like :set_include, :=== @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/include' -require 'set' describe "Set#===" do it_behaves_like :set_include, :=== @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#classify" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#clear" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' require_relative 'shared/collect' describe "Set#collect!" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#compare_by_identity" do it "compares its members by identity" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#<=>" do it "returns 0 if the sets are equal" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set[]" do it "returns a new Set populated with the passed Objects" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#delete_if" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#delete" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' require_relative 'shared/difference' describe "Set#difference" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' describe "Set#disjoint?" do it "returns false when two Sets have at least one element in common" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#divide" do it "divides self into a set of subsets based on the blocks return values" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#each" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#empty?" do it "returns true if self is empty" do @@ -1,5 +1,4 @@ require_relative '../../../spec_helper' -require 'set' describe "Enumerable#to_set" do it "returns a new Set created from self" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#eql?" do it "returns true when the passed argument is a Set and contains the same elements" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' describe "Set#==" do it "returns true when the passed Object is a Set and self and the Object contain the same elements" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#^" do before :each do @@ -1,4 +1,3 @@ -require 'set' module SetSpecs # This class is used to test the interaction of "Set-like" objects with real Sets @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#flatten_merge" do ruby_version_is ""..."3.5" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0' describe "Set#flatten" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#hash" do it "is static" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/include' -require 'set' describe "Set#include?" do it_behaves_like :set_include, :include? @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#initialize_clone" do # See https://bugs.ruby-lang.org/issues/14266 @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#initialize" do it "is private" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/inspect' -require 'set' describe "Set#inspect" do it_behaves_like :set_inspect, :inspect @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' describe "Set#intersect?" do it "returns true when two Sets have at least one element in common" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/intersection' -require 'set' describe "Set#intersection" do it_behaves_like :set_intersection, :intersection @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#join" do it "returns an empty string if the Set is empty" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#keep_if" do before :each do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/length' -require 'set' describe "Set#length" do it_behaves_like :set_length, :length @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' require_relative 'shared/collect' describe "Set#map!" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/include' -require 'set' describe "Set#member?" do it_behaves_like :set_include, :member? @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#merge" do it "adds the elements of the passed Enumerable to self" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' require_relative 'shared/difference' describe "Set#-" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/union' -require 'set' describe "Set#+" do it_behaves_like :set_union, :+ @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#pretty_print_cycle" do it "passes the 'pretty print' representation of a self-referencing Set to the pretty print writer" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0' describe "Set#proper_subset?" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' describe "Set#proper_superset?" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#reject!" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#replace" do before :each do @@ -0,0 +1,10 @@ @@ -1,5 +1,4 @@ require_relative '../../../spec_helper' -require 'set' describe :set_select_bang, shared: true do before :each do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/length' -require 'set' describe "Set#size" do it_behaves_like :set_length, :size @@ -1,5 +1,4 @@ require_relative '../../../spec_helper' -require 'set' describe "SortedSet" do it "raises error including message that it has been extracted from the set stdlib" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0' describe "Set#subset?" do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#subtract" do before :each do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'fixtures/set_like' -require 'set' describe "Set#superset?" do before :each do @@ -1,5 +1,4 @@ require_relative '../../spec_helper' -require 'set' describe "Set#to_a" do it "returns an array containing elements of self" do @@ -1,6 +1,5 @@ require_relative "../../spec_helper" require_relative 'shared/inspect' -require 'set' describe "Set#to_s" do it_behaves_like :set_inspect, :to_s @@ -1,6 +1,5 @@ require_relative '../../spec_helper' require_relative 'shared/union' -require 'set' describe "Set#union" do it_behaves_like :set_union, :union @@ -12,7 +12,5 @@ describe "SizedQueue#<<" do end describe "SizedQueue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.send(:<<, 1, timeout: v) } - end end @@ -7,7 +7,5 @@ describe "SizedQueue#deq" do end describe "SizedQueue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.deq(timeout: v) } - end end @@ -12,7 +12,5 @@ describe "SizedQueue#enq" do end describe "SizedQueue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.enq(1, timeout: v) } - end end @@ -7,7 +7,5 @@ describe "SizedQueue#pop" do end describe "SizedQueue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.pop(timeout: v) } - end end @@ -12,7 +12,5 @@ describe "SizedQueue#push" do end describe "SizedQueue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.push(1, timeout: v) } - end end @@ -7,7 +7,5 @@ describe "SizedQueue#shift" do end describe "SizedQueue operations with timeout" do - ruby_version_is "3.2" do - it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.shift(timeout: v) } - end end @@ -4,301 +4,295 @@ require_relative 'fixtures/classes' require_relative 'shared/byte_index_common.rb' describe "String#byteindex" do - ruby_version_is "3.2" do - it "calls #to_str to convert the first argument" do - char = mock("string index char") - char.should_receive(:to_str).and_return("b") - "abc".byteindex(char).should == 1 - end - - it "calls #to_int to convert the second argument" do - offset = mock("string index offset") - offset.should_receive(:to_int).and_return(1) - "abc".byteindex("c", offset).should == 2 - end - it "does not raise IndexError when byte offset is correct or on string boundary" do - "わ".byteindex("").should == 0 - "わ".byteindex("", 0).should == 0 - "わ".byteindex("", 3).should == 3 - end - it_behaves_like :byte_index_common, :byteindex end end describe "String#byteindex with String" do - ruby_version_is "3.2" do - it "behaves the same as String#byteindex(char) for one-character strings" do - "blablabla hello cruel world...!".split("").uniq.each do |str| - chr = str[0] - str.byteindex(str).should == str.byteindex(chr) - 0.upto(str.size + 1) do |start| - str.byteindex(str, start).should == str.byteindex(chr, start) - end - (-str.size - 1).upto(-1) do |start| - str.byteindex(str, start).should == str.byteindex(chr, start) - end end end - it "returns the byteindex of the first occurrence of the given substring" do - "blablabla".byteindex("").should == 0 - "blablabla".byteindex("b").should == 0 - "blablabla".byteindex("bla").should == 0 - "blablabla".byteindex("blabla").should == 0 - "blablabla".byteindex("blablabla").should == 0 - - "blablabla".byteindex("l").should == 1 - "blablabla".byteindex("la").should == 1 - "blablabla".byteindex("labla").should == 1 - "blablabla".byteindex("lablabla").should == 1 - - "blablabla".byteindex("a").should == 2 - "blablabla".byteindex("abla").should == 2 - "blablabla".byteindex("ablabla").should == 2 - end - it "treats the offset as a byteindex" do - "aaaaa".byteindex("a", 0).should == 0 - "aaaaa".byteindex("a", 2).should == 2 - "aaaaa".byteindex("a", 4).should == 4 - end - it "ignores string subclasses" do - "blablabla".byteindex(StringSpecs::MyString.new("bla")).should == 0 - StringSpecs::MyString.new("blablabla").byteindex("bla").should == 0 - StringSpecs::MyString.new("blablabla").byteindex(StringSpecs::MyString.new("bla")).should == 0 - end - it "starts the search at the given offset" do - "blablabla".byteindex("bl", 0).should == 0 - "blablabla".byteindex("bl", 1).should == 3 - "blablabla".byteindex("bl", 2).should == 3 - "blablabla".byteindex("bl", 3).should == 3 - - "blablabla".byteindex("bla", 0).should == 0 - "blablabla".byteindex("bla", 1).should == 3 - "blablabla".byteindex("bla", 2).should == 3 - "blablabla".byteindex("bla", 3).should == 3 - - "blablabla".byteindex("blab", 0).should == 0 - "blablabla".byteindex("blab", 1).should == 3 - "blablabla".byteindex("blab", 2).should == 3 - "blablabla".byteindex("blab", 3).should == 3 - - "blablabla".byteindex("la", 1).should == 1 - "blablabla".byteindex("la", 2).should == 4 - "blablabla".byteindex("la", 3).should == 4 - "blablabla".byteindex("la", 4).should == 4 - - "blablabla".byteindex("lab", 1).should == 1 - "blablabla".byteindex("lab", 2).should == 4 - "blablabla".byteindex("lab", 3).should == 4 - "blablabla".byteindex("lab", 4).should == 4 - - "blablabla".byteindex("ab", 2).should == 2 - "blablabla".byteindex("ab", 3).should == 5 - "blablabla".byteindex("ab", 4).should == 5 - "blablabla".byteindex("ab", 5).should == 5 - - "blablabla".byteindex("", 0).should == 0 - "blablabla".byteindex("", 1).should == 1 - "blablabla".byteindex("", 2).should == 2 - "blablabla".byteindex("", 7).should == 7 - "blablabla".byteindex("", 8).should == 8 - "blablabla".byteindex("", 9).should == 9 - end - it "starts the search at offset + self.length if offset is negative" do - str = "blablabla" - ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle| - (-str.length .. -1).each do |offset| - str.byteindex(needle, offset).should == - str.byteindex(needle, offset + str.length) - end end end - it "returns nil if the substring isn't found" do - "blablabla".byteindex("B").should == nil - "blablabla".byteindex("z").should == nil - "blablabla".byteindex("BLA").should == nil - "blablabla".byteindex("blablablabla").should == nil - "blablabla".byteindex("", 10).should == nil - "hello".byteindex("he", 1).should == nil - "hello".byteindex("he", 2).should == nil - "I’ve got a multibyte character.\n".byteindex("\n\n").should == nil - end - it "returns the character byteindex of a multibyte character" do - "ありがとう".byteindex("が").should == 6 - end - it "returns the character byteindex after offset" do - "われわれ".byteindex("わ", 3).should == 6 - "ありがとうありがとう".byteindex("が", 9).should == 21 - end - it "returns the character byteindex after a partial first match" do - "</</h".byteindex("</h").should == 2 - end - it "raises an Encoding::CompatibilityError if the encodings are incompatible" do - char = "れ".encode Encoding::EUC_JP - -> do - "あれ".byteindex(char) - end.should raise_error(Encoding::CompatibilityError) - end - it "handles a substring in a superset encoding" do - 'abc'.dup.force_encoding(Encoding::US_ASCII).byteindex('é').should == nil - end - it "handles a substring in a subset encoding" do - 'été'.byteindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2 - end end end describe "String#byteindex with Regexp" do - ruby_version_is "3.2" do - it "behaves the same as String#byteindex(string) for escaped string regexps" do - ["blablabla", "hello cruel world...!"].each do |str| - ["", "b", "bla", "lab", "o c", "d."].each do |needle| - regexp = Regexp.new(Regexp.escape(needle)) - str.byteindex(regexp).should == str.byteindex(needle) - - 0.upto(str.size + 1) do |start| - str.byteindex(regexp, start).should == str.byteindex(needle, start) - end - - (-str.size - 1).upto(-1) do |start| - str.byteindex(regexp, start).should == str.byteindex(needle, start) - end end end end - it "returns the byteindex of the first match of regexp" do - "blablabla".byteindex(/bla/).should == 0 - "blablabla".byteindex(/BLA/i).should == 0 - "blablabla".byteindex(/.{0}/).should == 0 - "blablabla".byteindex(/.{6}/).should == 0 - "blablabla".byteindex(/.{9}/).should == 0 - "blablabla".byteindex(/.*/).should == 0 - "blablabla".byteindex(/.+/).should == 0 - "blablabla".byteindex(/lab|b/).should == 0 - not_supported_on :opal do - "blablabla".byteindex(/\A/).should == 0 - "blablabla".byteindex(/\Z/).should == 9 - "blablabla".byteindex(/\z/).should == 9 - "blablabla\n".byteindex(/\Z/).should == 9 - "blablabla\n".byteindex(/\z/).should == 10 - end - "blablabla".byteindex(/^/).should == 0 - "\nblablabla".byteindex(/^/).should == 0 - "b\nablabla".byteindex(/$/).should == 1 - "bl\nablabla".byteindex(/$/).should == 2 - "blablabla".byteindex(/.l./).should == 0 - end - it "starts the search at the given offset" do - "blablabla".byteindex(/.{0}/, 5).should == 5 - "blablabla".byteindex(/.{1}/, 5).should == 5 - "blablabla".byteindex(/.{2}/, 5).should == 5 - "blablabla".byteindex(/.{3}/, 5).should == 5 - "blablabla".byteindex(/.{4}/, 5).should == 5 - - "blablabla".byteindex(/.{0}/, 3).should == 3 - "blablabla".byteindex(/.{1}/, 3).should == 3 - "blablabla".byteindex(/.{2}/, 3).should == 3 - "blablabla".byteindex(/.{5}/, 3).should == 3 - "blablabla".byteindex(/.{6}/, 3).should == 3 - - "blablabla".byteindex(/.l./, 0).should == 0 - "blablabla".byteindex(/.l./, 1).should == 3 - "blablabla".byteindex(/.l./, 2).should == 3 - "blablabla".byteindex(/.l./, 3).should == 3 - - "xblaxbla".byteindex(/x./, 0).should == 0 - "xblaxbla".byteindex(/x./, 1).should == 4 - "xblaxbla".byteindex(/x./, 2).should == 4 - - not_supported_on :opal do - "blablabla\n".byteindex(/\Z/, 9).should == 9 - end end - it "starts the search at offset + self.length if offset is negative" do - str = "blablabla" - ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle| - (-str.length .. -1).each do |offset| - str.byteindex(needle, offset).should == - str.byteindex(needle, offset + str.length) - end end end - it "returns nil if the substring isn't found" do - "blablabla".byteindex(/BLA/).should == nil - "blablabla".byteindex(/.{10}/).should == nil - "blaxbla".byteindex(/.x/, 3).should == nil - "blaxbla".byteindex(/..x/, 2).should == nil - end - it "returns nil if the Regexp matches the empty string and the offset is out of range" do - "ruby".byteindex(//, 12).should be_nil - end - it "supports \\G which matches at the given start offset" do - "helloYOU.".byteindex(/\GYOU/, 5).should == 5 - "helloYOU.".byteindex(/\GYOU/).should == nil - re = /\G.+YOU/ - # The # marks where \G will match. - [ - ["#hi!YOUall.", 0], - ["h#i!YOUall.", 1], - ["hi#!YOUall.", 2], - ["hi!#YOUall.", nil] - ].each do |spec| - start = spec[0].byteindex("#") - str = spec[0].delete("#") - str.byteindex(re, start).should == spec[1] - end end - it "converts start_offset to an integer via to_int" do - obj = mock('1') - obj.should_receive(:to_int).and_return(1) - "RWOARW".byteindex(/R./, obj).should == 4 - end - it "returns the character byteindex of a multibyte character" do - "ありがとう".byteindex(/が/).should == 6 - end - it "returns the character byteindex after offset" do - "われわれ".byteindex(/わ/, 3).should == 6 - end - it "treats the offset as a byteindex" do - "われわわれ".byteindex(/わ/, 6).should == 6 - end end end @@ -4,356 +4,350 @@ require_relative 'fixtures/classes' require_relative 'shared/byte_index_common.rb' describe "String#byterindex with object" do - ruby_version_is "3.2" do - it "tries to convert obj to a string via to_str" do - obj = mock('lo') - def obj.to_str() "lo" end - "hello".byterindex(obj).should == "hello".byterindex("lo") - - obj = mock('o') - def obj.respond_to?(arg, *) true end - def obj.method_missing(*args) "o" end - "hello".byterindex(obj).should == "hello".byterindex("o") - end - - it "calls #to_int to convert the second argument" do - offset = mock("string index offset") - offset.should_receive(:to_int).and_return(3) - "abc".byterindex("c", offset).should == 2 - end - it "does not raise IndexError when byte offset is correct or on string boundary" do - "わ".byterindex("", 0).should == 0 - "わ".byterindex("", 3).should == 3 - "わ".byterindex("").should == 3 - end - it_behaves_like :byte_index_common, :byterindex end end describe "String#byterindex with String" do - ruby_version_is "3.2" do - it "behaves the same as String#byterindex(char) for one-character strings" do - "blablabla hello cruel world...!".split("").uniq.each do |str| - chr = str[0] - str.byterindex(str).should == str.byterindex(chr) - 0.upto(str.size + 1) do |start| - str.byterindex(str, start).should == str.byterindex(chr, start) - end - (-str.size - 1).upto(-1) do |start| - str.byterindex(str, start).should == str.byterindex(chr, start) - end end end - it "behaves the same as String#byterindex(?char) for one-character strings" do - "blablabla hello cruel world...!".split("").uniq.each do |str| - chr = str[0] =~ / / ? str[0] : eval("?#{str[0]}") - str.byterindex(str).should == str.byterindex(chr) - 0.upto(str.size + 1) do |start| - str.byterindex(str, start).should == str.byterindex(chr, start) - end - (-str.size - 1).upto(-1) do |start| - str.byterindex(str, start).should == str.byterindex(chr, start) - end end end - it "returns the index of the last occurrence of the given substring" do - "blablabla".byterindex("").should == 9 - "blablabla".byterindex("a").should == 8 - "blablabla".byterindex("la").should == 7 - "blablabla".byterindex("bla").should == 6 - "blablabla".byterindex("abla").should == 5 - "blablabla".byterindex("labla").should == 4 - "blablabla".byterindex("blabla").should == 3 - "blablabla".byterindex("ablabla").should == 2 - "blablabla".byterindex("lablabla").should == 1 - "blablabla".byterindex("blablabla").should == 0 - - "blablabla".byterindex("l").should == 7 - "blablabla".byterindex("bl").should == 6 - "blablabla".byterindex("abl").should == 5 - "blablabla".byterindex("labl").should == 4 - "blablabla".byterindex("blabl").should == 3 - "blablabla".byterindex("ablabl").should == 2 - "blablabla".byterindex("lablabl").should == 1 - "blablabla".byterindex("blablabl").should == 0 - - "blablabla".byterindex("b").should == 6 - "blablabla".byterindex("ab").should == 5 - "blablabla".byterindex("lab").should == 4 - "blablabla".byterindex("blab").should == 3 - "blablabla".byterindex("ablab").should == 2 - "blablabla".byterindex("lablab").should == 1 - "blablabla".byterindex("blablab").should == 0 - end - it "ignores string subclasses" do - "blablabla".byterindex(StringSpecs::MyString.new("bla")).should == 6 - StringSpecs::MyString.new("blablabla").byterindex("bla").should == 6 - StringSpecs::MyString.new("blablabla").byterindex(StringSpecs::MyString.new("bla")).should == 6 - end - it "starts the search at the given offset" do - "blablabla".byterindex("bl", 0).should == 0 - "blablabla".byterindex("bl", 1).should == 0 - "blablabla".byterindex("bl", 2).should == 0 - "blablabla".byterindex("bl", 3).should == 3 - - "blablabla".byterindex("bla", 0).should == 0 - "blablabla".byterindex("bla", 1).should == 0 - "blablabla".byterindex("bla", 2).should == 0 - "blablabla".byterindex("bla", 3).should == 3 - - "blablabla".byterindex("blab", 0).should == 0 - "blablabla".byterindex("blab", 1).should == 0 - "blablabla".byterindex("blab", 2).should == 0 - "blablabla".byterindex("blab", 3).should == 3 - "blablabla".byterindex("blab", 6).should == 3 - "blablablax".byterindex("blab", 6).should == 3 - - "blablabla".byterindex("la", 1).should == 1 - "blablabla".byterindex("la", 2).should == 1 - "blablabla".byterindex("la", 3).should == 1 - "blablabla".byterindex("la", 4).should == 4 - - "blablabla".byterindex("lab", 1).should == 1 - "blablabla".byterindex("lab", 2).should == 1 - "blablabla".byterindex("lab", 3).should == 1 - "blablabla".byterindex("lab", 4).should == 4 - - "blablabla".byterindex("ab", 2).should == 2 - "blablabla".byterindex("ab", 3).should == 2 - "blablabla".byterindex("ab", 4).should == 2 - "blablabla".byterindex("ab", 5).should == 5 - - "blablabla".byterindex("", 0).should == 0 - "blablabla".byterindex("", 1).should == 1 - "blablabla".byterindex("", 2).should == 2 - "blablabla".byterindex("", 7).should == 7 - "blablabla".byterindex("", 8).should == 8 - "blablabla".byterindex("", 9).should == 9 - "blablabla".byterindex("", 10).should == 9 - end - it "starts the search at offset + self.length if offset is negative" do - str = "blablabla" - ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle| - (-str.length .. -1).each do |offset| - str.byterindex(needle, offset).should == - str.byterindex(needle, offset + str.length) - end end end - it "returns nil if the substring isn't found" do - "blablabla".byterindex("B").should == nil - "blablabla".byterindex("z").should == nil - "blablabla".byterindex("BLA").should == nil - "blablabla".byterindex("blablablabla").should == nil - "hello".byterindex("lo", 0).should == nil - "hello".byterindex("lo", 1).should == nil - "hello".byterindex("lo", 2).should == nil - "hello".byterindex("llo", 0).should == nil - "hello".byterindex("llo", 1).should == nil - "hello".byterindex("el", 0).should == nil - "hello".byterindex("ello", 0).should == nil - "hello".byterindex("", -6).should == nil - "hello".byterindex("", -7).should == nil - "hello".byterindex("h", -6).should == nil - end - it "tries to convert start_offset to an integer via to_int" do - obj = mock('5') - def obj.to_int() 5 end - "str".byterindex("st", obj).should == 0 - obj = mock('5') - def obj.respond_to?(arg, *) true end - def obj.method_missing(*args) 5 end - "str".byterindex("st", obj).should == 0 - end - it "raises a TypeError when given offset is nil" do - -> { "str".byterindex("st", nil) }.should raise_error(TypeError) - end - it "handles a substring in a superset encoding" do - 'abc'.dup.force_encoding(Encoding::US_ASCII).byterindex('é').should == nil - end - it "handles a substring in a subset encoding" do - 'été'.byterindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2 - end end end describe "String#byterindex with Regexp" do - ruby_version_is "3.2" do - it "behaves the same as String#byterindex(string) for escaped string regexps" do - ["blablabla", "hello cruel world...!"].each do |str| - ["", "b", "bla", "lab", "o c", "d."].each do |needle| - regexp = Regexp.new(Regexp.escape(needle)) - str.byterindex(regexp).should == str.byterindex(needle) - - 0.upto(str.size + 1) do |start| - str.byterindex(regexp, start).should == str.byterindex(needle, start) - end - - (-str.size - 1).upto(-1) do |start| - str.byterindex(regexp, start).should == str.byterindex(needle, start) - end end end end - it "returns the index of the first match from the end of string of regexp" do - "blablabla".byterindex(/bla/).should == 6 - "blablabla".byterindex(/BLA/i).should == 6 - - "blablabla".byterindex(/.{0}/).should == 9 - "blablabla".byterindex(/.{1}/).should == 8 - "blablabla".byterindex(/.{2}/).should == 7 - "blablabla".byterindex(/.{6}/).should == 3 - "blablabla".byterindex(/.{9}/).should == 0 - "blablabla".byterindex(/.*/).should == 9 - "blablabla".byterindex(/.+/).should == 8 - "blablabla".byterindex(/bla|a/).should == 8 - not_supported_on :opal do - "blablabla".byterindex(/\A/).should == 0 - "blablabla".byterindex(/\Z/).should == 9 - "blablabla".byterindex(/\z/).should == 9 - "blablabla\n".byterindex(/\Z/).should == 10 - "blablabla\n".byterindex(/\z/).should == 10 - end - "blablabla".byterindex(/^/).should == 0 - not_supported_on :opal do - "\nblablabla".byterindex(/^/).should == 1 - "b\nlablabla".byterindex(/^/).should == 2 - end - "blablabla".byterindex(/$/).should == 9 - - "blablabla".byterindex(/.l./).should == 6 end - it "starts the search at the given offset" do - "blablabla".byterindex(/.{0}/, 5).should == 5 - "blablabla".byterindex(/.{1}/, 5).should == 5 - "blablabla".byterindex(/.{2}/, 5).should == 5 - "blablabla".byterindex(/.{3}/, 5).should == 5 - "blablabla".byterindex(/.{4}/, 5).should == 5 - - "blablabla".byterindex(/.{0}/, 3).should == 3 - "blablabla".byterindex(/.{1}/, 3).should == 3 - "blablabla".byterindex(/.{2}/, 3).should == 3 - "blablabla".byterindex(/.{5}/, 3).should == 3 - "blablabla".byterindex(/.{6}/, 3).should == 3 - - "blablabla".byterindex(/.l./, 0).should == 0 - "blablabla".byterindex(/.l./, 1).should == 0 - "blablabla".byterindex(/.l./, 2).should == 0 - "blablabla".byterindex(/.l./, 3).should == 3 - - "blablablax".byterindex(/.x/, 10).should == 8 - "blablablax".byterindex(/.x/, 9).should == 8 - "blablablax".byterindex(/.x/, 8).should == 8 - - "blablablax".byterindex(/..x/, 10).should == 7 - "blablablax".byterindex(/..x/, 9).should == 7 - "blablablax".byterindex(/..x/, 8).should == 7 - "blablablax".byterindex(/..x/, 7).should == 7 - - not_supported_on :opal do - "blablabla\n".byterindex(/\Z/, 9).should == 9 - end end - it "starts the search at offset + self.length if offset is negative" do - str = "blablabla" - ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle| - (-str.length .. -1).each do |offset| - str.byterindex(needle, offset).should == - str.byterindex(needle, offset + str.length) - end - end end - it "returns nil if the substring isn't found" do - "blablabla".byterindex(/BLA/).should == nil - "blablabla".byterindex(/.{10}/).should == nil - "blablablax".byterindex(/.x/, 7).should == nil - "blablablax".byterindex(/..x/, 6).should == nil - not_supported_on :opal do - "blablabla".byterindex(/\Z/, 5).should == nil - "blablabla".byterindex(/\z/, 5).should == nil - "blablabla\n".byterindex(/\z/, 9).should == nil end end not_supported_on :opal do - it "supports \\G which matches at the given start offset" do - "helloYOU.".byterindex(/YOU\G/, 8).should == 5 - "helloYOU.".byterindex(/YOU\G/).should == nil - - idx = "helloYOUall!".index("YOU") - re = /YOU.+\G.+/ - # The # marks where \G will match. - [ - ["helloYOU#all.", nil], - ["helloYOUa#ll.", idx], - ["helloYOUal#l.", idx], - ["helloYOUall#.", idx], - ["helloYOUall.#", nil] - ].each do |i| - start = i[0].index("#") - str = i[0].delete("#") - - str.byterindex(re, start).should == i[1] - end end end - it "tries to convert start_offset to an integer" do - obj = mock('5') - def obj.to_int() 5 end - "str".byterindex(/../, obj).should == 1 - obj = mock('5') - def obj.respond_to?(arg, *) true end - def obj.method_missing(*args); 5; end - "str".byterindex(/../, obj).should == 1 - end - it "raises a TypeError when given offset is nil" do - -> { "str".byterindex(/../, nil) }.should raise_error(TypeError) - end - it "returns the reverse byte index of a multibyte character" do - "ありがりがとう".byterindex("が").should == 12 - "ありがりがとう".byterindex(/が/).should == 12 - end - it "returns the character index before the finish" do - "ありがりがとう".byterindex("が", 9).should == 6 - "ありがりがとう".byterindex(/が/, 9).should == 6 - end end end @@ -3,60 +3,58 @@ require_relative '../../spec_helper' describe "String#bytesplice" do - ruby_version_is "3.2" do - it "raises IndexError when index is less than -bytesize" do - -> { "hello".bytesplice(-6, 0, "xxx") }.should raise_error(IndexError, "index -6 out of string") - end - it "raises IndexError when index is greater than bytesize" do - -> { "hello".bytesplice(6, 0, "xxx") }.should raise_error(IndexError, "index 6 out of string") - end - it "raises IndexError for negative length" do - -> { "abc".bytesplice(0, -2, "") }.should raise_error(IndexError, "negative length -2") - end - it "replaces with integer indices" do - "hello".bytesplice(-5, 0, "xxx").should == "xxxhello" - "hello".bytesplice(0, 0, "xxx").should == "xxxhello" - "hello".bytesplice(0, 1, "xxx").should == "xxxello" - "hello".bytesplice(0, 5, "xxx").should == "xxx" - "hello".bytesplice(0, 6, "xxx").should == "xxx" - end - it "raises RangeError when range left boundary is less than -bytesize" do - -> { "hello".bytesplice(-6...-6, "xxx") }.should raise_error(RangeError, "-6...-6 out of range") - end - it "replaces with ranges" do - "hello".bytesplice(-5...-5, "xxx").should == "xxxhello" - "hello".bytesplice(0...0, "xxx").should == "xxxhello" - "hello".bytesplice(0..0, "xxx").should == "xxxello" - "hello".bytesplice(0...1, "xxx").should == "xxxello" - "hello".bytesplice(0..1, "xxx").should == "xxxllo" - "hello".bytesplice(0..-1, "xxx").should == "xxx" - "hello".bytesplice(0...5, "xxx").should == "xxx" - "hello".bytesplice(0...6, "xxx").should == "xxx" - end - it "raises TypeError when integer index is provided without length argument" do - -> { "hello".bytesplice(0, "xxx") }.should raise_error(TypeError, "wrong argument type Integer (expected Range)") - end - it "replaces on an empty string" do - "".bytesplice(0, 0, "").should == "" - "".bytesplice(0, 0, "xxx").should == "xxx" - end - it "mutates self" do - s = "hello" - s.bytesplice(2, 1, "xxx").should.equal?(s) - end - it "raises when string is frozen" do - s = "hello".freeze - -> { s.bytesplice(2, 1, "xxx") }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"") - end end ruby_version_is "3.3" do @@ -134,75 +132,73 @@ describe "String#bytesplice" do end describe "String#bytesplice with multibyte characters" do - ruby_version_is "3.2" do - it "raises IndexError when index is out of byte size boundary" do - -> { "こんにちは".bytesplice(-16, 0, "xxx") }.should raise_error(IndexError, "index -16 out of string") - end - it "raises IndexError when index is not on a codepoint boundary" do - -> { "こんにちは".bytesplice(1, 0, "xxx") }.should raise_error(IndexError, "offset 1 does not land on character boundary") - end - it "raises IndexError when length is not matching the codepoint boundary" do - -> { "こんにちは".bytesplice(0, 1, "xxx") }.should raise_error(IndexError, "offset 1 does not land on character boundary") - -> { "こんにちは".bytesplice(0, 2, "xxx") }.should raise_error(IndexError, "offset 2 does not land on character boundary") - end - it "replaces with integer indices" do - "こんにちは".bytesplice(-15, 0, "xxx").should == "xxxこんにちは" - "こんにちは".bytesplice(0, 0, "xxx").should == "xxxこんにちは" - "こんにちは".bytesplice(0, 3, "xxx").should == "xxxんにちは" - "こんにちは".bytesplice(3, 3, "はは").should == "こははにちは" - "こんにちは".bytesplice(15, 0, "xxx").should == "こんにちはxxx" - end - it "replaces with range" do - "こんにちは".bytesplice(-15...-16, "xxx").should == "xxxこんにちは" - "こんにちは".bytesplice(0...0, "xxx").should == "xxxこんにちは" - "こんにちは".bytesplice(0..2, "xxx").should == "xxxんにちは" - "こんにちは".bytesplice(0...3, "xxx").should == "xxxんにちは" - "こんにちは".bytesplice(0..5, "xxx").should == "xxxにちは" - "こんにちは".bytesplice(0..-1, "xxx").should == "xxx" - "こんにちは".bytesplice(0...15, "xxx").should == "xxx" - "こんにちは".bytesplice(0...18, "xxx").should == "xxx" - end - it "treats negative length for range as 0" do - "こんにちは".bytesplice(0...-100, "xxx").should == "xxxこんにちは" - "こんにちは".bytesplice(3...-100, "xxx").should == "こxxxんにちは" - "こんにちは".bytesplice(-15...-100, "xxx").should == "xxxこんにちは" - end - it "raises when ranges not match codepoint boundaries" do - -> { "こんにちは".bytesplice(0..0, "x") }.should raise_error(IndexError, "offset 1 does not land on character boundary") - -> { "こんにちは".bytesplice(0..1, "x") }.should raise_error(IndexError, "offset 2 does not land on character boundary") - # Begin is incorrect - -> { "こんにちは".bytesplice(-4..-1, "x") }.should raise_error(IndexError, "offset 11 does not land on character boundary") - -> { "こんにちは".bytesplice(-5..-1, "x") }.should raise_error(IndexError, "offset 10 does not land on character boundary") - # End is incorrect - -> { "こんにちは".bytesplice(-3..-2, "x") }.should raise_error(IndexError, "offset 14 does not land on character boundary") - -> { "こんにちは".bytesplice(-3..-3, "x") }.should raise_error(IndexError, "offset 13 does not land on character boundary") - end - it "deals with a different encoded argument" do - s = "こんにちは" - s.encoding.should == Encoding::UTF_8 - sub = "xxxxxx" - sub.force_encoding(Encoding::US_ASCII) - result = s.bytesplice(0, 3, sub) - result.should == "xxxxxxんにちは" - result.encoding.should == Encoding::UTF_8 - s = "xxxxxx" - s.force_encoding(Encoding::US_ASCII) - sub = "こんにちは" - sub.encoding.should == Encoding::UTF_8 - result = s.bytesplice(0, 3, sub) - result.should == "こんにちはxxx" - result.encoding.should == Encoding::UTF_8 - end end ruby_version_is "3.3" do @@ -2,7 +2,5 @@ require_relative '../../spec_helper' require_relative 'shared/dedup' describe 'String#dedup' do - ruby_version_is '3.2' do - it_behaves_like :string_dedup, :dedup - end end @@ -391,16 +391,8 @@ describe "String#%" do ("%c" % 'A').should == "A" end - ruby_version_is ""..."3.2" do - it "raises an exception for multiple character strings as argument for %c" do - -> { "%c" % 'AA' }.should raise_error(ArgumentError) - end - end - - ruby_version_is "3.2" do - it "supports only the first character as argument for %c" do - ("%c" % 'AA').should == "A" - end end it "calls to_str on argument for %c formats" do @@ -68,27 +68,13 @@ describe "String#rstrip!" do -> { "".freeze.rstrip! }.should raise_error(FrozenError) end - ruby_version_is "3.2" do - it "raises an Encoding::CompatibilityError if the last non-space codepoint is invalid" do - s = "abc\xDF".force_encoding(Encoding::UTF_8) - s.valid_encoding?.should be_false - -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError) - s = "abc\xDF ".force_encoding(Encoding::UTF_8) - s.valid_encoding?.should be_false - -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError) - end - end - - ruby_version_is ""..."3.2" do - it "raises an ArgumentError if the last non-space codepoint is invalid" do - s = "abc\xDF".force_encoding(Encoding::UTF_8) - s.valid_encoding?.should be_false - -> { s.rstrip! }.should raise_error(ArgumentError) - - s = "abc\xDF ".force_encoding(Encoding::UTF_8) - s.valid_encoding?.should be_false - -> { s.rstrip! }.should raise_error(ArgumentError) - end end end @@ -13,9 +13,7 @@ describe "String#to_c" do it "ignores trailing garbage" do '79+4iruby'.to_c.should == Complex(79, 4) - ruby_bug "[Bug #19087]", ""..."3.2" do - '7__9+4__0i'.to_c.should == Complex(7, 0) - end end context "it treats special float value strings as characters" do @@ -43,15 +41,13 @@ describe "String#to_c" do }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16") end - ruby_version_is "3.2" do - it "treats a sequence of underscores as an end of Complex string" do - "5+3_1i".to_c.should == Complex(5, 31) - "5+3__1i".to_c.should == Complex(5) - "5+3___1i".to_c.should == Complex(5) - "12_3".to_c.should == Complex(123) - "12__3".to_c.should == Complex(12) - "12___3".to_c.should == Complex(12) - end end end @@ -120,11 +120,9 @@ describe "String#to_f" do "\3771.2".b.to_f.should == 0 end - ruby_version_is "3.2" do - it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do - -> { - '1.2'.encode("UTF-16").to_f - }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16") - end end end @@ -26,7 +26,7 @@ describe "String#unpack" do "a".unpack("C", offset: 1).should == [nil] end - it "raises an ArgumentError when the offset is larget than the string" do -> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string") end end @@ -1,15 +1,13 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "Struct::Group" do - it "is no longer defined" do - Struct.should_not.const_defined?(:Group) - end end - describe "Struct::Passwd" do - it "is no longer defined" do - Struct.should_not.const_defined?(:Passwd) - end end end @@ -80,7 +80,7 @@ describe "Struct#deconstruct_keys" do obj.deconstruct_keys(nil).should == {x: 1, y: 2} end - it "raises TypeError if index is not a String, a Symbol and not convertible to Integer " do struct = Struct.new(:x, :y) s = struct.new(1, 2) @@ -41,21 +41,11 @@ describe "Struct#initialize" do StructClasses::SubclassX.new(:y).new.key.should == :value end - ruby_version_is ""..."3.2" do - it "warns about passing only keyword arguments" do - -> { - StructClasses::Ruby.new(version: "3.1", platform: "OS") - }.should complain(/warning: Passing only keyword arguments/) - end - end - ruby_version_is "3.2" do - it "can be initialized with keyword arguments" do - positional_args = StructClasses::Ruby.new("3.2", "OS") - keyword_args = StructClasses::Ruby.new(version: "3.2", platform: "OS") - - positional_args.version.should == keyword_args.version - positional_args.platform.should == keyword_args.platform - end end end @@ -73,20 +73,8 @@ describe "Struct.new" do -> { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError) end - ruby_version_is ""..."3.2" do - it "raises a TypeError or ArgumentError if passed a Hash with an unknown key" do - # CRuby < 3.2 raises ArgumentError: unknown keyword: :name, but that seems a bug: - # https://bugs.ruby-lang.org/issues/18632 - -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(StandardError) { |e| - [ArgumentError, TypeError].should.include?(e.class) - } - end - end - - ruby_version_is "3.2" do - it "raises a TypeError if passed a Hash with an unknown key" do - -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError) - end end ruby_version_is ""..."3.3" do @@ -166,17 +154,15 @@ describe "Struct.new" do -> { StructClasses::Ruby.new('2.0', 'i686', true) }.should raise_error(ArgumentError) end - ruby_version_is '3.2' do - it "accepts keyword arguments to initialize" do - type = Struct.new(:args) - obj = type.new(args: 42) - obj2 = type.new(42) - obj.should == obj2 - obj.args.should == 42 - obj2.args.should == 42 - end end end @@ -27,31 +27,29 @@ describe "Symbol#to_proc" do pr.parameters.should == [[:req], [:rest]] end - ruby_version_is "3.2" do - it "only calls public methods" do - body = proc do - public def pub; @a << :pub end - protected def pro; @a << :pro end - private def pri; @a << :pri end - attr_reader :a - end - @a = [] - singleton_class.class_eval(&body) - tap(&:pub) - proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/) - proc{tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/) - @a.should == [:pub] - @a = [] - c = Class.new(&body) - o = c.new - o.instance_variable_set(:@a, []) - o.tap(&:pub) - proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/) - proc{o.tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/) - o.a.should == [:pub] - end end it "raises an ArgumentError when calling #call on the Proc without receiver" do @@ -1,49 +1,47 @@ require_relative '../../spec_helper' describe "Thread.each_caller_location" do - ruby_version_is "3.2" do - it "iterates through the current execution stack and matches caller_locations content and type" do - ScratchPad.record [] - Thread.each_caller_location { |l| ScratchPad << l; } - ScratchPad.recorded.map(&:to_s).should == caller_locations.map(&:to_s) - ScratchPad.recorded[0].should be_kind_of(Thread::Backtrace::Location) - end - it "returns subset of 'Thread.to_enum(:each_caller_location)' locations" do - ar = [] - ecl = Thread.each_caller_location { |x| ar << x } - (ar.map(&:to_s) - Thread.to_enum(:each_caller_location).to_a.map(&:to_s)).should.empty? - end - it "stops the backtrace iteration if 'break' occurs" do - i = 0 - ar = [] - ecl = Thread.each_caller_location do |x| - ar << x - i += 1 - break x if i == 2 - end - - ar.map(&:to_s).should == caller_locations(1, 2).map(&:to_s) - ecl.should be_kind_of(Thread::Backtrace::Location) end - it "returns nil" do - Thread.each_caller_location {}.should == nil - end - it "raises LocalJumpError when called without a block" do - -> { - Thread.each_caller_location - }.should raise_error(LocalJumpError, "no block given") - end - it "doesn't accept keyword arguments" do - -> { - Thread.each_caller_location(12, foo: 10) {} - }.should raise_error(ArgumentError); - end end end @@ -1,45 +1,43 @@ require_relative '../../spec_helper' -ruby_version_is "3.2" do - describe "Time#deconstruct_keys" do - it "returns whole hash for nil as an argument" do - d = Time.utc(2022, 10, 5, 13, 30) - res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13, - min: 30, sec: 0, subsec: 0, dst: false, zone: "UTC" } - d.deconstruct_keys(nil).should == res - end - - it "returns only specified keys" do - d = Time.utc(2022, 10, 5, 13, 39) - d.deconstruct_keys([:zone, :subsec]).should == { zone: "UTC", subsec: 0 } - end - - it "requires one argument" do - -> { - Time.new(2022, 10, 5, 13, 30).deconstruct_keys - }.should raise_error(ArgumentError) - end - - it "it raises error when argument is neither nil nor array" do - d = Time.new(2022, 10, 5, 13, 30) - - -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)") - -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)") - -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)") - -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)") - end - - it "returns {} when passed []" do - Time.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {} - end - - it "ignores non-Symbol keys" do - Time.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {} - end - - it "ignores not existing Symbol keys and processes keys after the first non-existing one" do - d = Time.utc(2022, 10, 5, 13, 30) - d.deconstruct_keys([:year, :a, :month, :b, :day]).should == { year: 2022, month: 10, day: 5 } - end end end @@ -467,259 +467,253 @@ describe "Time.new with a timezone argument" do end end - ruby_version_is "3.2" do - describe "Time.new with a String argument" do - it "parses an ISO-8601 like format" do - t = Time.utc(2020, 12, 24, 15, 56, 17) - - Time.new("2020-12-24T15:56:17Z").should == t - Time.new("2020-12-25 00:56:17 +09:00").should == t - Time.new("2020-12-25 00:57:47 +09:01:30").should == t - Time.new("2020-12-25 00:56:17 +0900").should == t - Time.new("2020-12-25 00:57:47 +090130").should == t - Time.new("2020-12-25T00:56:17+09:00").should == t - - Time.new("2020-12-25T00:56:17.123456+09:00").should == Time.utc(2020, 12, 24, 15, 56, 17, 123456) - end - it "accepts precision keyword argument and truncates specified digits of sub-second part" do - Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec.should == 0.123456789r - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec.should == 0.123456789876r - Time.new("2021-12-25 00:00:00 +09:00", precision: 0).subsec.should == 0 - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: -1).subsec.should == 0.123456789876r - end - it "returns Time in local timezone if not provided in the String argument" do - Time.new("2021-12-25 00:00:00").zone.should == Time.new(2021, 12, 25).zone - Time.new("2021-12-25 00:00:00").utc_offset.should == Time.new(2021, 12, 25).utc_offset - end - it "returns Time in timezone specified in the String argument" do - Time.new("2021-12-25 00:00:00 +05:00").to_s.should == "2021-12-25 00:00:00 +0500" - end - it "returns Time in timezone specified in the String argument even if the in keyword argument provided" do - Time.new("2021-12-25 00:00:00 +09:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 +0900" - end - it "returns Time in timezone specified with in keyword argument if timezone isn't provided in the String argument" do - Time.new("2021-12-25 00:00:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 -0100" - end - it "returns Time of Jan 1 for string with just year" do - Time.new("2021").should == Time.new(2021, 1, 1) - Time.new("2021").zone.should == Time.new(2021, 1, 1).zone - Time.new("2021").utc_offset.should == Time.new(2021, 1, 1).utc_offset - end - it "returns Time of Jan 1 for string with just year in timezone specified with in keyword argument" do - Time.new("2021", in: "+17:00").to_s.should == "2021-01-01 00:00:00 +1700" - end - it "converts precision keyword argument into Integer if is not nil" do - obj = Object.new - def obj.to_int; 3; end - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 1.2).subsec.should == 0.1r - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: obj).subsec.should == 0.123r - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3r).subsec.should == 0.123r - end - ruby_version_is ""..."3.3" do - it "raise TypeError is can't convert precision keyword argument into Integer" do - -> { - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "") - }.should raise_error(TypeError, "no implicit conversion from string") - end - end - ruby_version_is "3.3" do - it "raise TypeError is can't convert precision keyword argument into Integer" do - -> { - Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "") - }.should raise_error(TypeError, "no implicit conversion of String into Integer") - end - end - it "raises ArgumentError if part of time string is missing" do -> { - Time.new("2020-12-25 00:56 +09:00") - }.should raise_error(ArgumentError, /missing sec part: 00:56 |can't parse:/) -> { - Time.new("2020-12-25 00 +09:00") - }.should raise_error(ArgumentError, /missing min part: 00 |can't parse:/) end - ruby_version_is "3.2.3" do - it "raises ArgumentError if the time part is missing" do - -> { - Time.new("2020-12-25") - }.should raise_error(ArgumentError, /no time information|can't parse:/) - end - - it "raises ArgumentError if day is missing" do - -> { - Time.new("2020-12") - }.should raise_error(ArgumentError, /no time information|can't parse:/) - end - end - it "raises ArgumentError if subsecond is missing after dot" do - -> { - Time.new("2020-12-25 00:56:17. +0900") - }.should raise_error(ArgumentError, /subsecond expected after dot: 00:56:17. |can't parse:/) - end - it "raises ArgumentError if String argument is not in the supported format" do - -> { - Time.new("021-12-25 00:00:00.123456 +09:00") - }.should raise_error(ArgumentError, /year must be 4 or more digits: 021|can't parse:/) - -> { - Time.new("2020-012-25 00:56:17 +0900") - }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z|can't parse:/) - -> { - Time.new("2020-2-25 00:56:17 +0900") - }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z|can't parse:/) - -> { - Time.new("2020-12-215 00:56:17 +0900") - }.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z|can't parse:/) - -> { - Time.new("2020-12-25 000:56:17 +0900") - }.should raise_error(ArgumentError, /two digits hour is expected: 000:56:17 |can't parse:/) - -> { - Time.new("2020-12-25 0:56:17 +0900") - }.should raise_error(ArgumentError, /two digits hour is expected: 0:56:17 \+0|can't parse:/) - -> { - Time.new("2020-12-25 00:516:17 +0900") - }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z|can't parse:/) - -> { - Time.new("2020-12-25 00:6:17 +0900") - }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z|can't parse:/) - -> { - Time.new("2020-12-25 00:56:137 +0900") - }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z|can't parse:/) - -> { - Time.new("2020-12-25 00:56:7 +0900") - }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z|can't parse:/) - -> { - Time.new("2020-12-25 00:56. +0900") - }.should raise_error(ArgumentError, /fraction min is not supported: 00:56\.|can't parse:/) - -> { - Time.new("2020-12-25 00. +0900") - }.should raise_error(ArgumentError, /fraction hour is not supported: 00\.|can't parse:/) - end - it "raises ArgumentError if date/time parts values are not valid" do - -> { - Time.new("2020-13-25 00:56:17 +09:00") - }.should raise_error(ArgumentError, /(mon|argument) out of range/) - -> { - Time.new("2020-12-32 00:56:17 +09:00") - }.should raise_error(ArgumentError, /(mday|argument) out of range/) - -> { - Time.new("2020-12-25 25:56:17 +09:00") - }.should raise_error(ArgumentError, /(hour|argument) out of range/) - -> { - Time.new("2020-12-25 00:61:17 +09:00") - }.should raise_error(ArgumentError, /(min|argument) out of range/) - -> { - Time.new("2020-12-25 00:56:61 +09:00") - }.should raise_error(ArgumentError, /(sec|argument) out of range/) - -> { - Time.new("2020-12-25 00:56:17 +23:59:60") - }.should raise_error(ArgumentError, /utc_offset|argument out of range/) - -> { - Time.new("2020-12-25 00:56:17 +24:00") - }.should raise_error(ArgumentError, /(utc_offset|argument) out of range/) -> { - Time.new("2020-12-25 00:56:17 +23:61") }.should raise_error(ArgumentError, /utc_offset/) - - ruby_bug '#20797', ''...'3.4' do - -> { - Time.new("2020-12-25 00:56:17 +00:23:61") - }.should raise_error(ArgumentError, /utc_offset/) - end end - it "raises ArgumentError if utc offset parts are not valid" do - -> { Time.new("2020-12-25 00:56:17 +24:00") }.should raise_error(ArgumentError, "utc_offset out of range") - -> { Time.new("2020-12-25 00:56:17 +2400") }.should raise_error(ArgumentError, "utc_offset out of range") - - -> { Time.new("2020-12-25 00:56:17 +99:00") }.should raise_error(ArgumentError, "utc_offset out of range") - -> { Time.new("2020-12-25 00:56:17 +9900") }.should raise_error(ArgumentError, "utc_offset out of range") - -> { Time.new("2020-12-25 00:56:17 +00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60') - -> { Time.new("2020-12-25 00:56:17 +0060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060') - -> { Time.new("2020-12-25 00:56:17 +00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99') - -> { Time.new("2020-12-25 00:56:17 +0099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099') - ruby_bug '#20797', ''...'3.4' do - -> { Time.new("2020-12-25 00:56:17 +00:00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60') - -> { Time.new("2020-12-25 00:56:17 +000060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060') - -> { Time.new("2020-12-25 00:56:17 +00:00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99') - -> { Time.new("2020-12-25 00:56:17 +000099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099') - end - end - it "raises ArgumentError if string has not ascii-compatible encoding" do - -> { - Time.new("2021-11-31 00:00:60 +09:00".encode("utf-32le")) - }.should raise_error(ArgumentError, "time string should have ASCII compatible encoding") end - it "raises ArgumentError if string doesn't start with year" do - -> { - Time.new("a\nb") - }.should raise_error(ArgumentError, "can't parse: \"a\\nb\"") - end - it "raises ArgumentError if string has extra characters after offset" do - -> { - Time.new("2021-11-31 00:00:59 +09:00 abc") - }.should raise_error(ArgumentError, /can't parse.+ abc/) - end - ruby_version_is "3.2.3" do - it "raises ArgumentError when there are leading space characters" do - -> { Time.new(" 2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("\t2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("\n2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("\v2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("\f2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("\r2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/) - end - - it "raises ArgumentError when there are trailing whitespaces" do - -> { Time.new("2020-12-02 00:00:00 ") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("2020-12-02 00:00:00\t") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("2020-12-02 00:00:00\n") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("2020-12-02 00:00:00\v") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("2020-12-02 00:00:00\f") }.should raise_error(ArgumentError, /can't parse/) - -> { Time.new("2020-12-02 00:00:00\r") }.should raise_error(ArgumentError, /can't parse/) - end - end end end end @@ -84,99 +84,97 @@ describe "Time.now" do end end - ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/17485 - describe "Timezone object" do - it "raises TypeError if timezone does not implement #utc_to_local method" do zone = Object.new - def zone.local_to_utc(time) - time end - -> { - Time.now(in: zone) - }.should raise_error(TypeError, /can't convert Object into an exact number/) end - it "does not raise exception if timezone does not implement #local_to_utc method" do zone = Object.new - def zone.utc_to_local(time) - time end Time.now(in: zone).should be_kind_of(Time) end - # The result also should be a Time or Time-like object (not necessary to be the same class) - # or Integer. The zone of the result is just ignored. - describe "returned value by #utc_to_local and #local_to_utc methods" do - it "could be Time instance" do - zone = Object.new - def zone.utc_to_local(t) - time = Time.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset) - time + 60 * 60 # + 1 hour - end - - Time.now(in: zone).should be_kind_of(Time) - Time.now(in: zone).utc_offset.should == 3600 end - it "could be Time subclass instance" do - zone = Object.new - def zone.utc_to_local(t) - time = Time.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset) - time += 60 * 60 # + 1 hour - - Class.new(Time).new(time.year, time.mon, time.day, time.hour, time.min, time.sec, time.utc_offset) - end - Time.now(in: zone).should be_kind_of(Time) - Time.now(in: zone).utc_offset.should == 3600 end - it "could be Integer" do - zone = Object.new - def zone.utc_to_local(time) - time.to_i + 60*60 - end - - Time.now(in: zone).should be_kind_of(Time) - Time.now(in: zone).utc_offset.should == 60*60 end - it "could have any #zone and #utc_offset because they are ignored" do - zone = Object.new - def zone.utc_to_local(t) - Struct.new(:year, :mon, :mday, :hour, :min, :sec, :isdst, :to_i, :zone, :utc_offset) # rubocop:disable Lint/StructNewOverride - .new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.isdst, t.to_i, 'America/New_York', -5*60*60) - end - Time.now(in: zone).utc_offset.should == 0 - - zone = Object.new - def zone.utc_to_local(t) - Struct.new(:year, :mon, :mday, :hour, :min, :sec, :isdst, :to_i, :zone, :utc_offset) # rubocop:disable Lint/StructNewOverride - .new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.isdst, t.to_i, 'Asia/Tokyo', 9*60*60) - end - Time.now(in: zone).utc_offset.should == 0 - - zone = Object.new - def zone.utc_to_local(t) - Time.new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, 9*60*60) - end - Time.now(in: zone).utc_offset.should == 0 end - it "raises ArgumentError if difference between argument and result is too large" do - zone = Object.new - def zone.utc_to_local(t) - time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset) - time -= 24 * 60 * 60 # - 1 day - Time.utc(time.year, time.mon, time.day, time.hour, time.min, time.sec, time.utc_offset) - end - - -> { - Time.now(in: zone) - }.should raise_error(ArgumentError, "utc_offset out of range") end end end end @@ -57,50 +57,25 @@ describe 'TracePoint#enable' do end.enable { event_name.should equal(:line) } end - ruby_version_is '3.2' do - it 'enables the trace object only for the current thread' do - threads = [] - trace = TracePoint.new(:line) do |tp| - # Runs on purpose on any Thread - threads << Thread.current - end - - thread = nil - trace.enable do - line_event = true - thread = Thread.new do - event_in_other_thread = true - end - thread.join - end - - threads = threads.uniq - threads.should.include?(Thread.current) - threads.should_not.include?(thread) end - end - ruby_version_is ''...'3.2' do - it 'enables the trace object for any thread' do - threads = [] - trace = TracePoint.new(:line) do |tp| - # Runs on purpose on any Thread - threads << Thread.current - end - - thread = nil - trace.enable do - line_event = true - thread = Thread.new do - event_in_other_thread = true - end - thread.join end - - threads = threads.uniq - threads.should.include?(Thread.current) - threads.should.include?(thread) end end it 'can accept arguments within a block but it should not yield arguments' do @@ -76,38 +76,19 @@ describe "UnboundMethod#==" do (@identical_body == @original_body).should == false end - ruby_version_is ""..."3.2" do - it "returns false if same method but one extracted from a subclass" do - (@parent == @child1).should == false - (@child1 == @parent).should == false - end - - it "returns false if same method but extracted from two different subclasses" do - (@child2 == @child1).should == false - (@child1 == @child2).should == false - end - - it "returns false if methods are the same but added from an included Module" do - (@includee == @includer).should == false - (@includer == @includee).should == false - end end - ruby_version_is "3.2" do - it "returns true if same method but one extracted from a subclass" do - (@parent == @child1).should == true - (@child1 == @parent).should == true - end - - it "returns false if same method but extracted from two different subclasses" do - (@child2 == @child1).should == true - (@child1 == @child2).should == true - end - it "returns true if methods are the same but added from an included Module" do - (@includee == @includer).should == true - (@includer == @includee).should == true - end end it "returns false if both have same Module, same name, identical body but not the same" do @@ -25,9 +25,7 @@ describe "UnboundMethod#owner" do child_singleton_class.instance_method(:another_class_method).owner.should == child_singleton_class end - ruby_version_is "3.2" do - it "returns the class on which public was called for a private method in ancestor" do - MethodSpecs::InheritedMethods::C.instance_method(:derp).owner.should == MethodSpecs::InheritedMethods::C - end end end @@ -2,27 +2,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "UnboundMethod#private?" do - ruby_version_is ""..."3.2" do - it "returns false when the method is public" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_public_method).unbind.private?.should == false - end - - it "returns false when the method is protected" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_protected_method).unbind.private?.should == false - end - - it "returns true when the method is private" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_private_method).unbind.private?.should == true - end - end - - ruby_version_is "3.2" do - it "has been removed" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_private_method).unbind.should_not.respond_to?(:private?) - end end end @@ -2,27 +2,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "UnboundMethod#protected?" do - ruby_version_is ""..."3.2" do - it "returns false when the method is public" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_public_method).unbind.protected?.should == false - end - - it "returns true when the method is protected" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_protected_method).unbind.protected?.should == true - end - - it "returns false when the method is private" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_private_method).unbind.protected?.should == false - end - end - - ruby_version_is "3.2" do - it "has been removed" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_protected_method).unbind.should_not.respond_to?(:protected?) - end end end @@ -2,27 +2,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' describe "UnboundMethod#public?" do - ruby_version_is ""..."3.2" do - it "returns true when the method is public" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_public_method).unbind.public?.should == true - end - - it "returns false when the method is protected" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_protected_method).unbind.public?.should == false - end - - it "returns false when the method is private" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_private_method).unbind.public?.should == false - end - end - - ruby_version_is "3.2" do - it "has been removed" do - obj = UnboundMethodSpecs::Methods.new - obj.method(:my_public_method).unbind.should_not.respond_to?(:public?) - end end end @@ -20,22 +20,11 @@ describe :unboundmethod_to_s, shared: true do it "the String shows the method name, Module defined in and Module extracted from" do @from_module.send(@method).should =~ /\bfrom_mod\b/ @from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/ - - ruby_version_is ""..."3.2" do - @from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/ - end end it "returns a String including all details" do - ruby_version_is ""..."3.2" do - @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod" - @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod" - end - - ruby_version_is "3.2" do - @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod" - @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod" - end end it "does not show the defining module if it is the same as the origin" do @@ -23,25 +23,12 @@ describe 'Assignments' do ScratchPad.recorded.should == [:receiver, :argument, :rhs] end - # similar tests for evaluation order are located in language/constants_spec.rb - ruby_version_is ''...'3.2' do - it 'evaluates expressions right to left when assignment with compounded constant' do - m = Module.new - ScratchPad.record [] - - (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value) - ScratchPad.recorded.should == [:rhs, :module] - end - end - - ruby_version_is '3.2' do - it 'evaluates expressions left to right when assignment with compounded constant' do - m = Module.new - ScratchPad.record [] - (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value) - ScratchPad.recorded.should == [:module, :rhs] - end end it 'raises TypeError after evaluation of right-hand-side when compounded constant module is not a module' do @@ -345,45 +332,33 @@ describe 'Multiple assignments' do ScratchPad.recorded.should == [:ra, :aa, :rb, :ab, :rc, :ac, :rd, :ad, :re, :ae, :rf, :af, :value] end - ruby_version_is ''...'3.2' do - it 'evaluates expressions right to left when assignment with compounded constant' do - m = Module.new - ScratchPad.record [] - (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d) - ScratchPad.recorded.should == [:c, :d, :a, :b] - end end - ruby_version_is '3.2' do - it 'evaluates expressions left to right when assignment with compounded constant' do - m = Module.new - ScratchPad.record [] - - (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d) - ScratchPad.recorded.should == [:a, :b, :c, :d] - end - - it 'evaluates expressions left to right when assignment with a nested compounded constant' do - m = Module.new - ScratchPad.record [] - ((ScratchPad << :a; m)::A, foo), bar = [(ScratchPad << :b; :b)] - ScratchPad.recorded.should == [:a, :b] - end - it 'evaluates expressions left to right when assignment with deeply nested compounded constants' do - m = Module.new - ScratchPad.record [] - (ScratchPad << :a; m)::A, - ((ScratchPad << :b; m)::B, - ((ScratchPad << :c; m)::C, (ScratchPad << :d; m)::D), - (ScratchPad << :e; m)::E), - (ScratchPad << :f; m)::F = (ScratchPad << :value; :value) - ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value] - end end end @@ -62,37 +62,18 @@ describe "A block yielded a single" do m([1, 2, 3, 4, 5, 6]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 2, 3, [4], 5, 6] end - ruby_version_is "3.2" do - it "does not autosplat single argument to required arguments when a keyword rest argument is present" do - m([1, 2]) { |a, **k| [a, k] }.should == [[1, 2], {}] - end - - it "does not autosplat single argument to required arguments when keyword arguments are present" do - m([1, 2]) { |a, b: :b, c: :c| [a, b, c] }.should == [[1, 2], :b, :c] - end - - it "raises error when required keyword arguments are present" do - -> { - m([1, 2]) { |a, b:, c:| [a, b, c] } - }.should raise_error(ArgumentError, "missing keywords: :b, :c") - end end - ruby_version_is ''..."3.2" do - # https://bugs.ruby-lang.org/issues/18633 - it "autosplats single argument to required arguments when a keyword rest argument is present" do - m([1, 2]) { |a, **k| [a, k] }.should == [1, {}] - end - - it "autosplats single argument to required arguments when optional keyword arguments are present" do - m([1, 2]) { |a, b: :b, c: :c| [a, b, c] }.should == [1, :b, :c] - end - it "raises error when required keyword arguments are present" do - -> { - m([1, 2]) { |a, b:, c:| [a, b, c] } - }.should raise_error(ArgumentError, "missing keywords: :b, :c") - end end it "assigns elements to mixed argument types" do @@ -1040,25 +1021,23 @@ describe "Anonymous block forwarding" do no_kw(:a) { 1 }.should == 1 end - ruby_version_is "3.2" do - it "works alongside explicit keyword arguments" do - eval <<-EOF - def inner; yield end - def rest_kw(*a, kwarg: 1, &); inner(&) end - def kw(kwarg: 1, &); inner(&) end - def pos_kw_kwrest(arg1, kwarg: 1, **kw, &); inner(&) end - def pos_rkw(arg1, kwarg1:, &); inner(&) end - def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &); inner(&) end - def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &); inner(&) end - EOF - - rest_kw { 1 }.should == 1 - kw { 1 }.should == 1 - pos_kw_kwrest(:a) { 1 }.should == 1 - pos_rkw(:a, kwarg1: 3) { 1 }.should == 1 - all(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1 - all_kwrest(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1 - end end end @@ -1090,3 +1069,10 @@ describe "`it` calls without arguments in a block with no ordinary parameters" d end end end @@ -161,34 +161,16 @@ describe "Literal (A::X) constant resolution" do ConstantSpecs::ClassB.send(:remove_const, :CS_CONST109) end - ruby_version_is "3.2" do - it "evaluates left-to-right" do - mod = Module.new - mod.module_eval <<-EOC - order = [] - ConstantSpecsRHS = Module.new - (order << :lhs; ConstantSpecsRHS)::B = (order << :rhs) - EOC - mod::ConstantSpecsRHS::B.should == [:lhs, :rhs] - end - end - - ruby_version_is ""..."3.2" do - it "evaluates the right hand side before evaluating a constant path" do - mod = Module.new - - mod.module_eval <<-EOC - ConstantSpecsRHS::B = begin - module ConstantSpecsRHS; end - - "hello" - end - EOC - - mod::ConstantSpecsRHS::B.should == 'hello' - end end end @@ -87,51 +87,47 @@ describe "delegation with def(x, ...)" do end end -ruby_version_is "3.2" do - describe "delegation with def(*)" do - it "delegates rest" do - a = Class.new(DelegationSpecs::Target) - a.class_eval(<<-RUBY) - def delegate(*) - target(*) - end - RUBY - - 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 -ruby_version_is "3.2" do - describe "delegation with def(**)" do - it "delegates kwargs" do - a = Class.new(DelegationSpecs::Target) - a.class_eval(<<-RUBY) - def delegate(**) - target(**) - end - RUBY - - a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}, nil] end - 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 @@ -0,0 +1,9 @@ @@ -336,61 +336,23 @@ describe "Keyword arguments" do end end - ruby_version_is "3.2" do - it "does not work with call(*ruby2_keyword_args) with missing ruby2_keywords in between" do - class << self - def n(*args) # Note the missing ruby2_keywords here - target(*args) - end - - ruby2_keywords def m(*args) - n(*args) - end end - empty = {} - m(**empty).should == [[], {}] - m(empty).should == [[{}], {}] - - m(a: 1).should == [[{a: 1}], {}] - m({a: 1}).should == [[{a: 1}], {}] - end - end - - ruby_version_is ""..."3.2" do - # https://bugs.ruby-lang.org/issues/18625 - it "works with call(*ruby2_keyword_args) with missing ruby2_keywords in between due to CRuby bug #18625" do - class << self - def n(*args) # Note the missing ruby2_keywords here - target(*args) - end - - ruby2_keywords def m(*args) - n(*args) - end end - empty = {} - m(**empty).should == [[], {}] - Hash.ruby2_keywords_hash?(empty).should == false - m(empty).should == [[{}], {}] - Hash.ruby2_keywords_hash?(empty).should == false - - m(a: 1).should == [[], {a: 1}] - m({a: 1}).should == [[{a: 1}], {}] - - kw = {a: 1} - - m(**kw).should == [[], {a: 1}] - m(**kw)[1].should == kw - m(**kw)[1].should_not.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false - m(kw).should == [[{a: 1}], {}] - m(kw)[0][0].should.equal?(kw) - Hash.ruby2_keywords_hash?(kw).should == false - end end end @@ -30,20 +30,11 @@ describe "The module keyword" do ModuleSpecs.send(:remove_const, :Reopened) end - ruby_version_is '3.2' do - it "does not reopen a module included in Object" do - module IncludedModuleSpecs; Reopened = true; end - ModuleSpecs::IncludedInObject::IncludedModuleSpecs.should_not == Object::IncludedModuleSpecs - ensure - IncludedModuleSpecs.send(:remove_const, :Reopened) - end - end - - ruby_version_is ''...'3.2' do - it "reopens a module included in Object" do - module IncludedModuleSpecs; Reopened = true; end - ModuleSpecs::IncludedInObject::IncludedModuleSpecs::Reopened.should be_true - end end it "raises a TypeError if the constant is a Class" do @@ -88,8 +88,8 @@ describe "Predefined global $~" do $~ = /foo/.match("foo") $~.should be_an_instance_of(MatchData) - -> { $~ = Object.new }.should raise_error(TypeError) - -> { $~ = 1 }.should raise_error(TypeError) end it "changes the value of derived capture globals when assigned" do @@ -136,6 +136,19 @@ describe "Predefined global $&" do "abc".dup.force_encoding(Encoding::EUC_JP) =~ /b/ $&.encoding.should equal(Encoding::EUC_JP) end end describe "Predefined global $`" do @@ -154,6 +167,19 @@ describe "Predefined global $`" do "abc".dup.force_encoding(Encoding::ISO_8859_1) =~ /a/ $`.encoding.should equal(Encoding::ISO_8859_1) end end describe "Predefined global $'" do @@ -172,6 +198,19 @@ describe "Predefined global $'" do "abc".dup.force_encoding(Encoding::ISO_8859_1) =~ /c/ $'.encoding.should equal(Encoding::ISO_8859_1) end end describe "Predefined global $+" do @@ -190,6 +229,19 @@ describe "Predefined global $+" do "abc".dup.force_encoding(Encoding::EUC_JP) =~ /(b)/ $+.encoding.should equal(Encoding::EUC_JP) end end describe "Predefined globals $1..N" do @@ -229,7 +281,7 @@ describe "Predefined global $stdout" do end it "raises TypeError error if assigned to nil" do - -> { $stdout = nil }.should raise_error(TypeError) end it "raises TypeError error if assigned to object that doesn't respond to #write" do @@ -253,6 +305,12 @@ describe "Predefined global $!" do $!.should == nil end # See http://jira.codehaus.org/browse/JRUBY-5550 it "remains nil after a failed core class \"checked\" coercion against a class that defines method_missing" do $!.should == nil @@ -512,6 +570,64 @@ describe "Predefined global $!" do end end # Input/Output Variables # --------------------------------------------------------------------------------------------------- # @@ -610,15 +726,15 @@ describe "Predefined global $/" do obj = mock("$/ value") obj.should_not_receive(:to_str) - -> { $/ = obj }.should raise_error(TypeError) end it "raises a TypeError if assigned an Integer" do - -> { $/ = 1 }.should raise_error(TypeError) end it "raises a TypeError if assigned a boolean" do - -> { $/ = true }.should raise_error(TypeError) end end @@ -687,15 +803,15 @@ describe "Predefined global $-0" do obj = mock("$-0 value") obj.should_not_receive(:to_str) - -> { $-0 = obj }.should raise_error(TypeError) end it "raises a TypeError if assigned an Integer" do - -> { $-0 = 1 }.should raise_error(TypeError) end it "raises a TypeError if assigned a boolean" do - -> { $-0 = true }.should raise_error(TypeError) end end @@ -729,12 +845,12 @@ describe "Predefined global $\\" do obj = mock("$\\ value") obj.should_not_receive(:to_str) - -> { $\ = obj }.should raise_error(TypeError) end it "raises a TypeError if assigned not String" do - -> { $\ = 1 }.should raise_error(TypeError) - -> { $\ = true }.should raise_error(TypeError) end end @@ -748,7 +864,7 @@ describe "Predefined global $," do end it "raises TypeError if assigned a non-String" do - -> { $, = Object.new }.should raise_error(TypeError) end it "warns if assigned non-nil" do @@ -933,15 +1049,15 @@ describe "Execution variable $:" do it "is read-only" do -> { $: = [] - }.should raise_error(NameError) -> { $LOAD_PATH = [] - }.should raise_error(NameError) -> { $-I = [] - }.should raise_error(NameError) end it "default $LOAD_PATH entries until sitelibdir included have @gem_prelude_index set" do @@ -963,11 +1079,11 @@ describe "Global variable $\"" do it "is read-only" do -> { $" = [] - }.should raise_error(NameError) -> { $LOADED_FEATURES = [] - }.should raise_error(NameError) end end @@ -975,7 +1091,7 @@ describe "Global variable $<" do it "is read-only" do -> { $< = nil - }.should raise_error(NameError) end end @@ -983,7 +1099,7 @@ describe "Global variable $FILENAME" do it "is read-only" do -> { $FILENAME = "-" - }.should raise_error(NameError) end end @@ -991,7 +1107,7 @@ describe "Global variable $?" do it "is read-only" do -> { $? = nil - }.should raise_error(NameError) end it "is thread-local" do @@ -1002,19 +1118,19 @@ end describe "Global variable $-a" do it "is read-only" do - -> { $-a = true }.should raise_error(NameError) end end describe "Global variable $-l" do it "is read-only" do - -> { $-l = true }.should raise_error(NameError) end end describe "Global variable $-p" do it "is read-only" do - -> { $-p = true }.should raise_error(NameError) end end @@ -1165,7 +1281,7 @@ describe "The predefined standard object nil" do end it "raises a SyntaxError if assigned to" do - -> { eval("nil = true") }.should raise_error(SyntaxError) end end @@ -1175,7 +1291,7 @@ describe "The predefined standard object true" do end it "raises a SyntaxError if assigned to" do - -> { eval("true = false") }.should raise_error(SyntaxError) end end @@ -1185,13 +1301,13 @@ describe "The predefined standard object false" do end it "raises a SyntaxError if assigned to" do - -> { eval("false = nil") }.should raise_error(SyntaxError) end end describe "The self pseudo-variable" do it "raises a SyntaxError if assigned to" do - -> { eval("self = 1") }.should raise_error(SyntaxError) end end @@ -1,6 +1,7 @@ # -*- encoding: binary -*- require_relative '../spec_helper' # TODO: rewrite these horrid specs. it "are..." seriously?! @@ -27,6 +28,11 @@ describe "Ruby character strings" do "#$ip".should == 'xxx' end it "allows underscore as part of a variable name in a simple interpolation" do @my_ip = 'xxx' "#@my_ip".should == 'xxx' @@ -280,15 +286,15 @@ describe "Ruby String interpolation" do it "creates a non-frozen String" do code = <<~'RUBY' - "a#{6*7}c" RUBY eval(code).should_not.frozen? end it "creates a non-frozen String when # frozen-string-literal: true is used" do code = <<~'RUBY' - # frozen-string-literal: true - "a#{6*7}c" RUBY eval(code).should_not.frozen? end @@ -228,15 +228,7 @@ describe "BigDecimal#round" do -> { BigDecimal('-Infinity').round(2) }.should_not raise_error(FloatDomainError) end - version_is BigDecimal::VERSION, ''...'3.1.3' do #ruby_version_is ''...'3.2' do - it 'raise for a non-existent round mode' do - -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode") - end - end - - version_is BigDecimal::VERSION, '3.1.3' do #ruby_version_is '3.2' do - it 'raise for a non-existent round mode' do - -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode (nonsense)") - end end end @@ -5,57 +5,55 @@ rescue LoadError require 'cgi' end -ruby_version_is "3.2" do - describe "CGI.escapeURIComponent" do - it "escapes whitespace" do - string = "&<>\" \xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93" - CGI.escapeURIComponent(string).should == '%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93' - end - - it "does not escape with unreserved characters" do - string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" - CGI.escapeURIComponent(string).should == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" - end - it "supports String with invalid encoding" do - string = "\xC0\<\<".dup.force_encoding("UTF-8") - CGI.escapeURIComponent(string).should == "%C0%3C%3C" - end - it "processes String bytes one by one, not characters" do - CGI.escapeURIComponent("β").should == "%CE%B2" # "β" bytes representation is CE B2 - end - it "raises a TypeError with nil" do - -> { - CGI.escapeURIComponent(nil) - }.should raise_error(TypeError, 'no implicit conversion of nil into String') - end - it "encodes empty string" do - CGI.escapeURIComponent("").should == "" - end - it "encodes single whitespace" do - CGI.escapeURIComponent(" ").should == "%20" - end - it "encodes double whitespace" do - CGI.escapeURIComponent(" ").should == "%20%20" - end - it "preserves encoding" do - string = "whatever".encode("ASCII-8BIT") - CGI.escapeURIComponent(string).encoding.should == Encoding::ASCII_8BIT - end - it "uses implicit type conversion to String" do - object = Object.new - def object.to_str - "a b" - end - CGI.escapeURIComponent(object).should == "a%20b" end end end @@ -34,39 +34,37 @@ describe 'Coverage.result' do } end - ruby_version_is "3.2" do - it 'returns results for each mode separately when enabled :all modes' do - Coverage.start(:all) - require @class_file.chomp('.rb') - result = Coverage.result - - result.should == { - @class_file => { lines: [ nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil - ], - branches: {}, - methods: { - [SomeClass, :some_method, 6, 2, 11, 5] => 0 - } } - } - end - - it 'returns results for each mode separately when enabled any mode explicitly' do - Coverage.start(lines: true) - require @class_file.chomp('.rb') - result = Coverage.result - - result.should == { - @class_file => - { - lines: [ - nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil - ] - } - } - end end it 'no requires/loads should give empty hash' do @@ -113,48 +111,32 @@ describe 'Coverage.result' do Coverage.result.should_not include(@config_file) end - ruby_version_is '3.1'...'3.2' do - it 'returns the correct results when eval is used' do - Coverage.start - require @eval_code_file.chomp('.rb') - result = Coverage.result - - result.should == { - @eval_code_file => [ - 1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1 - ] - } - end - end - ruby_version_is '3.2' do - it 'returns the correct results when eval coverage is enabled' do - Coverage.supported?(:eval).should == true - - Coverage.start(lines: true, eval: true) - require @eval_code_file.chomp('.rb') - result = Coverage.result - result.should == { - @eval_code_file => { - lines: [1, nil, 1, nil, 1, 1, nil, nil, nil, nil, 1] - } } - end - it 'returns the correct results when eval coverage is disabled' do - Coverage.supported?(:eval).should == true - Coverage.start(lines: true, eval: false) - require @eval_code_file.chomp('.rb') - result = Coverage.result - result.should == { - @eval_code_file => { - lines: [1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1] - } } - end end it "disables coverage measurement when stop option is not specified" do @@ -27,63 +27,61 @@ describe 'Coverage.start' do }.should raise_error(RuntimeError, 'coverage measurement is already setup') end - ruby_version_is '3.2' do - it "accepts :all optional argument" do - Coverage.start(:all) - Coverage.should.running? - end - - it "accepts lines: optional keyword argument" do - Coverage.start(lines: true) - Coverage.should.running? - end - - it "accepts branches: optional keyword argument" do - Coverage.start(branches: true) - Coverage.should.running? - end - - it "accepts methods: optional keyword argument" do - Coverage.start(methods: true) - Coverage.should.running? - end - - it "accepts eval: optional keyword argument" do - Coverage.start(eval: true) - Coverage.should.running? - end - - it "accepts oneshot_lines: optional keyword argument" do - Coverage.start(oneshot_lines: true) - Coverage.should.running? - end - - it "ignores unknown keyword arguments" do - Coverage.start(foo: true) - Coverage.should.running? - end - - it "expects a Hash if not passed :all" do - -> { - Coverage.start(42) - }.should raise_error(TypeError, "no implicit conversion of Integer into Hash") - end - - it "does not accept both lines: and oneshot_lines: keyword arguments" do - -> { - Coverage.start(lines: true, oneshot_lines: true) - }.should raise_error(RuntimeError, "cannot enable lines and oneshot_lines simultaneously") - end - - it "enables the coverage measurement if passed options with `false` value" do - Coverage.start(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false) - Coverage.should.running? - end - - it "measures coverage within eval" do - Coverage.start(lines: true, eval: true) - eval("Object.new\n"*3, binding, "test.rb", 1) - Coverage.result["test.rb"].should == {lines: [1, 1, 1]} - end end end @@ -2,31 +2,29 @@ require_relative '../../spec_helper' require 'coverage' describe "Coverage.supported?" do - ruby_version_is "3.2" do - it "returns true or false if coverage measurement is supported for the given mode" do - [true, false].should.include?(Coverage.supported?(:lines)) - [true, false].should.include?(Coverage.supported?(:branches)) - [true, false].should.include?(Coverage.supported?(:methods)) - [true, false].should.include?(Coverage.supported?(:eval)) - end - it "returns false for not existing modes" do - Coverage.supported?(:foo).should == false - Coverage.supported?(:bar).should == false - end - it "raise TypeError if argument is not Symbol" do - -> { - Coverage.supported?("lines") - }.should raise_error(TypeError, "wrong argument type String (expected Symbol)") - -> { - Coverage.supported?([]) - }.should raise_error(TypeError, "wrong argument type Array (expected Symbol)") - -> { - Coverage.supported?(1) - }.should raise_error(TypeError, "wrong argument type Integer (expected Symbol)") - end end end @@ -2,43 +2,41 @@ require_relative '../../spec_helper' require 'date' date_version = defined?(Date::VERSION) ? Date::VERSION : '3.1.0' -version_is date_version, "3.3" do #ruby_version_is "3.2" do - describe "Date#deconstruct_keys" do - it "returns whole hash for nil as an argument" do - d = Date.new(2022, 10, 5) - d.deconstruct_keys(nil).should == { year: 2022, month: 10, day: 5, yday: 278, wday: 3 } - end - - it "returns only specified keys" do - d = Date.new(2022, 10, 5) - d.deconstruct_keys([:year, :month]).should == { year: 2022, month: 10 } - end - - it "requires one argument" do - -> { - Date.new(2022, 10, 5).deconstruct_keys - }.should raise_error(ArgumentError) - end - - it "it raises error when argument is neither nil nor array" do - d = Date.new(2022, 10, 5) - - -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)") - -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)") - -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)") - -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)") - end - - it "returns {} when passed []" do - Date.new(2022, 10, 5).deconstruct_keys([]).should == {} - end - - it "ignores non-Symbol keys" do - Date.new(2022, 10, 5).deconstruct_keys(['year', []]).should == {} - end - - it "ignores not existing Symbol keys" do - Date.new(2022, 10, 5).deconstruct_keys([:year, :a]).should == { year: 2022 } - end end end @@ -2,45 +2,43 @@ require_relative '../../spec_helper' require 'date' date_version = defined?(Date::VERSION) ? Date::VERSION : '3.1.0' -version_is date_version, "3.3" do #ruby_version_is "3.2" do - describe "DateTime#deconstruct_keys" do - it "returns whole hash for nil as an argument" do - d = DateTime.new(2022, 10, 5, 13, 30) - res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13, - min: 30, sec: 0, sec_fraction: (0/1), zone: "+00:00" } - d.deconstruct_keys(nil).should == res - end - - it "returns only specified keys" do - d = DateTime.new(2022, 10, 5, 13, 39) - d.deconstruct_keys([:zone, :hour]).should == { zone: "+00:00", hour: 13 } - end - - it "requires one argument" do - -> { - DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys - }.should raise_error(ArgumentError) - end - - it "it raises error when argument is neither nil nor array" do - d = DateTime.new(2022, 10, 5, 13, 30) - - -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)") - -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)") - -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)") - -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)") - end - - it "returns {} when passed []" do - DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {} - end - - it "ignores non-Symbol keys" do - DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {} - end - - it "ignores not existing Symbol keys" do - DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys([:year, :a]).should == { year: 2022 } - end end end @@ -15,17 +15,15 @@ describe "Time#to_datetime" do datetime.sec.should == 59 end - version_is date_version, '3.2.3' do #ruby_version_is '3.2' do - it "returns a DateTime representing the same instant before Gregorian" do - time = Time.utc(1582, 10, 14, 23, 58, 59) - datetime = time.to_datetime - datetime.year.should == 1582 - datetime.month.should == 10 - datetime.day.should == 4 - datetime.hour.should == 23 - datetime.min.should == 58 - datetime.sec.should == 59 - end end it "roundtrips" do @@ -19,17 +19,15 @@ describe "DateTime#to_time" do time.sec.should == 59 end - version_is date_version, '3.2.3' do #ruby_version_is "3.2" do - it "returns a Time representing the same instant before Gregorian" do - datetime = DateTime.civil(1582, 10, 4, 23, 58, 59) - time = datetime.to_time.utc - time.year.should == 1582 - time.month.should == 10 - time.day.should == 14 - time.hour.should == 23 - time.min.should == 58 - time.sec.should == 59 - end end it "preserves the same time regardless of local time or zone" do @@ -1,9 +1,5 @@ require_relative '../../spec_helper' -ruby_version_is ''...'3.2' do - require 'io/wait' -end - describe "IO#wait_readable" do before :each do @io = File.new(__FILE__ ) @@ -1,10 +1,6 @@ require_relative '../../spec_helper' require_relative '../../fixtures/io' -ruby_version_is ''...'3.2' do - require 'io/wait' -end - describe "IO#wait" do before :each do @io = File.new(__FILE__ ) @@ -25,26 +21,13 @@ describe "IO#wait" do end context "[events, timeout] passed" do - ruby_version_is ""..."3.2" do - it "returns self when the READABLE event is ready during the timeout" do - @w.write('data to read') - @r.wait(IO::READABLE, 2).should.equal?(@r) - end - - it "returns self when the WRITABLE event is ready during the timeout" do - @w.wait(IO::WRITABLE, 0).should.equal?(@w) - end end - ruby_version_is "3.2" do - it "returns events mask when the READABLE event is ready during the timeout" do - @w.write('data to read') - @r.wait(IO::READABLE, 2).should == IO::READABLE - end - - it "returns events mask when the WRITABLE event is ready during the timeout" do - @w.wait(IO::WRITABLE, 0).should == IO::WRITABLE - end end it "waits for the READABLE event to be ready" do @@ -76,11 +59,9 @@ describe "IO#wait" do -> { @io.wait(IO::READABLE, 0) }.should raise_error(IOError, "closed stream") end - ruby_version_is "3.2" do - it "raises ArgumentError when events is not positive" do - -> { @w.wait(0, 0) }.should raise_error(ArgumentError, "Events must be positive integer!") - -> { @w.wait(-1, 0) }.should raise_error(ArgumentError, "Events must be positive integer!") - end end it "changes thread status to 'sleep' when waits for READABLE event" do @@ -159,31 +140,23 @@ describe "IO#wait" do @io.wait(0, :r, :w, :rw).should == @io end - # It works at least since 2.7 but by some reason may fail on 3.1 - ruby_version_is "3.2" do - it "accepts timeout and mode in any order" do - @io.wait(0, :r).should == @io - @io.wait(:r, 0).should == @io - @io.wait(:r, 0, :w).should == @io - end end it "raises ArgumentError when passed wrong Symbol value as mode argument" do -> { @io.wait(0, :wrong) }.should raise_error(ArgumentError, "unsupported mode: wrong") end - # It works since 3.0 but by some reason may fail on 3.1 - ruby_version_is "3.2" do - it "raises ArgumentError when several Integer arguments passed" do - -> { @w.wait(0, 10, :r) }.should raise_error(ArgumentError, "timeout given more than once") - end end - ruby_version_is "3.2" do - it "raises IOError when io is closed (closed stream (IOError))" do - @io.close - -> { @io.wait(0, :r) }.should raise_error(IOError, "closed stream") - end end end end @@ -1,10 +1,6 @@ require_relative '../../spec_helper' require_relative '../../fixtures/io' -ruby_version_is ''...'3.2' do - require 'io/wait' -end - describe "IO#wait_writable" do it "waits for the IO to become writable with no timeout" do STDOUT.wait_writable.should == STDOUT @@ -1,7 +1,8 @@ require_relative '../../../spec_helper' require 'openssl' -guard -> { OpenSSL::KDF.respond_to?(:scrypt) } do describe "OpenSSL::KDF.scrypt" do before :each do @defaults = { @@ -2,13 +2,7 @@ require_relative '../../spec_helper' require 'rbconfig' describe "RbConfig::CONFIG['UNICODE_EMOJI_VERSION']" do - ruby_version_is ""..."3.2" do - it "is 13.1" do - RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "13.1" - end - end - - ruby_version_is "3.2"..."3.4" do it "is 15.0" do RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "15.0" end @@ -2,13 +2,7 @@ require_relative '../../spec_helper' require 'rbconfig' describe "RbConfig::CONFIG['UNICODE_VERSION']" do - ruby_version_is ""..."3.2" do - it "is 13.0.0" do - RbConfig::CONFIG['UNICODE_VERSION'].should == "13.0.0" - end - end - - ruby_version_is "3.2"..."3.4" do it "is 15.0.0" do RbConfig::CONFIG['UNICODE_VERSION'].should == "15.0.0" end @@ -1,12 +0,0 @@ -require_relative '../../spec_helper' - -describe 'Set' do - ruby_version_is '3.2' do - it 'is available without explicit requiring' do - output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1') - puts Set.new([1, 2, 3]) - RUBY - output.chomp.should == "#<Set: {1, 2, 3}>" - end - end -end @@ -14,26 +14,13 @@ describe :tcpsocket_new, shared: true do } end - ruby_version_is ""..."3.2" do - it 'raises Errno::ETIMEDOUT with :connect_timeout when no server is listening on the given address' do - -> { - TCPSocket.send(@method, "192.0.2.1", 80, connect_timeout: 0) - }.should raise_error(Errno::ETIMEDOUT) - rescue Errno::ENETUNREACH - # In the case all network interfaces down. - # raise_error cannot deal with multiple expected exceptions - end - end - - ruby_version_is "3.2" do - it 'raises IO::TimeoutError with :connect_timeout when no server is listening on the given address' do - -> { - TCPSocket.send(@method, "192.0.2.1", 80, connect_timeout: 0) - }.should raise_error(IO::TimeoutError) - rescue Errno::ENETUNREACH - # In the case all network interfaces down. - # raise_error cannot deal with multiple expected exceptions - end end describe "with a running server" do @@ -1,6 +1,5 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/each' describe "StringIO#fileno" do it "returns nil" do @@ -36,22 +36,11 @@ describe :stringio_each_separator, shared: true do seen.should == ["2 1 2 1 2"] end - version_is StringIO::VERSION, ""..."3.0.4" do #ruby_version_is ""..."3.2" do - it "yields each paragraph with two separation characters when passed an empty String as separator" do - seen = [] - io = StringIO.new("para1\n\npara2\n\n\npara3") - io.send(@method, "") {|s| seen << s} - seen.should == ["para1\n\n", "para2\n\n", "para3"] - end - end - - version_is StringIO::VERSION, "3.0.4" do #ruby_version_is "3.2" do - it "yields each paragraph with all separation characters when passed an empty String as separator" do - seen = [] - io = StringIO.new("para1\n\npara2\n\n\npara3") - io.send(@method, "") {|s| seen << s} - seen.should == ["para1\n\n", "para2\n\n\n", "para3"] - end end end @@ -1,32 +1,30 @@ require_relative '../../spec_helper' require 'strscan' -version_is StringScanner::Version, "3.0.5" do # ruby_version_is "3.2" - describe "StringScanner#named_captures" do - before do - @s = StringScanner.new('Fri Dec 12 1975 14:39') - end - it "returns a hash of names and matched substrings for named capturing groups in a regular expression of the most recent matching" do - @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/) - @s.named_captures.should == {"wday" => "Fri", "month" => "Dec", "day" => "12"} - end - it "returns {} if there are no named capturing groups" do - @s.exist?(/(\w+) (\w+) (\d+)/) - @s.named_captures.should == {} - end - # https://.com/ruby/strscan/issues/132 - ruby_bug "", "3.2"..."3.3" do # fixed in strscan v3.0.7 - it "returns {} if there is no any matching done" do - @s.named_captures.should == {} - end end - it "returns nil for an optional named capturing group if it doesn't match" do - @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\s+)?/) - @s.named_captures.should == {"wday" => "Fri", "month" => "Dec", "day" => nil} - end end end @@ -22,6 +22,13 @@ describe :strscan_pos, shared: true do @s.terminate @s.send(@method).should == @s.string.length end end describe :strscan_pos_set, shared: true do @@ -2,11 +2,9 @@ require_relative '../../../spec_helper' require 'uri' describe "URI::Generic#host" do - version_is URI::VERSION, "0.12" do #ruby_version_is "3.2" do - # https://hackerone.com/reports/156615 - it "returns empty string when host is empty" do - URI.parse('http:////foo.com').host.should == '' - end end end @@ -2,10 +2,8 @@ require_relative '../../../spec_helper' require 'uri' describe "URI::Generic#to_s" do - version_is URI::VERSION, "0.12" do #ruby_version_is "3.2" do - # https://hackerone.com/reports/156615 - it "preserves / characters when host is empty" do - URI('http:///foo.com').to_s.should == 'http:///foo.com' - end end end @@ -8,21 +8,9 @@ describe "CApiBindingSpecs" do end describe "Kernel#binding" do - ruby_version_is '3.2' do - it "raises when called from C" do - foo = 14 - -> { @b.get_binding }.should raise_error(RuntimeError) - end - end - - ruby_version_is ''...'3.2' do - it "gives the top-most Ruby binding when called from C" do - foo = 14 - b = @b.get_binding - b.local_variable_get(:foo).should == 14 - b.local_variable_set :foo, 12 - foo.should == 12 - end end end end @@ -0,0 +1,99 @@ @@ -735,14 +735,12 @@ describe "C-API Encoding function" do index.should == Encoding.list.size - 1 end - ruby_version_is "3.2" do - it "raises EncodingError if too many encodings" do - code = <<-RUBY - require #{extension_path.dump} - 1_000.times {|i| CApiEncodingSpecs.new.rb_define_dummy_encoding("R_\#{i}") } - RUBY - ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)') - end end end end @@ -65,11 +65,9 @@ static VALUE class_spec_rb_class_new_instance(VALUE self, VALUE args, VALUE klas return rb_class_new_instance(RARRAY_LENINT(args), RARRAY_PTR(args), klass); } -#ifdef RUBY_VERSION_IS_3_0 static VALUE class_spec_rb_class_new_instance_kw(VALUE self, VALUE args, VALUE klass) { return rb_class_new_instance_kw(RARRAY_LENINT(args), RARRAY_PTR(args), klass, RB_PASS_KEYWORDS); } -#endif static VALUE class_spec_rb_class_real(VALUE self, VALUE object) { if (rb_type_p(object, T_FIXNUM)) { @@ -160,9 +158,7 @@ void Init_class_spec(void) { rb_define_method(cls, "rb_class_private_instance_methods", class_spec_rb_class_private_instance_methods, -1); rb_define_method(cls, "rb_class_new", class_spec_rb_class_new, 1); rb_define_method(cls, "rb_class_new_instance", class_spec_rb_class_new_instance, 2); -#ifdef RUBY_VERSION_IS_3_0 rb_define_method(cls, "rb_class_new_instance_kw", class_spec_rb_class_new_instance_kw, 2); -#endif rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1); rb_define_method(cls, "rb_class_get_superclass", class_spec_rb_class_get_superclass, 1); rb_define_method(cls, "rb_class_superclass", class_spec_rb_class_superclass, 1); @@ -14,9 +14,6 @@ defconstfunc(rb_cBinding) defconstfunc(rb_cClass) defconstfunc(rb_cComplex) defconstfunc(rb_mComparable) -#ifndef RUBY_VERSION_IS_3_0 -defconstfunc(rb_cData) -#endif defconstfunc(rb_cDir) defconstfunc(rb_cEncoding) defconstfunc(rb_mEnumerable) @@ -97,9 +94,6 @@ void Init_constants_spec(void) { rb_define_method(cls, "rb_cClass", constants_spec_rb_cClass, 0); rb_define_method(cls, "rb_cComplex", constants_spec_rb_cComplex, 0); rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0); - #ifndef RUBY_VERSION_IS_3_0 - rb_define_method(cls, "rb_cData", constants_spec_rb_cData, 0); - #endif rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0); rb_define_method(cls, "rb_cEncoding", constants_spec_rb_cEncoding, 0); rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0); @@ -0,0 +1,166 @@ @@ -44,12 +44,10 @@ VALUE fiber_spec_rb_fiber_new(VALUE self) { return rb_fiber_new(fiber_spec_rb_fiber_new_function, Qnil); } -#ifdef RUBY_VERSION_IS_3_1 VALUE fiber_spec_rb_fiber_raise(int argc, VALUE *argv, VALUE self) { VALUE fiber = argv[0]; return rb_fiber_raise(fiber, argc-1, argv+1); } -#endif void Init_fiber_spec(void) { VALUE cls = rb_define_class("CApiFiberSpecs", rb_cObject); @@ -58,10 +56,7 @@ void Init_fiber_spec(void) { rb_define_method(cls, "rb_fiber_resume", fiber_spec_rb_fiber_resume, 2); rb_define_method(cls, "rb_fiber_yield", fiber_spec_rb_fiber_yield, 1); rb_define_method(cls, "rb_fiber_new", fiber_spec_rb_fiber_new, 0); - -#ifdef RUBY_VERSION_IS_3_1 rb_define_method(cls, "rb_fiber_raise", fiber_spec_rb_fiber_raise, -1); -#endif } #ifdef __cplusplus @@ -105,11 +105,9 @@ VALUE hash_spec_rb_hash_new(VALUE self) { return rb_hash_new(); } -#ifdef RUBY_VERSION_IS_3_2 VALUE hash_spec_rb_hash_new_capa(VALUE self, VALUE capacity) { return rb_hash_new_capa(NUM2LONG(capacity)); } -#endif VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */ @@ -169,9 +167,7 @@ void Init_hash_spec(void) { rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3); rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2); rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0); -#ifdef RUBY_VERSION_IS_3_2 rb_define_method(cls, "rb_hash_new_capa", hash_spec_rb_hash_new_capa, 1); -#endif rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0); rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1); rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2); @@ -28,13 +28,7 @@ static int set_non_blocking(int fd) { } static int io_spec_get_fd(VALUE io) { -#ifdef RUBY_VERSION_IS_3_1 return rb_io_descriptor(io); -#else - rb_io_t* fp; - GetOpenFile(io, fp); - return fp->fd; -#endif } VALUE io_spec_GetOpenFile_fd(VALUE self, VALUE io) { @@ -143,11 +137,7 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) { errno = saved_errno; } -#ifdef RUBY_VERSION_IS_3_1 ret = rb_io_maybe_wait_readable(errno, io, Qnil); -#else - ret = rb_io_wait_readable(fd); -#endif if (RTEST(read_p)) { ssize_t r = read(fd, buf, RB_IO_WAIT_READABLE_BUF); @@ -166,22 +156,15 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) { } VALUE io_spec_rb_io_wait_writable(VALUE self, VALUE io) { -#ifdef RUBY_VERSION_IS_3_1 int ret = rb_io_maybe_wait_writable(errno, io, Qnil); -#else - int ret = rb_io_wait_writable(io_spec_get_fd(io)); -#endif return ret ? Qtrue : Qfalse; } -#ifdef RUBY_VERSION_IS_3_1 VALUE io_spec_rb_io_maybe_wait_writable(VALUE self, VALUE error, VALUE io, VALUE timeout) { int ret = rb_io_maybe_wait_writable(NUM2INT(error), io, timeout); return INT2NUM(ret); } -#endif -#ifdef RUBY_VERSION_IS_3_1 #ifdef SET_NON_BLOCKING_FAILS_ALWAYS NORETURN(VALUE io_spec_rb_io_maybe_wait_readable(VALUE self, VALUE error, VALUE io, VALUE timeout, VALUE read_p)); #endif @@ -224,13 +207,10 @@ VALUE io_spec_rb_io_maybe_wait_readable(VALUE self, VALUE error, VALUE io, VALUE UNREACHABLE_RETURN(Qnil); #endif } -#endif -#ifdef RUBY_VERSION_IS_3_1 VALUE io_spec_rb_io_maybe_wait(VALUE self, VALUE error, VALUE io, VALUE events, VALUE timeout) { return rb_io_maybe_wait(NUM2INT(error), io, events, timeout); } -#endif VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) { rb_thread_wait_fd(io_spec_get_fd(io)); @@ -238,7 +218,6 @@ VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) { } VALUE io_spec_rb_wait_for_single_fd(VALUE self, VALUE io, VALUE events, VALUE secs, VALUE usecs) { -#ifdef RUBY_VERSION_IS_3_0 VALUE timeout = Qnil; if (!NIL_P(secs)) { timeout = rb_float_new((double)FIX2INT(secs) + (0.000001 * FIX2INT(usecs))); @@ -246,15 +225,6 @@ VALUE io_spec_rb_wait_for_single_fd(VALUE self, VALUE io, VALUE events, VALUE se VALUE result = rb_io_wait(io, events, timeout); if (result == Qfalse) return INT2FIX(0); else return result; -#else - struct timeval tv; - if (!NIL_P(secs)) { - tv.tv_sec = FIX2INT(secs); - tv.tv_usec = FIX2INT(usecs); - } - int fd = io_spec_get_fd(io); - return INT2FIX(rb_wait_for_single_fd(fd, FIX2INT(events), NIL_P(secs) ? NULL : &tv)); -#endif } VALUE io_spec_rb_thread_fd_writable(VALUE self, VALUE io) { @@ -409,11 +379,9 @@ void Init_io_spec(void) { rb_define_method(cls, "rb_io_taint_check", io_spec_rb_io_taint_check, 1); rb_define_method(cls, "rb_io_wait_readable", io_spec_rb_io_wait_readable, 2); rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1); -#ifdef RUBY_VERSION_IS_3_1 rb_define_method(cls, "rb_io_maybe_wait_writable", io_spec_rb_io_maybe_wait_writable, 3); rb_define_method(cls, "rb_io_maybe_wait_readable", io_spec_rb_io_maybe_wait_readable, 4); rb_define_method(cls, "rb_io_maybe_wait", io_spec_rb_io_maybe_wait, 4); -#endif rb_define_method(cls, "rb_thread_wait_fd", io_spec_rb_thread_wait_fd, 1); rb_define_method(cls, "rb_thread_fd_writable", io_spec_rb_thread_fd_writable, 1); rb_define_method(cls, "rb_thread_fd_select_read", io_spec_rb_thread_fd_select_read, 1); @@ -351,7 +351,6 @@ static VALUE kernel_spec_rb_funcallv(VALUE self, VALUE obj, VALUE method, VALUE return rb_funcallv(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args)); } -#ifdef RUBY_VERSION_IS_3_0 static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VALUE args) { return rb_funcallv_kw(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args), RB_PASS_KEYWORDS); } @@ -359,7 +358,6 @@ static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VAL static VALUE kernel_spec_rb_keyword_given_p(int argc, VALUE *args, VALUE self) { return rb_keyword_given_p() ? Qtrue : Qfalse; } -#endif static VALUE kernel_spec_rb_funcallv_public(VALUE self, VALUE obj, VALUE method) { return rb_funcallv_public(obj, SYM2ID(method), 0, NULL); @@ -436,10 +434,8 @@ void Init_kernel_spec(void) { rb_define_method(cls, "rb_str_format", kernel_spec_rb_str_format, 3); rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0); rb_define_method(cls, "rb_funcallv", kernel_spec_rb_funcallv, 3); -#ifdef RUBY_VERSION_IS_3_0 rb_define_method(cls, "rb_funcallv_kw", kernel_spec_rb_funcallv_kw, 3); rb_define_method(cls, "rb_keyword_given_p", kernel_spec_rb_keyword_given_p, -1); -#endif rb_define_method(cls, "rb_funcallv_public", kernel_spec_rb_funcallv_public, 2); rb_define_method(cls, "rb_funcall_many_args", kernel_spec_rb_funcall_many_args, 2); rb_define_method(cls, "rb_funcall_with_block", kernel_spec_rb_funcall_with_block, 4); @@ -15,11 +15,6 @@ static VALUE object_spec_FL_ABLE(VALUE self, VALUE obj) { static int object_spec_FL_TEST_flag(VALUE flag_string) { char *flag_cstr = StringValueCStr(flag_string); -#ifndef RUBY_VERSION_IS_3_1 - if (strcmp(flag_cstr, "FL_TAINT") == 0) { - return FL_TAINT; - } -#endif if (strcmp(flag_cstr, "FL_FREEZE") == 0) { return FL_FREEZE; } @@ -30,22 +25,6 @@ static VALUE object_spec_FL_TEST(VALUE self, VALUE obj, VALUE flag) { return INT2FIX(FL_TEST(obj, object_spec_FL_TEST_flag(flag))); } -#ifndef RUBY_VERSION_IS_3_1 -static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) { - OBJ_TAINT(obj); - return Qnil; -} - -static VALUE object_spec_OBJ_TAINTED(VALUE self, VALUE obj) { - return OBJ_TAINTED(obj) ? Qtrue : Qfalse; -} - -static VALUE object_spec_OBJ_INFECT(VALUE self, VALUE host, VALUE source) { - OBJ_INFECT(host, source); - return Qnil; -} -#endif - static VALUE object_spec_rb_any_to_s(VALUE self, VALUE obj) { return rb_any_to_s(obj); } @@ -154,12 +133,6 @@ static VALUE object_specs_rb_obj_method(VALUE self, VALUE obj, VALUE method) { return rb_obj_method(obj, method); } -#ifndef RUBY_VERSION_IS_3_2 -static VALUE object_spec_rb_obj_taint(VALUE self, VALUE obj) { - return rb_obj_taint(obj); -} -#endif - static VALUE so_require(VALUE self) { rb_require("fixtures/foo"); return Qnil; @@ -414,11 +387,6 @@ void Init_object_spec(void) { VALUE cls = rb_define_class("CApiObjectSpecs", rb_cObject); rb_define_method(cls, "FL_ABLE", object_spec_FL_ABLE, 1); rb_define_method(cls, "FL_TEST", object_spec_FL_TEST, 2); -#ifndef RUBY_VERSION_IS_3_1 - rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1); - rb_define_method(cls, "OBJ_TAINTED", object_spec_OBJ_TAINTED, 1); - rb_define_method(cls, "OBJ_INFECT", object_spec_OBJ_INFECT, 2); -#endif rb_define_method(cls, "rb_any_to_s", object_spec_rb_any_to_s, 1); rb_define_method(cls, "rb_attr_get", so_attr_get, 2); rb_define_method(cls, "rb_obj_instance_variables", object_spec_rb_obj_instance_variables, 1); @@ -443,15 +411,11 @@ void Init_object_spec(void) { rb_define_method(cls, "rb_obj_is_kind_of", so_kind_of, 2); rb_define_method(cls, "rb_obj_method_arity", object_specs_rb_obj_method_arity, 2); rb_define_method(cls, "rb_obj_method", object_specs_rb_obj_method, 2); -#ifndef RUBY_VERSION_IS_3_2 - rb_define_method(cls, "rb_obj_taint", object_spec_rb_obj_taint, 1); -#endif rb_define_method(cls, "rb_require", so_require, 0); rb_define_method(cls, "rb_respond_to", so_respond_to, 2); rb_define_method(cls, "rb_method_boundp", object_spec_rb_method_boundp, 3); rb_define_method(cls, "rb_obj_respond_to", so_obj_respond_to, 3); rb_define_method(cls, "rb_special_const_p", object_spec_rb_special_const_p, 1); - rb_define_method(cls, "rb_to_id", so_to_id, 1); rb_define_method(cls, "RTEST", object_spec_RTEST, 1); rb_define_method(cls, "rb_check_type", so_check_type, 2); @@ -38,11 +38,49 @@ VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE begpv, VALUE le return ary; } void Init_range_spec(void) { VALUE cls = rb_define_class("CApiRangeSpecs", rb_cObject); rb_define_method(cls, "rb_range_new", range_spec_rb_range_new, -1); rb_define_method(cls, "rb_range_values", range_spec_rb_range_values, 1); rb_define_method(cls, "rb_range_beg_len", range_spec_rb_range_beg_len, 5); } #ifdef __cplusplus @@ -31,13 +31,6 @@ static const VALUE DATA_VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1); #error "unsupported" #endif - -#ifndef RUBY_VERSION_IS_3_1 -VALUE rbasic_spec_taint_flag(VALUE self) { - return VALUE2NUM(RUBY_FL_TAINT); -} -#endif - VALUE rbasic_spec_freeze_flag(VALUE self) { return VALUE2NUM(RUBY_FL_FREEZE); } @@ -93,9 +86,6 @@ static VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) { void Init_rbasic_spec(void) { VALUE cls = rb_define_class("CApiRBasicSpecs", rb_cObject); -#ifndef RUBY_VERSION_IS_3_1 - rb_define_method(cls, "taint_flag", rbasic_spec_taint_flag, 0); -#endif rb_define_method(cls, "freeze_flag", rbasic_spec_freeze_flag, 0); rb_define_method(cls, "get_flags", rbasic_spec_get_flags, 1); rb_define_method(cls, "set_flags", rbasic_spec_set_flags, 2); @@ -47,16 +47,4 @@ #define RUBY_VERSION_IS_3_3 #endif -#if RUBY_VERSION_SINCE(3, 2) -#define RUBY_VERSION_IS_3_2 -#endif - -#if RUBY_VERSION_SINCE(3, 1) -#define RUBY_VERSION_IS_3_1 -#endif - -#if RUBY_VERSION_SINCE(3, 0) -#define RUBY_VERSION_IS_3_0 -#endif - #endif @@ -252,16 +252,6 @@ VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) { return rb_str_new5(str, RSTRING_PTR(ptr), FIX2INT(len)); } -#ifndef RUBY_VERSION_IS_3_2 -VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) { - return rb_tainted_str_new(RSTRING_PTR(str), FIX2INT(len)); -} - -VALUE string_spec_rb_tainted_str_new2(VALUE self, VALUE str) { - return rb_tainted_str_new2(RSTRING_PTR(str)); -} -#endif - VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) { return rb_str_plus(str1, str2); } @@ -635,10 +625,6 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_new3", string_spec_rb_str_new3, 1); rb_define_method(cls, "rb_str_new4", string_spec_rb_str_new4, 1); rb_define_method(cls, "rb_str_new5", string_spec_rb_str_new5, 3); -#ifndef RUBY_VERSION_IS_3_2 - rb_define_method(cls, "rb_tainted_str_new", string_spec_rb_tainted_str_new, 2); - rb_define_method(cls, "rb_tainted_str_new2", string_spec_rb_tainted_str_new2, 1); -#endif rb_define_method(cls, "rb_str_plus", string_spec_rb_str_plus, 2); rb_define_method(cls, "rb_str_times", string_spec_rb_str_times, 2); rb_define_method(cls, "rb_str_modify_expand", string_spec_rb_str_modify_expand, 2); @@ -50,19 +50,17 @@ describe "C-API Hash function" do end end - ruby_version_is '3.2' do - describe "rb_hash_new_capa" do - it "returns a new hash" do - @s.rb_hash_new_capa(3).should == {} - end - it "creates a hash with no default proc" do - @s.rb_hash_new_capa(3) {}.default_proc.should be_nil - end - it "raises RuntimeError when negative index is provided" do - -> { @s.rb_hash_new_capa(-1) }.should raise_error(RuntimeError, "st_table too big") - end end end @@ -92,4 +92,140 @@ describe "C-API Range function" do result.should be_nil end end end @@ -1,7 +1,6 @@ describe :rbasic, shared: true do before :all do specs = CApiRBasicSpecs.new - @taint = ruby_version_is(''...'3.1') ? specs.taint_flag : 0 @freeze = specs.freeze_flag end @@ -1040,11 +1040,9 @@ describe "C-API String function" do @s.rb_sprintf3(true.class).should == s end - ruby_bug "#19167", ""..."3.2" do - it "formats a TrueClass VALUE as 'true' if sign specified in format" do - s = 'Result: TrueClass.' - @s.rb_sprintf4(true.class).should == s - end end it "truncates a string to a supplied precision if that is shorter than the string" do @@ -1,9 +1,7 @@ require_relative '../spec_helper' -ruby_version_is "3.2" do - describe "CVE-2024-49761 is resisted by" do - it "the Regexp implementation handling that regular expression in linear time" do - Regexp.linear_time?(/�*((?:\d+)|(?:x[a-fA-F0-9]+));/).should == true - end end end @@ -65,66 +65,64 @@ describe :queue_deq, shared: true do end describe "with a timeout" do - ruby_version_is "3.2" do - it "returns an item if one is available in time" do - q = @object.call - - t = Thread.new { - q.send(@method, timeout: TIME_TOLERANCE).should == 1 - } - Thread.pass until t.status == "sleep" && q.num_waiting == 1 - q << 1 - t.join - end - - it "returns nil if no item is available in time" do - q = @object.call - - Thread.new { - q.send(@method, timeout: 0.001).should == nil - }.join - end - - it "does nothing if the timeout is nil" do - q = @object.call - t = Thread.new { - q.send(@method, timeout: nil).should == 1 - } - Thread.pass until t.status == "sleep" && q.num_waiting == 1 - q << 1 - t.join - end - - it "immediately returns nil if no item is available and the timeout is 0" do - q = @object.call - q << 1 - q.send(@method, timeout: 0).should == 1 - q.send(@method, timeout: 0).should == nil - end - - it "raise TypeError if timeout is not a valid numeric" do - q = @object.call - -> { - q.send(@method, timeout: "1") - }.should raise_error(TypeError, "no implicit conversion to float from string") - - -> { - q.send(@method, timeout: false) - }.should raise_error(TypeError, "no implicit conversion to float from false") - end - - it "raise ArgumentError if non_block = true is passed too" do - q = @object.call - -> { - q.send(@method, true, timeout: 1) - }.should raise_error(ArgumentError, "can't set a timeout if non_block is enabled") - end - - it "returns nil for a closed empty queue" do - q = @object.call - q.close - q.send(@method, timeout: 0).should == nil - end end end @@ -49,83 +49,81 @@ describe :sizedqueue_enq, shared: true do end describe "with a timeout" do - ruby_version_is "3.2" do - it "returns self if the item was pushed in time" do - q = @object.call(1) - q << 1 - - t = Thread.new { - q.send(@method, 2, timeout: TIME_TOLERANCE).should == q - } - Thread.pass until t.status == "sleep" && q.num_waiting == 1 - q.pop - t.join - end - - it "does nothing if the timeout is nil" do - q = @object.call(1) - q << 1 - t = Thread.new { - q.send(@method, 2, timeout: nil).should == q - } - t.join(0.2).should == nil - q.pop - t.join - end - - it "returns nil if no space is available and timeout is 0" do - q = @object.call(1) - q.send(@method, 1, timeout: 0).should == q - q.send(@method, 2, timeout: 0).should == nil - end - - it "returns nil if no space is available in time" do - q = @object.call(1) - q << 1 - Thread.new { - q.send(@method, 2, timeout: 0.001).should == nil - }.join - end - - it "raise TypeError if timeout is not a valid numeric" do - q = @object.call(1) - -> { - q.send(@method, 2, timeout: "1") - }.should raise_error(TypeError, "no implicit conversion to float from string") - - -> { - q.send(@method, 2, timeout: false) - }.should raise_error(TypeError, "no implicit conversion to float from false") - end - - it "raise ArgumentError if non_block = true is passed too" do - q = @object.call(1) - -> { - q.send(@method, 2, true, timeout: 1) - }.should raise_error(ArgumentError, "can't set a timeout if non_block is enabled") - end - - it "raise ClosedQueueError when closed before enqueued" do - q = @object.call(1) - q.close - -> { q.send(@method, 2, timeout: 1) }.should raise_error(ClosedQueueError, "queue closed") - end - - it "interrupts enqueuing threads with ClosedQueueError when the queue is closed" do - q = @object.call(1) - q << 1 - - t = Thread.new { - -> { q.send(@method, 1, timeout: TIME_TOLERANCE) }.should raise_error(ClosedQueueError, "queue closed") - } - - Thread.pass until q.num_waiting == 1 - - q.close - - t.join - q.pop.should == 1 - end end end end |