diff options
Diffstat (limited to 'test/ruby/test_integer.rb')
| -rw-r--r-- | test/ruby/test_integer.rb | 1240 |
1 files changed, 682 insertions, 558 deletions
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb index cfda9e5985..f9bf4fa20c 100644 --- a/test/ruby/test_integer.rb +++ b/test/ruby/test_integer.rb @@ -1,160 +1,47 @@ +# frozen_string_literal: false require 'test/unit' class TestInteger < Test::Unit::TestCase - VS = [ - -0x1000000000000000000000000000000000000000000000002, - -0x1000000000000000000000000000000000000000000000001, - -0x1000000000000000000000000000000000000000000000000, - -0xffffffffffffffffffffffffffffffffffffffffffffffff, - -0x1000000000000000000000002, - -0x1000000000000000000000001, - -0x1000000000000000000000000, - -0xffffffffffffffffffffffff, - -0x10000000000000002, - -0x10000000000000001, - -0x10000000000000000, - -0xffffffffffffffff, - -0x4000000000000002, - -0x4000000000000001, - -0x4000000000000000, - -0x3fffffffffffffff, - -0x100000002, - -0x100000001, - -0x100000000, - -0xffffffff, - -0xc717a08d, # 0xc717a08d * 0x524b2245 = 0x4000000000000001 - -0x80000002, - -0x80000001, - -0x80000000, - -0x7fffffff, - -0x524b2245, - -0x40000002, - -0x40000001, - -0x40000000, - -0x3fffffff, - -0x10002, - -0x10001, - -0x10000, - -0xffff, - -0x8101, # 0x8101 * 0x7f01 = 0x40000001 - -0x8002, - -0x8001, - -0x8000, - -0x7fff, - -0x7f01, - -65, - -64, - -63, - -62, - -33, - -32, - -31, - -30, - -3, - -2, - -1, - 0, - 1, - 2, - 3, - 30, - 31, - 32, - 33, - 62, - 63, - 64, - 65, - 0x7f01, - 0x7ffe, - 0x7fff, - 0x8000, - 0x8001, - 0x8101, - 0xfffe, - 0xffff, - 0x10000, - 0x10001, - 0x3ffffffe, - 0x3fffffff, - 0x40000000, - 0x40000001, - 0x524b2245, - 0x7ffffffe, - 0x7fffffff, - 0x80000000, - 0x80000001, - 0xc717a08d, - 0xfffffffe, - 0xffffffff, - 0x100000000, - 0x100000001, - 0x3ffffffffffffffe, - 0x3fffffffffffffff, - 0x4000000000000000, - 0x4000000000000001, - 0xfffffffffffffffe, - 0xffffffffffffffff, - 0x10000000000000000, - 0x10000000000000001, - 0xffffffffffffffffffffffff, - 0x1000000000000000000000000, - 0x1000000000000000000000001, - 0xffffffffffffffffffffffffffffffffffffffffffffffff, - 0x1000000000000000000000000000000000000000000000000, - 0x1000000000000000000000000000000000000000000000001 - ] - - #VS.map! {|v| 0x4000000000000000.coerce(v)[0] } - - BDSIZE = 0x4000000000000000.coerce(0)[0].size - def self.bdsize(x) - ((x + 1) / 8 + BDSIZE) / BDSIZE * BDSIZE - end - def bdsize(x) - self.class.bdsize(x) - end - - min = -1 - min *= 2 while min.class == Fixnum - FIXNUM_MIN = min/2 - max = 1 - max *= 2 while (max-1).class == Fixnum - FIXNUM_MAX = max/2-1 - - def test_fixnum_range - assert_instance_of(Bignum, FIXNUM_MIN-1) - assert_instance_of(Fixnum, FIXNUM_MIN) - assert_instance_of(Fixnum, FIXNUM_MAX) - assert_instance_of(Bignum, FIXNUM_MAX+1) - end - - def check_class(n) - if FIXNUM_MIN <= n && n <= FIXNUM_MAX - assert_instance_of(Fixnum, n) - else - assert_instance_of(Bignum, n) - end - end + FIXNUM_MIN = RbConfig::LIMITS['FIXNUM_MIN'] + FIXNUM_MAX = RbConfig::LIMITS['FIXNUM_MAX'] + LONG_MAX = RbConfig::LIMITS['LONG_MAX'] def test_aref - VS.each {|a| - 100.times {|i| - assert_equal((a >> i).odd? ? 1 : 0, a[i], "(#{a})[#{i}]") - } - } - VS.each {|a| - VS.each {|b| - c = nil - assert_nothing_raised("(#{a})[#{b}]") { c = a[b] } - check_class(c) - if b < 0 - assert_equal(0, c, "(#{a})[#{b}]") + + [ + *-16..16, + *(FIXNUM_MIN-2)..(FIXNUM_MIN+2), + *(FIXNUM_MAX-2)..(FIXNUM_MAX+2), + ].each do |n| + (-64..64).each do |idx| + assert_equal((n >> idx) & 1, n[idx]) + end + [*-66..-62, *-34..-30, *-5..5, *30..34, *62..66].each do |idx| + (0..100).each do |len| + assert_equal((n >> idx) & ((1 << len) - 1), n[idx, len], "#{ n }[#{ idx }, #{ len }]") + end + (0..100).each do |len| + assert_equal((n >> idx) & ((1 << (len + 1)) - 1), n[idx..idx+len], "#{ n }[#{ idx }..#{ idx+len }]") + assert_equal((n >> idx) & ((1 << len) - 1), n[idx...idx+len], "#{ n }[#{ idx }...#{ idx+len }]") + end + + # endless + assert_equal((n >> idx), n[idx..], "#{ n }[#{ idx }..]") + assert_equal((n >> idx), n[idx...], "#{ n }[#{ idx }...#]") + + # beginless + if idx >= 0 && n & ((1 << (idx + 1)) - 1) != 0 + assert_raise(ArgumentError, "#{ n }[..#{ idx }]") { n[..idx] } else - assert_equal((a >> b).odd? ? 1 : 0, c, "(#{a})[#{b}]") + assert_equal(0, n[..idx], "#{ n }[..#{ idx }]") end - } - } + if idx >= 0 && n & ((1 << idx) - 1) != 0 + assert_raise(ArgumentError, "#{ n }[...#{ idx }]") { n[...idx] } + else + assert_equal(0, n[...idx], "#{ n }[...#{ idx }]") + end + end + end # assert_equal(1, (1 << 0x40000000)[0x40000000], "[ruby-dev:31271]") # assert_equal(0, (-1 << 0x40000001)[0x40000000], "[ruby-dev:31271]") @@ -163,491 +50,728 @@ class TestInteger < Test::Unit::TestCase assert_equal(1, 0x400000001[big_zero], "[ruby-dev:31271]") end - def test_plus - VS.each {|a| - VS.each {|b| - c = a + b - check_class(c) - assert_equal(b + a, c, "#{a} + #{b}") - assert_equal(a, c - b, "(#{a} + #{b}) - #{b}") - assert_equal(a-~b-1, c, "#{a} + #{b}") # Hacker's Delight - assert_equal((a^b)+2*(a&b), c, "#{a} + #{b}") # Hacker's Delight - assert_equal((a|b)+(a&b), c, "#{a} + #{b}") # Hacker's Delight - assert_equal(2*(a|b)-(a^b), c, "#{a} + #{b}") # Hacker's Delight - } - } + def test_pow + assert_not_equal(0, begin + 0**-1 + rescue + nil + end, "[ruby-dev:32084] [ruby-dev:34547]") + + assert_raise(ArgumentError) {2 ** -0x4000000000000000} + + <<~EXPRS.each_line.with_index(__LINE__+1) do |expr, line| + crash01: 111r+11**-11111161111111 + crash02: 1118111111111**-1111111111111111**1+1==11111 + crash03: -1111111**-1111*11 - -11** -1111111 + crash04: 1118111111111** -1111111111111111**1+11111111111**1 ===111 + crash05: 11** -111155555555555555 -55 !=5-555 + crash07: 1 + 111111111**-1111811111 + crash08: 18111111111**-1111111111111111**1 + 1111111111**-1111**1 + crash10: -7 - -1111111** -1111**11 + crash12: 1118111111111** -1111111111111111**1 + 1111 - -1111111** -1111*111111111119 + crash13: 1.0i - -11** -1111111 + crash14: 11111**111111111**111111 * -11111111111111111111**-111111111111 + crash15: ~1**1111 + -~1**~1**111 + crash17: 11** -1111111**1111 /11i + crash18: 5555i**-5155 - -9111111**-1111**11 + crash19: 111111*-11111111111111111111**-1111111111111111 + crash20: 1111**111-11**-11111**11 + crash21: 11**-10111111119-1i -1r + EXPRS + name, expr = expr.split(':', 2) + assert_ruby_status(%w"-W0", "begin; #{ expr }; rescue ArgumentError; end", name) + end end - def test_minus - VS.each {|a| - VS.each {|b| - c = a - b - check_class(c) - assert_equal(a, c + b, "(#{a} - #{b}) + #{b}") - assert_equal(-b, c - a, "(#{a} - #{b}) - #{a}") - assert_equal(a+~b+1, c, "#{a} - #{b}") # Hacker's Delight - assert_equal((a^b)-2*(b&~a), c, "#{a} - #{b}") # Hacker's Delight - assert_equal((a&~b)-(b&~a), c, "#{a} - #{b}") # Hacker's Delight - assert_equal(2*(a&~b)-(a^b), c, "#{a} - #{b}") # Hacker's Delight - } - } - end + def test_lshift + assert_equal(0, 1 << -0x40000000) + assert_equal(0, 1 << -0x40000001) + assert_equal(0, 1 << -0x80000000) + assert_equal(0, 1 << -0x80000001) - def test_mult - VS.each {|a| - VS.each {|b| - c = a * b - check_class(c) - assert_equal(b * a, c, "#{a} * #{b}") - assert_equal(b, c / a, "(#{a} * #{b}) / #{a}") if a != 0 - assert_equal(a.abs * b.abs, (a * b).abs, "(#{a} * #{b}).abs") - assert_equal((a-100)*(b-100)+(a-100)*100+(b-100)*100+10000, c, "#{a} * #{b}") - assert_equal((a+100)*(b+100)-(a+100)*100-(b+100)*100+10000, c, "#{a} * #{b}") - } + char_bit = RbConfig::LIMITS["UCHAR_MAX"].bit_length + size_max = RbConfig::LIMITS["SIZE_MAX"] + size_bit_max = size_max * char_bit + assert_raise_with_message(RangeError, /shift width/) { + 1 << size_bit_max } end - def test_divmod - VS.each {|a| - VS.each {|b| - if b == 0 - assert_raise(ZeroDivisionError) { a.divmod(b) } - else - q, r = a.divmod(b) - check_class(q) - check_class(r) - assert_equal(a, b*q+r) - assert(r.abs < b.abs) - assert(0 < b ? (0 <= r && r < b) : (b < r && r <= 0)) - assert_equal(q, a/b) - assert_equal(q, a.div(b)) - assert_equal(r, a%b) - assert_equal(r, a.modulo(b)) - end - } - } + def test_rshift + assert_predicate((1 >> 0x80000000), :zero?) + assert_predicate((1 >> 0xffffffff), :zero?) + assert_predicate((1 >> 0x100000000), :zero?) + # assert_equal((1 << 0x40000000), (1 >> -0x40000000)) + # assert_equal((1 << 0x40000001), (1 >> -0x40000001)) end - def test_pow - small_values = VS.find_all {|v| 0 <= v && v < 1000 } - VS.each {|a| - small_values.each {|b| - c = a ** b - check_class(c) - d = 1 - b.times { d *= a } - assert_equal(d, c, "(#{a}) ** #{b}") - if a != 0 - d = c - b.times { d /= a } - assert_equal(1, d, "((#{a}) ** #{b}) / #{a} / ...(#{b} times)...") - end - } + def test_Integer + assert_raise(ArgumentError) {Integer("0x-1")} + assert_raise(ArgumentError) {Integer("-0x-1")} + assert_raise(ArgumentError) {Integer("0x 123")} + assert_raise(ArgumentError) {Integer("0x 123")} + assert_raise(ArgumentError) {Integer("0x0x5")} + assert_raise(ArgumentError) {Integer("0x0x000000005")} + assert_nothing_raised(ArgumentError) { + assert_equal(1540841, "0x0x5".to_i(36)) + } + assert_raise(ArgumentError) { Integer("--0") } + assert_raise(ArgumentError) { Integer("-+0") } + assert_raise(ArgumentError) { Integer("++1") } + assert_raise(ArgumentError) { Integer("") } + assert_raise(ArgumentError) { Integer("10 x") } + assert_raise(ArgumentError) { Integer("1__2") } + assert_raise(ArgumentError) { Integer("1z") } + assert_raise(ArgumentError) { Integer("46116860184273__87904") } + assert_raise(ArgumentError) { Integer("4611686018427387904_") } + assert_raise(ArgumentError) { Integer("4611686018427387904 :") } + assert_equal(0x4000000000000000, Integer("46_11_686_0184273_87904")) + assert_raise(ArgumentError) { Integer("\0") } + assert_nothing_raised(ArgumentError, "[ruby-core:13873]") { + assert_equal(0, Integer("0 ")) } + assert_nothing_raised(ArgumentError, "[ruby-core:14139]") { + assert_equal(0377, Integer("0_3_7_7")) + } + assert_raise(ArgumentError, "[ruby-core:14139]") {Integer("0__3_7_7")} + assert_equal(1234, Integer(1234)) + assert_equal(1, Integer(1.234)) + + assert_equal(2 ** 50, Integer(2.0 ** 50)) + assert_raise(TypeError) { Integer(nil) } + + bug14552 = '[ruby-core:85813]' + obj = Object.new + def obj.to_int; "str"; end + assert_raise(TypeError, bug14552) { Integer(obj) } + def obj.to_i; 42; end + assert_equal(42, Integer(obj), bug14552) + + obj = Object.new + def obj.to_i; "str"; end + assert_raise(TypeError) { Integer(obj) } + + bug6192 = '[ruby-core:43566]' + assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-16be"))} + assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-16le"))} + assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-32be"))} + assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-32le"))} + assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("iso-2022-jp"))} + + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(ArgumentError, /\u{1f4a1}/) {Integer("\u{1f4a1}")} + end - assert_equal(0**-1 == 0, false) + obj = Struct.new(:s).new(%w[42 not-an-integer]) + def obj.to_str; s.shift; end + assert_equal(42, Integer(obj, 10)) + + assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + class Float + undef to_int + def to_int; raise "conversion failed"; end + end + assert_equal (1 << 100), Integer((1 << 100).to_f) + assert_equal 1, Integer(1.0) + end; end - def test_not - VS.each {|a| - b = ~a - check_class(b) - assert_equal(-1 ^ a, b, "~#{a}") - assert_equal(-a-1, b, "~#{a}") # Hacker's Delight - assert_equal(0, a & b, "#{a} & ~#{a}") - assert_equal(-1, a | b, "#{a} | ~#{a}") + def test_Integer_with_invalid_exception + assert_raise(ArgumentError) { + Integer("0", exception: 1) } end - def test_or - VS.each {|a| - VS.each {|b| - c = a | b - check_class(c) - assert_equal(b | a, c, "#{a} | #{b}") - assert_equal(a + b - (a&b), c, "#{a} | #{b}") - assert_equal((a & ~b) + b, c, "#{a} | #{b}") # Hacker's Delight - assert_equal(-1, c | ~a, "(#{a} | #{b}) | ~#{a})") - } + def test_Integer_with_exception_keyword + assert_nothing_raised(ArgumentError) { + assert_equal(nil, Integer("1z", exception: false)) + } + assert_nothing_raised(ArgumentError) { + assert_equal(nil, Integer(Object.new, exception: false)) + } + assert_nothing_raised(ArgumentError) { + o = Object.new + def o.to_i; 42.5; end + assert_equal(nil, Integer(o, exception: false)) + } + assert_nothing_raised(ArgumentError) { + o = Object.new + def o.to_i; raise; end + assert_equal(nil, Integer(o, exception: false)) + } + assert_nothing_raised(ArgumentError) { + o = Object.new + def o.to_int; raise; end + assert_equal(nil, Integer(o, exception: false)) + } + assert_nothing_raised(FloatDomainError) { + assert_equal(nil, Integer(Float::INFINITY, exception: false)) + } + assert_nothing_raised(FloatDomainError) { + assert_equal(nil, Integer(-Float::INFINITY, exception: false)) + } + assert_nothing_raised(FloatDomainError) { + assert_equal(nil, Integer(Float::NAN, exception: false)) } - end - def test_and - VS.each {|a| - VS.each {|b| - c = a & b - check_class(c) - assert_equal(b & a, c, "#{a} & #{b}") - assert_equal(a + b - (a|b), c, "#{a} & #{b}") - assert_equal((~a | b) - ~a, c, "#{a} & #{b}") # Hacker's Delight - assert_equal(0, c & ~a, "(#{a} & #{b}) & ~#{a}") - } + assert_raise(ArgumentError) { + Integer("1z", exception: true) + } + assert_raise(TypeError) { + Integer(nil, exception: true) } + assert_nothing_raised(TypeError) { + assert_equal(nil, Integer(nil, exception: false)) + } + + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + class Integer;def method_missing(*);"";end;end + assert_equal(0, Integer("0", 2)) + end; end - def test_xor - VS.each {|a| - VS.each {|b| - c = a ^ b - check_class(c) - assert_equal(b ^ a, c, "#{a} ^ #{b}") - assert_equal((a|b)-(a&b), c, "#{a} ^ #{b}") # Hacker's Delight - assert_equal(b, c ^ a, "(#{a} ^ #{b}) ^ #{a}") - } - } + def test_Integer_when_to_str + def (obj = Object.new).to_str + "0x10" + end + assert_equal(16, Integer(obj)) end - def test_lshift - small_values = VS.find_all {|v| v < 8000 } - VS.each {|a| - small_values.each {|b| - c = a << b - check_class(c) - if 0 <= b - assert_equal(a, c >> b, "(#{a} << #{b}) >> #{b}") - assert_equal(a * 2**b, c, "#{a} << #{b}") - end - 0.upto(c.size*8+10) {|nth| - assert_equal(a[nth-b], c[nth], "(#{a} << #{b})[#{nth}]") - } - } - } - assert_equal(0, 1 << -0x40000000) - assert_equal(0, 1 << -0x40000001) - assert_equal(0, 1 << -0x80000000) - assert_equal(0, 1 << -0x80000001) - # assert_equal(bdsize(0x80000000), (1 << 0x80000000).size) + def test_Integer_with_base + assert_equal(1234, Integer("1234", 10)) + assert_equal(668, Integer("1234", 8)) + assert_equal(4660, Integer("1234", 16)) + assert_equal(49360, Integer("1234", 36)) + # decimal, not octal + assert_equal(1234, Integer("01234", 10)) + assert_raise(ArgumentError) { Integer("0x123", 10) } + assert_raise(ArgumentError) { Integer(1234, 10) } + assert_raise(ArgumentError) { Integer(12.34, 10) } + assert_raise(ArgumentError) { Integer(Object.new, 1) } + + assert_raise(ArgumentError) { Integer(1, 1, 1) } + + def (base = Object.new).to_int + 8 + end + assert_equal(8, Integer("10", base)) + + assert_raise(TypeError) { Integer("10", "8") } + def (base = Object.new).to_int + "8" + end + assert_raise(TypeError) { Integer("10", base) } end - def test_rshift - small_values = VS.find_all {|v| -8000 < v } - VS.each {|a| - small_values.each {|b| - c = a >> b - check_class(c) - if b <= 0 - assert_equal(a, c << b, "(#{a} >> #{b}) << #{b}") - assert_equal(a * 2**(-b), c, "#{a} >> #{b}") - end - 0.upto(c.size*8+10) {|nth| - assert_equal(a[nth+b], c[nth], "(#{a} >> #{b})[#{nth}]") - } - } - } - # assert_equal(bdsize(0x40000001), (1 >> -0x40000001).size) - assert((1 >> 0x80000000).zero?) - assert((1 >> 0xffffffff).zero?) - assert((1 >> 0x100000000).zero?) - # assert_equal((1 << 0x40000000), (1 >> -0x40000000)) - # assert_equal((1 << 0x40000001), (1 >> -0x40000001)) + def test_int_p + assert_not_predicate(1.0, :integer?) + assert_predicate(1, :integer?) end def test_succ - VS.each {|a| - b = a.succ - check_class(b) - assert_equal(a+1, b, "(#{a}).succ") - assert_equal(a, b.pred, "(#{a}).succ.pred") - assert_equal(a, b-1, "(#{a}).succ - 1") - } + assert_equal(2, 1.send(:succ)) end - def test_pred - VS.each {|a| - b = a.pred - check_class(b) - assert_equal(a-1, b, "(#{a}).pred") - assert_equal(a, b.succ, "(#{a}).pred.succ") - assert_equal(a, b + 1, "(#{a}).pred + 1") - } + def test_chr + assert_equal("a", "a".ord.chr) + assert_raise(RangeError) { (-1).chr } + assert_raise(RangeError) { 0x100.chr } + assert_raise_with_message(RangeError, "3000000000 out of char range") { 3_000_000_000.chr } end - def test_unary_plus - VS.each {|a| - b = +a - check_class(b) - assert_equal(a, b, "+(#{a})") - } - end + def test_upto + a = [] + assert_equal(1, 1.upto(3) {|x| a << x }) + assert_equal([1, 2, 3], a) - def test_unary_minus - VS.each {|a| - b = -a - check_class(b) - assert_equal(0-a, b, "-(#{a})") - assert_equal(~a+1, b, "-(#{a})") - assert_equal(0, a+b, "#{a}+(-(#{a}))") - } + a = [] + assert_equal(1, 1.upto(0) {|x| a << x }) + assert_equal([], a) + + y = 2**30 - 1 + a = [] + assert_equal(y, y.upto(y+2) {|x| a << x }) + assert_equal([y, y+1, y+2], a) end - def test_cmp - VS.each_with_index {|a, i| - VS.each_with_index {|b, j| - assert_equal(i <=> j, a <=> b, "#{a} <=> #{b}") - assert_equal(i < j, a < b, "#{a} < #{b}") - assert_equal(i <= j, a <= b, "#{a} <= #{b}") - assert_equal(i > j, a > b, "#{a} > #{b}") - assert_equal(i >= j, a >= b, "#{a} >= #{b}") - } - } + def test_downto + a = [] + assert_equal(-1, -1.downto(-3) {|x| a << x }) + assert_equal([-1, -2, -3], a) + + a = [] + assert_equal(1, 1.downto(2) {|x| a << x }) + assert_equal([], a) + + y = -(2**30) + a = [] + assert_equal(y, y.downto(y-2) {|x| a << x }) + assert_equal([y, y-1, y-2], a) end - def test_eq - VS.each_with_index {|a, i| - VS.each_with_index {|b, j| - c = a == b - assert_equal(b == a, c, "#{a} == #{b}") - assert_equal(i == j, c, "#{a} == #{b}") - } - } + def test_times + (2**32).times do |i| + break if i == 2 + end end - def test_abs - VS.each {|a| - b = a.abs - check_class(b) - if a < 0 - assert_equal(-a, b, "(#{a}).abs") - else - assert_equal(a, b, "(#{a}).abs") + def test_times_bignum_redefine_plus_lt + assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}") + begin; + called = false + Integer.class_eval do + alias old_succ succ + undef succ + define_method(:succ){|x| called = true; x+1} + alias old_lt < + undef < + define_method(:<){|x| called = true} end - } + + fix = 1 + fix.times{break 0} + fix_called = called + + called = false + + big = 2**65 + big.times{break 0} + big_called = called + + Integer.class_eval do + undef succ + alias succ old_succ + undef < + alias < old_lt + end + + # Asssert that Fixnum and Bignum behave consistently + bug18377 = "[ruby-core:106361]" + assert_equal(fix_called, big_called, bug18377) + end; end - def test_ceil - VS.each {|a| - b = a.ceil - check_class(b) - assert_equal(a, b, "(#{a}).ceil") - } + def assert_int_equal(expected, result, mesg = nil) + assert_kind_of(Integer, result, mesg) + assert_equal(expected, result, mesg) end - def test_floor - VS.each {|a| - b = a.floor - check_class(b) - assert_equal(a, b, "(#{a}).floor") - } + def assert_float_equal(expected, result, mesg = nil) + assert_kind_of(Float, result, mesg) + assert_equal(expected, result, mesg) end def test_round - VS.each {|a| - b = a.round - check_class(b) - assert_equal(a, b, "(#{a}).round") - } + assert_int_equal(11111, 11111.round) + assert_int_equal(11111, 11111.round(0)) + + assert_int_equal(11111, 11111.round(1)) + assert_int_equal(11111, 11111.round(2)) + + assert_int_equal(11110, 11111.round(-1)) + assert_int_equal(11100, 11111.round(-2)) + assert_int_equal(+200, +249.round(-2)) + assert_int_equal(+300, +250.round(-2)) + assert_int_equal(-200, -249.round(-2)) + assert_int_equal(+200, +249.round(-2, half: :even)) + assert_int_equal(+200, +250.round(-2, half: :even)) + assert_int_equal(+300, +349.round(-2, half: :even)) + assert_int_equal(+400, +350.round(-2, half: :even)) + assert_int_equal(+200, +249.round(-2, half: :up)) + assert_int_equal(+300, +250.round(-2, half: :up)) + assert_int_equal(+300, +349.round(-2, half: :up)) + assert_int_equal(+400, +350.round(-2, half: :up)) + assert_int_equal(+200, +249.round(-2, half: :down)) + assert_int_equal(+200, +250.round(-2, half: :down)) + assert_int_equal(+300, +349.round(-2, half: :down)) + assert_int_equal(+300, +350.round(-2, half: :down)) + assert_int_equal(-300, -250.round(-2)) + assert_int_equal(-200, -249.round(-2, half: :even)) + assert_int_equal(-200, -250.round(-2, half: :even)) + assert_int_equal(-300, -349.round(-2, half: :even)) + assert_int_equal(-400, -350.round(-2, half: :even)) + assert_int_equal(-200, -249.round(-2, half: :up)) + assert_int_equal(-300, -250.round(-2, half: :up)) + assert_int_equal(-300, -349.round(-2, half: :up)) + assert_int_equal(-400, -350.round(-2, half: :up)) + assert_int_equal(-200, -249.round(-2, half: :down)) + assert_int_equal(-200, -250.round(-2, half: :down)) + assert_int_equal(-300, -349.round(-2, half: :down)) + assert_int_equal(-300, -350.round(-2, half: :down)) + assert_int_equal(+30 * 10**70, (+25 * 10**70).round(-71)) + assert_int_equal(-30 * 10**70, (-25 * 10**70).round(-71)) + assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).round(-71)) + assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).round(-71)) + assert_int_equal(+40 * 10**70, (+35 * 10**70).round(-71)) + assert_int_equal(-40 * 10**70, (-35 * 10**70).round(-71)) + assert_int_equal(+30 * 10**70, (+35 * 10**70 - 1).round(-71)) + assert_int_equal(-30 * 10**70, (-35 * 10**70 + 1).round(-71)) + assert_int_equal(+20 * 10**70, (+25 * 10**70).round(-71, half: :even)) + assert_int_equal(-20 * 10**70, (-25 * 10**70).round(-71, half: :even)) + assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).round(-71, half: :even)) + assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).round(-71, half: :even)) + assert_int_equal(+40 * 10**70, (+35 * 10**70).round(-71, half: :even)) + assert_int_equal(-40 * 10**70, (-35 * 10**70).round(-71, half: :even)) + assert_int_equal(+30 * 10**70, (+35 * 10**70 - 1).round(-71, half: :even)) + assert_int_equal(-30 * 10**70, (-35 * 10**70 + 1).round(-71, half: :even)) + assert_int_equal(+30 * 10**70, (+25 * 10**70).round(-71, half: :up)) + assert_int_equal(-30 * 10**70, (-25 * 10**70).round(-71, half: :up)) + assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).round(-71, half: :up)) + assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).round(-71, half: :up)) + assert_int_equal(+40 * 10**70, (+35 * 10**70).round(-71, half: :up)) + assert_int_equal(-40 * 10**70, (-35 * 10**70).round(-71, half: :up)) + assert_int_equal(+30 * 10**70, (+35 * 10**70 - 1).round(-71, half: :up)) + assert_int_equal(-30 * 10**70, (-35 * 10**70 + 1).round(-71, half: :up)) + assert_int_equal(+20 * 10**70, (+25 * 10**70).round(-71, half: :down)) + assert_int_equal(-20 * 10**70, (-25 * 10**70).round(-71, half: :down)) + assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).round(-71, half: :down)) + assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).round(-71, half: :down)) + assert_int_equal(+30 * 10**70, (+35 * 10**70).round(-71, half: :down)) + assert_int_equal(-30 * 10**70, (-35 * 10**70).round(-71, half: :down)) + assert_int_equal(+30 * 10**70, (+35 * 10**70 - 1).round(-71, half: :down)) + assert_int_equal(-30 * 10**70, (-35 * 10**70 + 1).round(-71, half: :down)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1110, 1111_1111_1111_1111_1111_1111_1111_1111.round(-1)) + assert_int_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).round(-1)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1111, 1111_1111_1111_1111_1111_1111_1111_1111.round(1)) + assert_int_equal(10**400, (10**400).round(1)) end - def test_truncate - VS.each {|a| - b = a.truncate - check_class(b) - assert_equal(a, b, "(#{a}).truncate") - } + def test_floor + assert_int_equal(11111, 11111.floor) + assert_int_equal(11111, 11111.floor(0)) + + assert_int_equal(11111, 11111.floor(1)) + assert_int_equal(11111, 11111.floor(2)) + + assert_int_equal(11110, 11110.floor(-1)) + assert_int_equal(11110, 11119.floor(-1)) + assert_int_equal(11100, 11100.floor(-2)) + assert_int_equal(11100, 11199.floor(-2)) + assert_int_equal(0, 11111.floor(-5)) + assert_int_equal(+200, +299.floor(-2)) + assert_int_equal(+300, +300.floor(-2)) + assert_int_equal(-300, -299.floor(-2)) + assert_int_equal(-300, -300.floor(-2)) + assert_int_equal(+20 * 10**70, (+25 * 10**70).floor(-71)) + assert_int_equal(-30 * 10**70, (-25 * 10**70).floor(-71)) + assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).floor(-71)) + assert_int_equal(-30 * 10**70, (-25 * 10**70 + 1).floor(-71)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1110, 1111_1111_1111_1111_1111_1111_1111_1111.floor(-1)) + assert_int_equal(-1111_1111_1111_1111_1111_1111_1111_1120, (-1111_1111_1111_1111_1111_1111_1111_1111).floor(-1)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1111, 1111_1111_1111_1111_1111_1111_1111_1111.floor(1)) + assert_int_equal(10**400, (10**400).floor(1)) + + assert_int_equal(-10000000000, -1.floor(-10), "[Bug #20654]") + assert_int_equal(-100000000000000000000, -1.floor(-20), "[Bug #20654]") + assert_int_equal(-100000000000000000000000000000000000000000000000000, -1.floor(-50), "[Bug #20654]") end - def test_remainder - VS.each {|a| - VS.each {|b| - if b == 0 - assert_raise(ZeroDivisionError) { a.divmod(b) } - else - r = a.remainder(b) - check_class(r) - if a < 0 - assert_operator(-b.abs, :<, r, "#{a}.remainder(#{b})") - assert_operator(0, :>=, r, "#{a}.remainder(#{b})") - elsif 0 < a - assert_operator(0, :<=, r, "#{a}.remainder(#{b})") - assert_operator(b.abs, :>, r, "#{a}.remainder(#{b})") - else - assert_equal(0, r, "#{a}.remainder(#{b})") - end - end - } - } + def test_ceil + assert_int_equal(11111, 11111.ceil) + assert_int_equal(11111, 11111.ceil(0)) + + assert_int_equal(11111, 11111.ceil(1)) + assert_int_equal(11111, 11111.ceil(2)) + + assert_int_equal(11110, 11110.ceil(-1)) + assert_int_equal(11120, 11119.ceil(-1)) + assert_int_equal(11200, 11101.ceil(-2)) + assert_int_equal(11200, 11200.ceil(-2)) + assert_int_equal(100000, 11111.ceil(-5)) + assert_int_equal(300, 299.ceil(-2)) + assert_int_equal(300, 300.ceil(-2)) + assert_int_equal(-200, -299.ceil(-2)) + assert_int_equal(-300, -300.ceil(-2)) + assert_int_equal(+30 * 10**70, (+25 * 10**70).ceil(-71)) + assert_int_equal(-20 * 10**70, (-25 * 10**70).ceil(-71)) + assert_int_equal(+30 * 10**70, (+25 * 10**70 - 1).ceil(-71)) + assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).ceil(-71)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1120, 1111_1111_1111_1111_1111_1111_1111_1111.ceil(-1)) + assert_int_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).ceil(-1)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1111, 1111_1111_1111_1111_1111_1111_1111_1111.ceil(1)) + assert_int_equal(10**400, (10**400).ceil(1)) + + assert_int_equal(10000000000, 1.ceil(-10), "[Bug #20654]") + assert_int_equal(100000000000000000000, 1.ceil(-20), "[Bug #20654]") + assert_int_equal(100000000000000000000000000000000000000000000000000, 1.ceil(-50), "[Bug #20654]") end - def test_zero_nonzero - VS.each {|a| - z = a.zero? - n = a.nonzero? - if a == 0 - assert_equal(true, z, "(#{a}).zero?") - assert_equal(nil, n, "(#{a}).nonzero?") - else - assert_equal(false, z, "(#{a}).zero?") - assert_equal(a, n, "(#{a}).nonzero?") - check_class(n) - end - assert(z ^ n, "(#{a}).zero? ^ (#{a}).nonzero?") - } + def test_truncate + assert_int_equal(11111, 11111.truncate) + assert_int_equal(11111, 11111.truncate(0)) + + assert_int_equal(11111, 11111.truncate(1)) + assert_int_equal(11111, 11111.truncate(2)) + + assert_int_equal(11110, 11110.truncate(-1)) + assert_int_equal(11110, 11119.truncate(-1)) + assert_int_equal(11100, 11100.truncate(-2)) + assert_int_equal(11100, 11199.truncate(-2)) + assert_int_equal(0, 11111.truncate(-5)) + assert_int_equal(+200, +299.truncate(-2)) + assert_int_equal(+300, +300.truncate(-2)) + assert_int_equal(-200, -299.truncate(-2)) + assert_int_equal(-300, -300.truncate(-2)) + assert_int_equal(+20 * 10**70, (+25 * 10**70).truncate(-71)) + assert_int_equal(-20 * 10**70, (-25 * 10**70).truncate(-71)) + assert_int_equal(+20 * 10**70, (+25 * 10**70 - 1).truncate(-71)) + assert_int_equal(-20 * 10**70, (-25 * 10**70 + 1).truncate(-71)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1110, 1111_1111_1111_1111_1111_1111_1111_1111.truncate(-1)) + assert_int_equal(-1111_1111_1111_1111_1111_1111_1111_1110, (-1111_1111_1111_1111_1111_1111_1111_1111).truncate(-1)) + + assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1111, 1111_1111_1111_1111_1111_1111_1111_1111.truncate(1)) + assert_int_equal(10**400, (10**400).truncate(1)) + end + + MimicInteger = Struct.new(:to_int) + module CoercionToInt + def coerce(other) + [other, to_int] + end end - def test_even_odd - VS.each {|a| - e = a.even? - o = a.odd? - assert_equal((a % 2) == 0, e, "(#{a}).even?") - assert_equal((a % 2) == 1, o, "(#{a}).odd") - assert_equal((a & 1) == 0, e, "(#{a}).even?") - assert_equal((a & 1) == 1, o, "(#{a}).odd") - assert(e ^ o, "(#{a}).even? ^ (#{a}).odd?") - } + def test_bitwise_and_with_integer_mimic_object + obj = MimicInteger.new(10) + assert_raise(TypeError, '[ruby-core:39491]') { 3 & obj } + obj.extend(CoercionToInt) + assert_equal(3 & 10, 3 & obj) end - def test_to_s - 2.upto(36) {|radix| - VS.each {|a| - s = a.to_s(radix) - b = s.to_i(radix) - assert_equal(a, b, "(#{a}).to_s(#{radix}).to_i(#{radix})") - } - } + def test_bitwise_or_with_integer_mimic_object + obj = MimicInteger.new(10) + assert_raise(TypeError, '[ruby-core:39491]') { 3 | obj } + obj.extend(CoercionToInt) + assert_equal(3 | 10, 3 | obj) end - def test_printf_x - VS.reverse_each {|a| - s = sprintf("%x", a) - if /\A\.\./ =~ s - b = -($'.tr('0123456789abcdef', 'fedcba9876543210').to_i(16) + 1) - else - b = s.to_i(16) - end - assert_equal(a, b, "sprintf('%x', #{a}) = #{s.inspect}") - } + def test_bitwise_xor_with_integer_mimic_object + obj = MimicInteger.new(10) + assert_raise(TypeError, '[ruby-core:39491]') { 3 ^ obj } + obj.extend(CoercionToInt) + assert_equal(3 ^ 10, 3 ^ obj) end - def test_printf_x_sign - VS.reverse_each {|a| - s = sprintf("%+x", a) - b = s.to_i(16) - assert_equal(a, b, "sprintf('%+x', #{a}) = #{s.inspect}") - s = sprintf("% x", a) - b = s.to_i(16) - assert_equal(a, b, "sprintf('% x', #{a}) = #{s.inspect}") - } + module CoercionToSelf + def coerce(other) + [self.class.new(other), self] + end end - def test_printf_o - VS.reverse_each {|a| - s = sprintf("%o", a) - if /\A\.\./ =~ s - b = -($'.tr('01234567', '76543210').to_i(8) + 1) - else - b = s.to_i(8) + def test_bitwise_and_with_integer_coercion + obj = Struct.new(:value) do + include(CoercionToSelf) + def &(other) + self.value & other.value end - assert_equal(a, b, "sprintf('%o', #{a}) = #{s.inspect}") - } + end.new(10) + assert_equal(3 & 10, 3 & obj) end - def test_printf_o_sign - VS.reverse_each {|a| - s = sprintf("%+o", a) - b = s.to_i(8) - assert_equal(a, b, "sprintf('%+o', #{a}) = #{s.inspect}") - s = sprintf("% o", a) - b = s.to_i(8) - assert_equal(a, b, "sprintf('% o', #{a}) = #{s.inspect}") - } + def test_bitwise_or_with_integer_coercion + obj = Struct.new(:value) do + include(CoercionToSelf) + def |(other) + self.value | other.value + end + end.new(10) + assert_equal(3 | 10, 3 | obj) end - def test_printf_b - VS.reverse_each {|a| - s = sprintf("%b", a) - if /\A\.\./ =~ s - b = -($'.tr('01', '10').to_i(2) + 1) + def test_bitwise_xor_with_integer_coercion + obj = Struct.new(:value) do + include(CoercionToSelf) + def ^(other) + self.value ^ other.value + end + end.new(10) + assert_equal(3 ^ 10, 3 ^ obj) + end + + def test_bit_length + assert_equal(13, (-2**12-1).bit_length) + assert_equal(12, (-2**12).bit_length) + assert_equal(12, (-2**12+1).bit_length) + assert_equal(9, -0x101.bit_length) + assert_equal(8, -0x100.bit_length) + assert_equal(8, -0xff.bit_length) + assert_equal(1, -2.bit_length) + assert_equal(0, -1.bit_length) + assert_equal(0, 0.bit_length) + assert_equal(1, 1.bit_length) + assert_equal(8, 0xff.bit_length) + assert_equal(9, 0x100.bit_length) + assert_equal(9, 0x101.bit_length) + assert_equal(12, (2**12-1).bit_length) + assert_equal(13, (2**12).bit_length) + assert_equal(13, (2**12+1).bit_length) + + assert_equal(10001, (-2**10000-1).bit_length) + assert_equal(10000, (-2**10000).bit_length) + assert_equal(10000, (-2**10000+1).bit_length) + assert_equal(10000, (2**10000-1).bit_length) + assert_equal(10001, (2**10000).bit_length) + assert_equal(10001, (2**10000+1).bit_length) + + 2.upto(1000) {|i| + n = 2**i + assert_equal(i+1, (-n-1).bit_length, "(#{-n-1}).bit_length") + assert_equal(i, (-n).bit_length, "(#{-n}).bit_length") + assert_equal(i, (-n+1).bit_length, "(#{-n+1}).bit_length") + assert_equal(i, (n-1).bit_length, "#{n-1}.bit_length") + assert_equal(i+1, (n).bit_length, "#{n}.bit_length") + assert_equal(i+1, (n+1).bit_length, "#{n+1}.bit_length") + } + end + + def test_digits + assert_equal([0], 0.digits) + assert_equal([1], 1.digits) + assert_equal([0, 9, 8, 7, 6, 5, 4, 3, 2, 1], 1234567890.digits) + assert_equal([90, 78, 56, 34, 12], 1234567890.digits(100)) + assert_equal([10, 5, 6, 8, 0, 10, 8, 6, 1], 1234567890.digits(13)) + assert_equal((2 ** 1024).to_s(7).chars.map(&:to_i).reverse, (2 ** 1024).digits(7)) + assert_equal([0] * 100 + [1], (2 ** (128 * 100)).digits(2 ** 128)) + end + + def test_digits_for_negative_numbers + assert_raise(Math::DomainError) { -1.digits } + assert_raise(Math::DomainError) { -1234567890.digits } + assert_raise(Math::DomainError) { -1234567890.digits(100) } + assert_raise(Math::DomainError) { -1234567890.digits(13) } + end + + def test_digits_for_invalid_base_numbers + assert_raise(ArgumentError) { 10.digits(-1) } + assert_raise(ArgumentError) { 10.digits(0) } + assert_raise(ArgumentError) { 10.digits(1) } + end + + def test_digits_for_non_integral_base_numbers + assert_equal([1], 1.digits(10r)) + assert_equal([1], 1.digits(10.0)) + assert_raise(RangeError) { 10.digits(10+1i) } + end + + def test_digits_for_non_numeric_base_argument + assert_raise(TypeError) { 10.digits("10") } + assert_raise(TypeError) { 10.digits("a") } + + class << (o = Object.new) + def to_int + 10 + end + end + assert_equal([0, 1], 10.digits(o)) + end + + def test_square_root + assert_raise(TypeError) {Integer.sqrt("x")} + assert_raise(Math::DomainError) {Integer.sqrt(-1)} + assert_equal(0, Integer.sqrt(0)) + (1...4).each {|i| assert_equal(1, Integer.sqrt(i))} + (4...9).each {|i| assert_equal(2, Integer.sqrt(i))} + (9...16).each {|i| assert_equal(3, Integer.sqrt(i))} + (1..40).each do |i| + mesg = "10**#{i}" + s = Integer.sqrt(n = 10**i) + if i.even? + assert_equal(10**(i/2), Integer.sqrt(n), mesg) else - b = s.to_i(2) + assert_include((s**2)...(s+1)**2, n, mesg) end - assert_equal(a, b, "sprintf('%b', #{a}) = #{s.inspect}") - } - end + end + 50.step(400, 10) do |i| + exact = 10**(i/2) + x = 10**i + assert_equal(exact, Integer.sqrt(x), "10**#{i}") + assert_equal(exact, Integer.sqrt(x+1), "10**#{i}+1") + assert_equal(exact-1, Integer.sqrt(x-1), "10**#{i}-1") + end - def test_printf_b_sign - VS.reverse_each {|a| - s = sprintf("%+b", a) - b = s.to_i(2) - assert_equal(a, b, "sprintf('%+b', #{a}) = #{s.inspect}") - s = sprintf("% b", a) - b = s.to_i(2) - assert_equal(a, b, "sprintf('% b', #{a}) = #{s.inspect}") - } - end + bug13440 = '[ruby-core:80696] [Bug #13440]' + failures = [] + 0.step(to: 50, by: 0.05) do |i| + n = (10**i).to_i + root = Integer.sqrt(n) + failures << n unless root*root <= n && (root+1)*(root+1) > n + end + assert_empty(failures, bug13440) - def test_printf_di - VS.reverse_each {|a| - s = sprintf("%d", a) - b = s.to_i - assert_equal(a, b, "sprintf('%d', #{a}) = #{s.inspect}") - s = sprintf("%i", a) - b = s.to_i - assert_equal(a, b, "sprintf('%i', #{a}) = #{s.inspect}") - } + x = 0xffff_ffff_ffff_ffff + assert_equal(x, Integer.sqrt(x ** 2), "[ruby-core:95453]") end - def test_marshal - VS.reverse_each {|a| - s = Marshal.dump(a) - b = Marshal.load(s) - assert_equal(a, b, "Marshal.load(Marshal.dump(#{a}))") - } + def test_bug_21217 + assert_equal(0x10000 * 2**10, Integer.sqrt(0x100000008 * 2**20)) end - def test_pack_ber - template = "w" - VS.reverse_each {|a| - if a < 0 - assert_raise(ArgumentError) { [a].pack(template) } - else - s = [a].pack(template) - b = s.unpack(template)[0] - assert_equal(a, b, "[#{a}].pack(#{template.dump}).unpack(#{template.dump})") - end - } - end + def test_fdiv + assert_equal(1.0, 1.fdiv(1)) + assert_equal(0.5, 1.fdiv(2)) - def test_pack_utf8 - template = "U" - VS.reverse_each {|a| - if a < 0 || 0x7fffffff < a - assert_raise(RangeError) { [a].pack(template) } - else - s = [a].pack(template) - b = s.unpack(template)[0] - assert_equal(a, b, "[#{a}].pack(#{template.dump}).unpack(#{template.dump})") - end - } + m = 50 << Float::MANT_DIG + prev = 1.0 + (1..100).each do |i| + val = (m + i).fdiv(m) + assert_operator val, :>=, prev, "1+epsilon*(#{i}/100)" + prev = val + end end - def test_Integer - assert_raise(ArgumentError) {Integer("0x-1")} - assert_raise(ArgumentError) {Integer("-0x-1")} - assert_raise(ArgumentError) {Integer("0x 123")} - assert_raise(ArgumentError) {Integer("0x 123")} - assert_raise(ArgumentError) {Integer("0x0x5")} - assert_raise(ArgumentError) {Integer("0x0x000000005")} - assert_nothing_raised(ArgumentError) { - assert_equal(1540841, "0x0x5".to_i(36)) - } - assert_raise(ArgumentError) { Integer("--0") } - assert_raise(ArgumentError) { Integer("-+0") } - assert_raise(ArgumentError) { Integer("++1") } - assert_raise(ArgumentError) { Integer("") } - assert_raise(ArgumentError) { Integer("10 x") } - assert_raise(ArgumentError) { Integer("1__2") } - assert_raise(ArgumentError) { Integer("1z") } - assert_raise(ArgumentError) { Integer("46116860184273__87904") } - assert_raise(ArgumentError) { Integer("4611686018427387904_") } - assert_raise(ArgumentError) { Integer("4611686018427387904 :") } - assert_equal(0x4000000000000000, Integer("46_11_686_0184273_87904")) - assert_raise(ArgumentError) { Integer("\0") } - assert_nothing_raised(ArgumentError, "[ruby-core:13873]") { - assert_equal(0, Integer("0 ")) - } - assert_nothing_raised(ArgumentError, "[ruby-core:14139]") { - assert_equal(0377, Integer("0_3_7_7")) - } - assert_raise(ArgumentError, "[ruby-core:14139]") {Integer("0__3_7_7")} + def test_obj_fdiv + o = Object.new + def o.coerce(x); [x, 0.5]; end + assert_equal(2.0, 1.fdiv(o)) + o = Object.new + def o.coerce(x); [self, x]; end + def o.fdiv(x); 1; end + assert_equal(1.0, 1.fdiv(o)) + end + + def test_try_convert + assert_equal(1, Integer.try_convert(1)) + assert_equal(1, Integer.try_convert(1.0)) + assert_nil Integer.try_convert("1") + o = Object.new + assert_nil Integer.try_convert(o) + def o.to_i; 1; end + assert_nil Integer.try_convert(o) + o = Object.new + def o.to_int; 1; end + assert_equal(1, Integer.try_convert(o)) + + o = Object.new + def o.to_int; Object.new; end + assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)} + end + + def test_ceildiv + assert_equal(0, 0.ceildiv(3)) + assert_equal(1, 1.ceildiv(3)) + assert_equal(1, 3.ceildiv(3)) + assert_equal(2, 4.ceildiv(3)) + + assert_equal(-1, 4.ceildiv(-3)) + assert_equal(-1, -4.ceildiv(3)) + assert_equal(2, -4.ceildiv(-3)) + + assert_equal(3, 3.ceildiv(1.2)) + assert_equal(3, 3.ceildiv(6/5r)) + + assert_equal(10, (10**100-11).ceildiv(10**99-1)) + assert_equal(11, (10**100-9).ceildiv(10**99-1)) + + o = Object.new + def o.coerce(other); [other, 10]; end + assert_equal(124, 1234.ceildiv(o)) end end |
