From 3fa5bd38af50fb3d98de0ea51043d73f8d06a24b Mon Sep 17 00:00:00 2001 From: eregon Date: Mon, 29 Jan 2018 16:08:16 +0000 Subject: Update to ruby/spec@83063a3 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62094 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- spec/ruby/core/integer/abs_spec.rb | 7 + spec/ruby/core/integer/bit_and_spec.rb | 97 +++++++++++ spec/ruby/core/integer/bit_length_spec.rb | 76 ++++++++ spec/ruby/core/integer/bit_or_spec.rb | 68 ++++++++ spec/ruby/core/integer/bit_xor_spec.rb | 72 ++++++++ spec/ruby/core/integer/case_compare_spec.rb | 6 + spec/ruby/core/integer/ceil_spec.rb | 4 +- spec/ruby/core/integer/chr_spec.rb | 4 + spec/ruby/core/integer/coerce_spec.rb | 105 +++++++++++ spec/ruby/core/integer/comparison_spec.rb | 189 ++++++++++++++++++++ spec/ruby/core/integer/complement_spec.rb | 20 +++ spec/ruby/core/integer/div_spec.rb | 138 +++++++++++++++ spec/ruby/core/integer/divide_spec.rb | 93 +++++++++- spec/ruby/core/integer/divmod_spec.rb | 117 +++++++++++++ spec/ruby/core/integer/dup_spec.rb | 10 -- spec/ruby/core/integer/element_reference_spec.rb | 111 ++++++++++++ spec/ruby/core/integer/equal_value_spec.rb | 7 + spec/ruby/core/integer/even_spec.rb | 42 +++-- spec/ruby/core/integer/exponent_spec.rb | 7 + spec/ruby/core/integer/fdiv_spec.rb | 49 ++++++ spec/ruby/core/integer/floor_spec.rb | 4 +- spec/ruby/core/integer/gt_spec.rb | 47 ++++- spec/ruby/core/integer/gte_spec.rb | 47 ++++- spec/ruby/core/integer/left_shift_spec.rb | 165 ++++++++++++++++++ spec/ruby/core/integer/lt_spec.rb | 50 +++++- spec/ruby/core/integer/lte_spec.rb | 53 +++++- spec/ruby/core/integer/magnitude_spec.rb | 7 + spec/ruby/core/integer/minus_spec.rb | 47 ++++- spec/ruby/core/integer/modulo_spec.rb | 10 ++ spec/ruby/core/integer/multiply_spec.rb | 50 +++++- spec/ruby/core/integer/next_spec.rb | 2 +- spec/ruby/core/integer/odd_spec.rb | 40 +++-- spec/ruby/core/integer/plus_spec.rb | 48 +++++- spec/ruby/core/integer/pow_spec.rb | 51 ++++++ spec/ruby/core/integer/remainder_spec.rb | 51 ++++++ spec/ruby/core/integer/right_shift_spec.rb | 191 +++++++++++++++++++++ spec/ruby/core/integer/round_spec.rb | 4 +- spec/ruby/core/integer/shared/abs.rb | 18 ++ spec/ruby/core/integer/shared/arithmetic_coerce.rb | 31 ++++ .../shared/arithmetic_exception_in_coerce.rb | 33 ---- spec/ruby/core/integer/shared/comparison_coerce.rb | 33 ++++ .../shared/comparison_exception_in_coerce.rb | 35 ---- spec/ruby/core/integer/shared/equal.rb | 58 +++++++ spec/ruby/core/integer/shared/exponent.rb | 118 +++++++++++++ spec/ruby/core/integer/shared/modulo.rb | 74 ++++++++ spec/ruby/core/integer/size_spec.rb | 34 ++++ spec/ruby/core/integer/succ_spec.rb | 2 +- spec/ruby/core/integer/to_f_spec.rb | 23 +++ spec/ruby/core/integer/to_i_spec.rb | 2 +- spec/ruby/core/integer/to_int_spec.rb | 2 +- spec/ruby/core/integer/to_s_spec.rb | 99 +++++++++++ spec/ruby/core/integer/truncate_spec.rb | 4 +- spec/ruby/core/integer/uminus_spec.rb | 28 +++ 53 files changed, 2556 insertions(+), 127 deletions(-) create mode 100644 spec/ruby/core/integer/abs_spec.rb create mode 100644 spec/ruby/core/integer/bit_and_spec.rb create mode 100644 spec/ruby/core/integer/bit_length_spec.rb create mode 100644 spec/ruby/core/integer/bit_or_spec.rb create mode 100644 spec/ruby/core/integer/bit_xor_spec.rb create mode 100644 spec/ruby/core/integer/case_compare_spec.rb create mode 100644 spec/ruby/core/integer/coerce_spec.rb create mode 100644 spec/ruby/core/integer/comparison_spec.rb create mode 100644 spec/ruby/core/integer/complement_spec.rb create mode 100644 spec/ruby/core/integer/div_spec.rb create mode 100644 spec/ruby/core/integer/divmod_spec.rb delete mode 100644 spec/ruby/core/integer/dup_spec.rb create mode 100644 spec/ruby/core/integer/element_reference_spec.rb create mode 100644 spec/ruby/core/integer/equal_value_spec.rb create mode 100644 spec/ruby/core/integer/exponent_spec.rb create mode 100644 spec/ruby/core/integer/fdiv_spec.rb create mode 100644 spec/ruby/core/integer/left_shift_spec.rb create mode 100644 spec/ruby/core/integer/magnitude_spec.rb create mode 100644 spec/ruby/core/integer/modulo_spec.rb create mode 100644 spec/ruby/core/integer/pow_spec.rb create mode 100644 spec/ruby/core/integer/remainder_spec.rb create mode 100644 spec/ruby/core/integer/right_shift_spec.rb create mode 100644 spec/ruby/core/integer/shared/abs.rb create mode 100644 spec/ruby/core/integer/shared/arithmetic_coerce.rb delete mode 100644 spec/ruby/core/integer/shared/arithmetic_exception_in_coerce.rb create mode 100644 spec/ruby/core/integer/shared/comparison_coerce.rb delete mode 100644 spec/ruby/core/integer/shared/comparison_exception_in_coerce.rb create mode 100644 spec/ruby/core/integer/shared/equal.rb create mode 100644 spec/ruby/core/integer/shared/exponent.rb create mode 100644 spec/ruby/core/integer/shared/modulo.rb create mode 100644 spec/ruby/core/integer/size_spec.rb create mode 100644 spec/ruby/core/integer/to_f_spec.rb create mode 100644 spec/ruby/core/integer/to_s_spec.rb create mode 100644 spec/ruby/core/integer/uminus_spec.rb (limited to 'spec/ruby/core/integer') diff --git a/spec/ruby/core/integer/abs_spec.rb b/spec/ruby/core/integer/abs_spec.rb new file mode 100644 index 0000000000..4f16d2c4b3 --- /dev/null +++ b/spec/ruby/core/integer/abs_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/abs', __FILE__) + +describe "Integer#abs" do + it_behaves_like :integer_abs, :abs +end + diff --git a/spec/ruby/core/integer/bit_and_spec.rb b/spec/ruby/core/integer/bit_and_spec.rb new file mode 100644 index 0000000000..75cd561e42 --- /dev/null +++ b/spec/ruby/core/integer/bit_and_spec.rb @@ -0,0 +1,97 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#&" do + context "fixnum" do + it "returns self bitwise AND other" do + (256 & 16).should == 0 + (2010 & 5).should == 0 + (65535 & 1).should == 1 + (0xffff & bignum_value + 0xffff_ffff).should == 65535 + end + + it "returns self bitwise AND other when one operand is negative" do + ((1 << 33) & -1).should == (1 << 33) + (-1 & (1 << 33)).should == (1 << 33) + + ((-(1<<33)-1) & 5).should == 5 + (5 & (-(1<<33)-1)).should == 5 + end + + it "returns self bitwise AND other when both operands are negative" do + (-5 & -1).should == -5 + (-3 & -4).should == -4 + (-12 & -13).should == -16 + (-13 & -12).should == -16 + end + + it "returns self bitwise AND a bignum" do + (-1 & 2**64).should == 18446744073709551616 + end + + it "coerces the rhs and calls #coerce" do + obj = mock("fixnum bit and") + obj.should_receive(:coerce).with(6).and_return([3, 6]) + (6 & obj).should == 2 + end + + it "raises a TypeError when passed a Float" do + lambda { (3 & 3.4) }.should raise_error(TypeError) + end + + it "raises a TypeError and does not call #to_int when defined on an object" do + obj = mock("fixnum bit and") + obj.should_not_receive(:to_int) + + lambda { 3 & obj }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(5) + end + + it "returns self bitwise AND other" do + @bignum = bignum_value(5) + (@bignum & 3).should == 1 + (@bignum & 52).should == 4 + (@bignum & bignum_value(9921)).should == 9223372036854775809 + + ((2*bignum_value) & 1).should == 0 + ((2*bignum_value) & (2*bignum_value)).should == 18446744073709551616 + end + + it "returns self bitwise AND other when one operand is negative" do + ((2*bignum_value) & -1).should == (2*bignum_value) + ((4*bignum_value) & -1).should == (4*bignum_value) + (@bignum & -0xffffffffffffff5).should == 9223372036854775809 + (@bignum & -@bignum).should == 1 + (@bignum & -0x8000000000000000).should == 9223372036854775808 + end + + it "returns self bitwise AND other when both operands are negative" do + (-@bignum & -0x4000000000000005).should == -13835058055282163717 + (-@bignum & -@bignum).should == -9223372036854775813 + (-@bignum & -0x4000000000000000).should == -13835058055282163712 + end + + it "returns self bitwise AND other when both are negative and a multiple in bitsize of Fixnum::MIN" do + val = - ((1 << 93) - 1) + (val & val).should == val + + val = - ((1 << 126) - 1) + (val & val).should == val + end + + it "raises a TypeError when passed a Float" do + lambda { (@bignum & 3.4) }.should raise_error(TypeError) + end + + it "raises a TypeError and does not call #to_int when defined on an object" do + obj = mock("bignum bit and") + obj.should_not_receive(:to_int) + + lambda { @bignum & obj }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/bit_length_spec.rb b/spec/ruby/core/integer/bit_length_spec.rb new file mode 100644 index 0000000000..9a2065af33 --- /dev/null +++ b/spec/ruby/core/integer/bit_length_spec.rb @@ -0,0 +1,76 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#bit_length" do + context "fixnum" do + it "returns the position of the leftmost bit of a positive number" do + 0.bit_length.should == 0 + 1.bit_length.should == 1 + 2.bit_length.should == 2 + 3.bit_length.should == 2 + 4.bit_length.should == 3 + n = fixnum_max.bit_length + fixnum_max[n].should == 0 + fixnum_max[n - 1].should == 1 + + 0.bit_length.should == 0 + 1.bit_length.should == 1 + 0xff.bit_length.should == 8 + 0x100.bit_length.should == 9 + (2**12 - 1).bit_length.should == 12 + (2**12).bit_length.should == 13 + (2**12 + 1).bit_length.should == 13 + end + + it "returns the position of the leftmost 0 bit of a negative number" do + -1.bit_length.should == 0 + -2.bit_length.should == 1 + -3.bit_length.should == 2 + -4.bit_length.should == 2 + -5.bit_length.should == 3 + n = fixnum_min.bit_length + fixnum_min[n].should == 1 + fixnum_min[n - 1].should == 0 + + (-2**12 - 1).bit_length.should == 13 + (-2**12).bit_length.should == 12 + (-2**12 + 1).bit_length.should == 12 + -0x101.bit_length.should == 9 + -0x100.bit_length.should == 8 + -0xff.bit_length.should == 8 + -2.bit_length.should == 1 + -1.bit_length.should == 0 + end + end + + context "bignum" do + it "returns the position of the leftmost bit of a positive number" do + (2**1000-1).bit_length.should == 1000 + (2**1000).bit_length.should == 1001 + (2**1000+1).bit_length.should == 1001 + + (2**10000-1).bit_length.should == 10000 + (2**10000).bit_length.should == 10001 + (2**10000+1).bit_length.should == 10001 + + (1 << 100).bit_length.should == 101 + (1 << 100).succ.bit_length.should == 101 + (1 << 100).pred.bit_length.should == 100 + (1 << 10000).bit_length.should == 10001 + end + + it "returns the position of the leftmost 0 bit of a negative number" do + (-2**10000-1).bit_length.should == 10001 + (-2**10000).bit_length.should == 10000 + (-2**10000+1).bit_length.should == 10000 + + (-2**1000-1).bit_length.should == 1001 + (-2**1000).bit_length.should == 1000 + (-2**1000+1).bit_length.should == 1000 + + ((-1 << 100)-1).bit_length.should == 101 + ((-1 << 100)-1).succ.bit_length.should == 100 + ((-1 << 100)-1).pred.bit_length.should == 101 + ((-1 << 10000)-1).bit_length.should == 10001 + end + end +end diff --git a/spec/ruby/core/integer/bit_or_spec.rb b/spec/ruby/core/integer/bit_or_spec.rb new file mode 100644 index 0000000000..61da1676c9 --- /dev/null +++ b/spec/ruby/core/integer/bit_or_spec.rb @@ -0,0 +1,68 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#|" do + context "fixnum" do + it "returns self bitwise OR other" do + (1 | 0).should == 1 + (5 | 4).should == 5 + (5 | 6).should == 7 + (248 | 4096).should == 4344 + (0xffff | bignum_value + 0xf0f0).should == 0x8000_0000_0000_ffff + end + + it "returns self bitwise OR a bignum" do + (-1 | 2**64).should == -1 + end + + it "raises a TypeError when passed a Float" do + lambda { (3 | 3.4) }.should raise_error(TypeError) + end + + it "raises a TypeError and does not call #to_int when defined on an object" do + obj = mock("integer bit or") + obj.should_not_receive(:to_int) + + lambda { 3 | obj }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(11) + end + + it "returns self bitwise OR other" do + (@bignum | 2).should == 9223372036854775819 + (@bignum | 9).should == 9223372036854775819 + (@bignum | bignum_value).should == 9223372036854775819 + end + + it "returns self bitwise OR other when one operand is negative" do + (@bignum | -0x40000000000000000).should == -64563604257983430645 + (@bignum | -@bignum).should == -1 + (@bignum | -0x8000000000000000).should == -9223372036854775797 + end + + it "returns self bitwise OR other when both operands are negative" do + (-@bignum | -0x4000000000000005).should == -1 + (-@bignum | -@bignum).should == -9223372036854775819 + (-@bignum | -0x4000000000000000).should == -11 + end + + it "raises a TypeError when passed a Float" do + not_supported_on :opal do + lambda { + bignum_value | bignum_value(0xffff).to_f + }.should raise_error(TypeError) + end + lambda { @bignum | 9.9 }.should raise_error(TypeError) + end + + it "raises a TypeError and does not call #to_int when defined on an object" do + obj = mock("bignum bit or") + obj.should_not_receive(:to_int) + + lambda { @bignum | obj }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/bit_xor_spec.rb b/spec/ruby/core/integer/bit_xor_spec.rb new file mode 100644 index 0000000000..f9e2fd74cb --- /dev/null +++ b/spec/ruby/core/integer/bit_xor_spec.rb @@ -0,0 +1,72 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#^" do + context "fixnum" do + it "returns self bitwise EXCLUSIVE OR other" do + (3 ^ 5).should == 6 + (-2 ^ -255).should == 255 + (5 ^ bignum_value + 0xffff_ffff).should == 0x8000_0000_ffff_fffa + end + + it "returns self bitwise EXCLUSIVE OR a bignum" do + (-1 ^ 2**64).should == -18446744073709551617 + end + + it "raises a TypeError when passed a Float" do + lambda { (3 ^ 3.4) }.should raise_error(TypeError) + end + + it "raises a TypeError and does not call #to_int when defined on an object" do + obj = mock("integer bit xor") + obj.should_not_receive(:to_int) + + lambda { 3 ^ obj }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(18) + end + + it "returns self bitwise EXCLUSIVE OR other" do + (@bignum ^ 2).should == 9223372036854775824 + (@bignum ^ @bignum).should == 0 + (@bignum ^ 14).should == 9223372036854775836 + end + + it "returns self bitwise EXCLUSIVE OR other when one operand is negative" do + (@bignum ^ -0x40000000000000000).should == -64563604257983430638 + (@bignum ^ -@bignum).should == -4 + (@bignum ^ -0x8000000000000000).should == -18446744073709551598 + end + + it "returns self bitwise EXCLUSIVE OR other when both operands are negative" do + (-@bignum ^ -0x40000000000000000).should == 64563604257983430638 + (-@bignum ^ -@bignum).should == 0 + (-@bignum ^ -0x4000000000000000).should == 13835058055282163694 + end + + it "returns self bitwise EXCLUSIVE OR other when all bits are 1 and other value is negative" do + (9903520314283042199192993791 ^ -1).should == -9903520314283042199192993792 + (784637716923335095479473677900958302012794430558004314111 ^ -1).should == + -784637716923335095479473677900958302012794430558004314112 + end + + it "raises a TypeError when passed a Float" do + not_supported_on :opal do + lambda { + bignum_value ^ bignum_value(0xffff).to_f + }.should raise_error(TypeError) + end + lambda { @bignum ^ 14.5 }.should raise_error(TypeError) + end + + it "raises a TypeError and does not call #to_int when defined on an object" do + obj = mock("bignum bit xor") + obj.should_not_receive(:to_int) + + lambda { @bignum ^ obj }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/case_compare_spec.rb b/spec/ruby/core/integer/case_compare_spec.rb new file mode 100644 index 0000000000..24f8580823 --- /dev/null +++ b/spec/ruby/core/integer/case_compare_spec.rb @@ -0,0 +1,6 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/equal', __FILE__) + +describe "Integer#===" do + it_behaves_like :integer_equal, :=== +end diff --git a/spec/ruby/core/integer/ceil_spec.rb b/spec/ruby/core/integer/ceil_spec.rb index 31c56f378d..8a0754475f 100644 --- a/spec/ruby/core/integer/ceil_spec.rb +++ b/spec/ruby/core/integer/ceil_spec.rb @@ -3,8 +3,8 @@ require File.expand_path('../shared/to_i', __FILE__) require File.expand_path('../shared/integer_rounding', __FILE__) describe "Integer#ceil" do - it_behaves_like(:integer_to_i, :ceil) - it_behaves_like(:integer_rounding_positive_precision, :ceil) + it_behaves_like :integer_to_i, :ceil + it_behaves_like :integer_rounding_positive_precision, :ceil ruby_version_is "2.4" do context "precision argument specified as part of the ceil method is negative" do diff --git a/spec/ruby/core/integer/chr_spec.rb b/spec/ruby/core/integer/chr_spec.rb index 50a678608e..1a3bed5c76 100644 --- a/spec/ruby/core/integer/chr_spec.rb +++ b/spec/ruby/core/integer/chr_spec.rb @@ -165,6 +165,10 @@ describe "Integer#chr with an encoding argument" do lambda { -bignum_value.chr(Encoding::EUC_JP) }.should raise_error(RangeError) end + it "raises a RangeError if self is too large" do + lambda { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError) + end + it "returns a String with the specified encoding" do 0x0000.chr(Encoding::US_ASCII).encoding.should == Encoding::US_ASCII 0x007F.chr(Encoding::US_ASCII).encoding.should == Encoding::US_ASCII diff --git a/spec/ruby/core/integer/coerce_spec.rb b/spec/ruby/core/integer/coerce_spec.rb new file mode 100644 index 0000000000..58e0aadc0a --- /dev/null +++ b/spec/ruby/core/integer/coerce_spec.rb @@ -0,0 +1,105 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#coerce" do + context "fixnum" do + describe "when given a Fixnum" do + it "returns an array containing two Fixnums" do + 1.coerce(2).should == [2, 1] + 1.coerce(2).map { |i| i.class }.should == [Fixnum, Fixnum] + end + end + + describe "when given a String" do + it "raises an ArgumentError when trying to coerce with a non-number String" do + lambda { 1.coerce(":)") }.should raise_error(ArgumentError) + end + + it "returns an array containing two Floats" do + 1.coerce("2").should == [2.0, 1.0] + 1.coerce("-2").should == [-2.0, 1.0] + end + end + + it "raises a TypeError when trying to coerce with nil" do + lambda { 1.coerce(nil) }.should raise_error(TypeError) + end + + it "tries to convert the given Object into a Float by using #to_f" do + (obj = mock('1.0')).should_receive(:to_f).and_return(1.0) + 2.coerce(obj).should == [1.0, 2.0] + + (obj = mock('0')).should_receive(:to_f).and_return('0') + lambda { 2.coerce(obj).should == [1.0, 2.0] }.should raise_error(TypeError) + end + + it "raises a TypeError when given an Object that does not respond to #to_f" do + lambda { 1.coerce(mock('x')) }.should raise_error(TypeError) + lambda { 1.coerce(1..4) }.should raise_error(TypeError) + lambda { 1.coerce(:test) }.should raise_error(TypeError) + end + end + + context "bignum" do + it "coerces other to a Bignum and returns [other, self] when passed a Fixnum" do + a = bignum_value + ary = a.coerce(2) + + ary[0].should be_kind_of(Bignum) + ary[1].should be_kind_of(Bignum) + ary.should == [2, a] + end + + it "returns [other, self] when passed a Bignum" do + a = bignum_value + b = bignum_value + ary = a.coerce(b) + + ary[0].should be_kind_of(Bignum) + ary[1].should be_kind_of(Bignum) + ary.should == [b, a] + end + + it "raises a TypeError when not passed a Fixnum or Bignum" do + a = bignum_value + + lambda { a.coerce(nil) }.should raise_error(TypeError) + lambda { a.coerce(mock('str')) }.should raise_error(TypeError) + lambda { a.coerce(1..4) }.should raise_error(TypeError) + lambda { a.coerce(:test) }.should raise_error(TypeError) + end + + ruby_version_is ""..."2.4" do + it "raises a TypeError when passed a String" do + a = bignum_value + lambda { a.coerce("123") }.should raise_error(TypeError) + end + + it "raises a TypeError when passed a Float" do + a = bignum_value + lambda { a.coerce(12.3) }.should raise_error(TypeError) + end + end + + ruby_version_is "2.4" do + it "coerces both values to Floats and returns [other, self] when passed a Float" do + a = bignum_value + a.coerce(1.2).should == [1.2, a.to_f] + end + + it "coerces both values to Floats and returns [other, self] when passed a String" do + a = bignum_value + a.coerce("123").should == [123.0, a.to_f] + end + + it "calls #to_f to coerce other to a Float" do + b = mock("bignum value") + b.should_receive(:to_f).and_return(1.2) + + a = bignum_value + ary = a.coerce(b) + + ary.should == [1.2, a.to_f] + end + end + end +end diff --git a/spec/ruby/core/integer/comparison_spec.rb b/spec/ruby/core/integer/comparison_spec.rb new file mode 100644 index 0000000000..c54471dd16 --- /dev/null +++ b/spec/ruby/core/integer/comparison_spec.rb @@ -0,0 +1,189 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#<=>" do + context "fixnum" do + it "returns -1 when self is less than the given argument" do + (-3 <=> -1).should == -1 + (-5 <=> 10).should == -1 + (-5 <=> -4.5).should == -1 + end + + it "returns 0 when self is equal to the given argument" do + (0 <=> 0).should == 0 + (954 <=> 954).should == 0 + (954 <=> 954.0).should == 0 + end + + it "returns 1 when self is greater than the given argument" do + (496 <=> 5).should == 1 + (200 <=> 100).should == 1 + (51 <=> 50.5).should == 1 + end + + it "returns nil when the given argument is not an Integer" do + (3 <=> mock('x')).should == nil + (3 <=> 'test').should == nil + end + end + + context "bignum" do + describe "with a Fixnum" do + it "returns -1 when other is larger" do + (-bignum_value <=> 2).should == -1 + end + + it "returns 1 when other is smaller" do + (bignum_value <=> 2).should == 1 + end + end + + describe "with a Bignum" do + describe "when other is negative" do + it "returns -1 when self is negative and other is larger" do + (-bignum_value(42) <=> -bignum_value).should == -1 + end + + it "returns 0 when other is equal" do + (-bignum_value <=> -bignum_value).should == 0 + end + + it "returns 1 when self is negative and other is smaller" do + (-bignum_value <=> -bignum_value(94)).should == 1 + end + + it "returns 1 when self is positive" do + (bignum_value <=> -bignum_value).should == 1 + end + end + + describe "when other is positive" do + it "returns -1 when self is negative" do + (-bignum_value <=> bignum_value).should == -1 + end + + it "returns -1 when self is positive and other is larger" do + (bignum_value <=> bignum_value(38)).should == -1 + end + + it "returns 0 when other is equal" do + (bignum_value <=> bignum_value).should == 0 + end + + it "returns 1 when other is smaller" do + (bignum_value(56) <=> bignum_value).should == 1 + end + end + end + + describe "with a Float" do + describe "when other is negative" do + it "returns -1 when self is negative and other is larger" do + (-bignum_value(0xffff) <=> -bignum_value.to_f).should == -1 + end + + it "returns 0 when other is equal" do + (-bignum_value <=> -bignum_value.to_f).should == 0 + end + + it "returns 1 when self is negative and other is smaller" do + (-bignum_value <=> -bignum_value(0xffef).to_f).should == 1 + end + + it "returns 1 when self is positive" do + (bignum_value <=> -bignum_value.to_f).should == 1 + end + end + + describe "when other is positive" do + it "returns -1 when self is negative" do + (-bignum_value <=> bignum_value.to_f).should == -1 + end + + it "returns -1 when self is positive and other is larger" do + (bignum_value <=> bignum_value(0xfffe).to_f).should == -1 + end + + it "returns 0 when other is equal" do + (bignum_value <=> bignum_value.to_f).should == 0 + end + + it "returns 1 when other is smaller" do + (bignum_value(0xfeff) <=> bignum_value.to_f).should == 1 + end + end + end + + describe "with an Object" do + before :each do + @big = bignum_value + @num = mock("value for Bignum#<=>") + end + + it "calls #coerce on other" do + @num.should_receive(:coerce).with(@big).and_return([@big.to_f, 2.5]) + @big <=> @num + end + + ruby_version_is ""..."2.5" do + it "returns nil if #coerce raises an exception" do + @num.should_receive(:coerce).with(@big).and_raise(RuntimeError) + lambda { + @result = (@big <=> @num) + }.should complain(/Numerical comparison operators will no more rescue exceptions/) + @result.should be_nil + end + end + + ruby_version_is "2.5" do + it "lets the exception go through if #coerce raises an exception" do + @num.should_receive(:coerce).with(@big).and_raise(RuntimeError.new("my error")) + lambda { + @big <=> @num + }.should raise_error(RuntimeError, "my error") + end + end + + it "raises an exception if #coerce raises a non-StandardError exception" do + @num.should_receive(:coerce).with(@big).and_raise(Exception) + lambda { @big <=> @num }.should raise_error(Exception) + end + + it "returns nil if #coerce does not return an Array" do + @num.should_receive(:coerce).with(@big).and_return(nil) + (@big <=> @num).should be_nil + end + + it "returns -1 if the coerced value is larger" do + @num.should_receive(:coerce).with(@big).and_return([@big, bignum_value(10)]) + (@big <=> @num).should == -1 + end + + it "returns 0 if the coerced value is equal" do + @num.should_receive(:coerce).with(@big).and_return([@big, bignum_value]) + (@big <=> @num).should == 0 + end + + it "returns 1 if the coerced value is smaller" do + @num.should_receive(:coerce).with(@big).and_return([@big, 22]) + (@big <=> @num).should == 1 + end + end + + # The tests below are taken from matz's revision 23730 for Ruby trunk + it "returns 1 when self is Infinity and other is a Bignum" do + (infinity_value <=> Float::MAX.to_i*2).should == 1 + end + + it "returns -1 when self is negative and other is Infinty" do + (-Float::MAX.to_i*2 <=> infinity_value).should == -1 + end + + it "returns 1 when self is negative and other is -Infinity" do + (-Float::MAX.to_i*2 <=> -infinity_value).should == 1 + end + + it "returns -1 when self is -Infinity and other is negative" do + (-infinity_value <=> -Float::MAX.to_i*2).should == -1 + end + end +end diff --git a/spec/ruby/core/integer/complement_spec.rb b/spec/ruby/core/integer/complement_spec.rb new file mode 100644 index 0000000000..faef88ae21 --- /dev/null +++ b/spec/ruby/core/integer/complement_spec.rb @@ -0,0 +1,20 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#~" do + context "fixnum" do + it "returns self with each bit flipped" do + (~0).should == -1 + (~1221).should == -1222 + (~-2).should == 1 + (~-599).should == 598 + end + end + + context "bignum" do + it "returns self with each bit flipped" do + (~bignum_value(48)).should == -9223372036854775857 + (~(-bignum_value(21))).should == 9223372036854775828 + (~bignum_value(1)).should == -9223372036854775810 + end + end +end diff --git a/spec/ruby/core/integer/div_spec.rb b/spec/ruby/core/integer/div_spec.rb new file mode 100644 index 0000000000..99efedd483 --- /dev/null +++ b/spec/ruby/core/integer/div_spec.rb @@ -0,0 +1,138 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#div" do + context "fixnum" do + it "returns self divided by the given argument as an Integer" do + 2.div(2).should == 1 + 1.div(2).should == 0 + 5.div(2).should == 2 + end + + it "rounds towards -inf" do + 8192.div(10).should == 819 + 8192.div(-10).should == -820 + (-8192).div(10).should == -820 + (-8192).div(-10).should == 819 + end + + it "means (x / y).floor" do + 5.div(2).should == (5 / 2).floor + 5.div(2.0).should == (5 / 2.0).floor + 5.div(-2).should == (5 / -2).floor + + 5.div(100).should == (5 / 100).floor + 5.div(100.0).should == (5 / 100.0).floor + 5.div(-100).should == (5 / -100).floor + end + + it "calls #coerce and #div if argument responds to #coerce" do + x = mock("x") + y = mock("y") + result = mock("result") + + y.should_receive(:coerce).and_return([x, y]) + x.should_receive(:div).with(y).and_return(result) + + 10.div(y).should == result + end + + it "coerces self and the given argument to Floats and returns self divided by other as Fixnum" do + 1.div(0.2).should == 5 + 1.div(0.16).should == 6 + 1.div(0.169).should == 5 + -1.div(50.4).should == -1 + 1.div(bignum_value).should == 0 + 1.div(Rational(1, 5)).should == 5 + end + + it "raises a ZeroDivisionError when the given argument is 0 and a Float" do + lambda { 0.div(0.0) }.should raise_error(ZeroDivisionError) + lambda { 10.div(0.0) }.should raise_error(ZeroDivisionError) + lambda { -10.div(0.0) }.should raise_error(ZeroDivisionError) + end + + it "raises a ZeroDivisionError when the given argument is 0 and not a Float" do + lambda { 13.div(0) }.should raise_error(ZeroDivisionError) + lambda { 13.div(-0) }.should raise_error(ZeroDivisionError) + end + + it "raises a TypeError when given a non-numeric argument" do + lambda { 13.div(mock('10')) }.should raise_error(TypeError) + lambda { 5.div("2") }.should raise_error(TypeError) + lambda { 5.div(:"2") }.should raise_error(TypeError) + lambda { 5.div([]) }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(88) + end + + it "returns self divided by other" do + @bignum.div(4).should == 2305843009213693974 + @bignum.div(Rational(4, 1)).should == 2305843009213693974 + @bignum.div(bignum_value(2)).should == 1 + + (-(10**50)).div(-(10**40 + 1)).should == 9999999999 + (10**50).div(10**40 + 1).should == 9999999999 + + (-10**50).div(10**40 + 1).should == -10000000000 + (10**50).div(-(10**40 + 1)).should == -10000000000 + end + + it "calls #coerce and #div if argument responds to #coerce" do + x = mock("x") + y = mock("y") + result = mock("result") + + y.should_receive(:coerce).and_return([x, y]) + x.should_receive(:div).with(y).and_return(result) + + @bignum.div(y).should == result + end + + it "means (x / y).floor" do + @bignum.div(2).should == (@bignum / 2).floor + @bignum.div(-2).should == (@bignum / -2).floor + + @bignum.div(@bignum+1).should == (@bignum / (@bignum+1)).floor + @bignum.div(-(@bignum+1)).should == (@bignum / -(@bignum+1)).floor + + @bignum.div(2.0).should == (@bignum / 2.0).floor + @bignum.div(100.0).should == (@bignum / 100.0).floor + end + + it "looses precision if passed Float argument" do + @bignum.div(1).should_not == @bignum.div(1.0) + @bignum.div(4).should_not == @bignum.div(4.0) + @bignum.div(21).should_not == @bignum.div(21.0) + end + + it "raises a TypeError when given a non-numeric" do + lambda { @bignum.div(mock("10")) }.should raise_error(TypeError) + lambda { @bignum.div("2") }.should raise_error(TypeError) + lambda { @bignum.div(:symbol) }.should raise_error(TypeError) + end + + it "returns a result of integer division of self by a float argument" do + @bignum.div(4294967295.5).should eql(2147483648) + not_supported_on :opal do + @bignum.div(4294967295.0).should eql(2147483648) + @bignum.div(bignum_value(88).to_f).should eql(1) + @bignum.div(-bignum_value(88).to_f).should eql(-1) + end + end + + # #5490 + it "raises ZeroDivisionError if the argument is 0 and is a Float" do + lambda { @bignum.div(0.0) }.should raise_error(ZeroDivisionError) + lambda { @bignum.div(-0.0) }.should raise_error(ZeroDivisionError) + end + + it "raises ZeroDivisionError if the argument is 0 and is not a Float" do + lambda { @bignum.div(0) }.should raise_error(ZeroDivisionError) + lambda { @bignum.div(-0) }.should raise_error(ZeroDivisionError) + end + end +end diff --git a/spec/ruby/core/integer/divide_spec.rb b/spec/ruby/core/integer/divide_spec.rb index 6c81d5474f..c49b4b0d4a 100644 --- a/spec/ruby/core/integer/divide_spec.rb +++ b/spec/ruby/core/integer/divide_spec.rb @@ -1,7 +1,96 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/arithmetic_exception_in_coerce', __FILE__) +require File.expand_path('../shared/arithmetic_coerce', __FILE__) describe "Integer#/" do - it_behaves_like :integer_arithmetic_exception_in_coerce, :/ + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_arithmetic_coerce_rescue, :/ + end + + ruby_version_is "2.5" do + it_behaves_like :integer_arithmetic_coerce_not_rescue, :/ + end + + context "fixnum" do + it "returns self divided by the given argument" do + (2 / 2).should == 1 + (3 / 2).should == 1 + end + + it "supports dividing negative numbers" do + (-1 / 10).should == -1 + end + + it "returns result the same class as the argument" do + (3 / 2).should == 1 + (3 / 2.0).should == 1.5 + (3 / Rational(2, 1)).should == Rational(3, 2) + end + + it "raises a ZeroDivisionError if the given argument is zero and not a Float" do + lambda { 1 / 0 }.should raise_error(ZeroDivisionError) + end + + it "does NOT raise ZeroDivisionError if the given argument is zero and is a Float" do + (1 / 0.0).to_s.should == 'Infinity' + (-1 / 0.0).to_s.should == '-Infinity' + end + + it "coerces fixnum and return self divided by other" do + (-1 / 50.4).should be_close(-0.0198412698412698, TOLERANCE) + (1 / bignum_value).should == 0 + end + + it "raises a TypeError when given a non-Integer" do + lambda { 13 / mock('10') }.should raise_error(TypeError) + lambda { 13 / "10" }.should raise_error(TypeError) + lambda { 13 / :symbol }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(88) + end + + it "returns self divided by other" do + (@bignum / 4).should == 2305843009213693974 + + (@bignum / bignum_value(2)).should == 1 + + (-(10**50) / -(10**40 + 1)).should == 9999999999 + ((10**50) / (10**40 + 1)).should == 9999999999 + + ((-10**50) / (10**40 + 1)).should == -10000000000 + ((10**50) / -(10**40 + 1)).should == -10000000000 + end + + it "returns self divided by Float" do + not_supported_on :opal do + (bignum_value(88) / 4294967295.0).should be_close(2147483648.5, TOLERANCE) + end + (bignum_value(88) / 4294967295.5).should be_close(2147483648.25, TOLERANCE) + end + + it "returns result the same class as the argument" do + (@bignum / 4).should == 2305843009213693974 + (@bignum / 4.0).should be_close(2305843009213693974, TOLERANCE) + (@bignum / Rational(4, 1)).should == Rational(2305843009213693974, 1) + end + + it "does NOT raise ZeroDivisionError if other is zero and is a Float" do + (bignum_value / 0.0).to_s.should == 'Infinity' + (bignum_value / -0.0).to_s.should == '-Infinity' + end + + it "raises a ZeroDivisionError if other is zero and not a Float" do + lambda { @bignum / 0 }.should raise_error(ZeroDivisionError) + end + + it "raises a TypeError when given a non-numeric" do + lambda { @bignum / mock('10') }.should raise_error(TypeError) + lambda { @bignum / "2" }.should raise_error(TypeError) + lambda { @bignum / :symbol }.should raise_error(TypeError) + end + end end diff --git a/spec/ruby/core/integer/divmod_spec.rb b/spec/ruby/core/integer/divmod_spec.rb new file mode 100644 index 0000000000..d52d1d0577 --- /dev/null +++ b/spec/ruby/core/integer/divmod_spec.rb @@ -0,0 +1,117 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#divmod" do + context "fixnum" do + it "returns an Array containing quotient and modulus obtained from dividing self by the given argument" do + 13.divmod(4).should == [3, 1] + 4.divmod(13).should == [0, 4] + + 13.divmod(4.0).should == [3, 1] + 4.divmod(13.0).should == [0, 4] + + 1.divmod(2.0).should == [0, 1.0] + 200.divmod(bignum_value).should == [0, 200] + end + + it "raises a ZeroDivisionError when the given argument is 0" do + lambda { 13.divmod(0) }.should raise_error(ZeroDivisionError) + lambda { 0.divmod(0) }.should raise_error(ZeroDivisionError) + lambda { -10.divmod(0) }.should raise_error(ZeroDivisionError) + end + + it "raises a ZeroDivisionError when the given argument is 0 and a Float" do + lambda { 0.divmod(0.0) }.should raise_error(ZeroDivisionError) + lambda { 10.divmod(0.0) }.should raise_error(ZeroDivisionError) + lambda { -10.divmod(0.0) }.should raise_error(ZeroDivisionError) + end + + it "raises a TypeError when given a non-Integer" do + lambda { + (obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10) + 13.divmod(obj) + }.should raise_error(TypeError) + lambda { 13.divmod("10") }.should raise_error(TypeError) + lambda { 13.divmod(:symbol) }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(55) + end + + # Based on MRI's test/test_integer.rb (test_divmod), + # MRI maintains the following property: + # if q, r = a.divmod(b) ==> + # assert(0 < b ? (0 <= r && r < b) : (b < r && r <= 0)) + # So, r is always between 0 and b. + it "returns an Array containing quotient and modulus obtained from dividing self by the given argument" do + @bignum.divmod(4).should == [2305843009213693965, 3] + @bignum.divmod(13).should == [709490156681136604, 11] + + @bignum.divmod(4.5).should == [2049638230412172288, 3.5] + + not_supported_on :opal do + @bignum.divmod(4.0).should == [2305843009213693952, 0.0] + @bignum.divmod(13.0).should == [709490156681136640, 8.0] + + @bignum.divmod(2.0).should == [4611686018427387904, 0.0] + end + + @bignum.divmod(bignum_value).should == [1, 55] + + (-(10**50)).divmod(-(10**40 + 1)).should == [9999999999, -9999999999999999999999999999990000000001] + (10**50).divmod(10**40 + 1).should == [9999999999, 9999999999999999999999999999990000000001] + + (-10**50).divmod(10**40 + 1).should == [-10000000000, 10000000000] + (10**50).divmod(-(10**40 + 1)).should == [-10000000000, -10000000000] + end + + describe "with q = floor(x/y), a = q*b + r," do + it "returns [q,r] when a < 0, b > 0 and |a| < b" do + a = -@bignum + 1 + b = @bignum + a.divmod(b).should == [-1, 1] + end + + it "returns [q,r] when a > 0, b < 0 and a > |b|" do + b = -@bignum + 1 + a = @bignum + a.divmod(b).should == [-2, -@bignum + 2] + end + + it "returns [q,r] when a > 0, b < 0 and a < |b|" do + a = @bignum - 1 + b = -@bignum + a.divmod(b).should == [-1, -1] + end + + it "returns [q,r] when a < 0, b < 0 and |a| < |b|" do + a = -@bignum + 1 + b = -@bignum + a.divmod(b).should == [0, -@bignum + 1] + end + end + + it "raises a ZeroDivisionError when the given argument is 0" do + lambda { @bignum.divmod(0) }.should raise_error(ZeroDivisionError) + lambda { (-@bignum).divmod(0) }.should raise_error(ZeroDivisionError) + end + + # Behaviour established as correct in r23953 + it "raises a FloatDomainError if other is NaN" do + lambda { @bignum.divmod(nan_value) }.should raise_error(FloatDomainError) + end + + it "raises a ZeroDivisionError when the given argument is 0 and a Float" do + lambda { @bignum.divmod(0.0) }.should raise_error(ZeroDivisionError) + lambda { (-@bignum).divmod(0.0) }.should raise_error(ZeroDivisionError) + end + + it "raises a TypeError when the given argument is not an Integer" do + lambda { @bignum.divmod(mock('10')) }.should raise_error(TypeError) + lambda { @bignum.divmod("10") }.should raise_error(TypeError) + lambda { @bignum.divmod(:symbol) }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/dup_spec.rb b/spec/ruby/core/integer/dup_spec.rb deleted file mode 100644 index f46bdf89bd..0000000000 --- a/spec/ruby/core/integer/dup_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.expand_path('../../../spec_helper', __FILE__) - -ruby_version_is '2.4' do - describe "Integer#dup" do - it "returns self" do - int = 2 - int.dup.should equal(int) - end - end -end diff --git a/spec/ruby/core/integer/element_reference_spec.rb b/spec/ruby/core/integer/element_reference_spec.rb new file mode 100644 index 0000000000..2a2e8981a3 --- /dev/null +++ b/spec/ruby/core/integer/element_reference_spec.rb @@ -0,0 +1,111 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#[]" do + context "fixnum" do + it "behaves like (n >> b) & 1" do + 0b101[1].should == 0 + 0b101[2].should == 1 + end + + it "returns 1 if the nth bit is set" do + 15[1].should == 1 + end + + it "returns 1 if the nth bit is set (in two's-complement representation)" do + (-1)[1].should == 1 + end + + it "returns 0 if the nth bit is not set" do + 8[2].should == 0 + end + + it "returns 0 if the nth bit is not set (in two's-complement representation)" do + (-2)[0].should == 0 + end + + it "returns 0 if the nth bit is greater than the most significant bit" do + 2[3].should == 0 + end + + it "returns 1 if self is negative and the nth bit is greater than the most significant bit" do + (-1)[3].should == 1 + end + + it "returns 0 when passed a negative argument" do + 3[-1].should == 0 + (-1)[-1].should == 0 + end + + it "calls #to_int to convert the argument to an Integer and returns 1 if the nth bit is set" do + obj = mock('1') + obj.should_receive(:to_int).and_return(1) + + 2[obj].should == 1 + end + + it "calls #to_int to convert the argument to an Integer and returns 0 if the nth bit is set" do + obj = mock('0') + obj.should_receive(:to_int).and_return(0) + + 2[obj].should == 0 + end + + it "accepts a Float argument and returns 0 if the bit at the truncated value is not set" do + 13[1.3].should == 0 + end + + it "accepts a Float argument and returns 1 if the bit at the truncated value is set" do + 13[2.1].should == 1 + end + + it "raises a TypeError when passed a String" do + lambda { 3["3"] }.should raise_error(TypeError) + end + + it "raises a TypeError when #to_int does not return an Integer" do + obj = mock('asdf') + obj.should_receive(:to_int).and_return("asdf") + lambda { 3[obj] }.should raise_error(TypeError) + end + + it "calls #to_int to coerce a String to a Bignum and returns 0" do + obj = mock('bignum value') + obj.should_receive(:to_int).and_return(bignum_value) + + 3[obj].should == 0 + end + + it "returns 0 when passed a Float in the range of a Bignum" do + 3[bignum_value.to_f].should == 0 + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(4996) + end + + it "returns the nth bit in the binary representation of self" do + @bignum[2].should == 1 + @bignum[9.2].should == 1 + @bignum[21].should == 0 + @bignum[0xffffffff].should == 0 + @bignum[-0xffffffff].should == 0 + end + + it "tries to convert the given argument to an Integer using #to_int" do + @bignum[1.3].should == @bignum[1] + + (obj = mock('2')).should_receive(:to_int).at_least(1).and_return(2) + @bignum[obj].should == 1 + end + + it "raises a TypeError when the given argument can't be converted to Integer" do + obj = mock('asdf') + lambda { @bignum[obj] }.should raise_error(TypeError) + + obj.should_receive(:to_int).and_return("asdf") + lambda { @bignum[obj] }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/equal_value_spec.rb b/spec/ruby/core/integer/equal_value_spec.rb new file mode 100644 index 0000000000..102cbb1f26 --- /dev/null +++ b/spec/ruby/core/integer/equal_value_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/equal', __FILE__) + +describe "Integer#==" do + it_behaves_like :integer_equal, :== +end + diff --git a/spec/ruby/core/integer/even_spec.rb b/spec/ruby/core/integer/even_spec.rb index c14cf84947..edc8b13dd9 100644 --- a/spec/ruby/core/integer/even_spec.rb +++ b/spec/ruby/core/integer/even_spec.rb @@ -1,20 +1,40 @@ require File.expand_path('../../../spec_helper', __FILE__) describe "Integer#even?" do - it "returns true for a Fixnum when it is an even number" do - (-2).even?.should be_true - (-1).even?.should be_false + context "fixnum" do + it "returns true for a Fixnum when it is an even number" do + (-2).even?.should be_true + (-1).even?.should be_false - 0.even?.should be_true - 1.even?.should be_false - 2.even?.should be_true + 0.even?.should be_true + 1.even?.should be_false + 2.even?.should be_true + end + + it "returns true for a Bignum when it is an even number" do + bignum_value(0).even?.should be_true + bignum_value(1).even?.should be_false + + (-bignum_value(0)).even?.should be_true + (-bignum_value(1)).even?.should be_false + end end - it "returns true for a Bignum when it is an even number" do - bignum_value(0).even?.should be_true - bignum_value(1).even?.should be_false + context "bignum" do + it "returns true if self is even and positive" do + (10000**10).even?.should be_true + end + + it "returns true if self is even and negative" do + (-10000**10).even?.should be_true + end + + it "returns false if self is odd and positive" do + (9879**976).even?.should be_false + end - (-bignum_value(0)).even?.should be_true - (-bignum_value(1)).even?.should be_false + it "returns false if self is odd and negative" do + (-9879**976).even?.should be_false + end end end diff --git a/spec/ruby/core/integer/exponent_spec.rb b/spec/ruby/core/integer/exponent_spec.rb new file mode 100644 index 0000000000..a009eaa131 --- /dev/null +++ b/spec/ruby/core/integer/exponent_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/exponent', __FILE__) + +describe "Integer#**" do + it_behaves_like :integer_exponent, :** +end diff --git a/spec/ruby/core/integer/fdiv_spec.rb b/spec/ruby/core/integer/fdiv_spec.rb new file mode 100644 index 0000000000..7650fa0f52 --- /dev/null +++ b/spec/ruby/core/integer/fdiv_spec.rb @@ -0,0 +1,49 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#fdiv" do + it "performs floating-point division between self and a fixnum" do + 8.fdiv(7).should be_close(1.14285714285714, TOLERANCE) + end + + it "performs floating-point division between self and a bignum" do + 8.fdiv(bignum_value).should be_close(8.673617379884035e-19, TOLERANCE) + end + + it "performs floating-point division between self and a Float" do + 8.fdiv(9.0).should be_close(0.888888888888889, TOLERANCE) + end + + it "returns NaN when the argument is NaN" do + -1.fdiv(nan_value).nan?.should be_true + 1.fdiv(nan_value).nan?.should be_true + end + + it "returns Infinity when the argument is 0" do + 1.fdiv(0).infinite?.should == 1 + end + + it "returns -Infinity when the argument is 0 and self is negative" do + -1.fdiv(0).infinite?.should == -1 + end + + it "returns Infinity when the argument is 0.0" do + 1.fdiv(0.0).infinite?.should == 1 + end + + it "returns -Infinity when the argument is 0.0 and self is negative" do + -1.fdiv(0.0).infinite?.should == -1 + end + + it "raises a TypeError when argument isn't numeric" do + lambda { 1.fdiv(mock('non-numeric')) }.should raise_error(TypeError) + end + + it "raises an ArgumentError when passed multiple arguments" do + lambda { 1.fdiv(6,0.2) }.should raise_error(ArgumentError) + end + + it "follows the coercion protocol" do + (obj = mock('10')).should_receive(:coerce).with(1).and_return([1, 10]) + 1.fdiv(obj).should == 0.1 + end +end diff --git a/spec/ruby/core/integer/floor_spec.rb b/spec/ruby/core/integer/floor_spec.rb index 9babcd9a3e..156b0ba055 100644 --- a/spec/ruby/core/integer/floor_spec.rb +++ b/spec/ruby/core/integer/floor_spec.rb @@ -3,8 +3,8 @@ require File.expand_path('../shared/to_i', __FILE__) require File.expand_path('../shared/integer_rounding', __FILE__) describe "Integer#floor" do - it_behaves_like(:integer_to_i, :floor) - it_behaves_like(:integer_rounding_positive_precision, :floor) + it_behaves_like :integer_to_i, :floor + it_behaves_like :integer_rounding_positive_precision, :floor ruby_version_is "2.4" do context "precision argument specified as part of the floor method is negative" do diff --git a/spec/ruby/core/integer/gt_spec.rb b/spec/ruby/core/integer/gt_spec.rb index ec0834d346..d63ee5e34f 100644 --- a/spec/ruby/core/integer/gt_spec.rb +++ b/spec/ruby/core/integer/gt_spec.rb @@ -1,7 +1,50 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/comparison_exception_in_coerce', __FILE__) +require File.expand_path('../shared/comparison_coerce', __FILE__) describe "Integer#>" do - it_behaves_like :integer_comparison_exception_in_coerce, :> + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_comparison_coerce_rescue, :> + end + + ruby_version_is "2.5" do + it_behaves_like :integer_comparison_coerce_not_rescue, :> + end + + context "fixnum" do + it "returns true if self is greater than the given argument" do + (13 > 2).should == true + (-500 > -600).should == true + + (1 > 5).should == false + (5 > 5).should == false + + (900 > bignum_value).should == false + (5 > 4.999).should == true + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { 5 > "4" }.should raise_error(ArgumentError) + lambda { 5 > mock('x') }.should raise_error(ArgumentError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(732) + end + + it "returns true if self is greater than the given argument" do + (@bignum > (@bignum - 1)).should == true + (@bignum > 14.6).should == true + (@bignum > 10).should == true + + (@bignum > (@bignum + 500)).should == false + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { @bignum > "4" }.should raise_error(ArgumentError) + lambda { @bignum > mock('str') }.should raise_error(ArgumentError) + end + end end diff --git a/spec/ruby/core/integer/gte_spec.rb b/spec/ruby/core/integer/gte_spec.rb index a49535f823..66ca49249c 100644 --- a/spec/ruby/core/integer/gte_spec.rb +++ b/spec/ruby/core/integer/gte_spec.rb @@ -1,7 +1,50 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/comparison_exception_in_coerce', __FILE__) +require File.expand_path('../shared/comparison_coerce', __FILE__) describe "Integer#>=" do - it_behaves_like :integer_comparison_exception_in_coerce, :>= + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_comparison_coerce_rescue, :>= + end + + ruby_version_is "2.5" do + it_behaves_like :integer_comparison_coerce_not_rescue, :>= + end + + context "fixnum" do + it "returns true if self is greater than or equal to the given argument" do + (13 >= 2).should == true + (-500 >= -600).should == true + + (1 >= 5).should == false + (2 >= 2).should == true + (5 >= 5).should == true + + (900 >= bignum_value).should == false + (5 >= 4.999).should == true + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { 5 >= "4" }.should raise_error(ArgumentError) + lambda { 5 >= mock('x') }.should raise_error(ArgumentError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(14) + end + + it "returns true if self is greater than or equal to other" do + (@bignum >= @bignum).should == true + (@bignum >= (@bignum + 2)).should == false + (@bignum >= 5664.2).should == true + (@bignum >= 4).should == true + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { @bignum >= "4" }.should raise_error(ArgumentError) + lambda { @bignum >= mock('str') }.should raise_error(ArgumentError) + end + end end diff --git a/spec/ruby/core/integer/left_shift_spec.rb b/spec/ruby/core/integer/left_shift_spec.rb new file mode 100644 index 0000000000..c25785b39e --- /dev/null +++ b/spec/ruby/core/integer/left_shift_spec.rb @@ -0,0 +1,165 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#<< (with n << m)" do + context "fixnum" do + it "returns n shifted left m bits when n > 0, m > 0" do + (1 << 1).should == 2 + end + + it "returns n shifted left m bits when n < 0, m > 0" do + (-1 << 1).should == -2 + (-7 << 1).should == -14 + (-42 << 2).should == -168 + end + + it "returns n shifted right m bits when n > 0, m < 0" do + (2 << -1).should == 1 + end + + it "returns n shifted right m bits when n < 0, m < 0" do + (-2 << -1).should == -1 + end + + it "returns 0 when n == 0" do + (0 << 1).should == 0 + end + + it "returns n when n > 0, m == 0" do + (1 << 0).should == 1 + end + + it "returns n when n < 0, m == 0" do + (-1 << 0).should == -1 + end + + it "returns 0 when n > 0, m < 0 and n < 2**-m" do + (3 << -2).should == 0 + (7 << -3).should == 0 + (127 << -7).should == 0 + + # To make sure the exponent is not truncated + (7 << -32).should == 0 + (7 << -64).should == 0 + end + + it "returns -1 when n < 0, m < 0 and n > -(2**-m)" do + (-3 << -2).should == -1 + (-7 << -3).should == -1 + (-127 << -7).should == -1 + + # To make sure the exponent is not truncated + (-7 << -32).should == -1 + (-7 << -64).should == -1 + end + + it "returns 0 when m < 0 and m is a Bignum" do + (3 << -bignum_value).should == 0 + end + + it "returns an Bignum == fixnum_max * 2 when fixnum_max << 1 and n > 0" do + result = fixnum_max << 1 + result.should be_an_instance_of(Bignum) + result.should == fixnum_max * 2 + end + + it "returns an Bignum == fixnum_min * 2 when fixnum_min << 1 and n < 0" do + result = fixnum_min << 1 + result.should be_an_instance_of(Bignum) + result.should == fixnum_min * 2 + end + + it "calls #to_int to convert the argument to an Integer" do + obj = mock("4") + obj.should_receive(:to_int).and_return(4) + + (3 << obj).should == 48 + end + + it "raises a TypeError when #to_int does not return an Integer" do + obj = mock("a string") + obj.should_receive(:to_int).and_return("asdf") + + lambda { 3 << obj }.should raise_error(TypeError) + end + + it "raises a TypeError when passed nil" do + lambda { 3 << nil }.should raise_error(TypeError) + end + + it "raises a TypeError when passed a String" do + lambda { 3 << "4" }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value * 16 + end + + it "returns n shifted left m bits when n > 0, m > 0" do + (@bignum << 4).should == 2361183241434822606848 + end + + it "returns n shifted left m bits when n < 0, m > 0" do + (-@bignum << 9).should == -75557863725914323419136 + end + + it "returns n shifted right m bits when n > 0, m < 0" do + (@bignum << -1).should == 73786976294838206464 + end + + it "returns n shifted right m bits when n < 0, m < 0" do + (-@bignum << -2).should == -36893488147419103232 + end + + it "returns n when n > 0, m == 0" do + (@bignum << 0).should == @bignum + end + + it "returns n when n < 0, m == 0" do + (-@bignum << 0).should == -@bignum + end + + it "returns 0 when m < 0 and m == p where 2**p > n >= 2**(p-1)" do + (@bignum << -68).should == 0 + end + + it "returns 0 when m < 0 and m is a Bignum" do + (@bignum << -bignum_value).should == 0 + end + + it "returns a Fixnum == fixnum_max when (fixnum_max * 2) << -1 and n > 0" do + result = (fixnum_max * 2) << -1 + result.should be_an_instance_of(Fixnum) + result.should == fixnum_max + end + + it "returns a Fixnum == fixnum_min when (fixnum_min * 2) << -1 and n < 0" do + result = (fixnum_min * 2) << -1 + result.should be_an_instance_of(Fixnum) + result.should == fixnum_min + end + + it "calls #to_int to convert the argument to an Integer" do + obj = mock("4") + obj.should_receive(:to_int).and_return(4) + + (@bignum << obj).should == 2361183241434822606848 + end + + it "raises a TypeError when #to_int does not return an Integer" do + obj = mock("a string") + obj.should_receive(:to_int).and_return("asdf") + + lambda { @bignum << obj }.should raise_error(TypeError) + end + + it "raises a TypeError when passed nil" do + lambda { @bignum << nil }.should raise_error(TypeError) + end + + it "raises a TypeError when passed a String" do + lambda { @bignum << "4" }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/lt_spec.rb b/spec/ruby/core/integer/lt_spec.rb index 3b778d7f6c..03ef701a89 100644 --- a/spec/ruby/core/integer/lt_spec.rb +++ b/spec/ruby/core/integer/lt_spec.rb @@ -1,6 +1,52 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/comparison_exception_in_coerce', __FILE__) +require File.expand_path('../shared/comparison_coerce', __FILE__) describe "Integer#<" do - it_behaves_like :integer_comparison_exception_in_coerce, :< + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_comparison_coerce_rescue, :< + end + + ruby_version_is "2.5" do + it_behaves_like :integer_comparison_coerce_not_rescue, :< + end + + context "fixnum" do + it "returns true if self is less than the given argument" do + (2 < 13).should == true + (-600 < -500).should == true + + (5 < 1).should == false + (5 < 5).should == false + + (900 < bignum_value).should == true + (5 < 4.999).should == false + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { 5 < "4" }.should raise_error(ArgumentError) + lambda { 5 < mock('x') }.should raise_error(ArgumentError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(32) + end + + it "returns true if self is less than the given argument" do + (@bignum < @bignum + 1).should == true + (-@bignum < -(@bignum - 1)).should == true + + (@bignum < 1).should == false + (@bignum < 5).should == false + + (@bignum < 4.999).should == false + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { @bignum < "4" }.should raise_error(ArgumentError) + lambda { @bignum < mock('str') }.should raise_error(ArgumentError) + end + end end + diff --git a/spec/ruby/core/integer/lte_spec.rb b/spec/ruby/core/integer/lte_spec.rb index d62780c78c..592e72116c 100644 --- a/spec/ruby/core/integer/lte_spec.rb +++ b/spec/ruby/core/integer/lte_spec.rb @@ -1,6 +1,55 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/comparison_exception_in_coerce', __FILE__) +require File.expand_path('../shared/comparison_coerce', __FILE__) describe "Integer#<=" do - it_behaves_like :integer_comparison_exception_in_coerce, :<= + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_comparison_coerce_rescue, :<= + end + + ruby_version_is "2.5" do + it_behaves_like :integer_comparison_coerce_not_rescue, :<= + end + + context "fixnum" do + it "returns true if self is less than or equal to other" do + (2 <= 13).should == true + (-600 <= -500).should == true + + (5 <= 1).should == false + (5 <= 5).should == true + (-2 <= -2).should == true + + (900 <= bignum_value).should == true + (5 <= 4.999).should == false + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { 5 <= "4" }.should raise_error(ArgumentError) + lambda { 5 <= mock('x') }.should raise_error(ArgumentError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(39) + end + + it "returns true if self is less than or equal to other" do + (@bignum <= @bignum).should == true + (-@bignum <= -(@bignum - 1)).should == true + + (@bignum <= 4.999).should == false + end + + it "returns false if compares with near float" do + (@bignum <= (@bignum + 0.0)).should == false + (@bignum <= (@bignum + 0.5)).should == false + end + + it "raises an ArgumentError when given a non-Integer" do + lambda { @bignum <= "4" }.should raise_error(ArgumentError) + lambda { @bignum <= mock('str') }.should raise_error(ArgumentError) + end + end end + diff --git a/spec/ruby/core/integer/magnitude_spec.rb b/spec/ruby/core/integer/magnitude_spec.rb new file mode 100644 index 0000000000..72929b827e --- /dev/null +++ b/spec/ruby/core/integer/magnitude_spec.rb @@ -0,0 +1,7 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/abs', __FILE__) + +describe "Integer#magnitude" do + it_behaves_like :integer_abs, :magnitude +end + diff --git a/spec/ruby/core/integer/minus_spec.rb b/spec/ruby/core/integer/minus_spec.rb index 6e8fa69759..6a84bca429 100644 --- a/spec/ruby/core/integer/minus_spec.rb +++ b/spec/ruby/core/integer/minus_spec.rb @@ -1,7 +1,50 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/arithmetic_exception_in_coerce', __FILE__) +require File.expand_path('../shared/arithmetic_coerce', __FILE__) describe "Integer#-" do - it_behaves_like :integer_arithmetic_exception_in_coerce, :- + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_arithmetic_coerce_rescue, :- + end + + ruby_version_is "2.5" do + it_behaves_like :integer_arithmetic_coerce_not_rescue, :- + end + + context "fixnum" do + it "returns self minus the given Integer" do + (5 - 10).should == -5 + (9237212 - 5_280).should == 9231932 + + (781 - 0.5).should == 780.5 + (2_560_496 - bignum_value).should == -9223372036852215312 + end + + it "raises a TypeError when given a non-Integer" do + lambda { + (obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10) + 13 - obj + }.should raise_error(TypeError) + lambda { 13 - "10" }.should raise_error(TypeError) + lambda { 13 - :symbol }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(314) + end + + it "returns self minus the given Integer" do + (@bignum - 9).should == 9223372036854776113 + (@bignum - 12.57).should be_close(9223372036854776109.43, TOLERANCE) + (@bignum - bignum_value(42)).should == 272 + end + + it "raises a TypeError when given a non-Integer" do + lambda { @bignum - mock('10') }.should raise_error(TypeError) + lambda { @bignum - "10" }.should raise_error(TypeError) + lambda { @bignum - :symbol }.should raise_error(TypeError) + end + end end diff --git a/spec/ruby/core/integer/modulo_spec.rb b/spec/ruby/core/integer/modulo_spec.rb new file mode 100644 index 0000000000..34649f0d01 --- /dev/null +++ b/spec/ruby/core/integer/modulo_spec.rb @@ -0,0 +1,10 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../shared/modulo', __FILE__) + +describe "Integer#%" do + it_behaves_like :integer_modulo, :% +end + +describe "Integer#modulo" do + it_behaves_like :integer_modulo, :modulo +end diff --git a/spec/ruby/core/integer/multiply_spec.rb b/spec/ruby/core/integer/multiply_spec.rb index cfce2418a4..e5872e6fa0 100644 --- a/spec/ruby/core/integer/multiply_spec.rb +++ b/spec/ruby/core/integer/multiply_spec.rb @@ -1,6 +1,52 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/arithmetic_exception_in_coerce', __FILE__) +require File.expand_path('../shared/arithmetic_coerce', __FILE__) describe "Integer#*" do - it_behaves_like :integer_arithmetic_exception_in_coerce, :* + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_arithmetic_coerce_rescue, :* + end + + ruby_version_is "2.5" do + it_behaves_like :integer_arithmetic_coerce_not_rescue, :* + end + + context "fixnum" do + it "returns self multiplied by the given Integer" do + (4923 * 2).should == 9846 + (1342177 * 800).should == 1073741600 + (65536 * 65536).should == 4294967296 + + (256 * bignum_value).should == 2361183241434822606848 + (6712 * 0.25).should == 1678.0 + end + + it "raises a TypeError when given a non-Integer" do + lambda { + (obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10) + 13 * obj + }.should raise_error(TypeError) + lambda { 13 * "10" }.should raise_error(TypeError) + lambda { 13 * :symbol }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(772) + end + + it "returns self multiplied by the given Integer" do + (@bignum * (1/bignum_value(0xffff).to_f)).should be_close(1.0, TOLERANCE) + (@bignum * (1/bignum_value(0xffff).to_f)).should be_close(1.0, TOLERANCE) + (@bignum * 10).should == 92233720368547765800 + (@bignum * (@bignum - 40)).should == 85070591730234629737795195287525433200 + end + + it "raises a TypeError when given a non-Integer" do + lambda { @bignum * mock('10') }.should raise_error(TypeError) + lambda { @bignum * "10" }.should raise_error(TypeError) + lambda { @bignum * :symbol }.should raise_error(TypeError) + end + end end + diff --git a/spec/ruby/core/integer/next_spec.rb b/spec/ruby/core/integer/next_spec.rb index a34db0a6f6..bc3a9b797f 100644 --- a/spec/ruby/core/integer/next_spec.rb +++ b/spec/ruby/core/integer/next_spec.rb @@ -2,5 +2,5 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/next', __FILE__) describe "Integer#next" do - it_behaves_like(:integer_next, :next) + it_behaves_like :integer_next, :next end diff --git a/spec/ruby/core/integer/odd_spec.rb b/spec/ruby/core/integer/odd_spec.rb index 2aa76d054a..c0c907a906 100644 --- a/spec/ruby/core/integer/odd_spec.rb +++ b/spec/ruby/core/integer/odd_spec.rb @@ -1,18 +1,38 @@ require File.expand_path('../../../spec_helper', __FILE__) describe "Integer#odd?" do - it "returns true when self is an odd number" do - (-2).odd?.should be_false - (-1).odd?.should be_true + context "fixnum" do + it "returns true when self is an odd number" do + (-2).odd?.should be_false + (-1).odd?.should be_true - 0.odd?.should be_false - 1.odd?.should be_true - 2.odd?.should be_false + 0.odd?.should be_false + 1.odd?.should be_true + 2.odd?.should be_false - bignum_value(0).odd?.should be_false - bignum_value(1).odd?.should be_true + bignum_value(0).odd?.should be_false + bignum_value(1).odd?.should be_true - (-bignum_value(0)).odd?.should be_false - (-bignum_value(1)).odd?.should be_true + (-bignum_value(0)).odd?.should be_false + (-bignum_value(1)).odd?.should be_true + end + end + + context "bignum" do + it "returns true if self is odd and positive" do + (987279**19).odd?.should be_true + end + + it "returns true if self is odd and negative" do + (-9873389**97).odd?.should be_true + end + + it "returns false if self is even and positive" do + (10000000**10).odd?.should be_false + end + + it "returns false if self is even and negative" do + (-1000000**100).odd?.should be_false + end end end diff --git a/spec/ruby/core/integer/plus_spec.rb b/spec/ruby/core/integer/plus_spec.rb index c292943d06..5d1169c7da 100644 --- a/spec/ruby/core/integer/plus_spec.rb +++ b/spec/ruby/core/integer/plus_spec.rb @@ -1,6 +1,50 @@ require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../shared/arithmetic_exception_in_coerce', __FILE__) +require File.expand_path('../shared/arithmetic_coerce', __FILE__) describe "Integer#+" do - it_behaves_like :integer_arithmetic_exception_in_coerce, :+ + ruby_version_is "2.4"..."2.5" do + it_behaves_like :integer_arithmetic_coerce_rescue, :+ + end + + ruby_version_is "2.5" do + it_behaves_like :integer_arithmetic_coerce_not_rescue, :+ + end + + context "fixnum" do + it "returns self plus the given Integer" do + (491 + 2).should == 493 + (90210 + 10).should == 90220 + + (9 + bignum_value).should == 9223372036854775817 + (1001 + 5.219).should == 1006.219 + end + + it "raises a TypeError when given a non-Integer" do + lambda { + (obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10) + 13 + obj + }.should raise_error(TypeError) + lambda { 13 + "10" }.should raise_error(TypeError) + lambda { 13 + :symbol }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(76) + end + + it "returns self plus the given Integer" do + (@bignum + 4).should == 9223372036854775888 + (@bignum + 4.2).should be_close(9223372036854775888.2, TOLERANCE) + (@bignum + bignum_value(3)).should == 18446744073709551695 + end + + it "raises a TypeError when given a non-Integer" do + lambda { @bignum + mock('10') }.should raise_error(TypeError) + lambda { @bignum + "10" }.should raise_error(TypeError) + lambda { @bignum + :symbol}.should raise_error(TypeError) + end + end end + diff --git a/spec/ruby/core/integer/pow_spec.rb b/spec/ruby/core/integer/pow_spec.rb new file mode 100644 index 0000000000..5811576d92 --- /dev/null +++ b/spec/ruby/core/integer/pow_spec.rb @@ -0,0 +1,51 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../shared/exponent', __FILE__) + +ruby_version_is "2.5" do + describe "Integer#pow" do + context "one argument is passed" do + it_behaves_like :integer_exponent, :pow + end + + context "two arguments are passed" do + it "returns modulo of self raised to the given power" do + 2.pow(5, 12).should == 8 + 2.pow(6, 13).should == 12 + 2.pow(7, 14).should == 2 + 2.pow(8, 15).should == 1 + end + + ruby_bug '#13669', '2.5'...'2.5.1' do + it "works well with bignums" do + 2.pow(61, 5843009213693951).should eql 3697379018277258 + 2.pow(62, 5843009213693952).should eql 1551748822859776 + 2.pow(63, 5843009213693953).should eql 3103497645717974 + 2.pow(64, 5843009213693954).should eql 363986077738838 + end + end + + it "handles sign like #divmod does" do + 2.pow(5, 12).should == 8 + 2.pow(5, -12).should == -4 + -2.pow(5, 12).should == 4 + -2.pow(5, -12).should == -8 + end + + it "ensures all arguments are integers" do + -> { 2.pow(5, 12.0) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/) + -> { 2.pow(5, Rational(12, 1)) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/) + end + + it "raises TypeError for non-numeric value" do + -> { 2.pow(5, "12") }.should raise_error(TypeError) + -> { 2.pow(5, []) }.should raise_error(TypeError) + -> { 2.pow(5, nil) }.should raise_error(TypeError) + end + + it "raises a ZeroDivisionError when the given argument is 0" do + -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError) + end + end + end +end diff --git a/spec/ruby/core/integer/remainder_spec.rb b/spec/ruby/core/integer/remainder_spec.rb new file mode 100644 index 0000000000..926b86135b --- /dev/null +++ b/spec/ruby/core/integer/remainder_spec.rb @@ -0,0 +1,51 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#remainder" do + context "fixnum" do + it "returns the remainder of dividing self by other" do + 5.remainder(3).should == 2 + 5.remainder(3.0).should == 2.0 + 5.remainder(Rational(3, 1)).should == Rational(2, 1) + end + + it "means x-y*(x/y).truncate" do + 5.remainder(3).should == 2 + 5.remainder(3.3).should be_close(1.7, TOLERANCE) + 5.remainder(3.7).should be_close(1.3, TOLERANCE) + end + + it "keeps sign of self" do + 5.remainder( 3).should == 2 + 5.remainder(-3).should == 2 + -5.remainder( 3).should == -2 + -5.remainder(-3).should == -2 + end + + it "raises TypeError if passed non-numeric argument" do + -> { 5.remainder("3") }.should raise_error(TypeError) + -> { 5.remainder(:"3") }.should raise_error(TypeError) + -> { 5.remainder([]) }.should raise_error(TypeError) + -> { 5.remainder(nil) }.should raise_error(TypeError) + end + end + + context "bignum" do + it "returns the remainder of dividing self by other" do + a = bignum_value(79) + a.remainder(2).should == 1 + a.remainder(97.345).should be_close(46.5674996147722, TOLERANCE) + a.remainder(bignum_value).should == 79 + end + + it "raises a ZeroDivisionError if other is zero and not a Float" do + lambda { bignum_value(66).remainder(0) }.should raise_error(ZeroDivisionError) + end + + it "does raises ZeroDivisionError if other is zero and a Float" do + a = bignum_value(7) + b = bignum_value(32) + lambda { a.remainder(0.0) }.should raise_error(ZeroDivisionError) + lambda { b.remainder(-0.0) }.should raise_error(ZeroDivisionError) + end + end +end diff --git a/spec/ruby/core/integer/right_shift_spec.rb b/spec/ruby/core/integer/right_shift_spec.rb new file mode 100644 index 0000000000..7a82df6ba9 --- /dev/null +++ b/spec/ruby/core/integer/right_shift_spec.rb @@ -0,0 +1,191 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#>> (with n >> m)" do + context "fixnum" do + it "returns n shifted right m bits when n > 0, m > 0" do + (2 >> 1).should == 1 + end + + it "returns n shifted right m bits when n < 0, m > 0" do + (-2 >> 1).should == -1 + (-7 >> 1).should == -4 + (-42 >> 2).should == -11 + end + + it "returns n shifted left m bits when n > 0, m < 0" do + (1 >> -1).should == 2 + end + + it "returns n shifted left m bits when n < 0, m < 0" do + (-1 >> -1).should == -2 + end + + it "returns 0 when n == 0" do + (0 >> 1).should == 0 + end + + it "returns n when n > 0, m == 0" do + (1 >> 0).should == 1 + end + + it "returns n when n < 0, m == 0" do + (-1 >> 0).should == -1 + end + + it "returns 0 when n > 0, m > 0 and n < 2**m" do + (3 >> 2).should == 0 + (7 >> 3).should == 0 + (127 >> 7).should == 0 + + # To make sure the exponent is not truncated + (7 >> 32).should == 0 + (7 >> 64).should == 0 + end + + it "returns -1 when n < 0, m > 0 and n > -(2**m)" do + (-3 >> 2).should == -1 + (-7 >> 3).should == -1 + (-127 >> 7).should == -1 + + # To make sure the exponent is not truncated + (-7 >> 32).should == -1 + (-7 >> 64).should == -1 + end + + it "returns 0 when m is a bignum" do + (3 >> bignum_value).should == 0 + end + + it "returns an Bignum == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do + result = fixnum_max >> -1 + result.should be_an_instance_of(Bignum) + result.should == fixnum_max * 2 + end + + it "returns an Bignum == fixnum_min * 2 when fixnum_min >> -1 and n < 0" do + result = fixnum_min >> -1 + result.should be_an_instance_of(Bignum) + result.should == fixnum_min * 2 + end + + it "calls #to_int to convert the argument to an Integer" do + obj = mock("2") + obj.should_receive(:to_int).and_return(2) + + (8 >> obj).should == 2 + end + + it "raises a TypeError when #to_int does not return an Integer" do + obj = mock("a string") + obj.should_receive(:to_int).and_return("asdf") + + lambda { 3 >> obj }.should raise_error(TypeError) + end + + it "raises a TypeError when passed nil" do + lambda { 3 >> nil }.should raise_error(TypeError) + end + + it "raises a TypeError when passed a String" do + lambda { 3 >> "4" }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value * 16 + end + + it "returns n shifted right m bits when n > 0, m > 0" do + (@bignum >> 1).should == 73786976294838206464 + end + + it "returns n shifted right m bits when n < 0, m > 0" do + (-@bignum >> 2).should == -36893488147419103232 + end + + it "respects twos complement signed shifting" do + # This explicit left hand value is important because it is the + # exact bit pattern that matters, so it's important it's right + # here to show the significance. + # + + (-42949672980000000000000 >> 14).should == -2621440001220703125 + (-42949672980000000000001 >> 14).should == -2621440001220703126 + # Note the off by one -------------------- ^^^^^^^^^^^^^^^^^^^^ + # This is because even though we discard the lowest bit, in twos + # complement it would influence the bits to the left of it. + + (-42949672980000000000000 >> 15).should == -1310720000610351563 + (-42949672980000000000001 >> 15).should == -1310720000610351563 + + (-0xfffffffffffffffff >> 32).should == -68719476736 + end + + it "respects twos complement signed shifting for very large values" do + giant = 42949672980000000000000000000000000000000000000000000000000000000000000000000000000000000000 + neg = -giant + + (giant >> 84).should == 2220446050284288846538547929770901490087453566957265138626098632812 + (neg >> 84).should == -2220446050284288846538547929770901490087453566957265138626098632813 + end + + it "returns n shifted left m bits when n > 0, m < 0" do + (@bignum >> -2).should == 590295810358705651712 + end + + it "returns n shifted left m bits when n < 0, m < 0" do + (-@bignum >> -3).should == -1180591620717411303424 + end + + it "returns n when n > 0, m == 0" do + (@bignum >> 0).should == @bignum + end + + it "returns n when n < 0, m == 0" do + (-@bignum >> 0).should == -@bignum + end + + it "returns 0 when m > 0 and m == p where 2**p > n >= 2**(p-1)" do + (@bignum >> 68).should == 0 + end + + it "returns 0 when m is a Bignum" do + (@bignum >> bignum_value).should == 0 + end + + it "returns a Fixnum == fixnum_max when (fixnum_max * 2) >> 1 and n > 0" do + result = (fixnum_max * 2) >> 1 + result.should be_an_instance_of(Fixnum) + result.should == fixnum_max + end + + it "returns a Fixnum == fixnum_min when (fixnum_min * 2) >> 1 and n < 0" do + result = (fixnum_min * 2) >> 1 + result.should be_an_instance_of(Fixnum) + result.should == fixnum_min + end + + it "calls #to_int to convert the argument to an Integer" do + obj = mock("2") + obj.should_receive(:to_int).and_return(2) + + (@bignum >> obj).should == 36893488147419103232 + end + + it "raises a TypeError when #to_int does not return an Integer" do + obj = mock("a string") + obj.should_receive(:to_int).and_return("asdf") + + lambda { @bignum >> obj }.should raise_error(TypeError) + end + + it "raises a TypeError when passed nil" do + lambda { @bignum >> nil }.should raise_error(TypeError) + end + + it "raises a TypeError when passed a String" do + lambda { @bignum >> "4" }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/round_spec.rb b/spec/ruby/core/integer/round_spec.rb index 5a46e6cba6..061b33c933 100644 --- a/spec/ruby/core/integer/round_spec.rb +++ b/spec/ruby/core/integer/round_spec.rb @@ -3,8 +3,8 @@ require File.expand_path('../shared/to_i', __FILE__) require File.expand_path('../shared/integer_rounding', __FILE__) describe "Integer#round" do - it_behaves_like(:integer_to_i, :round) - it_behaves_like(:integer_rounding_positive_precision, :round) + it_behaves_like :integer_to_i, :round + it_behaves_like :integer_rounding_positive_precision, :round ruby_version_is ""..."2.5" do # Not just since 2.4 it "rounds itself as a float if passed a positive precision" do diff --git a/spec/ruby/core/integer/shared/abs.rb b/spec/ruby/core/integer/shared/abs.rb new file mode 100644 index 0000000000..946aa21864 --- /dev/null +++ b/spec/ruby/core/integer/shared/abs.rb @@ -0,0 +1,18 @@ +describe :integer_abs, shared: true do + context "fixnum" do + it "returns self's absolute fixnum value" do + { 0 => [0, -0, +0], 2 => [2, -2, +2], 100 => [100, -100, +100] }.each do |key, values| + values.each do |value| + value.send(@method).should == key + end + end + end + end + + context "bignum" do + it "returns the absolute bignum value" do + bignum_value(39).send(@method).should == 9223372036854775847 + (-bignum_value(18)).send(@method).should == 9223372036854775826 + end + end +end diff --git a/spec/ruby/core/integer/shared/arithmetic_coerce.rb b/spec/ruby/core/integer/shared/arithmetic_coerce.rb new file mode 100644 index 0000000000..e33c5ff0f4 --- /dev/null +++ b/spec/ruby/core/integer/shared/arithmetic_coerce.rb @@ -0,0 +1,31 @@ +require File.expand_path('../../fixtures/classes', __FILE__) + +describe :integer_arithmetic_coerce_rescue, shared: true do + it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) + + # e.g. 1 + b + -> { 1.send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into Integer/) + end + + it "does not rescue Exception and StandardError siblings raised in other#coerce" do + [Exception, NoMemoryError].each do |exception| + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(exception) + + # e.g. 1 + b + -> { 1.send(@method, b) }.should raise_error(exception) + end + end +end + +describe :integer_arithmetic_coerce_not_rescue, 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(IntegerSpecs::CoerceError) + + # e.g. 1 + b + -> { 1.send(@method, b) }.should raise_error(IntegerSpecs::CoerceError) + end +end diff --git a/spec/ruby/core/integer/shared/arithmetic_exception_in_coerce.rb b/spec/ruby/core/integer/shared/arithmetic_exception_in_coerce.rb deleted file mode 100644 index dd3f55d444..0000000000 --- a/spec/ruby/core/integer/shared/arithmetic_exception_in_coerce.rb +++ /dev/null @@ -1,33 +0,0 @@ -require File.expand_path('../../fixtures/classes', __FILE__) - -describe :integer_arithmetic_exception_in_coerce, shared: true do - ruby_version_is ""..."2.5" do - it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) - - # e.g. 1 + b - -> { 1.send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into #{1.class}/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - # e.g. 1 + b - -> { 1.send(@method, b) }.should raise_error(exception) - end - end - end - - ruby_version_is "2.5" do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) - - # e.g. 1 + b - -> { 1.send(@method, b) }.should raise_error(IntegerSpecs::CoerceError) - end - end -end diff --git a/spec/ruby/core/integer/shared/comparison_coerce.rb b/spec/ruby/core/integer/shared/comparison_coerce.rb new file mode 100644 index 0000000000..6d5e69b774 --- /dev/null +++ b/spec/ruby/core/integer/shared/comparison_coerce.rb @@ -0,0 +1,33 @@ +require File.expand_path('../../fixtures/classes', __FILE__) + +describe :integer_comparison_coerce_rescue, shared: true do + it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) + + # e.g. 1 > b + -> { + -> { 1.send(@method, b) }.should raise_error(ArgumentError, /comparison of Integer with MockObject failed/) + }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/) + end + + it "does not rescue Exception and StandardError siblings raised in other#coerce" do + [Exception, NoMemoryError].each do |exception| + b = mock("numeric with failed #coerce") + b.should_receive(:coerce).and_raise(exception) + + # e.g. 1 > b + -> { 1.send(@method, b) }.should raise_error(exception) + end + end +end + +describe :integer_comparison_coerce_not_rescue, 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(IntegerSpecs::CoerceError) + + # e.g. 1 > b + -> { 1.send(@method, b) }.should raise_error(IntegerSpecs::CoerceError) + end +end diff --git a/spec/ruby/core/integer/shared/comparison_exception_in_coerce.rb b/spec/ruby/core/integer/shared/comparison_exception_in_coerce.rb deleted file mode 100644 index f99d680d6d..0000000000 --- a/spec/ruby/core/integer/shared/comparison_exception_in_coerce.rb +++ /dev/null @@ -1,35 +0,0 @@ -require File.expand_path('../../fixtures/classes', __FILE__) - -describe :integer_comparison_exception_in_coerce, shared: true do - ruby_version_is ""..."2.5" do - it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) - - # e.g. 1 > b - -> { - -> { 1.send(@method, b) }.should raise_error(ArgumentError, /comparison of #{1.class} with MockObject failed/) - }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/) - end - - it "does not rescue Exception and StandardError siblings raised in other#coerce" do - [Exception, NoMemoryError].each do |exception| - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(exception) - - # e.g. 1 > b - -> { 1.send(@method, b) }.should raise_error(exception) - end - end - end - - ruby_version_is "2.5" do - it "does not rescue exception raised in other#coerce" do - b = mock("numeric with failed #coerce") - b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError) - - # e.g. 1 > b - -> { 1.send(@method, b) }.should raise_error(IntegerSpecs::CoerceError) - end - end -end diff --git a/spec/ruby/core/integer/shared/equal.rb b/spec/ruby/core/integer/shared/equal.rb new file mode 100644 index 0000000000..03416b60f5 --- /dev/null +++ b/spec/ruby/core/integer/shared/equal.rb @@ -0,0 +1,58 @@ +describe :integer_equal, shared: true do + context "fixnum" do + it "returns true if self has the same value as other" do + 1.send(@method, 1).should == true + 9.send(@method, 5).should == false + + # Actually, these call Float#==, Bignum#== etc. + 9.send(@method, 9.0).should == true + 9.send(@method, 9.01).should == false + + 10.send(@method, bignum_value).should == false + end + + it "calls 'other == self' if the given argument is not a Integer" do + 1.send(@method, '*').should == false + + obj = mock('one other') + obj.should_receive(:==).any_number_of_times.and_return(false) + 1.send(@method, obj).should == false + + obj = mock('another') + obj.should_receive(:==).any_number_of_times.and_return(true) + 2.send(@method, obj).should == true + end + end + + context "bignum" do + before :each do + @bignum = bignum_value + end + + it "returns true if self has the same value as the given argument" do + @bignum.send(@method, @bignum).should == true + @bignum.send(@method, @bignum.to_f).should == true + + @bignum.send(@method, @bignum + 1).should == false + (@bignum + 1).send(@method, @bignum).should == false + + @bignum.send(@method, 9).should == false + @bignum.send(@method, 9.01).should == false + + @bignum.send(@method, bignum_value(10)).should == false + end + + it "calls 'other == self' if the given argument is not an Integer" do + obj = mock('not integer') + obj.should_receive(:==).and_return(true) + @bignum.send(@method, obj).should == true + end + + it "returns the result of 'other == self' as a boolean" do + obj = mock('not integer') + obj.should_receive(:==).exactly(2).times.and_return("woot", nil) + @bignum.send(@method, obj).should == true + @bignum.send(@method, obj).should == false + end + end +end diff --git a/spec/ruby/core/integer/shared/exponent.rb b/spec/ruby/core/integer/shared/exponent.rb new file mode 100644 index 0000000000..810e2a7101 --- /dev/null +++ b/spec/ruby/core/integer/shared/exponent.rb @@ -0,0 +1,118 @@ +describe :integer_exponent, shared: true do + context "fixnum" do + it "returns self raised to the given power" do + 2.send(@method, 0).should eql 1 + 2.send(@method, 1).should eql 2 + 2.send(@method, 2).should eql 4 + + 9.send(@method, 0.5).should eql 3.0 + 9.send(@method, Rational(1, 2)).should eql 3.0 + 5.send(@method, -1).to_f.to_s.should == '0.2' + + 2.send(@method, 40).should eql 1099511627776 + end + + it "overflows the answer to a bignum transparently" do + 2.send(@method, 29).should eql 536870912 + 2.send(@method, 30).should eql 1073741824 + 2.send(@method, 31).should eql 2147483648 + 2.send(@method, 32).should eql 4294967296 + + 2.send(@method, 61).should eql 2305843009213693952 + 2.send(@method, 62).should eql 4611686018427387904 + 2.send(@method, 63).should eql 9223372036854775808 + 2.send(@method, 64).should eql 18446744073709551616 + 8.send(@method, 23).should eql 590295810358705651712 + end + + it "raises negative numbers to the given power" do + (-2).send(@method, 29).should eql(-536870912) + (-2).send(@method, 30).should eql(1073741824) + (-2).send(@method, 31).should eql(-2147483648) + (-2).send(@method, 32).should eql(4294967296) + + (-2).send(@method, 61).should eql(-2305843009213693952) + (-2).send(@method, 62).should eql(4611686018427387904) + (-2).send(@method, 63).should eql(-9223372036854775808) + (-2).send(@method, 64).should eql(18446744073709551616) + end + + it "can raise 1 to a bignum safely" do + 1.send(@method, 4611686018427387904).should eql 1 + end + + it "can raise -1 to a bignum safely" do + (-1).send(@method, 4611686018427387904).should eql(1) + (-1).send(@method, 4611686018427387905).should eql(-1) + end + + it "returns Float::INFINITY when the number is too big" do + 2.send(@method, 427387904).should == Float::INFINITY + end + + it "raises a ZeroDivisionError for 0 ** -1" do + -> { 0.send(@method, -1) }.should raise_error(ZeroDivisionError) + -> { 0.send(@method, Rational(-1, 1)) }.should raise_error(ZeroDivisionError) + end + + it "returns Float::INFINITY for 0 ** -1.0" do + 0.send(@method, -1.0).should == Float::INFINITY + end + + it "raises a TypeError when given a non-numeric power" do + -> { 13.send(@method, "10") }.should raise_error(TypeError) + -> { 13.send(@method, :symbol) }.should raise_error(TypeError) + -> { 13.send(@method, nil) }.should raise_error(TypeError) + end + + it "coerces power and calls #**" do + num_2 = mock("2") + num_13 = mock("13") + num_2.should_receive(:coerce).with(13).and_return([num_13, num_2]) + num_13.should_receive(:**).with(num_2).and_return(169) + + 13.send(@method, num_2).should == 169 + end + + it "returns Float when power is Float" do + 2.send(@method, 2.0).should == 4.0 + end + + it "returns Rational when power is Rational" do + 2.send(@method, Rational(2, 1)).should == Rational(4, 1) + end + + it "returns a complex number when negative and raised to a fractional power" do + (-8).send(@method, 1.0/3) .should be_close(Complex(1, 1.73205), TOLERANCE) + (-8).send(@method, Rational(1, 3)).should be_close(Complex(1, 1.73205), TOLERANCE) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value(47) + end + + it "returns self raised to other power" do + (@bignum.send(@method, 4)).should == 7237005577332262361485077344629993318496048279512298547155833600056910050625 + (@bignum.send(@method, 1.2)).should be_close(57262152889751597425762.57804, TOLERANCE) + end + + it "raises a TypeError when given a non-Integer" do + lambda { @bignum.send(@method, mock('10')) }.should raise_error(TypeError) + lambda { @bignum.send(@method, "10") }.should raise_error(TypeError) + lambda { @bignum.send(@method, :symbol) }.should raise_error(TypeError) + end + + it "switch to a Float when the values is too big" do + flt = @bignum.send(@method, @bignum) + flt.should be_kind_of(Float) + flt.infinite?.should == 1 + end + + it "returns a complex number when negative and raised to a fractional power" do + ((-@bignum).send(@method, (1.0/3))) .should be_close(Complex(1048576,1816186.907597341), TOLERANCE) + ((-@bignum).send(@method, Rational(1,3))).should be_close(Complex(1048576,1816186.907597341), TOLERANCE) + end + end +end diff --git a/spec/ruby/core/integer/shared/modulo.rb b/spec/ruby/core/integer/shared/modulo.rb new file mode 100644 index 0000000000..d545a9af55 --- /dev/null +++ b/spec/ruby/core/integer/shared/modulo.rb @@ -0,0 +1,74 @@ +describe :integer_modulo, shared: true do + context "fixnum" do + it "returns the modulus obtained from dividing self by the given argument" do + 13.send(@method, 4).should == 1 + 4.send(@method, 13).should == 4 + + 13.send(@method, 4.0).should == 1 + 4.send(@method, 13.0).should == 4 + + (-200).send(@method, 256).should == 56 + (-1000).send(@method, 512).should == 24 + + (-200).send(@method, -256).should == -200 + (-1000).send(@method, -512).should == -488 + + (200).send(@method, -256).should == -56 + (1000).send(@method, -512).should == -24 + + 1.send(@method, 2.0).should == 1.0 + 200.send(@method, bignum_value).should == 200 + end + + it "raises a ZeroDivisionError when the given argument is 0" do + lambda { 13.send(@method, 0) }.should raise_error(ZeroDivisionError) + lambda { 0.send(@method, 0) }.should raise_error(ZeroDivisionError) + lambda { -10.send(@method, 0) }.should raise_error(ZeroDivisionError) + end + + it "raises a ZeroDivisionError when the given argument is 0 and a Float" do + lambda { 0.send(@method, 0.0) }.should raise_error(ZeroDivisionError) + lambda { 10.send(@method, 0.0) }.should raise_error(ZeroDivisionError) + lambda { -10.send(@method, 0.0) }.should raise_error(ZeroDivisionError) + end + + it "raises a TypeError when given a non-Integer" do + lambda { + (obj = mock('10')).should_receive(:to_int).any_number_of_times.and_return(10) + 13.send(@method, obj) + }.should raise_error(TypeError) + lambda { 13.send(@method, "10") }.should raise_error(TypeError) + lambda { 13.send(@method, :symbol) }.should raise_error(TypeError) + end + end + + context "bignum" do + before :each do + @bignum = bignum_value + end + + it "returns the modulus obtained from dividing self by the given argument" do + @bignum.send(@method, 5).should == 3 + @bignum.send(@method, -5).should == -2 + @bignum.send(@method, -100).should == -92 + @bignum.send(@method, 2.22).should be_close(0.780180180180252, TOLERANCE) + @bignum.send(@method, bignum_value(10)).should == 9223372036854775808 + end + + it "raises a ZeroDivisionError when the given argument is 0" do + lambda { @bignum.send(@method, 0) }.should raise_error(ZeroDivisionError) + lambda { (-@bignum).send(@method, 0) }.should raise_error(ZeroDivisionError) + end + + it "raises a ZeroDivisionError when the given argument is 0 and a Float" do + lambda { @bignum.send(@method, 0.0) }.should raise_error(ZeroDivisionError) + lambda { -@bignum.send(@method, 0.0) }.should raise_error(ZeroDivisionError) + end + + it "raises a TypeError when given a non-Integer" do + lambda { @bignum.send(@method, mock('10')) }.should raise_error(TypeError) + lambda { @bignum.send(@method, "10") }.should raise_error(TypeError) + lambda { @bignum.send(@method, :symbol) }.should raise_error(TypeError) + end + end +end diff --git a/spec/ruby/core/integer/size_spec.rb b/spec/ruby/core/integer/size_spec.rb new file mode 100644 index 0000000000..dc0519d6b9 --- /dev/null +++ b/spec/ruby/core/integer/size_spec.rb @@ -0,0 +1,34 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#size" do + platform_is wordsize: 32 do + it "returns the number of bytes in the machine representation of self" do + -1.size.should == 4 + 0.size.should == 4 + 4091.size.should == 4 + end + end + + platform_is wordsize: 64 do + it "returns the number of bytes in the machine representation of self" do + -1.size.should == 8 + 0.size.should == 8 + 4091.size.should == 8 + end + end + + context "bignum" do + it "returns the number of bytes required to hold the unsigned bignum data" do + # that is, n such that 256 * n <= val.abs < 256 * (n+1) + (256**7).size.should == 8 + (256**8).size.should == 9 + (256**9).size.should == 10 + (256**10).size.should == 11 + (256**10-1).size.should == 10 + (256**11).size.should == 12 + (256**12).size.should == 13 + (256**20-1).size.should == 20 + (256**40-1).size.should == 40 + end + end +end diff --git a/spec/ruby/core/integer/succ_spec.rb b/spec/ruby/core/integer/succ_spec.rb index a1405684fc..fc6bd84093 100644 --- a/spec/ruby/core/integer/succ_spec.rb +++ b/spec/ruby/core/integer/succ_spec.rb @@ -2,5 +2,5 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/next', __FILE__) describe "Integer#succ" do - it_behaves_like(:integer_next, :succ) + it_behaves_like :integer_next, :succ end diff --git a/spec/ruby/core/integer/to_f_spec.rb b/spec/ruby/core/integer/to_f_spec.rb new file mode 100644 index 0000000000..5a4ca18128 --- /dev/null +++ b/spec/ruby/core/integer/to_f_spec.rb @@ -0,0 +1,23 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#to_f" do + context "fixnum" do + it "returns self converted to a Float" do + 0.to_f.should == 0.0 + -500.to_f.should == -500.0 + 9_641_278.to_f.should == 9641278.0 + end + end + + context "bignum" do + it "returns self converted to a Float" do + bignum_value(0x4000_0aa0_0bb0_0000).to_f.should eql(13_835_069_737_789_292_544.00) + bignum_value(0x8000_0000_0000_0ccc).to_f.should eql(18_446_744_073_709_555_712.00) + (-bignum_value(99)).to_f.should eql(-9_223_372_036_854_775_808.00) + end + + it "converts number close to Float::MAX without exceeding MAX or producing NaN" do + (10**308).to_f.should == 10.0 ** 308 + end + end +end diff --git a/spec/ruby/core/integer/to_i_spec.rb b/spec/ruby/core/integer/to_i_spec.rb index 1e6f21f191..8134048b5d 100644 --- a/spec/ruby/core/integer/to_i_spec.rb +++ b/spec/ruby/core/integer/to_i_spec.rb @@ -2,5 +2,5 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/to_i', __FILE__) describe "Integer#to_i" do - it_behaves_like(:integer_to_i, :to_i) + it_behaves_like :integer_to_i, :to_i end diff --git a/spec/ruby/core/integer/to_int_spec.rb b/spec/ruby/core/integer/to_int_spec.rb index 5e87c86ccd..349cb2e4e7 100644 --- a/spec/ruby/core/integer/to_int_spec.rb +++ b/spec/ruby/core/integer/to_int_spec.rb @@ -2,5 +2,5 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../shared/to_i', __FILE__) describe "Integer#to_int" do - it_behaves_like(:integer_to_i, :to_int) + it_behaves_like :integer_to_i, :to_int end diff --git a/spec/ruby/core/integer/to_s_spec.rb b/spec/ruby/core/integer/to_s_spec.rb new file mode 100644 index 0000000000..63f5995457 --- /dev/null +++ b/spec/ruby/core/integer/to_s_spec.rb @@ -0,0 +1,99 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#to_s" do + context "fixnum" do + context "when given a base" do + it "returns self converted to a String in the given base" do + 12345.to_s(2).should == "11000000111001" + 12345.to_s(8).should == "30071" + 12345.to_s(10).should == "12345" + 12345.to_s(16).should == "3039" + 95.to_s(16).should == "5f" + 12345.to_s(36).should == "9ix" + end + + it "raises an ArgumentError if the base is less than 2 or higher than 36" do + lambda { 123.to_s(-1) }.should raise_error(ArgumentError) + lambda { 123.to_s(0) }.should raise_error(ArgumentError) + lambda { 123.to_s(1) }.should raise_error(ArgumentError) + lambda { 123.to_s(37) }.should raise_error(ArgumentError) + end + end + + context "when no base given" do + it "returns self converted to a String using base 10" do + 255.to_s.should == '255' + 3.to_s.should == '3' + 0.to_s.should == '0' + -9002.to_s.should == '-9002' + end + end + + with_feature :encoding do + before :each do + @internal = Encoding.default_internal + end + + after :each do + Encoding.default_internal = @internal + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do + Encoding.default_internal = nil + 1.to_s.encoding.should equal(Encoding::US_ASCII) + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do + Encoding.default_internal = Encoding::IBM437 + 1.to_s.encoding.should equal(Encoding::US_ASCII) + end + end + end + + context "bignum" do + describe "when given a base" do + it "returns self converted to a String using the given base" do + a = 2**64 + a.to_s(2).should == "10000000000000000000000000000000000000000000000000000000000000000" + a.to_s(8).should == "2000000000000000000000" + a.to_s(16).should == "10000000000000000" + a.to_s(32).should == "g000000000000" + end + + it "raises an ArgumentError if the base is less than 2 or higher than 36" do + lambda { 123.to_s(-1) }.should raise_error(ArgumentError) + lambda { 123.to_s(0) }.should raise_error(ArgumentError) + lambda { 123.to_s(1) }.should raise_error(ArgumentError) + lambda { 123.to_s(37) }.should raise_error(ArgumentError) + end + end + + describe "when given no base" do + it "returns self converted to a String using base 10" do + bignum_value(9).to_s.should == "9223372036854775817" + bignum_value.to_s.should == "9223372036854775808" + (-bignum_value(675)).to_s.should == "-9223372036854776483" + end + end + + with_feature :encoding do + before :each do + @internal = Encoding.default_internal + end + + after :each do + Encoding.default_internal = @internal + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do + Encoding.default_internal = nil + bignum_value.to_s.encoding.should equal(Encoding::US_ASCII) + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do + Encoding.default_internal = Encoding::IBM437 + bignum_value.to_s.encoding.should equal(Encoding::US_ASCII) + end + end + end +end diff --git a/spec/ruby/core/integer/truncate_spec.rb b/spec/ruby/core/integer/truncate_spec.rb index 429ab1a312..98d40b3026 100644 --- a/spec/ruby/core/integer/truncate_spec.rb +++ b/spec/ruby/core/integer/truncate_spec.rb @@ -3,8 +3,8 @@ require File.expand_path('../shared/to_i', __FILE__) require File.expand_path('../shared/integer_rounding', __FILE__) describe "Integer#truncate" do - it_behaves_like(:integer_to_i, :truncate) - it_behaves_like(:integer_rounding_positive_precision, :truncate) + it_behaves_like :integer_to_i, :truncate + it_behaves_like :integer_rounding_positive_precision, :truncate ruby_version_is "2.4" do context "precision argument specified as part of the truncate method is negative" do diff --git a/spec/ruby/core/integer/uminus_spec.rb b/spec/ruby/core/integer/uminus_spec.rb new file mode 100644 index 0000000000..ad7cd194e3 --- /dev/null +++ b/spec/ruby/core/integer/uminus_spec.rb @@ -0,0 +1,28 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "Integer#-@" do + context "fixnum" do + it "returns self as a negative value" do + 2.send(:-@).should == -2 + -2.should == -2 + -268435455.should == -268435455 + (--5).should == 5 + -8.send(:-@).should == 8 + end + + it "negates self at Fixnum/Bignum boundaries" do + fixnum_max.send(:-@).should == (0 - fixnum_max) + fixnum_min.send(:-@).should == (0 - fixnum_min) + end + end + + context "bignum" do + it "returns self as a negative value" do + bignum_value.send(:-@).should == -9223372036854775808 + (-bignum_value).send(:-@).should == 9223372036854775808 + + bignum_value(921).send(:-@).should == -9223372036854776729 + (-bignum_value(921).send(:-@)).should == 9223372036854776729 + end + end +end -- cgit v1.2.3