From 35dd046a83a6840ff42694e60f9424ac7aa52bf2 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Tue, 7 Jan 2025 12:56:51 +0200 Subject: [PATCH 1/3] Update to ruby/mspec@52431ca --- spec/mspec/lib/mspec/commands/mspec-run.rb | 3 + .../lib/mspec/runner/formatters/launchable.rb | 88 +++++++++++++++++++ spec/mspec/lib/mspec/utils/options.rb | 9 ++ spec/mspec/lib/mspec/utils/script.rb | 8 +- 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 spec/mspec/lib/mspec/runner/formatters/launchable.rb diff --git a/spec/mspec/lib/mspec/commands/mspec-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb index 064c177d69b9..36463d8c6f5f 100644 --- a/spec/mspec/lib/mspec/commands/mspec-run.rb +++ b/spec/mspec/lib/mspec/commands/mspec-run.rb @@ -53,6 +53,9 @@ def options(argv = ARGV) options.doc "\n When to perform it" options.action_filters + options.doc "\n Launchable" + options.launchable + options.doc "\n Help!" options.debug options.version MSpec::VERSION diff --git a/spec/mspec/lib/mspec/runner/formatters/launchable.rb b/spec/mspec/lib/mspec/runner/formatters/launchable.rb new file mode 100644 index 000000000000..f738781c71ac --- /dev/null +++ b/spec/mspec/lib/mspec/runner/formatters/launchable.rb @@ -0,0 +1,88 @@ +module LaunchableFormatter + def self.extend_object(obj) + super + obj.init + end + + def self.setDir(dir) + @@path = File.join(dir, "#{rand.to_s}.json") + self + end + + def init + @timer = nil + @tests = [] + end + + def before(state = nil) + super + @timer = TimerAction.new + @timer.start + end + + def after(state = nil) + super + @timer.finish + file = MSpec.file + return if file.nil? || state&.example.nil? || exception? + + @tests << {:test => state, :file => file, :exception => false, duration: @timer.elapsed} + end + + def exception(exception) + super + @timer.finish + file = MSpec.file + return if file.nil? + + @tests << {:test => exception, :file => file, :exception => true, duration: @timer.elapsed} + end + + def finish + super + + require_relative '../../../../../../tool/lib/launchable' + + @writer = writer = Launchable::JsonStreamWriter.new(@@path) + @writer.write_array('testCases') + at_exit { + @writer.close + } + + repo_path = File.expand_path("#{__dir__}/../../../../../../") + + @tests.each do |t| + testcase = t[:test].description + relative_path = t[:file].delete_prefix("#{repo_path}/") + # The test path is a URL-encoded representation. + # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18 + test_path = {file: relative_path, testcase: testcase}.map{|key, val| + "#{encode_test_path_component(key)}=#{encode_test_path_component(val)}" + }.join('#') + + status = 'TEST_PASSED' + if t[:exception] + message = t[:test].message + backtrace = t[:test].backtrace + e = "#{message}\n#{backtrace}" + status = 'TEST_FAILED' + end + + @writer.write_object( + { + testPath: test_path, + status: status, + duration: t[:duration], + createdAt: Time.now.to_s, + stderr: e, + stdout: nil + } + ) + end + end + + private + def encode_test_path_component component + component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26').tr("\x00-\x08", "") + end +end diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb index 23cf915e66d2..adeafa1f813c 100644 --- a/spec/mspec/lib/mspec/utils/options.rb +++ b/spec/mspec/lib/mspec/utils/options.rb @@ -489,6 +489,14 @@ def debug end end + def launchable + on("--launchable-test-reports", "DIR", + "DIR The directory for reporting test results in Launchable JSON format") do |o| + require 'mspec/runner/formatters/launchable' + config[:launchable] = LaunchableFormatter.setDir(o) + end + end + def all configure {} env @@ -508,5 +516,6 @@ def all action_filters actions debug + launchable end end diff --git a/spec/mspec/lib/mspec/utils/script.rb b/spec/mspec/lib/mspec/utils/script.rb index e86beaab86f2..15fd23fabfe8 100644 --- a/spec/mspec/lib/mspec/utils/script.rb +++ b/spec/mspec/lib/mspec/utils/script.rb @@ -159,8 +159,14 @@ def config_formatter end if config[:formatter] - config[:formatter].new(config[:output]) + config[:formatter] = config[:formatter].new(config[:output]) end + + if config[:launchable] + config[:formatter].extend config[:launchable] + end + + config[:formatter] end # Callback for enabling custom actions, etc. This version is a From bdcd9746a60d18451b866abe02bdfe9c61602ac2 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Tue, 7 Jan 2025 12:56:57 +0200 Subject: [PATCH 2/3] Update to ruby/spec@18032a7 --- spec/ruby/CONTRIBUTING.md | 4 +- spec/ruby/README.md | 2 +- spec/ruby/core/dir/close_spec.rb | 22 +- .../core/enumerator/each_with_index_spec.rb | 2 +- .../core/enumerator/each_with_object_spec.rb | 2 +- spec/ruby/core/enumerator/enum_for_spec.rb | 2 +- .../enumerator/fixtures}/classes.rb | 0 .../enumerator/shared}/enum_for.rb | 0 .../enumerator/shared}/with_index.rb | 4 +- .../enumerator/shared}/with_object.rb | 2 +- spec/ruby/core/enumerator/to_enum_spec.rb | 4 +- spec/ruby/core/enumerator/with_index_spec.rb | 2 +- spec/ruby/core/enumerator/with_object_spec.rb | 2 +- spec/ruby/core/env/inspect_spec.rb | 2 +- spec/ruby/core/fiber/storage_spec.rb | 12 +- spec/ruby/core/kernel/Rational_spec.rb | 148 ++++++++++- spec/ruby/core/math/atanh_spec.rb | 4 +- .../math => core/math/fixtures}/common.rb | 0 .../math => core/math/shared}/atanh.rb | 0 spec/ruby/core/process/status/bit_and_spec.rb | 49 ++-- .../core/process/status/right_shift_spec.rb | 47 ++-- spec/ruby/core/rational/abs_spec.rb | 2 +- spec/ruby/core/rational/ceil_spec.rb | 43 +++- spec/ruby/core/rational/comparison_spec.rb | 84 +++++- spec/ruby/core/rational/denominator_spec.rb | 12 +- spec/ruby/core/rational/div_spec.rb | 46 +++- spec/ruby/core/rational/divide_spec.rb | 66 ++++- spec/ruby/core/rational/divmod_spec.rb | 36 ++- spec/ruby/core/rational/equal_value_spec.rb | 31 ++- spec/ruby/core/rational/exponent_spec.rb | 236 ++++++++++++++++- spec/ruby/core/rational/fdiv_spec.rb | 3 +- .../{ => core/rational}/fixtures/rational.rb | 0 spec/ruby/core/rational/floor_spec.rb | 43 +++- spec/ruby/core/rational/hash_spec.rb | 7 +- spec/ruby/core/rational/inspect_spec.rb | 12 +- spec/ruby/core/rational/magnitude_spec.rb | 2 +- spec/ruby/core/rational/minus_spec.rb | 2 +- spec/ruby/core/rational/modulo_spec.rb | 41 ++- spec/ruby/core/rational/multiply_spec.rb | 57 ++++- spec/ruby/core/rational/numerator_spec.rb | 8 +- spec/ruby/core/rational/plus_spec.rb | 43 +++- spec/ruby/core/rational/quo_spec.rb | 23 +- spec/ruby/core/rational/remainder_spec.rb | 3 +- spec/ruby/core/rational/round_spec.rb | 104 +++++++- .../rational => core/rational/shared}/abs.rb | 2 +- .../shared}/arithmetic_exception_in_coerce.rb | 2 +- spec/ruby/core/rational/to_f_spec.rb | 14 +- spec/ruby/core/rational/to_i_spec.rb | 10 +- spec/ruby/core/rational/to_r_spec.rb | 9 +- spec/ruby/core/rational/to_s_spec.rb | 12 +- spec/ruby/core/rational/truncate_spec.rb | 69 ++++- spec/ruby/language/regexp_spec.rb | 2 +- .../library/bigdecimal/BigDecimal_spec.rb | 6 +- .../library/socket/socket/connect_spec.rb | 4 + spec/ruby/shared/rational/Rational.rb | 150 ----------- spec/ruby/shared/rational/ceil.rb | 45 ---- spec/ruby/shared/rational/comparison.rb | 95 ------- spec/ruby/shared/rational/denominator.rb | 14 - spec/ruby/shared/rational/div.rb | 54 ---- spec/ruby/shared/rational/divide.rb | 71 ------ spec/ruby/shared/rational/divmod.rb | 42 --- spec/ruby/shared/rational/equal_value.rb | 39 --- spec/ruby/shared/rational/exponent.rb | 240 ------------------ spec/ruby/shared/rational/fdiv.rb | 5 - spec/ruby/shared/rational/floor.rb | 45 ---- spec/ruby/shared/rational/hash.rb | 9 - spec/ruby/shared/rational/inspect.rb | 14 - spec/ruby/shared/rational/modulo.rb | 43 ---- spec/ruby/shared/rational/multiply.rb | 62 ----- spec/ruby/shared/rational/numerator.rb | 10 - spec/ruby/shared/rational/plus.rb | 48 ---- spec/ruby/shared/rational/remainder.rb | 5 - spec/ruby/shared/rational/round.rb | 106 -------- spec/ruby/shared/rational/to_f.rb | 16 -- spec/ruby/shared/rational/to_i.rb | 12 - spec/ruby/shared/rational/to_r.rb | 11 - spec/ruby/shared/rational/to_s.rb | 14 - spec/ruby/shared/rational/truncate.rb | 71 ------ 78 files changed, 1192 insertions(+), 1373 deletions(-) rename spec/ruby/{fixtures/enumerator => core/enumerator/fixtures}/classes.rb (100%) rename spec/ruby/{shared/enumerator => core/enumerator/shared}/enum_for.rb (100%) rename spec/ruby/{shared/enumerator => core/enumerator/shared}/with_index.rb (89%) rename spec/ruby/{shared/enumerator => core/enumerator/shared}/with_object.rb (96%) rename spec/ruby/{fixtures/math => core/math/fixtures}/common.rb (100%) rename spec/ruby/{shared/math => core/math/shared}/atanh.rb (100%) rename spec/ruby/{ => core/rational}/fixtures/rational.rb (100%) rename spec/ruby/{shared/rational => core/rational/shared}/abs.rb (90%) rename spec/ruby/{shared/rational => core/rational/shared}/arithmetic_exception_in_coerce.rb (89%) delete mode 100644 spec/ruby/shared/rational/Rational.rb delete mode 100644 spec/ruby/shared/rational/ceil.rb delete mode 100644 spec/ruby/shared/rational/comparison.rb delete mode 100644 spec/ruby/shared/rational/denominator.rb delete mode 100644 spec/ruby/shared/rational/div.rb delete mode 100644 spec/ruby/shared/rational/divide.rb delete mode 100644 spec/ruby/shared/rational/divmod.rb delete mode 100644 spec/ruby/shared/rational/equal_value.rb delete mode 100644 spec/ruby/shared/rational/exponent.rb delete mode 100644 spec/ruby/shared/rational/fdiv.rb delete mode 100644 spec/ruby/shared/rational/floor.rb delete mode 100644 spec/ruby/shared/rational/hash.rb delete mode 100644 spec/ruby/shared/rational/inspect.rb delete mode 100644 spec/ruby/shared/rational/modulo.rb delete mode 100644 spec/ruby/shared/rational/multiply.rb delete mode 100644 spec/ruby/shared/rational/numerator.rb delete mode 100644 spec/ruby/shared/rational/plus.rb delete mode 100644 spec/ruby/shared/rational/remainder.rb delete mode 100644 spec/ruby/shared/rational/round.rb delete mode 100644 spec/ruby/shared/rational/to_f.rb delete mode 100644 spec/ruby/shared/rational/to_i.rb delete mode 100644 spec/ruby/shared/rational/to_r.rb delete mode 100644 spec/ruby/shared/rational/to_s.rb delete mode 100644 spec/ruby/shared/rational/truncate.rb diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md index 5c3256948b87..366b484bada1 100644 --- a/spec/ruby/CONTRIBUTING.md +++ b/spec/ruby/CONTRIBUTING.md @@ -113,9 +113,9 @@ Also `have_constant`, `have_private_instance_method`, `have_singleton_method`, e } ``` -##### should_not raise_error +##### `should_not raise_error` -**To avoid!** Instead, use an expectation testing what the code in the lambda does. +**Avoid this!** Instead, use an expectation testing what the code in the lambda does. If an exception is raised, it will fail the example anyway. ```ruby diff --git a/spec/ruby/README.md b/spec/ruby/README.md index 964efbec48bd..42d116206ecc 100644 --- a/spec/ruby/README.md +++ b/spec/ruby/README.md @@ -44,7 +44,7 @@ For *testing* the development version of a Ruby implementation, one should alway Also, this repository doesn't always contain the latest spec changes from MRI (it's synchronized monthly), and does not contain tags (specs marked as failing on that Ruby implementation). Running specs on a Ruby implementation can be done with: -``` +```console $ cd ruby_implementation/spec/ruby # Add ../ruby_implementation/bin in PATH, or pass -t /path/to/bin/ruby $ ../mspec/bin/mspec diff --git a/spec/ruby/core/dir/close_spec.rb b/spec/ruby/core/dir/close_spec.rb index 5174a8896bc6..5fbf5fcaf29e 100644 --- a/spec/ruby/core/dir/close_spec.rb +++ b/spec/ruby/core/dir/close_spec.rb @@ -11,10 +11,12 @@ it "does not raise an IOError even if the Dir instance is closed" do dir = Dir.open DirSpecs.mock_dir - dir.close - dir.close + dir.close.should == nil + dir.close.should == nil - -> { dir.fileno }.should raise_error(IOError, /closed directory/) + guard -> { dir.respond_to? :fileno } do + -> { dir.fileno }.should raise_error(IOError, /closed directory/) + end end it "returns nil" do @@ -22,7 +24,7 @@ dir.close.should == nil end - ruby_version_is '3.3' do + 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 @@ -36,4 +38,16 @@ end end 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) + dir.close + + -> { dir_new.close }.should raise_error(Errno::EBADF, 'Bad file descriptor - closedir') + end + end + end end diff --git a/spec/ruby/core/enumerator/each_with_index_spec.rb b/spec/ruby/core/enumerator/each_with_index_spec.rb index 271e61fec655..4898e86fa9c6 100644 --- a/spec/ruby/core/enumerator/each_with_index_spec.rb +++ b/spec/ruby/core/enumerator/each_with_index_spec.rb @@ -1,5 +1,5 @@ require_relative '../../spec_helper' -require_relative '../../shared/enumerator/with_index' +require_relative 'shared/with_index' require_relative '../enumerable/shared/enumeratorized' describe "Enumerator#each_with_index" do diff --git a/spec/ruby/core/enumerator/each_with_object_spec.rb b/spec/ruby/core/enumerator/each_with_object_spec.rb index 68524dc74af6..84a45ae89dfc 100644 --- a/spec/ruby/core/enumerator/each_with_object_spec.rb +++ b/spec/ruby/core/enumerator/each_with_object_spec.rb @@ -1,5 +1,5 @@ require_relative '../../spec_helper' -require_relative '../../shared/enumerator/with_object' +require_relative 'shared/with_object' describe "Enumerator#each_with_object" do it_behaves_like :enum_with_object, :each_with_object diff --git a/spec/ruby/core/enumerator/enum_for_spec.rb b/spec/ruby/core/enumerator/enum_for_spec.rb index fd33f463bfeb..fbdf98545a96 100644 --- a/spec/ruby/core/enumerator/enum_for_spec.rb +++ b/spec/ruby/core/enumerator/enum_for_spec.rb @@ -1,5 +1,5 @@ require_relative '../../spec_helper' -require_relative '../../shared/enumerator/enum_for' +require_relative 'shared/enum_for' describe "Enumerator#enum_for" do it_behaves_like :enum_for, :enum_for diff --git a/spec/ruby/fixtures/enumerator/classes.rb b/spec/ruby/core/enumerator/fixtures/classes.rb similarity index 100% rename from spec/ruby/fixtures/enumerator/classes.rb rename to spec/ruby/core/enumerator/fixtures/classes.rb diff --git a/spec/ruby/shared/enumerator/enum_for.rb b/spec/ruby/core/enumerator/shared/enum_for.rb similarity index 100% rename from spec/ruby/shared/enumerator/enum_for.rb rename to spec/ruby/core/enumerator/shared/enum_for.rb diff --git a/spec/ruby/shared/enumerator/with_index.rb b/spec/ruby/core/enumerator/shared/with_index.rb similarity index 89% rename from spec/ruby/shared/enumerator/with_index.rb rename to spec/ruby/core/enumerator/shared/with_index.rb index 89f40070e0d9..78771ffe82d8 100644 --- a/spec/ruby/shared/enumerator/with_index.rb +++ b/spec/ruby/core/enumerator/shared/with_index.rb @@ -1,8 +1,8 @@ -require_relative '../../spec_helper' +require_relative '../../../spec_helper' describe :enum_with_index, shared: true do - require_relative '../../fixtures/enumerator/classes' + require_relative '../fixtures/classes' before :each do @origin = [1, 2, 3, 4] diff --git a/spec/ruby/shared/enumerator/with_object.rb b/spec/ruby/core/enumerator/shared/with_object.rb similarity index 96% rename from spec/ruby/shared/enumerator/with_object.rb rename to spec/ruby/core/enumerator/shared/with_object.rb index c2e3a793666c..d8e9d8e9f7be 100644 --- a/spec/ruby/shared/enumerator/with_object.rb +++ b/spec/ruby/core/enumerator/shared/with_object.rb @@ -1,4 +1,4 @@ -require_relative '../../spec_helper' +require_relative '../../../spec_helper' describe :enum_with_object, shared: true do before :each do diff --git a/spec/ruby/core/enumerator/to_enum_spec.rb b/spec/ruby/core/enumerator/to_enum_spec.rb index cadfcf631446..7fb73d0c3cdd 100644 --- a/spec/ruby/core/enumerator/to_enum_spec.rb +++ b/spec/ruby/core/enumerator/to_enum_spec.rb @@ -1,6 +1,6 @@ require_relative '../../spec_helper' -require_relative '../../shared/enumerator/enum_for' +require_relative 'shared/enum_for' describe "Enumerator#to_enum" do - it_behaves_like :enum_for, :enum_for + it_behaves_like :enum_for, :to_enum end diff --git a/spec/ruby/core/enumerator/with_index_spec.rb b/spec/ruby/core/enumerator/with_index_spec.rb index 3aeb3fc869ac..e49aa7a939b9 100644 --- a/spec/ruby/core/enumerator/with_index_spec.rb +++ b/spec/ruby/core/enumerator/with_index_spec.rb @@ -1,5 +1,5 @@ require_relative '../../spec_helper' -require_relative '../../shared/enumerator/with_index' +require_relative 'shared/with_index' require_relative '../enumerable/shared/enumeratorized' describe "Enumerator#with_index" do diff --git a/spec/ruby/core/enumerator/with_object_spec.rb b/spec/ruby/core/enumerator/with_object_spec.rb index e7ba83fd9f7e..58031fd765d5 100644 --- a/spec/ruby/core/enumerator/with_object_spec.rb +++ b/spec/ruby/core/enumerator/with_object_spec.rb @@ -1,5 +1,5 @@ require_relative '../../spec_helper' -require_relative '../../shared/enumerator/with_object' +require_relative 'shared/with_object' describe "Enumerator#with_object" do it_behaves_like :enum_with_object, :with_object diff --git a/spec/ruby/core/env/inspect_spec.rb b/spec/ruby/core/env/inspect_spec.rb index 3c611c24a177..7dd92b120ffb 100644 --- a/spec/ruby/core/env/inspect_spec.rb +++ b/spec/ruby/core/env/inspect_spec.rb @@ -4,7 +4,7 @@ it "returns a String that looks like a Hash with real data" do ENV["foo"] = "bar" - ENV.inspect.should =~ /\{.*"foo"=>"bar".*\}/ + ENV.inspect.should =~ /\{.*"foo" *=> *"bar".*\}/ ENV.delete "foo" end diff --git a/spec/ruby/core/fiber/storage_spec.rb b/spec/ruby/core/fiber/storage_spec.rb index 5c87ed5d41d5..d5603f006c8d 100644 --- a/spec/ruby/core/fiber/storage_spec.rb +++ b/spec/ruby/core/fiber/storage_spec.rb @@ -90,12 +90,14 @@ key = :"#{self.class.name}#.#{self.object_id}" Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42 end + end - it "can't use invalid keys" do - invalid_keys = [Object.new, "Foo", 12] - invalid_keys.each do |key| - -> { Fiber[key] }.should raise_error(TypeError) - 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[key] = 42 + Fiber["Foo"].should == 42 end end diff --git a/spec/ruby/core/kernel/Rational_spec.rb b/spec/ruby/core/kernel/Rational_spec.rb index 2d1051db7f4a..841c8e8c64d1 100644 --- a/spec/ruby/core/kernel/Rational_spec.rb +++ b/spec/ruby/core/kernel/Rational_spec.rb @@ -1,6 +1,150 @@ require_relative '../../spec_helper' -require_relative '../../shared/rational/Rational' +require_relative '../rational/fixtures/rational' describe "Kernel.Rational" do - it_behaves_like :kernel_Rational, :Rational + describe "passed Integer" do + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + it "returns a new Rational number with 1 as the denominator" do + Rational(1).should eql(Rational(1, 1)) + Rational(-3).should eql(Rational(-3, 1)) + Rational(bignum_value).should eql(Rational(bignum_value, 1)) + end + end + end + + describe "passed two integers" do + it "returns a new Rational number" do + rat = Rational(1, 2) + rat.numerator.should == 1 + rat.denominator.should == 2 + rat.should be_an_instance_of(Rational) + + rat = Rational(-3, -5) + rat.numerator.should == 3 + rat.denominator.should == 5 + rat.should be_an_instance_of(Rational) + + rat = Rational(bignum_value, 3) + rat.numerator.should == bignum_value + rat.denominator.should == 3 + rat.should be_an_instance_of(Rational) + end + + it "reduces the Rational" do + rat = Rational(2, 4) + rat.numerator.should == 1 + rat.denominator.should == 2 + + rat = Rational(3, 9) + rat.numerator.should == 1 + rat.denominator.should == 3 + end + end + + describe "when passed a String" do + it "converts the String to a Rational using the same method as String#to_r" do + r = Rational(13, 25) + s_r = ".52".to_r + r_s = Rational(".52") + + r_s.should == r + r_s.should == s_r + end + + it "scales the Rational value of the first argument by the Rational value of the second" do + Rational(".52", ".6").should == Rational(13, 15) + Rational(".52", "1.6").should == Rational(13, 40) + end + + it "does not use the same method as Float#to_r" do + r = Rational(3, 5) + f_r = 0.6.to_r + r_s = Rational("0.6") + + r_s.should == r + r_s.should_not == f_r + end + end + + describe "when passed a Numeric" do + it "calls #to_r to convert the first argument to a Rational" do + num = RationalSpecs::SubNumeric.new(2) + + Rational(num).should == Rational(2) + end + end + + describe "when passed a Complex" do + it "returns a Rational from the real part if the imaginary part is 0" do + Rational(Complex(1, 0)).should == Rational(1) + end + + it "raises a RangeError if the imaginary part is not 0" do + -> { Rational(Complex(1, 2)) }.should raise_error(RangeError) + end + end + + it "raises a ZeroDivisionError if the second argument is 0" do + -> { Rational(1, 0) }.should raise_error(ZeroDivisionError, "divided by 0") + -> { Rational(1, 0.0) }.should raise_error(ZeroDivisionError, "divided by 0") + end + + it "raises a TypeError if the first argument is nil" do + -> { Rational(nil) }.should raise_error(TypeError) + end + + it "raises a TypeError if the second argument is nil" do + -> { Rational(1, nil) }.should raise_error(TypeError) + end + + it "raises a TypeError if the first argument is a Symbol" do + -> { Rational(:sym) }.should raise_error(TypeError) + end + + it "raises a TypeError if the second argument is a Symbol" do + -> { Rational(1, :sym) }.should raise_error(TypeError) + end + + describe "when passed exception: false" do + describe "and [non-Numeric]" do + it "swallows an error" do + Rational(:sym, exception: false).should == nil + Rational("abc", exception: false).should == nil + end + end + + describe "and [non-Numeric, Numeric]" do + it "swallows an error" do + Rational(:sym, 1, exception: false).should == nil + Rational("abc", 1, exception: false).should == nil + end + end + + describe "and [anything, non-Numeric]" do + it "swallows an error" do + Rational(:sym, :sym, exception: false).should == nil + Rational("abc", :sym, exception: false).should == nil + end + end + + describe "and non-Numeric String arguments" do + it "swallows an error" do + Rational("a", "b", exception: false).should == nil + Rational("a", 0, exception: false).should == nil + Rational(0, "b", exception: false).should == nil + end + end + + describe "and nil arguments" do + it "swallows an error" do + Rational(nil, exception: false).should == nil + Rational(nil, nil, exception: false).should == nil + end + end + end + + it "freezes its result" do + Rational(1).frozen?.should == true + end end diff --git a/spec/ruby/core/math/atanh_spec.rb b/spec/ruby/core/math/atanh_spec.rb index 21fb209941af..edcb8f2e5203 100644 --- a/spec/ruby/core/math/atanh_spec.rb +++ b/spec/ruby/core/math/atanh_spec.rb @@ -1,6 +1,6 @@ require_relative '../../spec_helper' -require_relative '../../fixtures/math/common' -require_relative '../../shared/math/atanh' +require_relative 'fixtures/common' +require_relative 'shared/atanh' describe "Math.atanh" do it_behaves_like :math_atanh_base, :atanh, Math diff --git a/spec/ruby/fixtures/math/common.rb b/spec/ruby/core/math/fixtures/common.rb similarity index 100% rename from spec/ruby/fixtures/math/common.rb rename to spec/ruby/core/math/fixtures/common.rb diff --git a/spec/ruby/shared/math/atanh.rb b/spec/ruby/core/math/shared/atanh.rb similarity index 100% rename from spec/ruby/shared/math/atanh.rb rename to spec/ruby/core/math/shared/atanh.rb diff --git a/spec/ruby/core/process/status/bit_and_spec.rb b/spec/ruby/core/process/status/bit_and_spec.rb index f4a4328907d8..0e0edb0afa39 100644 --- a/spec/ruby/core/process/status/bit_and_spec.rb +++ b/spec/ruby/core/process/status/bit_and_spec.rb @@ -1,35 +1,38 @@ require_relative '../../../spec_helper' -describe "Process::Status#&" do - it "returns a bitwise and of the integer status of an exited child" do - suppress_warning do - ruby_exe("exit(29)", exit_status: 29) - ($? & 0).should == 0 - ($? & $?.to_i).should == $?.to_i +ruby_version_is ""..."3.5" do - # Actual value is implementation specific - platform_is :linux do - # 29 == 0b11101 - ($? & 0b1011100000000).should == 0b1010100000000 + describe "Process::Status#&" do + it "returns a bitwise and of the integer status of an exited child" do + suppress_warning do + ruby_exe("exit(29)", exit_status: 29) + ($? & 0).should == 0 + ($? & $?.to_i).should == $?.to_i + + # Actual value is implementation specific + platform_is :linux do + # 29 == 0b11101 + ($? & 0b1011100000000).should == 0b1010100000000 + end end end - end - ruby_version_is "3.3" do - it "raises an ArgumentError if mask is negative" do - suppress_warning do + ruby_version_is "3.3"..."3.5" do + it "raises an ArgumentError if mask is negative" do + suppress_warning do + ruby_exe("exit(0)") + -> { + $? & -1 + }.should raise_error(ArgumentError, 'negative mask value: -1') + end + end + + it "shows a deprecation warning" do ruby_exe("exit(0)") -> { - $? & -1 - }.should raise_error(ArgumentError, 'negative mask value: -1') + $? & 0 + }.should complain(/warning: Process::Status#& is deprecated and will be removed .*use other Process::Status predicates instead/) end end - - it "shows a deprecation warning" do - ruby_exe("exit(0)") - -> { - $? & 0 - }.should complain(/warning: Process::Status#& is deprecated and will be removed .*use other Process::Status predicates instead/) - end end end diff --git a/spec/ruby/core/process/status/right_shift_spec.rb b/spec/ruby/core/process/status/right_shift_spec.rb index 034ce348cbf9..a1ab75141a38 100644 --- a/spec/ruby/core/process/status/right_shift_spec.rb +++ b/spec/ruby/core/process/status/right_shift_spec.rb @@ -1,34 +1,37 @@ require_relative '../../../spec_helper' -describe "Process::Status#>>" do - it "returns a right shift of the integer status of an exited child" do - suppress_warning do - ruby_exe("exit(29)", exit_status: 29) - ($? >> 0).should == $?.to_i - ($? >> 1).should == $?.to_i >> 1 +ruby_version_is ""..."3.5" do - # Actual value is implementation specific - platform_is :linux do - ($? >> 8).should == 29 + describe "Process::Status#>>" do + it "returns a right shift of the integer status of an exited child" do + suppress_warning do + ruby_exe("exit(29)", exit_status: 29) + ($? >> 0).should == $?.to_i + ($? >> 1).should == $?.to_i >> 1 + + # Actual value is implementation specific + platform_is :linux do + ($? >> 8).should == 29 + end end end - end - ruby_version_is "3.3" do - it "raises an ArgumentError if shift value is negative" do - suppress_warning do + ruby_version_is "3.3"..."3.5" do + it "raises an ArgumentError if shift value is negative" do + suppress_warning do + ruby_exe("exit(0)") + -> { + $? >> -1 + }.should raise_error(ArgumentError, 'negative shift value: -1') + end + end + + it "shows a deprecation warning" do ruby_exe("exit(0)") -> { - $? >> -1 - }.should raise_error(ArgumentError, 'negative shift value: -1') + $? >> 0 + }.should complain(/warning: Process::Status#>> is deprecated and will be removed .*use other Process::Status attributes instead/) end end - - it "shows a deprecation warning" do - ruby_exe("exit(0)") - -> { - $? >> 0 - }.should complain(/warning: Process::Status#>> is deprecated and will be removed .*use other Process::Status attributes instead/) - end end end diff --git a/spec/ruby/core/rational/abs_spec.rb b/spec/ruby/core/rational/abs_spec.rb index 7272ad242208..54099aa14d0c 100644 --- a/spec/ruby/core/rational/abs_spec.rb +++ b/spec/ruby/core/rational/abs_spec.rb @@ -1,5 +1,5 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/abs' +require_relative 'shared/abs' describe "Rational#abs" do it_behaves_like :rational_abs, :abs diff --git a/spec/ruby/core/rational/ceil_spec.rb b/spec/ruby/core/rational/ceil_spec.rb index e73635160431..d5bdadf3b6b0 100644 --- a/spec/ruby/core/rational/ceil_spec.rb +++ b/spec/ruby/core/rational/ceil_spec.rb @@ -1,6 +1,45 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/ceil' describe "Rational#ceil" do - it_behaves_like :rational_ceil, :ceil + before do + @rational = Rational(2200, 7) + end + + describe "with no arguments (precision = 0)" do + it "returns an Integer" do + @rational.ceil.should be_kind_of(Integer) + end + + it "returns the truncated value toward positive infinity" do + @rational.ceil.should == 315 + Rational(1, 2).ceil.should == 1 + Rational(-1, 2).ceil.should == 0 + end + end + + describe "with a precision < 0" do + it "returns an Integer" do + @rational.ceil(-2).should be_kind_of(Integer) + @rational.ceil(-1).should be_kind_of(Integer) + end + + it "moves the truncation point n decimal places left" do + @rational.ceil(-3).should == 1000 + @rational.ceil(-2).should == 400 + @rational.ceil(-1).should == 320 + end + end + + describe "with precision > 0" do + it "returns a Rational" do + @rational.ceil(1).should be_kind_of(Rational) + @rational.ceil(2).should be_kind_of(Rational) + end + + it "moves the truncation point n decimal places right" do + @rational.ceil(1).should == Rational(3143, 10) + @rational.ceil(2).should == Rational(31429, 100) + @rational.ceil(3).should == Rational(157143, 500) + end + end end diff --git a/spec/ruby/core/rational/comparison_spec.rb b/spec/ruby/core/rational/comparison_spec.rb index 877069fb8fc0..c9db60d5c782 100644 --- a/spec/ruby/core/rational/comparison_spec.rb +++ b/spec/ruby/core/rational/comparison_spec.rb @@ -1,23 +1,93 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/comparison' +require_relative 'fixtures/rational' describe "Rational#<=> when passed a Rational object" do - it_behaves_like :rational_cmp_rat, :<=> + it "returns 1 when self is greater than the passed argument" do + (Rational(4, 4) <=> Rational(3, 4)).should equal(1) + (Rational(-3, 4) <=> Rational(-4, 4)).should equal(1) + end + + it "returns 0 when self is equal to the passed argument" do + (Rational(4, 4) <=> Rational(4, 4)).should equal(0) + (Rational(-3, 4) <=> Rational(-3, 4)).should equal(0) + end + + it "returns -1 when self is less than the passed argument" do + (Rational(3, 4) <=> Rational(4, 4)).should equal(-1) + (Rational(-4, 4) <=> Rational(-3, 4)).should equal(-1) + end end describe "Rational#<=> when passed an Integer object" do - it_behaves_like :rational_cmp_int, :<=> + it "returns 1 when self is greater than the passed argument" do + (Rational(4, 4) <=> 0).should equal(1) + (Rational(4, 4) <=> -10).should equal(1) + (Rational(-3, 4) <=> -1).should equal(1) + end + + it "returns 0 when self is equal to the passed argument" do + (Rational(4, 4) <=> 1).should equal(0) + (Rational(-8, 4) <=> -2).should equal(0) + end + + it "returns -1 when self is less than the passed argument" do + (Rational(3, 4) <=> 1).should equal(-1) + (Rational(-4, 4) <=> 0).should equal(-1) + end end describe "Rational#<=> when passed a Float object" do - it_behaves_like :rational_cmp_float, :<=> + it "returns 1 when self is greater than the passed argument" do + (Rational(4, 4) <=> 0.5).should equal(1) + (Rational(4, 4) <=> -1.5).should equal(1) + (Rational(-3, 4) <=> -0.8).should equal(1) + end + + it "returns 0 when self is equal to the passed argument" do + (Rational(4, 4) <=> 1.0).should equal(0) + (Rational(-6, 4) <=> -1.5).should equal(0) + end + + it "returns -1 when self is less than the passed argument" do + (Rational(3, 4) <=> 1.2).should equal(-1) + (Rational(-4, 4) <=> 0.5).should equal(-1) + end end describe "Rational#<=> when passed an Object that responds to #coerce" do - it_behaves_like :rational_cmp_coerce, :<=> - it_behaves_like :rational_cmp_coerce_exception, :<=> + it "calls #coerce on the passed argument with self" do + rational = Rational(3, 4) + + obj = mock("Object") + obj.should_receive(:coerce).with(rational).and_return([1, 2]) + + rational <=> obj + end + + it "calls #<=> on the coerced Rational with the coerced Object" do + rational = Rational(3, 4) + + coerced_rational = mock("Coerced Rational") + coerced_rational.should_receive(:<=>).and_return(:result) + + coerced_obj = mock("Coerced Object") + + obj = mock("Object") + obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) + + (rational <=> obj).should == :result + end + + it "does not rescue exception raised in other#coerce" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) + + -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError) + end end describe "Rational#<=> when passed a non-Numeric Object that doesn't respond to #coerce" do - it_behaves_like :rational_cmp_other, :<=> + it "returns nil" do + (Rational <=> mock("Object")).should be_nil + end end diff --git a/spec/ruby/core/rational/denominator_spec.rb b/spec/ruby/core/rational/denominator_spec.rb index c2f49b4190f2..468724489398 100644 --- a/spec/ruby/core/rational/denominator_spec.rb +++ b/spec/ruby/core/rational/denominator_spec.rb @@ -1,6 +1,14 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/denominator' describe "Rational#denominator" do - it_behaves_like :rational_denominator, :denominator + it "returns the denominator" do + Rational(3, 4).denominator.should equal(4) + Rational(3, -4).denominator.should equal(4) + + Rational(1, bignum_value).denominator.should == bignum_value + end + + it "returns 1 if no denominator was given" do + Rational(80).denominator.should == 1 + end end diff --git a/spec/ruby/core/rational/div_spec.rb b/spec/ruby/core/rational/div_spec.rb index bee7d01a6744..d3adb9b53676 100644 --- a/spec/ruby/core/rational/div_spec.rb +++ b/spec/ruby/core/rational/div_spec.rb @@ -1,18 +1,54 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/div' describe "Rational#div" do - it_behaves_like :rational_div, :div + it "returns an Integer" do + Rational(229, 21).div(82).should be_kind_of(Integer) + end + + it "raises an ArgumentError if passed more than one argument" do + -> { Rational(3, 4).div(2,3) }.should raise_error(ArgumentError) + end + + # See http://redmine.ruby-lang.org/issues/show/1648 + it "raises a TypeError if passed a non-numeric argument" do + -> { Rational(3, 4).div([]) }.should raise_error(TypeError) + end end describe "Rational#div passed a Rational" do - it_behaves_like :rational_div_rat, :div + it "performs integer division and returns the result" do + Rational(2, 3).div(Rational(2, 3)).should == 1 + Rational(-2, 9).div(Rational(-9, 2)).should == 0 + end + + it "raises a ZeroDivisionError when the argument has a numerator of 0" do + -> { Rational(3, 4).div(Rational(0, 3)) }.should raise_error(ZeroDivisionError) + end + + it "raises a ZeroDivisionError when the argument has a numerator of 0.0" do + -> { Rational(3, 4).div(Rational(0.0, 3)) }.should raise_error(ZeroDivisionError) + end end describe "Rational#div passed an Integer" do - it_behaves_like :rational_div_int, :div + it "performs integer division and returns the result" do + Rational(2, 1).div(1).should == 2 + Rational(25, 5).div(-50).should == -1 + end + + it "raises a ZeroDivisionError when the argument is 0" do + -> { Rational(3, 4).div(0) }.should raise_error(ZeroDivisionError) + end end describe "Rational#div passed a Float" do - it_behaves_like :rational_div_float, :div + it "performs integer division and returns the result" do + Rational(2, 3).div(30.333).should == 0 + Rational(2, 9).div(Rational(-8.6)).should == -1 + Rational(3.12).div(0.5).should == 6 + end + + it "raises a ZeroDivisionError when the argument is 0.0" do + -> { Rational(3, 4).div(0.0) }.should raise_error(ZeroDivisionError) + end end diff --git a/spec/ruby/core/rational/divide_spec.rb b/spec/ruby/core/rational/divide_spec.rb index 14e8c4c195f0..8f5ca1fdec7a 100644 --- a/spec/ruby/core/rational/divide_spec.rb +++ b/spec/ruby/core/rational/divide_spec.rb @@ -1,20 +1,74 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/divide' -require_relative '../../shared/rational/arithmetic_exception_in_coerce' +require_relative 'shared/arithmetic_exception_in_coerce' describe "Rational#/" do - it_behaves_like :rational_divide, :/ + it "calls #coerce on the passed argument with self" do + rational = Rational(3, 4) + obj = mock("Object") + obj.should_receive(:coerce).with(rational).and_return([1, 2]) + + rational / obj + end + + it "calls #/ on the coerced Rational with the coerced Object" do + rational = Rational(3, 4) + + coerced_rational = mock("Coerced Rational") + coerced_rational.should_receive(:/).and_return(:result) + + coerced_obj = mock("Coerced Object") + + obj = mock("Object") + obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) + + (rational / obj).should == :result + end + it_behaves_like :rational_arithmetic_exception_in_coerce, :/ end describe "Rational#/ when passed an Integer" do - it_behaves_like :rational_divide_int, :/ + it "returns self divided by other as a Rational" do + (Rational(3, 4) / 2).should eql(Rational(3, 8)) + (Rational(2, 4) / 2).should eql(Rational(1, 4)) + (Rational(6, 7) / -2).should eql(Rational(-3, 7)) + end + + it "raises a ZeroDivisionError when passed 0" do + -> { Rational(3, 4) / 0 }.should raise_error(ZeroDivisionError) + end end describe "Rational#/ when passed a Rational" do - it_behaves_like :rational_divide_rat, :/ + it "returns self divided by other as a Rational" do + (Rational(3, 4) / Rational(3, 4)).should eql(Rational(1, 1)) + (Rational(2, 4) / Rational(1, 4)).should eql(Rational(2, 1)) + + (Rational(2, 4) / 2).should == Rational(1, 4) + (Rational(6, 7) / -2).should == Rational(-3, 7) + end + + it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do + -> { Rational(3, 4) / Rational(0, 1) }.should raise_error(ZeroDivisionError) + end end describe "Rational#/ when passed a Float" do - it_behaves_like :rational_divide_float, :/ + it "returns self divided by other as a Float" do + (Rational(3, 4) / 0.75).should eql(1.0) + (Rational(3, 4) / 0.25).should eql(3.0) + (Rational(3, 4) / 0.3).should eql(2.5) + + (Rational(-3, 4) / 0.3).should eql(-2.5) + (Rational(3, -4) / 0.3).should eql(-2.5) + (Rational(3, 4) / -0.3).should eql(-2.5) + end + + it "returns infinity when passed 0" do + (Rational(3, 4) / 0.0).infinite?.should eql(1) + (Rational(-3, -4) / 0.0).infinite?.should eql(1) + + (Rational(-3, 4) / 0.0).infinite?.should eql(-1) + (Rational(3, -4) / 0.0).infinite?.should eql(-1) + end end diff --git a/spec/ruby/core/rational/divmod_spec.rb b/spec/ruby/core/rational/divmod_spec.rb index 7ffdde74f479..f0555294a3a5 100644 --- a/spec/ruby/core/rational/divmod_spec.rb +++ b/spec/ruby/core/rational/divmod_spec.rb @@ -1,14 +1,42 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/divmod' describe "Rational#divmod when passed a Rational" do - it_behaves_like :rational_divmod_rat, :divmod + it "returns the quotient as Integer and the remainder as Rational" do + Rational(7, 4).divmod(Rational(1, 2)).should eql([3, Rational(1, 4)]) + Rational(7, 4).divmod(Rational(-1, 2)).should eql([-4, Rational(-1, 4)]) + Rational(0, 4).divmod(Rational(4, 3)).should eql([0, Rational(0, 1)]) + + Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([3458764513820540928, Rational(0, 1)]) + end + + it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do + -> { Rational(7, 4).divmod(Rational(0, 3)) }.should raise_error(ZeroDivisionError) + end end describe "Rational#divmod when passed an Integer" do - it_behaves_like :rational_divmod_int, :divmod + it "returns the quotient as Integer and the remainder as Rational" do + Rational(7, 4).divmod(2).should eql([0, Rational(7, 4)]) + Rational(7, 4).divmod(-2).should eql([-1, Rational(-1, 4)]) + + Rational(bignum_value, 4).divmod(3).should eql([1537228672809129301, Rational(1, 1)]) + end + + it "raises a ZeroDivisionError when passed 0" do + -> { Rational(7, 4).divmod(0) }.should raise_error(ZeroDivisionError) + end end describe "Rational#divmod when passed a Float" do - it_behaves_like :rational_divmod_float, :divmod + it "returns the quotient as Integer and the remainder as Float" do + Rational(7, 4).divmod(0.5).should eql([3, 0.25]) + end + + it "returns the quotient as Integer and the remainder as Float" do + Rational(7, 4).divmod(-0.5).should eql([-4, -0.25]) + end + + it "raises a ZeroDivisionError when passed 0" do + -> { Rational(7, 4).divmod(0.0) }.should raise_error(ZeroDivisionError) + end end diff --git a/spec/ruby/core/rational/equal_value_spec.rb b/spec/ruby/core/rational/equal_value_spec.rb index c6f7f4c6a29b..ba40d29c3b13 100644 --- a/spec/ruby/core/rational/equal_value_spec.rb +++ b/spec/ruby/core/rational/equal_value_spec.rb @@ -1,18 +1,39 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/equal_value' describe "Rational#==" do - it_behaves_like :rational_equal_value, :== + it "returns the result of calling #== with self on the passed argument" do + obj = mock("Object") + obj.should_receive(:==).and_return(:result) + + (Rational(3, 4) == obj).should_not be_false + end end describe "Rational#== when passed a Rational" do - it_behaves_like :rational_equal_value_rat, :== + it "returns true if self has the same numerator and denominator as the passed argument" do + (Rational(3, 4) == Rational(3, 4)).should be_true + (Rational(-3, -4) == Rational(3, 4)).should be_true + (Rational(-4, 5) == Rational(4, -5)).should be_true + + (Rational(bignum_value, 3) == Rational(bignum_value, 3)).should be_true + (Rational(-bignum_value, 3) == Rational(bignum_value, -3)).should be_true + end end describe "Rational#== when passed a Float" do - it_behaves_like :rational_equal_value_float, :== + it "converts self to a Float and compares it with the passed argument" do + (Rational(3, 4) == 0.75).should be_true + (Rational(4, 2) == 2.0).should be_true + (Rational(-4, 2) == -2.0).should be_true + (Rational(4, -2) == -2.0).should be_true + end end describe "Rational#== when passed an Integer" do - it_behaves_like :rational_equal_value_int, :== + it "returns true if self has the passed argument as numerator and a denominator of 1" do + # Rational(x, y) reduces x and y automatically + (Rational(4, 2) == 2).should be_true + (Rational(-4, 2) == -2).should be_true + (Rational(4, -2) == -2).should be_true + end end diff --git a/spec/ruby/core/rational/exponent_spec.rb b/spec/ruby/core/rational/exponent_spec.rb index 7e35b4ebc190..f9fdbcb33ef0 100644 --- a/spec/ruby/core/rational/exponent_spec.rb +++ b/spec/ruby/core/rational/exponent_spec.rb @@ -1,6 +1,238 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/exponent' describe "Rational#**" do - it_behaves_like :rational_exponent, :** + describe "when passed Rational" do + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + it "returns Rational(1) if the exponent is Rational(0)" do + (Rational(0) ** Rational(0)).should eql(Rational(1)) + (Rational(1) ** Rational(0)).should eql(Rational(1)) + (Rational(3, 4) ** Rational(0)).should eql(Rational(1)) + (Rational(-1) ** Rational(0)).should eql(Rational(1)) + (Rational(-3, 4) ** Rational(0)).should eql(Rational(1)) + (Rational(bignum_value) ** Rational(0)).should eql(Rational(1)) + (Rational(-bignum_value) ** Rational(0)).should eql(Rational(1)) + end + + it "returns self raised to the argument as a Rational if the exponent's denominator is 1" do + (Rational(3, 4) ** Rational(1, 1)).should eql(Rational(3, 4)) + (Rational(3, 4) ** Rational(2, 1)).should eql(Rational(9, 16)) + (Rational(3, 4) ** Rational(-1, 1)).should eql(Rational(4, 3)) + (Rational(3, 4) ** Rational(-2, 1)).should eql(Rational(16, 9)) + end + + it "returns self raised to the argument as a Float if the exponent's denominator is not 1" do + (Rational(3, 4) ** Rational(4, 3)).should be_close(0.681420222312052, TOLERANCE) + (Rational(3, 4) ** Rational(-4, 3)).should be_close(1.46752322173095, TOLERANCE) + (Rational(3, 4) ** Rational(4, -3)).should be_close(1.46752322173095, TOLERANCE) + end + + it "returns a complex number when self is negative and the passed argument is not 0" do + (Rational(-3, 4) ** Rational(-4, 3)).should be_close(Complex(-0.7337616108654732, 1.2709123906625817), TOLERANCE) + end + end + end + + describe "when passed Integer" do + it "returns the Rational value of self raised to the passed argument" do + (Rational(3, 4) ** 4).should == Rational(81, 256) + (Rational(3, 4) ** -4).should == Rational(256, 81) + (Rational(-3, 4) ** -4).should == Rational(256, 81) + (Rational(3, -4) ** -4).should == Rational(256, 81) + + (Rational(bignum_value, 4) ** 4).should == Rational(452312848583266388373324160190187140051835877600158453279131187530910662656, 1) + (Rational(3, bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81) + (Rational(-bignum_value, 4) ** -4).should == Rational(1, 452312848583266388373324160190187140051835877600158453279131187530910662656) + (Rational(3, -bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81) + end + + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + it "returns Rational(1, 1) when the passed argument is 0" do + (Rational(3, 4) ** 0).should eql(Rational(1, 1)) + (Rational(-3, 4) ** 0).should eql(Rational(1, 1)) + (Rational(3, -4) ** 0).should eql(Rational(1, 1)) + + (Rational(bignum_value, 4) ** 0).should eql(Rational(1, 1)) + (Rational(3, -bignum_value) ** 0).should eql(Rational(1, 1)) + end + end + end + + describe "when passed Bignum" do + # #5713 + it "returns Rational(0) when self is Rational(0) and the exponent is positive" do + (Rational(0) ** bignum_value).should eql(Rational(0)) + end + + it "raises ZeroDivisionError when self is Rational(0) and the exponent is negative" do + -> { Rational(0) ** -bignum_value }.should raise_error(ZeroDivisionError) + end + + it "returns Rational(1) when self is Rational(1)" do + (Rational(1) ** bignum_value).should eql(Rational(1)) + (Rational(1) ** -bignum_value).should eql(Rational(1)) + end + + it "returns Rational(1) when self is Rational(-1) and the exponent is positive and even" do + (Rational(-1) ** bignum_value(0)).should eql(Rational(1)) + (Rational(-1) ** bignum_value(2)).should eql(Rational(1)) + end + + it "returns Rational(-1) when self is Rational(-1) and the exponent is positive and odd" do + (Rational(-1) ** bignum_value(1)).should eql(Rational(-1)) + (Rational(-1) ** bignum_value(3)).should eql(Rational(-1)) + end + + ruby_version_is ""..."3.4" do + it "returns positive Infinity when self is > 1" do + -> { + (Rational(2) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_max) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + end + + it "returns 0.0 when self is > 1 and the exponent is negative" do + -> { + (Rational(2) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_max) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + end + end + + ruby_version_is "3.4" do + it "raises an ArgumentError when self is > 1" do + -> { + (Rational(2) ** bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_max) ** bignum_value) + }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when self is > 1 and the exponent is negative" do + -> { + (Rational(2) ** -bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_max) ** -bignum_value) + }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when self is < -1" do + -> { + (Rational(-2) ** bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_min) ** bignum_value) + }.should raise_error(ArgumentError) + end + + it "raises an ArgumentError when self is < -1 and the exponent is negative" do + -> { + (Rational(-2) ** -bignum_value) + }.should raise_error(ArgumentError) + -> { + (Rational(fixnum_min) ** -bignum_value) + }.should raise_error(ArgumentError) + end + end + + # Fails on linux due to pow() bugs in glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=3866 + platform_is_not :linux do + ruby_version_is ""..."3.4" do + it "returns positive Infinity when self < -1" do + -> { + (Rational(-2) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_min) ** bignum_value).infinite?.should == 1 + }.should complain(/warning: in a\*\*b, b may be too big/) + end + + it "returns 0.0 when self is < -1 and the exponent is negative" do + -> { + (Rational(-2) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + -> { + (Rational(fixnum_min) ** -bignum_value).should eql(0.0) + }.should complain(/warning: in a\*\*b, b may be too big/) + end + end + end + end + + describe "when passed Float" do + it "returns self converted to Float and raised to the passed argument" do + (Rational(3, 1) ** 3.0).should eql(27.0) + (Rational(3, 1) ** 1.5).should be_close(5.19615242270663, TOLERANCE) + (Rational(3, 1) ** -1.5).should be_close(0.192450089729875, TOLERANCE) + end + + it "returns a complex number if self is negative and the passed argument is not 0" do + (Rational(-3, 2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE) + (Rational(3, -2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE) + (Rational(3, -2) ** -1.5).should be_close(Complex(0.0, 0.5443310539518174), TOLERANCE) + end + + it "returns Complex(1.0) when the passed argument is 0.0" do + (Rational(3, 4) ** 0.0).should == Complex(1.0) + (Rational(-3, 4) ** 0.0).should == Complex(1.0) + (Rational(-3, 4) ** 0.0).should == Complex(1.0) + end + end + + it "calls #coerce on the passed argument with self" do + rational = Rational(3, 4) + obj = mock("Object") + obj.should_receive(:coerce).with(rational).and_return([1, 2]) + + rational ** obj + end + + it "calls #** on the coerced Rational with the coerced Object" do + rational = Rational(3, 4) + + coerced_rational = mock("Coerced Rational") + coerced_rational.should_receive(:**).and_return(:result) + + coerced_obj = mock("Coerced Object") + + obj = mock("Object") + obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) + + (rational ** obj).should == :result + end + + it "raises ZeroDivisionError for Rational(0, 1) passed a negative Integer" do + [-1, -4, -9999].each do |exponent| + -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0") + end + end + + it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational with denominator 1" do + [Rational(-1, 1), Rational(-3, 1)].each do |exponent| + -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0") + end + end + + # #7513 + it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational" do + -> { Rational(0, 1) ** Rational(-3, 2) }.should raise_error(ZeroDivisionError, "divided by 0") + end + + platform_is_not :solaris do # See https://github.com/ruby/spec/issues/134 + it "returns Infinity for Rational(0, 1) passed a negative Float" do + [-1.0, -3.0, -3.14].each do |exponent| + (Rational(0, 1) ** exponent).infinite?.should == 1 + end + end + end end diff --git a/spec/ruby/core/rational/fdiv_spec.rb b/spec/ruby/core/rational/fdiv_spec.rb index b75f39abd584..118d93dbe726 100644 --- a/spec/ruby/core/rational/fdiv_spec.rb +++ b/spec/ruby/core/rational/fdiv_spec.rb @@ -1,6 +1,5 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/fdiv' describe "Rational#fdiv" do - it_behaves_like :rational_fdiv, :fdiv + it "needs to be reviewed for spec completeness" end diff --git a/spec/ruby/fixtures/rational.rb b/spec/ruby/core/rational/fixtures/rational.rb similarity index 100% rename from spec/ruby/fixtures/rational.rb rename to spec/ruby/core/rational/fixtures/rational.rb diff --git a/spec/ruby/core/rational/floor_spec.rb b/spec/ruby/core/rational/floor_spec.rb index 70db0499d0d7..8068aaf119e7 100644 --- a/spec/ruby/core/rational/floor_spec.rb +++ b/spec/ruby/core/rational/floor_spec.rb @@ -1,6 +1,45 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/floor' describe "Rational#floor" do - it_behaves_like :rational_floor, :floor + before do + @rational = Rational(2200, 7) + end + + describe "with no arguments (precision = 0)" do + it "returns an integer" do + @rational.floor.should be_kind_of(Integer) + end + + it "returns the truncated value toward negative infinity" do + @rational.floor.should == 314 + Rational(1, 2).floor.should == 0 + Rational(-1, 2).floor.should == -1 + end + end + + describe "with a precision < 0" do + it "returns an integer" do + @rational.floor(-2).should be_kind_of(Integer) + @rational.floor(-1).should be_kind_of(Integer) + end + + it "moves the truncation point n decimal places left" do + @rational.floor(-3).should == 0 + @rational.floor(-2).should == 300 + @rational.floor(-1).should == 310 + end + end + + describe "with a precision > 0" do + it "returns a Rational" do + @rational.floor(1).should be_kind_of(Rational) + @rational.floor(2).should be_kind_of(Rational) + end + + it "moves the truncation point n decimal places right" do + @rational.floor(1).should == Rational(1571, 5) + @rational.floor(2).should == Rational(7857, 25) + @rational.floor(3).should == Rational(62857, 200) + end + end end diff --git a/spec/ruby/core/rational/hash_spec.rb b/spec/ruby/core/rational/hash_spec.rb index 7e8d30049b32..528638056a02 100644 --- a/spec/ruby/core/rational/hash_spec.rb +++ b/spec/ruby/core/rational/hash_spec.rb @@ -1,6 +1,9 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/hash' describe "Rational#hash" do - it_behaves_like :rational_hash, :hash + # BUG: Rational(2, 3).hash == Rational(3, 2).hash + it "is static" do + Rational(2, 3).hash.should == Rational(2, 3).hash + Rational(2, 4).hash.should_not == Rational(2, 3).hash + end end diff --git a/spec/ruby/core/rational/inspect_spec.rb b/spec/ruby/core/rational/inspect_spec.rb index 2cbf6cadc14d..edc5cffee948 100644 --- a/spec/ruby/core/rational/inspect_spec.rb +++ b/spec/ruby/core/rational/inspect_spec.rb @@ -1,6 +1,14 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/inspect' describe "Rational#inspect" do - it_behaves_like :rational_inspect, :inspect + it "returns a string representation of self" do + Rational(3, 4).inspect.should == "(3/4)" + Rational(-5, 8).inspect.should == "(-5/8)" + Rational(-1, -2).inspect.should == "(1/2)" + + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + Rational(bignum_value, 1).inspect.should == "(#{bignum_value}/1)" + end + end end diff --git a/spec/ruby/core/rational/magnitude_spec.rb b/spec/ruby/core/rational/magnitude_spec.rb index 27d9af6a8146..f5f667edb1b4 100644 --- a/spec/ruby/core/rational/magnitude_spec.rb +++ b/spec/ruby/core/rational/magnitude_spec.rb @@ -1,5 +1,5 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/abs' +require_relative 'shared/abs' describe "Rational#abs" do it_behaves_like :rational_abs, :magnitude diff --git a/spec/ruby/core/rational/minus_spec.rb b/spec/ruby/core/rational/minus_spec.rb index a61b62ebe641..8aee85f9dd6d 100644 --- a/spec/ruby/core/rational/minus_spec.rb +++ b/spec/ruby/core/rational/minus_spec.rb @@ -1,5 +1,5 @@ require_relative '../../spec_helper' -require_relative '../../shared/rational/arithmetic_exception_in_coerce' +require_relative 'shared/arithmetic_exception_in_coerce' describe "Rational#-" do it_behaves_like :rational_arithmetic_exception_in_coerce, :- diff --git a/spec/ruby/core/rational/modulo_spec.rb b/spec/ruby/core/rational/modulo_spec.rb index 7a60c176acfd..23ed93e118e6 100644 --- a/spec/ruby/core/rational/modulo_spec.rb +++ b/spec/ruby/core/rational/modulo_spec.rb @@ -1,6 +1,43 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/modulo' describe "Rational#%" do - it_behaves_like :rational_modulo, :% + it "returns the remainder when this value is divided by other" do + (Rational(2, 3) % Rational(2, 3)).should == Rational(0, 1) + (Rational(4, 3) % Rational(2, 3)).should == Rational(0, 1) + (Rational(2, -3) % Rational(-2, 3)).should == Rational(0, 1) + (Rational(0, -1) % -1).should == Rational(0, 1) + + (Rational(7, 4) % Rational(1, 2)).should == Rational(1, 4) + (Rational(7, 4) % 1).should == Rational(3, 4) + (Rational(7, 4) % Rational(1, 7)).should == Rational(1, 28) + + (Rational(3, 4) % -1).should == Rational(-1, 4) + (Rational(1, -5) % -1).should == Rational(-1, 5) + end + + it "returns a Float value when the argument is Float" do + (Rational(7, 4) % 1.0).should be_kind_of(Float) + (Rational(7, 4) % 1.0).should == 0.75 + (Rational(7, 4) % 0.26).should be_close(0.19, 0.0001) + end + + it "raises ZeroDivisionError on zero denominator" do + -> { + Rational(3, 5) % Rational(0, 1) + }.should raise_error(ZeroDivisionError) + + -> { + Rational(0, 1) % Rational(0, 1) + }.should raise_error(ZeroDivisionError) + + -> { + Rational(3, 5) % 0 + }.should raise_error(ZeroDivisionError) + end + + it "raises a ZeroDivisionError when the argument is 0.0" do + -> { + Rational(3, 5) % 0.0 + }.should raise_error(ZeroDivisionError) + end end diff --git a/spec/ruby/core/rational/multiply_spec.rb b/spec/ruby/core/rational/multiply_spec.rb index 7413376bb166..87fb4de2b449 100644 --- a/spec/ruby/core/rational/multiply_spec.rb +++ b/spec/ruby/core/rational/multiply_spec.rb @@ -1,20 +1,65 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/multiply' -require_relative '../../shared/rational/arithmetic_exception_in_coerce' +require_relative 'shared/arithmetic_exception_in_coerce' describe "Rational#*" do - it_behaves_like :rational_multiply, :* + it "calls #coerce on the passed argument with self" do + rational = Rational(3, 4) + obj = mock("Object") + obj.should_receive(:coerce).with(rational).and_return([1, 2]) + + rational * obj + end + + it "calls #* on the coerced Rational with the coerced Object" do + rational = Rational(3, 4) + + coerced_rational = mock("Coerced Rational") + coerced_rational.should_receive(:*).and_return(:result) + + coerced_obj = mock("Coerced Object") + + obj = mock("Object") + obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) + + (rational * obj).should == :result + end + it_behaves_like :rational_arithmetic_exception_in_coerce, :* end describe "Rational#* passed a Rational" do - it_behaves_like :rational_multiply_rat, :* + it "returns self divided by other as a Rational" do + (Rational(3, 4) * Rational(3, 4)).should eql(Rational(9, 16)) + (Rational(2, 4) * Rational(1, 4)).should eql(Rational(1, 8)) + + (Rational(3, 4) * Rational(0, 1)).should eql(Rational(0, 4)) + end end describe "Rational#* passed a Float" do - it_behaves_like :rational_multiply_float, :* + it "returns self divided by other as a Float" do + (Rational(3, 4) * 0.75).should eql(0.5625) + (Rational(3, 4) * 0.25).should eql(0.1875) + (Rational(3, 4) * 0.3).should be_close(0.225, TOLERANCE) + + (Rational(-3, 4) * 0.3).should be_close(-0.225, TOLERANCE) + (Rational(3, -4) * 0.3).should be_close(-0.225, TOLERANCE) + (Rational(3, 4) * -0.3).should be_close(-0.225, TOLERANCE) + + (Rational(3, 4) * 0.0).should eql(0.0) + (Rational(-3, -4) * 0.0).should eql(0.0) + + (Rational(-3, 4) * 0.0).should eql(0.0) + (Rational(3, -4) * 0.0).should eql(0.0) + end end describe "Rational#* passed an Integer" do - it_behaves_like :rational_multiply_int, :* + it "returns self divided by other as a Rational" do + (Rational(3, 4) * 2).should eql(Rational(3, 2)) + (Rational(2, 4) * 2).should eql(Rational(1, 1)) + (Rational(6, 7) * -2).should eql(Rational(-12, 7)) + + (Rational(3, 4) * 0).should eql(Rational(0, 4)) + end end diff --git a/spec/ruby/core/rational/numerator_spec.rb b/spec/ruby/core/rational/numerator_spec.rb index 6f9a9c0e3b2a..2b9fe2ff5c15 100644 --- a/spec/ruby/core/rational/numerator_spec.rb +++ b/spec/ruby/core/rational/numerator_spec.rb @@ -1,6 +1,10 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/numerator' describe "Rational#numerator" do - it_behaves_like :rational_numerator, :numerator + it "returns the numerator" do + Rational(3, 4).numerator.should equal(3) + Rational(3, -4).numerator.should equal(-3) + + Rational(bignum_value, 1).numerator.should == bignum_value + end end diff --git a/spec/ruby/core/rational/plus_spec.rb b/spec/ruby/core/rational/plus_spec.rb index 67c0ff63d236..01df5f67192e 100644 --- a/spec/ruby/core/rational/plus_spec.rb +++ b/spec/ruby/core/rational/plus_spec.rb @@ -1,19 +1,50 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/plus' -require_relative '../../shared/rational/arithmetic_exception_in_coerce' +require_relative 'shared/arithmetic_exception_in_coerce' describe "Rational#+" do - it_behaves_like :rational_plus, :+ + it "calls #coerce on the passed argument with self" do + rational = Rational(3, 4) + obj = mock("Object") + obj.should_receive(:coerce).with(rational).and_return([1, 2]) + + rational + obj + end + + it "calls #+ on the coerced Rational with the coerced Object" do + rational = Rational(3, 4) + + coerced_rational = mock("Coerced Rational") + coerced_rational.should_receive(:+).and_return(:result) + + coerced_obj = mock("Coerced Object") + + obj = mock("Object") + obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) + + (rational + obj).should == :result + end + it_behaves_like :rational_arithmetic_exception_in_coerce, :+ end describe "Rational#+ with a Rational" do - it_behaves_like :rational_plus_rat, :+ + it "returns the result of subtracting other from self as a Rational" do + (Rational(3, 4) + Rational(0, 1)).should eql(Rational(3, 4)) + (Rational(3, 4) + Rational(1, 4)).should eql(Rational(1, 1)) + + (Rational(3, 4) + Rational(2, 1)).should eql(Rational(11, 4)) + end end describe "Rational#+ with a Float" do - it_behaves_like :rational_plus_float, :+ + it "returns the result of subtracting other from self as a Float" do + (Rational(3, 4) + 0.2).should eql(0.95) + (Rational(3, 4) + 2.5).should eql(3.25) + end end describe "Rational#+ with an Integer" do - it_behaves_like :rational_plus_int, :+ + it "returns the result of subtracting other from self as a Rational" do + (Rational(3, 4) + 1).should eql(Rational(7, 4)) + (Rational(3, 4) + 2).should eql(Rational(11, 4)) + end end diff --git a/spec/ruby/core/rational/quo_spec.rb b/spec/ruby/core/rational/quo_spec.rb index 181f091f7c63..907898ad3492 100644 --- a/spec/ruby/core/rational/quo_spec.rb +++ b/spec/ruby/core/rational/quo_spec.rb @@ -1,6 +1,25 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/divide' describe "Rational#quo" do - it_behaves_like :rational_divide, :quo + it "calls #coerce on the passed argument with self" do + rational = Rational(3, 4) + obj = mock("Object") + obj.should_receive(:coerce).with(rational).and_return([1, 2]) + + rational.quo(obj) + end + + it "calls #/ on the coerced Rational with the coerced Object" do + rational = Rational(3, 4) + + coerced_rational = mock("Coerced Rational") + coerced_rational.should_receive(:/).and_return(:result) + + coerced_obj = mock("Coerced Object") + + obj = mock("Object") + obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) + + rational.quo(obj).should == :result + end end diff --git a/spec/ruby/core/rational/remainder_spec.rb b/spec/ruby/core/rational/remainder_spec.rb index 1c0035e5f4a8..86ba4674e63a 100644 --- a/spec/ruby/core/rational/remainder_spec.rb +++ b/spec/ruby/core/rational/remainder_spec.rb @@ -1,6 +1,5 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/remainder' describe "Rational#remainder" do - it_behaves_like :rational_remainder, :remainder + it "needs to be reviewed for spec completeness" end diff --git a/spec/ruby/core/rational/round_spec.rb b/spec/ruby/core/rational/round_spec.rb index 36614a552de0..ac3dcafe7bd7 100644 --- a/spec/ruby/core/rational/round_spec.rb +++ b/spec/ruby/core/rational/round_spec.rb @@ -1,6 +1,106 @@ require_relative '../../spec_helper' -require_relative '../../shared/rational/round' describe "Rational#round" do - it_behaves_like :rational_round, :round + before do + @rational = Rational(2200, 7) + end + + describe "with no arguments (precision = 0)" do + it "returns an integer" do + @rational.round.should be_kind_of(Integer) + Rational(0, 1).round(0).should be_kind_of(Integer) + Rational(124, 1).round(0).should be_kind_of(Integer) + end + + it "returns the truncated value toward the nearest integer" do + @rational.round.should == 314 + Rational(0, 1).round(0).should == 0 + Rational(2, 1).round(0).should == 2 + end + + it "returns the rounded value toward the nearest integer" do + Rational(1, 2).round.should == 1 + Rational(-1, 2).round.should == -1 + Rational(3, 2).round.should == 2 + Rational(-3, 2).round.should == -2 + Rational(5, 2).round.should == 3 + Rational(-5, 2).round.should == -3 + end + end + + describe "with a precision < 0" do + it "returns an integer" do + @rational.round(-2).should be_kind_of(Integer) + @rational.round(-1).should be_kind_of(Integer) + Rational(0, 1).round(-1).should be_kind_of(Integer) + Rational(2, 1).round(-1).should be_kind_of(Integer) + end + + it "moves the truncation point n decimal places left" do + @rational.round(-3).should == 0 + @rational.round(-2).should == 300 + @rational.round(-1).should == 310 + end + end + + describe "with a precision > 0" do + it "returns a Rational" do + @rational.round(1).should be_kind_of(Rational) + @rational.round(2).should be_kind_of(Rational) + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + Rational(0, 1).round(1).should be_kind_of(Rational) + Rational(2, 1).round(1).should be_kind_of(Rational) + end + end + + it "moves the truncation point n decimal places right" do + @rational.round(1).should == Rational(3143, 10) + @rational.round(2).should == Rational(31429, 100) + @rational.round(3).should == Rational(157143, 500) + Rational(0, 1).round(1).should == Rational(0, 1) + Rational(2, 1).round(1).should == Rational(2, 1) + end + + it "doesn't alter the value if the precision is too great" do + Rational(3, 2).round(10).should == Rational(3, 2).round(20) + end + + # #6605 + it "doesn't fail when rounding to an absurdly large positive precision" do + Rational(3, 2).round(2_097_171).should == Rational(3, 2) + end + end + + describe "with half option" do + it "returns an Integer when precision is not passed" do + Rational(10, 4).round(half: nil).should == 3 + Rational(10, 4).round(half: :up).should == 3 + Rational(10, 4).round(half: :down).should == 2 + Rational(10, 4).round(half: :even).should == 2 + Rational(-10, 4).round(half: nil).should == -3 + Rational(-10, 4).round(half: :up).should == -3 + Rational(-10, 4).round(half: :down).should == -2 + Rational(-10, 4).round(half: :even).should == -2 + end + + it "returns a Rational when the precision is greater than 0" do + Rational(25, 100).round(1, half: nil).should == Rational(3, 10) + Rational(25, 100).round(1, half: :up).should == Rational(3, 10) + Rational(25, 100).round(1, half: :down).should == Rational(1, 5) + Rational(25, 100).round(1, half: :even).should == Rational(1, 5) + Rational(35, 100).round(1, half: nil).should == Rational(2, 5) + Rational(35, 100).round(1, half: :up).should == Rational(2, 5) + Rational(35, 100).round(1, half: :down).should == Rational(3, 10) + Rational(35, 100).round(1, half: :even).should == Rational(2, 5) + Rational(-25, 100).round(1, half: nil).should == Rational(-3, 10) + Rational(-25, 100).round(1, half: :up).should == Rational(-3, 10) + Rational(-25, 100).round(1, half: :down).should == Rational(-1, 5) + Rational(-25, 100).round(1, half: :even).should == Rational(-1, 5) + end + + it "raise for a non-existent round mode" do + -> { Rational(10, 4).round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense") + end + end end diff --git a/spec/ruby/shared/rational/abs.rb b/spec/ruby/core/rational/shared/abs.rb similarity index 90% rename from spec/ruby/shared/rational/abs.rb rename to spec/ruby/core/rational/shared/abs.rb index 8beb20da7e3f..3d64bcc1a0e9 100644 --- a/spec/ruby/shared/rational/abs.rb +++ b/spec/ruby/core/rational/shared/abs.rb @@ -1,4 +1,4 @@ -require_relative '../../spec_helper' +require_relative '../../../spec_helper' describe :rational_abs, shared: true do it "returns self's absolute value" do diff --git a/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb b/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb similarity index 89% rename from spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb rename to spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb index 0dff91d522b7..f4cf70d147d2 100644 --- a/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb +++ b/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb @@ -1,4 +1,4 @@ -require_relative '../../fixtures/rational' +require_relative '../fixtures/rational' describe :rational_arithmetic_exception_in_coerce, shared: true do it "does not rescue exception raised in other#coerce" do diff --git a/spec/ruby/core/rational/to_f_spec.rb b/spec/ruby/core/rational/to_f_spec.rb index a9cd1be3b534..d0da49d3772b 100644 --- a/spec/ruby/core/rational/to_f_spec.rb +++ b/spec/ruby/core/rational/to_f_spec.rb @@ -1,6 +1,16 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/to_f' describe "Rational#to_f" do - it_behaves_like :rational_to_f, :to_f + it "returns self converted to a Float" do + Rational(3, 4).to_f.should eql(0.75) + Rational(3, -4).to_f.should eql(-0.75) + Rational(-1, 4).to_f.should eql(-0.25) + Rational(-1, -4).to_f.should eql(0.25) + end + + it "converts to a Float for large numerator and denominator" do + num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009 + den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + Rational(num, den).to_f.should == 500.0 + end end diff --git a/spec/ruby/core/rational/to_i_spec.rb b/spec/ruby/core/rational/to_i_spec.rb index 22cf02b4daea..520a380b2aeb 100644 --- a/spec/ruby/core/rational/to_i_spec.rb +++ b/spec/ruby/core/rational/to_i_spec.rb @@ -1,6 +1,12 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/to_i' describe "Rational#to_i" do - it_behaves_like :rational_to_i, :to_i + it "converts self to an Integer by truncation" do + Rational(7, 4).to_i.should eql(1) + Rational(11, 4).to_i.should eql(2) + end + + it "converts self to an Integer by truncation" do + Rational(-7, 4).to_i.should eql(-1) + end end diff --git a/spec/ruby/core/rational/to_r_spec.rb b/spec/ruby/core/rational/to_r_spec.rb index 03f204daf174..34f16d7890d7 100644 --- a/spec/ruby/core/rational/to_r_spec.rb +++ b/spec/ruby/core/rational/to_r_spec.rb @@ -1,8 +1,13 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/to_r' describe "Rational#to_r" do - it_behaves_like :rational_to_r, :to_r + it "returns self" do + a = Rational(3, 4) + a.to_r.should equal(a) + + a = Rational(bignum_value, 4) + a.to_r.should equal(a) + end it "raises TypeError trying to convert BasicObject" do obj = BasicObject.new diff --git a/spec/ruby/core/rational/to_s_spec.rb b/spec/ruby/core/rational/to_s_spec.rb index 5d90c7d80b04..24e30778e5a6 100644 --- a/spec/ruby/core/rational/to_s_spec.rb +++ b/spec/ruby/core/rational/to_s_spec.rb @@ -1,6 +1,14 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/to_s' describe "Rational#to_s" do - it_behaves_like :rational_to_s, :to_s + it "returns a string representation of self" do + # Guard against the Mathn library + guard -> { !defined?(Math.rsqrt) } do + Rational(1, 1).to_s.should == "1/1" + Rational(2, 1).to_s.should == "2/1" + end + Rational(1, 2).to_s.should == "1/2" + Rational(-1, 3).to_s.should == "-1/3" + Rational(1, -3).to_s.should == "-1/3" + end end diff --git a/spec/ruby/core/rational/truncate_spec.rb b/spec/ruby/core/rational/truncate_spec.rb index 47a7cdf17c8d..728fca34eaea 100644 --- a/spec/ruby/core/rational/truncate_spec.rb +++ b/spec/ruby/core/rational/truncate_spec.rb @@ -1,6 +1,71 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/truncate' describe "Rational#truncate" do - it_behaves_like :rational_truncate, :truncate + before do + @rational = Rational(2200, 7) + end + + describe "with no arguments (precision = 0)" do + it "returns an integer" do + @rational.truncate.should be_kind_of(Integer) + end + + it "returns the truncated value toward 0" do + @rational.truncate.should == 314 + Rational(1, 2).truncate.should == 0 + Rational(-1, 2).truncate.should == 0 + end + end + + describe "with an explicit precision = 0" do + it "returns an integer" do + @rational.truncate(0).should be_kind_of(Integer) + end + + it "returns the truncated value toward 0" do + @rational.truncate(0).should == 314 + Rational(1, 2).truncate(0).should == 0 + Rational(-1, 2).truncate(0).should == 0 + end + end + + describe "with a precision < 0" do + it "returns an integer" do + @rational.truncate(-2).should be_kind_of(Integer) + @rational.truncate(-1).should be_kind_of(Integer) + end + + it "moves the truncation point n decimal places left" do + @rational.truncate(-3).should == 0 + @rational.truncate(-2).should == 300 + @rational.truncate(-1).should == 310 + end + end + + describe "with a precision > 0" do + it "returns a Rational" do + @rational.truncate(1).should be_kind_of(Rational) + @rational.truncate(2).should be_kind_of(Rational) + end + + it "moves the truncation point n decimal places right" do + @rational.truncate(1).should == Rational(1571, 5) + @rational.truncate(2).should == Rational(7857, 25) + @rational.truncate(3).should == Rational(62857, 200) + end + end + + describe "with an invalid value for precision" do + it "raises a TypeError" do + -> { @rational.truncate(nil) }.should raise_error(TypeError, "not an integer") + -> { @rational.truncate(1.0) }.should raise_error(TypeError, "not an integer") + -> { @rational.truncate('') }.should raise_error(TypeError, "not an integer") + end + + it "does not call to_int on the argument" do + object = Object.new + object.should_not_receive(:to_int) + -> { @rational.truncate(object) }.should raise_error(TypeError, "not an integer") + end + end end diff --git a/spec/ruby/language/regexp_spec.rb b/spec/ruby/language/regexp_spec.rb index dbf341b19ea5..0cd9584549b8 100644 --- a/spec/ruby/language/regexp_spec.rb +++ b/spec/ruby/language/regexp_spec.rb @@ -112,7 +112,7 @@ /foo.(?<=\d)/.match("fooA foo1").to_a.should == ["foo1"] end - ruby_bug "#13671", ""..."3.5" do # https://bugs.ruby-lang.org/issues/13671 + ruby_bug "#13671", ""..."3.6" do # https://bugs.ruby-lang.org/issues/13671 it "handles a lookbehind with ss characters" do r = Regexp.new("(?= "3.1.9" + BigDecimal("0.", exception: false).to_i.should == 0 + else + BigDecimal("0.", exception: false).should be_nil + end end end diff --git a/spec/ruby/library/socket/socket/connect_spec.rb b/spec/ruby/library/socket/socket/connect_spec.rb index 7fceb47b009f..130379ce2b5e 100644 --- a/spec/ruby/library/socket/socket/connect_spec.rb +++ b/spec/ruby/library/socket/socket/connect_spec.rb @@ -67,8 +67,12 @@ client.connect(address) rescue Errno::ECONNREFUSED skip "Outgoing packets may be filtered" + rescue Errno::ENETUNREACH + skip "Off line" end }.should raise_error(IO::TimeoutError) + ensure + client.close end end end diff --git a/spec/ruby/shared/rational/Rational.rb b/spec/ruby/shared/rational/Rational.rb deleted file mode 100644 index 500f7ed271e8..000000000000 --- a/spec/ruby/shared/rational/Rational.rb +++ /dev/null @@ -1,150 +0,0 @@ -require_relative '../../spec_helper' -require_relative '../../fixtures/rational' - -describe :kernel_Rational, shared: true do - describe "passed Integer" do - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - it "returns a new Rational number with 1 as the denominator" do - Rational(1).should eql(Rational(1, 1)) - Rational(-3).should eql(Rational(-3, 1)) - Rational(bignum_value).should eql(Rational(bignum_value, 1)) - end - end - end - - describe "passed two integers" do - it "returns a new Rational number" do - rat = Rational(1, 2) - rat.numerator.should == 1 - rat.denominator.should == 2 - rat.should be_an_instance_of(Rational) - - rat = Rational(-3, -5) - rat.numerator.should == 3 - rat.denominator.should == 5 - rat.should be_an_instance_of(Rational) - - rat = Rational(bignum_value, 3) - rat.numerator.should == bignum_value - rat.denominator.should == 3 - rat.should be_an_instance_of(Rational) - end - - it "reduces the Rational" do - rat = Rational(2, 4) - rat.numerator.should == 1 - rat.denominator.should == 2 - - rat = Rational(3, 9) - rat.numerator.should == 1 - rat.denominator.should == 3 - end - end - - describe "when passed a String" do - it "converts the String to a Rational using the same method as String#to_r" do - r = Rational(13, 25) - s_r = ".52".to_r - r_s = Rational(".52") - - r_s.should == r - r_s.should == s_r - end - - it "scales the Rational value of the first argument by the Rational value of the second" do - Rational(".52", ".6").should == Rational(13, 15) - Rational(".52", "1.6").should == Rational(13, 40) - end - - it "does not use the same method as Float#to_r" do - r = Rational(3, 5) - f_r = 0.6.to_r - r_s = Rational("0.6") - - r_s.should == r - r_s.should_not == f_r - end - end - - describe "when passed a Numeric" do - it "calls #to_r to convert the first argument to a Rational" do - num = RationalSpecs::SubNumeric.new(2) - - Rational(num).should == Rational(2) - end - end - - describe "when passed a Complex" do - it "returns a Rational from the real part if the imaginary part is 0" do - Rational(Complex(1, 0)).should == Rational(1) - end - - it "raises a RangeError if the imaginary part is not 0" do - -> { Rational(Complex(1, 2)) }.should raise_error(RangeError) - end - end - - it "raises a ZeroDivisionError if the second argument is 0" do - -> { Rational(1, 0) }.should raise_error(ZeroDivisionError, "divided by 0") - -> { Rational(1, 0.0) }.should raise_error(ZeroDivisionError, "divided by 0") - end - - it "raises a TypeError if the first argument is nil" do - -> { Rational(nil) }.should raise_error(TypeError) - end - - it "raises a TypeError if the second argument is nil" do - -> { Rational(1, nil) }.should raise_error(TypeError) - end - - it "raises a TypeError if the first argument is a Symbol" do - -> { Rational(:sym) }.should raise_error(TypeError) - end - - it "raises a TypeError if the second argument is a Symbol" do - -> { Rational(1, :sym) }.should raise_error(TypeError) - end - - describe "when passed exception: false" do - describe "and [non-Numeric]" do - it "swallows an error" do - Rational(:sym, exception: false).should == nil - Rational("abc", exception: false).should == nil - end - end - - describe "and [non-Numeric, Numeric]" do - it "swallows an error" do - Rational(:sym, 1, exception: false).should == nil - Rational("abc", 1, exception: false).should == nil - end - end - - describe "and [anything, non-Numeric]" do - it "swallows an error" do - Rational(:sym, :sym, exception: false).should == nil - Rational("abc", :sym, exception: false).should == nil - end - end - - describe "and non-Numeric String arguments" do - it "swallows an error" do - Rational("a", "b", exception: false).should == nil - Rational("a", 0, exception: false).should == nil - Rational(0, "b", exception: false).should == nil - end - end - - describe "and nil arguments" do - it "swallows an error" do - Rational(nil, exception: false).should == nil - Rational(nil, nil, exception: false).should == nil - end - end - end - - it "freezes its result" do - Rational(1).frozen?.should == true - end -end diff --git a/spec/ruby/shared/rational/ceil.rb b/spec/ruby/shared/rational/ceil.rb deleted file mode 100644 index f1cf60d2be4f..000000000000 --- a/spec/ruby/shared/rational/ceil.rb +++ /dev/null @@ -1,45 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_ceil, shared: true do - before do - @rational = Rational(2200, 7) - end - - describe "with no arguments (precision = 0)" do - it "returns an Integer" do - @rational.ceil.should be_kind_of(Integer) - end - - it "returns the truncated value toward positive infinity" do - @rational.ceil.should == 315 - Rational(1, 2).ceil.should == 1 - Rational(-1, 2).ceil.should == 0 - end - end - - describe "with a precision < 0" do - it "returns an Integer" do - @rational.ceil(-2).should be_kind_of(Integer) - @rational.ceil(-1).should be_kind_of(Integer) - end - - it "moves the truncation point n decimal places left" do - @rational.ceil(-3).should == 1000 - @rational.ceil(-2).should == 400 - @rational.ceil(-1).should == 320 - end - end - - describe "with precision > 0" do - it "returns a Rational" do - @rational.ceil(1).should be_kind_of(Rational) - @rational.ceil(2).should be_kind_of(Rational) - end - - it "moves the truncation point n decimal places right" do - @rational.ceil(1).should == Rational(3143, 10) - @rational.ceil(2).should == Rational(31429, 100) - @rational.ceil(3).should == Rational(157143, 500) - end - end -end diff --git a/spec/ruby/shared/rational/comparison.rb b/spec/ruby/shared/rational/comparison.rb deleted file mode 100644 index 860462f5797d..000000000000 --- a/spec/ruby/shared/rational/comparison.rb +++ /dev/null @@ -1,95 +0,0 @@ -require_relative '../../spec_helper' -require_relative '../../fixtures/rational' - -describe :rational_cmp_rat, shared: true do - it "returns 1 when self is greater than the passed argument" do - (Rational(4, 4) <=> Rational(3, 4)).should equal(1) - (Rational(-3, 4) <=> Rational(-4, 4)).should equal(1) - end - - it "returns 0 when self is equal to the passed argument" do - (Rational(4, 4) <=> Rational(4, 4)).should equal(0) - (Rational(-3, 4) <=> Rational(-3, 4)).should equal(0) - end - - it "returns -1 when self is less than the passed argument" do - (Rational(3, 4) <=> Rational(4, 4)).should equal(-1) - (Rational(-4, 4) <=> Rational(-3, 4)).should equal(-1) - end -end - -describe :rational_cmp_int, shared: true do - it "returns 1 when self is greater than the passed argument" do - (Rational(4, 4) <=> 0).should equal(1) - (Rational(4, 4) <=> -10).should equal(1) - (Rational(-3, 4) <=> -1).should equal(1) - end - - it "returns 0 when self is equal to the passed argument" do - (Rational(4, 4) <=> 1).should equal(0) - (Rational(-8, 4) <=> -2).should equal(0) - end - - it "returns -1 when self is less than the passed argument" do - (Rational(3, 4) <=> 1).should equal(-1) - (Rational(-4, 4) <=> 0).should equal(-1) - end -end - -describe :rational_cmp_float, shared: true do - it "returns 1 when self is greater than the passed argument" do - (Rational(4, 4) <=> 0.5).should equal(1) - (Rational(4, 4) <=> -1.5).should equal(1) - (Rational(-3, 4) <=> -0.8).should equal(1) - end - - it "returns 0 when self is equal to the passed argument" do - (Rational(4, 4) <=> 1.0).should equal(0) - (Rational(-6, 4) <=> -1.5).should equal(0) - end - - it "returns -1 when self is less than the passed argument" do - (Rational(3, 4) <=> 1.2).should equal(-1) - (Rational(-4, 4) <=> 0.5).should equal(-1) - end -end - -describe :rational_cmp_coerce, shared: true do - it "calls #coerce on the passed argument with self" do - rational = Rational(3, 4) - - obj = mock("Object") - obj.should_receive(:coerce).with(rational).and_return([1, 2]) - - rational <=> obj - end - - it "calls #<=> on the coerced Rational with the coerced Object" do - rational = Rational(3, 4) - - coerced_rational = mock("Coerced Rational") - coerced_rational.should_receive(:<=>).and_return(:result) - - coerced_obj = mock("Coerced Object") - - obj = mock("Object") - obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) - - (rational <=> obj).should == :result - end -end - -describe :rational_cmp_coerce_exception, shared: true do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError) - - -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError) - end -end - -describe :rational_cmp_other, shared: true do - it "returns nil" do - (Rational <=> mock("Object")).should be_nil - end -end diff --git a/spec/ruby/shared/rational/denominator.rb b/spec/ruby/shared/rational/denominator.rb deleted file mode 100644 index 10d46aacb393..000000000000 --- a/spec/ruby/shared/rational/denominator.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_denominator, shared: true do - it "returns the denominator" do - Rational(3, 4).denominator.should equal(4) - Rational(3, -4).denominator.should equal(4) - - Rational(1, bignum_value).denominator.should == bignum_value - end - - it "returns 1 if no denominator was given" do - Rational(80).denominator.should == 1 - end -end diff --git a/spec/ruby/shared/rational/div.rb b/spec/ruby/shared/rational/div.rb deleted file mode 100644 index d5bd9e664482..000000000000 --- a/spec/ruby/shared/rational/div.rb +++ /dev/null @@ -1,54 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_div_rat, shared: true do - it "performs integer division and returns the result" do - Rational(2, 3).div(Rational(2, 3)).should == 1 - Rational(-2, 9).div(Rational(-9, 2)).should == 0 - end - - it "raises a ZeroDivisionError when the argument has a numerator of 0" do - -> { Rational(3, 4).div(Rational(0, 3)) }.should raise_error(ZeroDivisionError) - end - - it "raises a ZeroDivisionError when the argument has a numerator of 0.0" do - -> { Rational(3, 4).div(Rational(0.0, 3)) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_div_float, shared: true do - it "performs integer division and returns the result" do - Rational(2, 3).div(30.333).should == 0 - Rational(2, 9).div(Rational(-8.6)).should == -1 - Rational(3.12).div(0.5).should == 6 - end - - it "raises a ZeroDivisionError when the argument is 0.0" do - -> { Rational(3, 4).div(0.0) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_div_int, shared: true do - it "performs integer division and returns the result" do - Rational(2, 1).div(1).should == 2 - Rational(25, 5).div(-50).should == -1 - end - - it "raises a ZeroDivisionError when the argument is 0" do - -> { Rational(3, 4).div(0) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_div, shared: true do - it "returns an Integer" do - Rational(229, 21).div(82).should be_kind_of(Integer) - end - - it "raises an ArgumentError if passed more than one argument" do - -> { Rational(3, 4).div(2,3) }.should raise_error(ArgumentError) - end - - # See http://redmine.ruby-lang.org/issues/show/1648 - it "raises a TypeError if passed a non-numeric argument" do - -> { Rational(3, 4).div([]) }.should raise_error(TypeError) - end -end diff --git a/spec/ruby/shared/rational/divide.rb b/spec/ruby/shared/rational/divide.rb deleted file mode 100644 index 7d6d66390f7e..000000000000 --- a/spec/ruby/shared/rational/divide.rb +++ /dev/null @@ -1,71 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_divide_rat, shared: true do - it "returns self divided by other as a Rational" do - Rational(3, 4).send(@method, Rational(3, 4)).should eql(Rational(1, 1)) - Rational(2, 4).send(@method, Rational(1, 4)).should eql(Rational(2, 1)) - - Rational(2, 4).send(@method, 2).should == Rational(1, 4) - Rational(6, 7).send(@method, -2).should == Rational(-3, 7) - end - - it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do - -> { Rational(3, 4).send(@method, Rational(0, 1)) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_divide_int, shared: true do - it "returns self divided by other as a Rational" do - Rational(3, 4).send(@method, 2).should eql(Rational(3, 8)) - Rational(2, 4).send(@method, 2).should eql(Rational(1, 4)) - Rational(6, 7).send(@method, -2).should eql(Rational(-3, 7)) - end - - it "raises a ZeroDivisionError when passed 0" do - -> { Rational(3, 4).send(@method, 0) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_divide_float, shared: true do - it "returns self divided by other as a Float" do - Rational(3, 4).send(@method, 0.75).should eql(1.0) - Rational(3, 4).send(@method, 0.25).should eql(3.0) - Rational(3, 4).send(@method, 0.3).should eql(2.5) - - Rational(-3, 4).send(@method, 0.3).should eql(-2.5) - Rational(3, -4).send(@method, 0.3).should eql(-2.5) - Rational(3, 4).send(@method, -0.3).should eql(-2.5) - end - - it "returns infinity when passed 0" do - Rational(3, 4).send(@method, 0.0).infinite?.should eql(1) - Rational(-3, -4).send(@method, 0.0).infinite?.should eql(1) - - Rational(-3, 4).send(@method, 0.0).infinite?.should eql(-1) - Rational(3, -4).send(@method, 0.0).infinite?.should eql(-1) - end -end - -describe :rational_divide, shared: true do - it "calls #coerce on the passed argument with self" do - rational = Rational(3, 4) - obj = mock("Object") - obj.should_receive(:coerce).with(rational).and_return([1, 2]) - - rational.send(@method, obj) - end - - it "calls #/ on the coerced Rational with the coerced Object" do - rational = Rational(3, 4) - - coerced_rational = mock("Coerced Rational") - coerced_rational.should_receive(:/).and_return(:result) - - coerced_obj = mock("Coerced Object") - - obj = mock("Object") - obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) - - rational.send(@method, obj).should == :result - end -end diff --git a/spec/ruby/shared/rational/divmod.rb b/spec/ruby/shared/rational/divmod.rb deleted file mode 100644 index 9e23a1818641..000000000000 --- a/spec/ruby/shared/rational/divmod.rb +++ /dev/null @@ -1,42 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_divmod_rat, shared: true do - it "returns the quotient as Integer and the remainder as Rational" do - Rational(7, 4).divmod(Rational(1, 2)).should eql([3, Rational(1, 4)]) - Rational(7, 4).divmod(Rational(-1, 2)).should eql([-4, Rational(-1, 4)]) - Rational(0, 4).divmod(Rational(4, 3)).should eql([0, Rational(0, 1)]) - - Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([3458764513820540928, Rational(0, 1)]) - end - - it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do - -> { Rational(7, 4).divmod(Rational(0, 3)) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_divmod_int, shared: true do - it "returns the quotient as Integer and the remainder as Rational" do - Rational(7, 4).divmod(2).should eql([0, Rational(7, 4)]) - Rational(7, 4).divmod(-2).should eql([-1, Rational(-1, 4)]) - - Rational(bignum_value, 4).divmod(3).should eql([1537228672809129301, Rational(1, 1)]) - end - - it "raises a ZeroDivisionError when passed 0" do - -> { Rational(7, 4).divmod(0) }.should raise_error(ZeroDivisionError) - end -end - -describe :rational_divmod_float, shared: true do - it "returns the quotient as Integer and the remainder as Float" do - Rational(7, 4).divmod(0.5).should eql([3, 0.25]) - end - - it "returns the quotient as Integer and the remainder as Float" do - Rational(7, 4).divmod(-0.5).should eql([-4, -0.25]) - end - - it "raises a ZeroDivisionError when passed 0" do - -> { Rational(7, 4).divmod(0.0) }.should raise_error(ZeroDivisionError) - end -end diff --git a/spec/ruby/shared/rational/equal_value.rb b/spec/ruby/shared/rational/equal_value.rb deleted file mode 100644 index b2e7e0941551..000000000000 --- a/spec/ruby/shared/rational/equal_value.rb +++ /dev/null @@ -1,39 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_equal_value_rat, shared: true do - it "returns true if self has the same numerator and denominator as the passed argument" do - (Rational(3, 4) == Rational(3, 4)).should be_true - (Rational(-3, -4) == Rational(3, 4)).should be_true - (Rational(-4, 5) == Rational(4, -5)).should be_true - - (Rational(bignum_value, 3) == Rational(bignum_value, 3)).should be_true - (Rational(-bignum_value, 3) == Rational(bignum_value, -3)).should be_true - end -end - -describe :rational_equal_value_int, shared: true do - it "returns true if self has the passed argument as numerator and a denominator of 1" do - # Rational(x, y) reduces x and y automatically - (Rational(4, 2) == 2).should be_true - (Rational(-4, 2) == -2).should be_true - (Rational(4, -2) == -2).should be_true - end -end - -describe :rational_equal_value_float, shared: true do - it "converts self to a Float and compares it with the passed argument" do - (Rational(3, 4) == 0.75).should be_true - (Rational(4, 2) == 2.0).should be_true - (Rational(-4, 2) == -2.0).should be_true - (Rational(4, -2) == -2.0).should be_true - end -end - -describe :rational_equal_value, shared: true do - it "returns the result of calling #== with self on the passed argument" do - obj = mock("Object") - obj.should_receive(:==).and_return(:result) - - (Rational(3, 4) == obj).should_not be_false - end -end diff --git a/spec/ruby/shared/rational/exponent.rb b/spec/ruby/shared/rational/exponent.rb deleted file mode 100644 index 2145d6baceae..000000000000 --- a/spec/ruby/shared/rational/exponent.rb +++ /dev/null @@ -1,240 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_exponent, shared: true do - describe "when passed Rational" do - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - it "returns Rational(1) if the exponent is Rational(0)" do - (Rational(0) ** Rational(0)).should eql(Rational(1)) - (Rational(1) ** Rational(0)).should eql(Rational(1)) - (Rational(3, 4) ** Rational(0)).should eql(Rational(1)) - (Rational(-1) ** Rational(0)).should eql(Rational(1)) - (Rational(-3, 4) ** Rational(0)).should eql(Rational(1)) - (Rational(bignum_value) ** Rational(0)).should eql(Rational(1)) - (Rational(-bignum_value) ** Rational(0)).should eql(Rational(1)) - end - - it "returns self raised to the argument as a Rational if the exponent's denominator is 1" do - (Rational(3, 4) ** Rational(1, 1)).should eql(Rational(3, 4)) - (Rational(3, 4) ** Rational(2, 1)).should eql(Rational(9, 16)) - (Rational(3, 4) ** Rational(-1, 1)).should eql(Rational(4, 3)) - (Rational(3, 4) ** Rational(-2, 1)).should eql(Rational(16, 9)) - end - - it "returns self raised to the argument as a Float if the exponent's denominator is not 1" do - (Rational(3, 4) ** Rational(4, 3)).should be_close(0.681420222312052, TOLERANCE) - (Rational(3, 4) ** Rational(-4, 3)).should be_close(1.46752322173095, TOLERANCE) - (Rational(3, 4) ** Rational(4, -3)).should be_close(1.46752322173095, TOLERANCE) - end - - it "returns a complex number when self is negative and the passed argument is not 0" do - (Rational(-3, 4) ** Rational(-4, 3)).should be_close(Complex(-0.7337616108654732, 1.2709123906625817), TOLERANCE) - end - end - end - - describe "when passed Integer" do - it "returns the Rational value of self raised to the passed argument" do - (Rational(3, 4) ** 4).should == Rational(81, 256) - (Rational(3, 4) ** -4).should == Rational(256, 81) - (Rational(-3, 4) ** -4).should == Rational(256, 81) - (Rational(3, -4) ** -4).should == Rational(256, 81) - - (Rational(bignum_value, 4) ** 4).should == Rational(452312848583266388373324160190187140051835877600158453279131187530910662656, 1) - (Rational(3, bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81) - (Rational(-bignum_value, 4) ** -4).should == Rational(1, 452312848583266388373324160190187140051835877600158453279131187530910662656) - (Rational(3, -bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81) - end - - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - it "returns Rational(1, 1) when the passed argument is 0" do - (Rational(3, 4) ** 0).should eql(Rational(1, 1)) - (Rational(-3, 4) ** 0).should eql(Rational(1, 1)) - (Rational(3, -4) ** 0).should eql(Rational(1, 1)) - - (Rational(bignum_value, 4) ** 0).should eql(Rational(1, 1)) - (Rational(3, -bignum_value) ** 0).should eql(Rational(1, 1)) - end - end - end - - describe "when passed Bignum" do - # #5713 - it "returns Rational(0) when self is Rational(0) and the exponent is positive" do - (Rational(0) ** bignum_value).should eql(Rational(0)) - end - - it "raises ZeroDivisionError when self is Rational(0) and the exponent is negative" do - -> { Rational(0) ** -bignum_value }.should raise_error(ZeroDivisionError) - end - - it "returns Rational(1) when self is Rational(1)" do - (Rational(1) ** bignum_value).should eql(Rational(1)) - (Rational(1) ** -bignum_value).should eql(Rational(1)) - end - - it "returns Rational(1) when self is Rational(-1) and the exponent is positive and even" do - (Rational(-1) ** bignum_value(0)).should eql(Rational(1)) - (Rational(-1) ** bignum_value(2)).should eql(Rational(1)) - end - - it "returns Rational(-1) when self is Rational(-1) and the exponent is positive and odd" do - (Rational(-1) ** bignum_value(1)).should eql(Rational(-1)) - (Rational(-1) ** bignum_value(3)).should eql(Rational(-1)) - end - - ruby_version_is ""..."3.4" do - it "returns positive Infinity when self is > 1" do - -> { - (Rational(2) ** bignum_value).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_max) ** bignum_value).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - end - - it "returns 0.0 when self is > 1 and the exponent is negative" do - -> { - (Rational(2) ** -bignum_value).should eql(0.0) - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_max) ** -bignum_value).should eql(0.0) - }.should complain(/warning: in a\*\*b, b may be too big/) - end - end - - ruby_version_is "3.4" do - it "raises an ArgumentError when self is > 1" do - -> { - (Rational(2) ** bignum_value) - }.should raise_error(ArgumentError) - -> { - (Rational(fixnum_max) ** bignum_value) - }.should raise_error(ArgumentError) - end - - it "raises an ArgumentError when self is > 1 and the exponent is negative" do - -> { - (Rational(2) ** -bignum_value) - }.should raise_error(ArgumentError) - -> { - (Rational(fixnum_max) ** -bignum_value) - }.should raise_error(ArgumentError) - end - end - - # Fails on linux due to pow() bugs in glibc: http://sources.redhat.com/bugzilla/show_bug.cgi?id=3866 - platform_is_not :linux do - ruby_version_is ""..."3.4" do - it "returns positive Infinity when self < -1" do - -> { - (Rational(-2) ** bignum_value).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(-2) ** (bignum_value + 1)).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_min) ** bignum_value).infinite?.should == 1 - }.should complain(/warning: in a\*\*b, b may be too big/) - end - - it "returns 0.0 when self is < -1 and the exponent is negative" do - -> { - (Rational(-2) ** -bignum_value).should eql(0.0) - }.should complain(/warning: in a\*\*b, b may be too big/) - -> { - (Rational(fixnum_min) ** -bignum_value).should eql(0.0) - }.should complain(/warning: in a\*\*b, b may be too big/) - end - end - - ruby_version_is "3.4" do - it "returns positive Infinity when self < -1" do - -> { - (Rational(-2) ** bignum_value) - }.should raise_error(ArgumentError) - -> { - (Rational(fixnum_min) ** bignum_value) - }.should raise_error(ArgumentError) - end - - it "returns 0.0 when self is < -1 and the exponent is negative" do - -> { - (Rational(-2) ** -bignum_value) - }.should raise_error(ArgumentError) - -> { - (Rational(fixnum_min) ** -bignum_value) - }.should raise_error(ArgumentError) - end - end - end - end - - describe "when passed Float" do - it "returns self converted to Float and raised to the passed argument" do - (Rational(3, 1) ** 3.0).should eql(27.0) - (Rational(3, 1) ** 1.5).should be_close(5.19615242270663, TOLERANCE) - (Rational(3, 1) ** -1.5).should be_close(0.192450089729875, TOLERANCE) - end - - it "returns a complex number if self is negative and the passed argument is not 0" do - (Rational(-3, 2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE) - (Rational(3, -2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE) - (Rational(3, -2) ** -1.5).should be_close(Complex(0.0, 0.5443310539518174), TOLERANCE) - end - - it "returns Complex(1.0) when the passed argument is 0.0" do - (Rational(3, 4) ** 0.0).should == Complex(1.0) - (Rational(-3, 4) ** 0.0).should == Complex(1.0) - (Rational(-3, 4) ** 0.0).should == Complex(1.0) - end - end - - it "calls #coerce on the passed argument with self" do - rational = Rational(3, 4) - obj = mock("Object") - obj.should_receive(:coerce).with(rational).and_return([1, 2]) - - rational ** obj - end - - it "calls #** on the coerced Rational with the coerced Object" do - rational = Rational(3, 4) - - coerced_rational = mock("Coerced Rational") - coerced_rational.should_receive(:**).and_return(:result) - - coerced_obj = mock("Coerced Object") - - obj = mock("Object") - obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) - - (rational ** obj).should == :result - end - - it "raises ZeroDivisionError for Rational(0, 1) passed a negative Integer" do - [-1, -4, -9999].each do |exponent| - -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0") - end - end - - it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational with denominator 1" do - [Rational(-1, 1), Rational(-3, 1)].each do |exponent| - -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0") - end - end - - # #7513 - it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational" do - -> { Rational(0, 1) ** Rational(-3, 2) }.should raise_error(ZeroDivisionError, "divided by 0") - end - - platform_is_not :solaris do # See https://github.com/ruby/spec/issues/134 - it "returns Infinity for Rational(0, 1) passed a negative Float" do - [-1.0, -3.0, -3.14].each do |exponent| - (Rational(0, 1) ** exponent).infinite?.should == 1 - end - end - end -end diff --git a/spec/ruby/shared/rational/fdiv.rb b/spec/ruby/shared/rational/fdiv.rb deleted file mode 100644 index 6911ade8ac64..000000000000 --- a/spec/ruby/shared/rational/fdiv.rb +++ /dev/null @@ -1,5 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_fdiv, shared: true do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/shared/rational/floor.rb b/spec/ruby/shared/rational/floor.rb deleted file mode 100644 index ddf7fdbd1734..000000000000 --- a/spec/ruby/shared/rational/floor.rb +++ /dev/null @@ -1,45 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_floor, shared: true do - before do - @rational = Rational(2200, 7) - end - - describe "with no arguments (precision = 0)" do - it "returns an integer" do - @rational.floor.should be_kind_of(Integer) - end - - it "returns the truncated value toward negative infinity" do - @rational.floor.should == 314 - Rational(1, 2).floor.should == 0 - Rational(-1, 2).floor.should == -1 - end - end - - describe "with a precision < 0" do - it "returns an integer" do - @rational.floor(-2).should be_kind_of(Integer) - @rational.floor(-1).should be_kind_of(Integer) - end - - it "moves the truncation point n decimal places left" do - @rational.floor(-3).should == 0 - @rational.floor(-2).should == 300 - @rational.floor(-1).should == 310 - end - end - - describe "with a precision > 0" do - it "returns a Rational" do - @rational.floor(1).should be_kind_of(Rational) - @rational.floor(2).should be_kind_of(Rational) - end - - it "moves the truncation point n decimal places right" do - @rational.floor(1).should == Rational(1571, 5) - @rational.floor(2).should == Rational(7857, 25) - @rational.floor(3).should == Rational(62857, 200) - end - end -end diff --git a/spec/ruby/shared/rational/hash.rb b/spec/ruby/shared/rational/hash.rb deleted file mode 100644 index 50f21cec20aa..000000000000 --- a/spec/ruby/shared/rational/hash.rb +++ /dev/null @@ -1,9 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_hash, shared: true do - # BUG: Rational(2, 3).hash == Rational(3, 2).hash - it "is static" do - Rational(2, 3).hash.should == Rational(2, 3).hash - Rational(2, 4).hash.should_not == Rational(2, 3).hash - end -end diff --git a/spec/ruby/shared/rational/inspect.rb b/spec/ruby/shared/rational/inspect.rb deleted file mode 100644 index 19691a2f255f..000000000000 --- a/spec/ruby/shared/rational/inspect.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_inspect, shared: true do - it "returns a string representation of self" do - Rational(3, 4).inspect.should == "(3/4)" - Rational(-5, 8).inspect.should == "(-5/8)" - Rational(-1, -2).inspect.should == "(1/2)" - - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - Rational(bignum_value, 1).inspect.should == "(#{bignum_value}/1)" - end - end -end diff --git a/spec/ruby/shared/rational/modulo.rb b/spec/ruby/shared/rational/modulo.rb deleted file mode 100644 index 9e4b0c49e6ce..000000000000 --- a/spec/ruby/shared/rational/modulo.rb +++ /dev/null @@ -1,43 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_modulo, shared: true do - it "returns the remainder when this value is divided by other" do - Rational(2, 3).send(@method, Rational(2, 3)).should == Rational(0, 1) - Rational(4, 3).send(@method, Rational(2, 3)).should == Rational(0, 1) - Rational(2, -3).send(@method, Rational(-2, 3)).should == Rational(0, 1) - Rational(0, -1).send(@method, -1).should == Rational(0, 1) - - Rational(7, 4).send(@method, Rational(1, 2)).should == Rational(1, 4) - Rational(7, 4).send(@method, 1).should == Rational(3, 4) - Rational(7, 4).send(@method, Rational(1, 7)).should == Rational(1, 28) - - Rational(3, 4).send(@method, -1).should == Rational(-1, 4) - Rational(1, -5).send(@method, -1).should == Rational(-1, 5) - end - - it "returns a Float value when the argument is Float" do - Rational(7, 4).send(@method, 1.0).should be_kind_of(Float) - Rational(7, 4).send(@method, 1.0).should == 0.75 - Rational(7, 4).send(@method, 0.26).should be_close(0.19, 0.0001) - end - - it "raises ZeroDivisionError on zero denominator" do - -> { - Rational(3, 5).send(@method, Rational(0, 1)) - }.should raise_error(ZeroDivisionError) - - -> { - Rational(0, 1).send(@method, Rational(0, 1)) - }.should raise_error(ZeroDivisionError) - - -> { - Rational(3, 5).send(@method, 0) - }.should raise_error(ZeroDivisionError) - end - - it "raises a ZeroDivisionError when the argument is 0.0" do - -> { - Rational(3, 5).send(@method, 0.0) - }.should raise_error(ZeroDivisionError) - end -end diff --git a/spec/ruby/shared/rational/multiply.rb b/spec/ruby/shared/rational/multiply.rb deleted file mode 100644 index 9c861cf79d3a..000000000000 --- a/spec/ruby/shared/rational/multiply.rb +++ /dev/null @@ -1,62 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_multiply_rat, shared: true do - it "returns self divided by other as a Rational" do - (Rational(3, 4) * Rational(3, 4)).should eql(Rational(9, 16)) - (Rational(2, 4) * Rational(1, 4)).should eql(Rational(1, 8)) - - (Rational(3, 4) * Rational(0, 1)).should eql(Rational(0, 4)) - end -end - -describe :rational_multiply_int, shared: true do - it "returns self divided by other as a Rational" do - (Rational(3, 4) * 2).should eql(Rational(3, 2)) - (Rational(2, 4) * 2).should eql(Rational(1, 1)) - (Rational(6, 7) * -2).should eql(Rational(-12, 7)) - - (Rational(3, 4) * 0).should eql(Rational(0, 4)) - end -end - -describe :rational_multiply_float, shared: true do - it "returns self divided by other as a Float" do - (Rational(3, 4) * 0.75).should eql(0.5625) - (Rational(3, 4) * 0.25).should eql(0.1875) - (Rational(3, 4) * 0.3).should be_close(0.225, TOLERANCE) - - (Rational(-3, 4) * 0.3).should be_close(-0.225, TOLERANCE) - (Rational(3, -4) * 0.3).should be_close(-0.225, TOLERANCE) - (Rational(3, 4) * -0.3).should be_close(-0.225, TOLERANCE) - - (Rational(3, 4) * 0.0).should eql(0.0) - (Rational(-3, -4) * 0.0).should eql(0.0) - - (Rational(-3, 4) * 0.0).should eql(0.0) - (Rational(3, -4) * 0.0).should eql(0.0) - end -end - -describe :rational_multiply, shared: true do - it "calls #coerce on the passed argument with self" do - rational = Rational(3, 4) - obj = mock("Object") - obj.should_receive(:coerce).with(rational).and_return([1, 2]) - - rational * obj - end - - it "calls #* on the coerced Rational with the coerced Object" do - rational = Rational(3, 4) - - coerced_rational = mock("Coerced Rational") - coerced_rational.should_receive(:*).and_return(:result) - - coerced_obj = mock("Coerced Object") - - obj = mock("Object") - obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) - - (rational * obj).should == :result - end -end diff --git a/spec/ruby/shared/rational/numerator.rb b/spec/ruby/shared/rational/numerator.rb deleted file mode 100644 index 50d768168c19..000000000000 --- a/spec/ruby/shared/rational/numerator.rb +++ /dev/null @@ -1,10 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_numerator, shared: true do - it "returns the numerator" do - Rational(3, 4).numerator.should equal(3) - Rational(3, -4).numerator.should equal(-3) - - Rational(bignum_value, 1).numerator.should == bignum_value - end -end diff --git a/spec/ruby/shared/rational/plus.rb b/spec/ruby/shared/rational/plus.rb deleted file mode 100644 index b126360ee496..000000000000 --- a/spec/ruby/shared/rational/plus.rb +++ /dev/null @@ -1,48 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_plus_rat, shared: true do - it "returns the result of subtracting other from self as a Rational" do - (Rational(3, 4) + Rational(0, 1)).should eql(Rational(3, 4)) - (Rational(3, 4) + Rational(1, 4)).should eql(Rational(1, 1)) - - (Rational(3, 4) + Rational(2, 1)).should eql(Rational(11, 4)) - end -end - -describe :rational_plus_int, shared: true do - it "returns the result of subtracting other from self as a Rational" do - (Rational(3, 4) + 1).should eql(Rational(7, 4)) - (Rational(3, 4) + 2).should eql(Rational(11, 4)) - end -end - -describe :rational_plus_float, shared: true do - it "returns the result of subtracting other from self as a Float" do - (Rational(3, 4) + 0.2).should eql(0.95) - (Rational(3, 4) + 2.5).should eql(3.25) - end -end - -describe :rational_plus, shared: true do - it "calls #coerce on the passed argument with self" do - rational = Rational(3, 4) - obj = mock("Object") - obj.should_receive(:coerce).with(rational).and_return([1, 2]) - - rational + obj - end - - it "calls #+ on the coerced Rational with the coerced Object" do - rational = Rational(3, 4) - - coerced_rational = mock("Coerced Rational") - coerced_rational.should_receive(:+).and_return(:result) - - coerced_obj = mock("Coerced Object") - - obj = mock("Object") - obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) - - (rational + obj).should == :result - end -end diff --git a/spec/ruby/shared/rational/remainder.rb b/spec/ruby/shared/rational/remainder.rb deleted file mode 100644 index dd907608db20..000000000000 --- a/spec/ruby/shared/rational/remainder.rb +++ /dev/null @@ -1,5 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_remainder, shared: true do - it "needs to be reviewed for spec completeness" -end diff --git a/spec/ruby/shared/rational/round.rb b/spec/ruby/shared/rational/round.rb deleted file mode 100644 index 5b159ee3e6c6..000000000000 --- a/spec/ruby/shared/rational/round.rb +++ /dev/null @@ -1,106 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_round, shared: true do - before do - @rational = Rational(2200, 7) - end - - describe "with no arguments (precision = 0)" do - it "returns an integer" do - @rational.round.should be_kind_of(Integer) - Rational(0, 1).round(0).should be_kind_of(Integer) - Rational(124, 1).round(0).should be_kind_of(Integer) - end - - it "returns the truncated value toward the nearest integer" do - @rational.round.should == 314 - Rational(0, 1).round(0).should == 0 - Rational(2, 1).round(0).should == 2 - end - - it "returns the rounded value toward the nearest integer" do - Rational(1, 2).round.should == 1 - Rational(-1, 2).round.should == -1 - Rational(3, 2).round.should == 2 - Rational(-3, 2).round.should == -2 - Rational(5, 2).round.should == 3 - Rational(-5, 2).round.should == -3 - end - end - - describe "with a precision < 0" do - it "returns an integer" do - @rational.round(-2).should be_kind_of(Integer) - @rational.round(-1).should be_kind_of(Integer) - Rational(0, 1).round(-1).should be_kind_of(Integer) - Rational(2, 1).round(-1).should be_kind_of(Integer) - end - - it "moves the truncation point n decimal places left" do - @rational.round(-3).should == 0 - @rational.round(-2).should == 300 - @rational.round(-1).should == 310 - end - end - - describe "with a precision > 0" do - it "returns a Rational" do - @rational.round(1).should be_kind_of(Rational) - @rational.round(2).should be_kind_of(Rational) - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - Rational(0, 1).round(1).should be_kind_of(Rational) - Rational(2, 1).round(1).should be_kind_of(Rational) - end - end - - it "moves the truncation point n decimal places right" do - @rational.round(1).should == Rational(3143, 10) - @rational.round(2).should == Rational(31429, 100) - @rational.round(3).should == Rational(157143, 500) - Rational(0, 1).round(1).should == Rational(0, 1) - Rational(2, 1).round(1).should == Rational(2, 1) - end - - it "doesn't alter the value if the precision is too great" do - Rational(3, 2).round(10).should == Rational(3, 2).round(20) - end - - # #6605 - it "doesn't fail when rounding to an absurdly large positive precision" do - Rational(3, 2).round(2_097_171).should == Rational(3, 2) - end - end - - describe "with half option" do - it "returns an Integer when precision is not passed" do - Rational(10, 4).round(half: nil).should == 3 - Rational(10, 4).round(half: :up).should == 3 - Rational(10, 4).round(half: :down).should == 2 - Rational(10, 4).round(half: :even).should == 2 - Rational(-10, 4).round(half: nil).should == -3 - Rational(-10, 4).round(half: :up).should == -3 - Rational(-10, 4).round(half: :down).should == -2 - Rational(-10, 4).round(half: :even).should == -2 - end - - it "returns a Rational when the precision is greater than 0" do - Rational(25, 100).round(1, half: nil).should == Rational(3, 10) - Rational(25, 100).round(1, half: :up).should == Rational(3, 10) - Rational(25, 100).round(1, half: :down).should == Rational(1, 5) - Rational(25, 100).round(1, half: :even).should == Rational(1, 5) - Rational(35, 100).round(1, half: nil).should == Rational(2, 5) - Rational(35, 100).round(1, half: :up).should == Rational(2, 5) - Rational(35, 100).round(1, half: :down).should == Rational(3, 10) - Rational(35, 100).round(1, half: :even).should == Rational(2, 5) - Rational(-25, 100).round(1, half: nil).should == Rational(-3, 10) - Rational(-25, 100).round(1, half: :up).should == Rational(-3, 10) - Rational(-25, 100).round(1, half: :down).should == Rational(-1, 5) - Rational(-25, 100).round(1, half: :even).should == Rational(-1, 5) - end - - it "raise for a non-existent round mode" do - -> { Rational(10, 4).round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense") - end - end -end diff --git a/spec/ruby/shared/rational/to_f.rb b/spec/ruby/shared/rational/to_f.rb deleted file mode 100644 index 472a585daad0..000000000000 --- a/spec/ruby/shared/rational/to_f.rb +++ /dev/null @@ -1,16 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_to_f, shared: true do - it "returns self converted to a Float" do - Rational(3, 4).to_f.should eql(0.75) - Rational(3, -4).to_f.should eql(-0.75) - Rational(-1, 4).to_f.should eql(-0.25) - Rational(-1, -4).to_f.should eql(0.25) - end - - it "converts to a Float for large numerator and denominator" do - num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009 - den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - Rational(num, den).to_f.should == 500.0 - end -end diff --git a/spec/ruby/shared/rational/to_i.rb b/spec/ruby/shared/rational/to_i.rb deleted file mode 100644 index 9be1183aa41b..000000000000 --- a/spec/ruby/shared/rational/to_i.rb +++ /dev/null @@ -1,12 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_to_i, shared: true do - it "converts self to an Integer by truncation" do - Rational(7, 4).to_i.should eql(1) - Rational(11, 4).to_i.should eql(2) - end - - it "converts self to an Integer by truncation" do - Rational(-7, 4).to_i.should eql(-1) - end -end diff --git a/spec/ruby/shared/rational/to_r.rb b/spec/ruby/shared/rational/to_r.rb deleted file mode 100644 index 372c0868505c..000000000000 --- a/spec/ruby/shared/rational/to_r.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_to_r, shared: true do - it "returns self" do - a = Rational(3, 4) - a.to_r.should equal(a) - - a = Rational(bignum_value, 4) - a.to_r.should equal(a) - end -end diff --git a/spec/ruby/shared/rational/to_s.rb b/spec/ruby/shared/rational/to_s.rb deleted file mode 100644 index e90c6e5e3921..000000000000 --- a/spec/ruby/shared/rational/to_s.rb +++ /dev/null @@ -1,14 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_to_s, shared: true do - it "returns a string representation of self" do - # Guard against the Mathn library - guard -> { !defined?(Math.rsqrt) } do - Rational(1, 1).to_s.should == "1/1" - Rational(2, 1).to_s.should == "2/1" - end - Rational(1, 2).to_s.should == "1/2" - Rational(-1, 3).to_s.should == "-1/3" - Rational(1, -3).to_s.should == "-1/3" - end -end diff --git a/spec/ruby/shared/rational/truncate.rb b/spec/ruby/shared/rational/truncate.rb deleted file mode 100644 index df5198ca02dc..000000000000 --- a/spec/ruby/shared/rational/truncate.rb +++ /dev/null @@ -1,71 +0,0 @@ -require_relative '../../spec_helper' - -describe :rational_truncate, shared: true do - before do - @rational = Rational(2200, 7) - end - - describe "with no arguments (precision = 0)" do - it "returns an integer" do - @rational.truncate.should be_kind_of(Integer) - end - - it "returns the truncated value toward 0" do - @rational.truncate.should == 314 - Rational(1, 2).truncate.should == 0 - Rational(-1, 2).truncate.should == 0 - end - end - - describe "with an explicit precision = 0" do - it "returns an integer" do - @rational.truncate(0).should be_kind_of(Integer) - end - - it "returns the truncated value toward 0" do - @rational.truncate(0).should == 314 - Rational(1, 2).truncate(0).should == 0 - Rational(-1, 2).truncate(0).should == 0 - end - end - - describe "with a precision < 0" do - it "returns an integer" do - @rational.truncate(-2).should be_kind_of(Integer) - @rational.truncate(-1).should be_kind_of(Integer) - end - - it "moves the truncation point n decimal places left" do - @rational.truncate(-3).should == 0 - @rational.truncate(-2).should == 300 - @rational.truncate(-1).should == 310 - end - end - - describe "with a precision > 0" do - it "returns a Rational" do - @rational.truncate(1).should be_kind_of(Rational) - @rational.truncate(2).should be_kind_of(Rational) - end - - it "moves the truncation point n decimal places right" do - @rational.truncate(1).should == Rational(1571, 5) - @rational.truncate(2).should == Rational(7857, 25) - @rational.truncate(3).should == Rational(62857, 200) - end - end - - describe "with an invalid value for precision" do - it "raises a TypeError" do - -> { @rational.truncate(nil) }.should raise_error(TypeError, "not an integer") - -> { @rational.truncate(1.0) }.should raise_error(TypeError, "not an integer") - -> { @rational.truncate('') }.should raise_error(TypeError, "not an integer") - end - - it "does not call to_int on the argument" do - object = Object.new - object.should_not_receive(:to_int) - -> { @rational.truncate(object) }.should raise_error(TypeError, "not an integer") - end - end -end From bff2520c64acf45c86884326391a93aa02cb1272 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Tue, 7 Jan 2025 13:09:40 +0200 Subject: [PATCH 3/3] Add tags for new failing specs --- spec/tags/core/fiber/storage_tags.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/tags/core/fiber/storage_tags.txt b/spec/tags/core/fiber/storage_tags.txt index 3101530af27b..21299f8096ca 100644 --- a/spec/tags/core/fiber/storage_tags.txt +++ b/spec/tags/core/fiber/storage_tags.txt @@ -22,3 +22,4 @@ fails:Fiber.[]= can't access the storage of the fiber with non-symbol keys fails:Fiber.[] can use dynamically defined keys fails:Fiber.[] can't use invalid keys fails:Fiber.[]= deletes the fiber storage key when assigning nil +fails:Fiber.[] can use keys as strings