Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 146 additions & 2 deletions core/kernel/Rational_spec.rb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion core/rational/abs_spec.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
43 changes: 41 additions & 2 deletions core/rational/ceil_spec.rb
Original file line number Diff line number Diff line change
@@ -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
84 changes: 77 additions & 7 deletions core/rational/comparison_spec.rb
Original file line number Diff line number Diff line change
@@ -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
12 changes: 10 additions & 2 deletions core/rational/denominator_spec.rb
Original file line number Diff line number Diff line change
@@ -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
46 changes: 41 additions & 5 deletions core/rational/div_spec.rb
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading