diff options
Diffstat (limited to 'test/ruby/test_range.rb')
-rw-r--r-- | test/ruby/test_range.rb | 672 |
1 files changed, 579 insertions, 93 deletions
diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb index bb5ef6df8f..e0c1d20bd2 100644 --- a/test/ruby/test_range.rb +++ b/test/ruby/test_range.rb @@ -2,7 +2,7 @@ require 'test/unit' require 'delegate' require 'timeout' -require 'bigdecimal' +require 'date' require 'rbconfig/sizeof' class TestRange < Test::Unit::TestCase @@ -246,67 +246,138 @@ class TestRange < Test::Unit::TestCase assert_kind_of(String, (0..1).hash.to_s) end - def test_step - a = [] - (0..10).step {|x| a << x } - assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a) + def test_step_numeric_range + # Fixnums, floats and all other numbers (like rationals) should behave exactly the same, + # but the behavior is implemented independently in 3 different branches of code, + # so we need to test each of them. + %i[to_i to_r to_f].each do |type| + conv = type.to_proc - a = [] - (0..).step {|x| a << x; break if a.size == 10 } - assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a) + from = conv.(0) + to = conv.(10) + step = conv.(2) - a = [] - (0..10).step(2) {|x| a << x } - assert_equal([0, 2, 4, 6, 8, 10], a) + # finite + a = [] + (from..to).step(step) {|x| a << x } + assert_equal([0, 2, 4, 6, 8, 10].map(&conv), a) - a = [] - (0..).step(2) {|x| a << x; break if a.size == 10 } - assert_equal([0, 2, 4, 6, 8, 10, 12, 14, 16, 18], a) + a = [] + (from...to).step(step) {|x| a << x } + assert_equal([0, 2, 4, 6, 8].map(&conv), a) - assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step) - assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step(2)) - assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step(0.5)) - assert_kind_of(Enumerator::ArithmeticSequence, (10..0).step(-1)) - assert_kind_of(Enumerator::ArithmeticSequence, (..10).step(2)) - assert_kind_of(Enumerator::ArithmeticSequence, (1..).step(2)) + # Note: ArithmeticSequence behavior tested in its own test, but we also put it here + # to demonstrate the result is the same + assert_kind_of(Enumerator::ArithmeticSequence, (from..to).step(step)) + assert_equal([0, 2, 4, 6, 8, 10].map(&conv), (from..to).step(step).to_a) + assert_kind_of(Enumerator::ArithmeticSequence, (from...to).step(step)) + assert_equal([0, 2, 4, 6, 8].map(&conv), (from...to).step(step).to_a) - assert_raise(ArgumentError) { (0..10).step(-1) { } } - assert_raise(ArgumentError) { (0..10).step(0) } - assert_raise(ArgumentError) { (0..10).step(0) { } } - assert_raise(ArgumentError) { (0..).step(-1) { } } - assert_raise(ArgumentError) { (0..).step(0) } - assert_raise(ArgumentError) { (0..).step(0) { } } + # endless + a = [] + (from..).step(step) {|x| a << x; break if a.size == 5 } + assert_equal([0, 2, 4, 6, 8].map(&conv), a) - a = [] - ("a" .. "z").step(2) {|x| a << x } - assert_equal(%w(a c e g i k m o q s u w y), a) + assert_kind_of(Enumerator::ArithmeticSequence, (from..).step(step)) + assert_equal([0, 2, 4, 6, 8].map(&conv), (from..).step(step).take(5)) - a = [] - ("a" .. ).step(2) {|x| a << x; break if a.size == 13 } - assert_equal(%w(a c e g i k m o q s u w y), a) + # beginless + assert_raise(ArgumentError) { (..to).step(step) {} } + assert_kind_of(Enumerator::ArithmeticSequence, (..to).step(step)) + # This is inconsistent, but so it is implemented by ArithmeticSequence + assert_raise(TypeError) { (..to).step(step).to_a } - a = [] - ("a" .. "z").step(2**32) {|x| a << x } - assert_equal(["a"], a) + # negative step - a = [] - (:a .. :z).step(2) {|x| a << x } - assert_equal(%i(a c e g i k m o q s u w y), a) + a = [] + (from..to).step(-step) {|x| a << x } + assert_equal([], a) - a = [] - (:a .. ).step(2) {|x| a << x; break if a.size == 13 } - assert_equal(%i(a c e g i k m o q s u w y), a) + a = [] + (from..-to).step(-step) {|x| a << x } + assert_equal([0, -2, -4, -6, -8, -10].map(&conv), a) - a = [] - (:a .. :z).step(2**32) {|x| a << x } - assert_equal([:a], a) + a = [] + (from...-to).step(-step) {|x| a << x } + assert_equal([0, -2, -4, -6, -8].map(&conv), a) + + a = [] + (from...).step(-step) {|x| a << x; break if a.size == 5 } + assert_equal([0, -2, -4, -6, -8].map(&conv), a) + + assert_kind_of(Enumerator::ArithmeticSequence, (from..to).step(-step)) + assert_equal([], (from..to).step(-step).to_a) + + assert_kind_of(Enumerator::ArithmeticSequence, (from..-to).step(-step)) + assert_equal([0, -2, -4, -6, -8, -10].map(&conv), (from..-to).step(-step).to_a) + + assert_kind_of(Enumerator::ArithmeticSequence, (from...-to).step(-step)) + assert_equal([0, -2, -4, -6, -8].map(&conv), (from...-to).step(-step).to_a) + + assert_kind_of(Enumerator::ArithmeticSequence, (from...).step(-step)) + assert_equal([0, -2, -4, -6, -8].map(&conv), (from...).step(-step).take(5)) + + # zero step + + assert_raise(ArgumentError) { (from..to).step(0) {} } + assert_raise(ArgumentError) { (from..to).step(0) } + + # default step + + a = [] + (from..to).step {|x| a << x } + assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(&conv), a) + + assert_kind_of(Enumerator::ArithmeticSequence, (from..to).step) + assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(&conv), (from..to).step.to_a) + + # default + endless range + a = [] + (from..).step {|x| a << x; break if a.size == 5 } + assert_equal([0, 1, 2, 3, 4].map(&conv), a) + + assert_kind_of(Enumerator::ArithmeticSequence, (from..).step) + assert_equal([0, 1, 2, 3, 4].map(&conv), (from..).step.take(5)) + + # default + beginless range + assert_kind_of(Enumerator::ArithmeticSequence, (..to).step) + # step is not numeric + + to = conv.(5) + + val = Struct.new(:val) + + a = [] + assert_raise(TypeError) { (from..to).step(val.new(step)) {|x| a << x } } + assert_kind_of(Enumerator, (from..to).step(val.new(step))) + assert_raise(TypeError) { (from..to).step(val.new(step)).to_a } + + # step is not numeric, but coercible + val = Struct.new(:val) do + def coerce(num) = [self.class.new(num), self] + def +(other) = self.class.new(val + other.val) + def <=>(other) = other.is_a?(self.class) ? val <=> other.val : val <=> other + end + + a = [] + (from..to).step(val.new(step)) {|x| a << x } + assert_equal([from, val.new(conv.(2)), val.new(conv.(4))], a) + + assert_kind_of(Enumerator, (from..to).step(val.new(step))) + assert_equal([from, val.new(conv.(2)), val.new(conv.(4))], (from..to).step(val.new(step)).to_a) + end + end + + def test_step_numeric_fixnum_boundary a = [] (2**32-1 .. 2**32+1).step(2) {|x| a << x } assert_equal([4294967295, 4294967297], a) + zero = (2**32).coerce(0).first assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) } assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } } + a = [] (2**32-1 .. ).step(2) {|x| a << x; break if a.size == 2 } assert_equal([4294967295, 4294967297], a) @@ -315,58 +386,189 @@ class TestRange < Test::Unit::TestCase a = [] (max..).step {|x| a << x; break if a.size == 2 } assert_equal([max, max+1], a) + a = [] (max..).step(max) {|x| a << x; break if a.size == 4 } assert_equal([max, 2*max, 3*max, 4*max], a) + end - o1 = Object.new - o2 = Object.new - def o1.<=>(x); -1; end - def o2.<=>(x); 0; end - assert_raise(TypeError) { (o1..o2).step(1) { } } - assert_raise(TypeError) { (o1..).step(1) { } } + def test_step_big_float + a = [] + (0x40000000..0x40000002).step(0.5) {|x| a << x } + assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a) + end - class << o1; self; end.class_eval do - define_method(:succ) { o2 } - end + def test_step_non_numeric_range + # finite a = [] - (o1..o2).step(1) {|x| a << x } - assert_equal([o1, o2], a) + ('a'..'aaaa').step('a') { a << _1 } + assert_equal(%w[a aa aaa aaaa], a) + + assert_kind_of(Enumerator, ('a'..'aaaa').step('a')) + assert_equal(%w[a aa aaa aaaa], ('a'..'aaaa').step('a').to_a) a = [] - (o1...o2).step(1) {|x| a << x } - assert_equal([o1], a) + ('a'...'aaaa').step('a') { a << _1 } + assert_equal(%w[a aa aaa], a) - assert_nothing_raised("[ruby-dev:34557]") { (0..2).step(0.5) {|x| } } + assert_kind_of(Enumerator, ('a'...'aaaa').step('a')) + assert_equal(%w[a aa aaa], ('a'...'aaaa').step('a').to_a) + # endless a = [] - (0..2).step(0.5) {|x| a << x } - assert_equal([0, 0.5, 1.0, 1.5, 2.0], a) + ('a'...).step('a') { a << _1; break if a.size == 3 } + assert_equal(%w[a aa aaa], a) + + assert_kind_of(Enumerator, ('a'...).step('a')) + assert_equal(%w[a aa aaa], ('a'...).step('a').take(3)) + + # beginless + assert_raise(ArgumentError) { (...'aaa').step('a') {} } + assert_raise(ArgumentError) { (...'aaa').step('a') } + # step is not provided + assert_raise(ArgumentError) { (Time.new(2022)...Time.new(2023)).step } + + # step is incompatible + assert_raise(TypeError) { (Time.new(2022)...Time.new(2023)).step('a') {} } + assert_raise(TypeError) { (Time.new(2022)...Time.new(2023)).step('a').to_a } + + # step is compatible, but shouldn't convert into numeric domain: a = [] - (0..).step(0.5) {|x| a << x; break if a.size == 5 } - assert_equal([0, 0.5, 1.0, 1.5, 2.0], a) + (Time.utc(2022, 2, 24)...).step(1) { a << _1; break if a.size == 2 } + assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 24, 0, 0, 1)], a) a = [] - (0x40000000..0x40000002).step(0.5) {|x| a << x } - assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a) + (Time.utc(2022, 2, 24)...).step(1.0) { a << _1; break if a.size == 2 } + assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 24, 0, 0, 1)], a) - o = Object.new - def o.to_int() 1 end - assert_nothing_raised("[ruby-dev:34558]") { (0..2).step(o) {|x| } } + a = [] + (Time.utc(2022, 2, 24)...).step(1r) { a << _1; break if a.size == 2 } + assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 24, 0, 0, 1)], a) - o = Object.new - class << o - def to_str() "a" end - def <=>(other) to_str <=> other end - end + # step decreases the value + a = [] + (Time.utc(2022, 2, 24)...).step(-1) { a << _1; break if a.size == 2 } + assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 23, 23, 59, 59)], a) a = [] - (o.."c").step(1) {|x| a << x} - assert_equal(["a", "b", "c"], a) + (Time.utc(2022, 2, 24)...Time.utc(2022, 2, 23, 23, 59, 57)).step(-1) { a << _1 } + assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 23, 23, 59, 59), + Time.utc(2022, 2, 23, 23, 59, 58)], a) + a = [] - (o..).step(1) {|x| a << x; break if a.size >= 3} - assert_equal(["a", "b", "c"], a) + (Time.utc(2022, 2, 24)..Time.utc(2022, 2, 23, 23, 59, 57)).step(-1) { a << _1 } + assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 23, 23, 59, 59), + Time.utc(2022, 2, 23, 23, 59, 58), Time.utc(2022, 2, 23, 23, 59, 57)], a) + + # step decreases, but the range is forward-directed: + a = [] + (Time.utc(2022, 2, 24)...Time.utc(2022, 2, 24, 01, 01, 03)).step(-1) { a << _1 } + assert_equal([], a) + end + + def test_step_string_legacy + # finite + a = [] + ('a'..'g').step(2) { a << _1 } + assert_equal(%w[a c e g], a) + + assert_kind_of(Enumerator, ('a'..'g').step(2)) + assert_equal(%w[a c e g], ('a'..'g').step(2).to_a) + + a = [] + ('a'...'g').step(2) { a << _1 } + assert_equal(%w[a c e], a) + + assert_kind_of(Enumerator, ('a'...'g').step(2)) + assert_equal(%w[a c e], ('a'...'g').step(2).to_a) + + # endless + a = [] + ('a'...).step(2) { a << _1; break if a.size == 3 } + assert_equal(%w[a c e], a) + + assert_kind_of(Enumerator, ('a'...).step(2)) + assert_equal(%w[a c e], ('a'...).step(2).take(3)) + + # beginless + assert_raise(ArgumentError) { (...'g').step(2) {} } + assert_raise(ArgumentError) { (...'g').step(2) } + + # step is not provided + a = [] + ('a'..'d').step { a << _1 } + assert_equal(%w[a b c d], a) + + assert_kind_of(Enumerator, ('a'..'d').step) + assert_equal(%w[a b c d], ('a'..'d').step.to_a) + + a = [] + ('a'...'d').step { a << _1 } + assert_equal(%w[a b c], a) + + assert_kind_of(Enumerator, ('a'...'d').step) + assert_equal(%w[a b c], ('a'...'d').step.to_a) + + # endless + a = [] + ('a'...).step { a << _1; break if a.size == 3 } + assert_equal(%w[a b c], a) + + assert_kind_of(Enumerator, ('a'...).step) + assert_equal(%w[a b c], ('a'...).step.take(3)) + end + + def test_step_symbol_legacy + # finite + a = [] + (:a..:g).step(2) { a << _1 } + assert_equal(%i[a c e g], a) + + assert_kind_of(Enumerator, (:a..:g).step(2)) + assert_equal(%i[a c e g], (:a..:g).step(2).to_a) + + a = [] + (:a...:g).step(2) { a << _1 } + assert_equal(%i[a c e], a) + + assert_kind_of(Enumerator, (:a...:g).step(2)) + assert_equal(%i[a c e], (:a...:g).step(2).to_a) + + # endless + a = [] + (:a...).step(2) { a << _1; break if a.size == 3 } + assert_equal(%i[a c e], a) + + assert_kind_of(Enumerator, (:a...).step(2)) + assert_equal(%i[a c e], (:a...).step(2).take(3)) + + # beginless + assert_raise(ArgumentError) { (...:g).step(2) {} } + assert_raise(ArgumentError) { (...:g).step(2) } + + # step is not provided + a = [] + (:a..:d).step { a << _1 } + assert_equal(%i[a b c d], a) + + assert_kind_of(Enumerator, (:a..:d).step) + assert_equal(%i[a b c d], (:a..:d).step.to_a) + + a = [] + (:a...:d).step { a << _1 } + assert_equal(%i[a b c], a) + + assert_kind_of(Enumerator, (:a...:d).step) + assert_equal(%i[a b c], (:a...:d).step.to_a) + + # endless + a = [] + (:a...).step { a << _1; break if a.size == 3 } + assert_equal(%i[a b c], a) + + assert_kind_of(Enumerator, (:a...).step) + assert_equal(%i[a b c], (:a...).step.take(3)) end def test_step_bug15537 @@ -456,6 +658,171 @@ class TestRange < Test::Unit::TestCase assert_equal(["a", "b", "c"], a) end + def test_each_with_succ + c = Struct.new(:i) do + def succ; self.class.new(i+1); end + def <=>(other) i <=> other.i;end + end.new(0) + + result = [] + (c..c.succ).each do |d| + result << d.i + end + assert_equal([0, 1], result) + + result = [] + (c..).each do |d| + result << d.i + break if d.i >= 4 + end + assert_equal([0, 1, 2, 3, 4], result) + end + + def test_reverse_each + a = [] + (1..3).reverse_each {|x| a << x } + assert_equal([3, 2, 1], a) + + a = [] + (1...3).reverse_each {|x| a << x } + assert_equal([2, 1], a) + + fmax = RbConfig::LIMITS['FIXNUM_MAX'] + fmin = RbConfig::LIMITS['FIXNUM_MIN'] + + a = [] + (fmax+1..fmax+3).reverse_each {|x| a << x } + assert_equal([fmax+3, fmax+2, fmax+1], a) + + a = [] + (fmax+1...fmax+3).reverse_each {|x| a << x } + assert_equal([fmax+2, fmax+1], a) + + a = [] + (fmax-1..fmax+1).reverse_each {|x| a << x } + assert_equal([fmax+1, fmax, fmax-1], a) + + a = [] + (fmax-1...fmax+1).reverse_each {|x| a << x } + assert_equal([fmax, fmax-1], a) + + a = [] + (fmin-1..fmin+1).reverse_each{|x| a << x } + assert_equal([fmin+1, fmin, fmin-1], a) + + a = [] + (fmin-1...fmin+1).reverse_each{|x| a << x } + assert_equal([fmin, fmin-1], a) + + a = [] + (fmin-3..fmin-1).reverse_each{|x| a << x } + assert_equal([fmin-1, fmin-2, fmin-3], a) + + a = [] + (fmin-3...fmin-1).reverse_each{|x| a << x } + assert_equal([fmin-2, fmin-3], a) + + a = [] + ("a".."c").reverse_each {|x| a << x } + assert_equal(["c", "b", "a"], a) + end + + def test_reverse_each_for_beginless_range + fmax = RbConfig::LIMITS['FIXNUM_MAX'] + fmin = RbConfig::LIMITS['FIXNUM_MIN'] + + a = [] + (..3).reverse_each {|x| a << x; break if x <= 0 } + assert_equal([3, 2, 1, 0], a) + + a = [] + (...3).reverse_each {|x| a << x; break if x <= 0 } + assert_equal([2, 1, 0], a) + + a = [] + (..fmax+1).reverse_each {|x| a << x; break if x <= fmax-1 } + assert_equal([fmax+1, fmax, fmax-1], a) + + a = [] + (...fmax+1).reverse_each {|x| a << x; break if x <= fmax-1 } + assert_equal([fmax, fmax-1], a) + + a = [] + (..fmin+1).reverse_each {|x| a << x; break if x <= fmin-1 } + assert_equal([fmin+1, fmin, fmin-1], a) + + a = [] + (...fmin+1).reverse_each {|x| a << x; break if x <= fmin-1 } + assert_equal([fmin, fmin-1], a) + + a = [] + (..fmin-1).reverse_each {|x| a << x; break if x <= fmin-3 } + assert_equal([fmin-1, fmin-2, fmin-3], a) + + a = [] + (...fmin-1).reverse_each {|x| a << x; break if x <= fmin-3 } + assert_equal([fmin-2, fmin-3], a) + end + + def test_reverse_each_for_endless_range + assert_raise(TypeError) { (1..).reverse_each {} } + + enum = nil + assert_nothing_raised { enum = (1..).reverse_each } + assert_raise(TypeError) { enum.each {} } + end + + def test_reverse_each_for_single_point_range + fmin = RbConfig::LIMITS['FIXNUM_MIN'] + fmax = RbConfig::LIMITS['FIXNUM_MAX'] + + values = [fmin*2, fmin-1, fmin, 0, fmax, fmax+1, fmax*2] + + values.each do |b| + r = b..b + a = [] + r.reverse_each {|x| a << x } + assert_equal([b], a, "failed on #{r}") + + r = b...b+1 + a = [] + r.reverse_each {|x| a << x } + assert_equal([b], a, "failed on #{r}") + end + end + + def test_reverse_each_for_empty_range + fmin = RbConfig::LIMITS['FIXNUM_MIN'] + fmax = RbConfig::LIMITS['FIXNUM_MAX'] + + values = [fmin*2, fmin-1, fmin, 0, fmax, fmax+1, fmax*2] + + values.each do |b| + r = b..b-1 + a = [] + r.reverse_each {|x| a << x } + assert_equal([], a, "failed on #{r}") + end + + values.repeated_permutation(2).to_a.product([true, false]).each do |(b, e), excl| + next unless b > e || (b == e && excl) + + r = Range.new(b, e, excl) + a = [] + r.reverse_each {|x| a << x } + assert_equal([], a, "failed on #{r}") + end + end + + def test_reverse_each_with_no_block + enum = (1..5).reverse_each + assert_equal 5, enum.size + + a = [] + enum.each {|x| a << x } + assert_equal [5, 4, 3, 2, 1], a + end + def test_begin_end assert_equal(0, (0..1).begin) assert_equal(1, (0..1).end) @@ -539,6 +906,10 @@ class TestRange < Test::Unit::TestCase assert_not_operator(0..10, :===, 11) assert_operator(5..nil, :===, 11) assert_not_operator(5..nil, :===, 0) + assert_operator(nil..10, :===, 0) + assert_operator(nil..nil, :===, 0) + assert_operator(nil..nil, :===, Object.new) + assert_not_operator(0..10, :===, 0..10) end def test_eqq_string @@ -546,7 +917,7 @@ class TestRange < Test::Unit::TestCase assert_not_operator('A'..'Z', :===, 'ana') assert_operator('A'.., :===, 'ANA') assert_operator(..'Z', :===, 'ANA') - assert_raise(TypeError) {(nil..nil) === 'ANA'} + assert_operator(nil..nil, :===, 'ANA') end def test_eqq_time @@ -583,6 +954,28 @@ class TestRange < Test::Unit::TestCase assert_operator(c.new(0)..c.new(10), :===, c.new(5), bug12003) end + def test_eqq_unbounded_ruby_bug_19864 + t1 = Date.today + t2 = t1 + 1 + assert_equal(true, (..t1) === t1) + assert_equal(false, (..t1) === t2) + assert_equal(true, (..t2) === t1) + assert_equal(true, (..t2) === t2) + assert_equal(false, (...t1) === t1) + assert_equal(false, (...t1) === t2) + assert_equal(true, (...t2) === t1) + assert_equal(false, (...t2) === t2) + + assert_equal(true, (t1..) === t1) + assert_equal(true, (t1..) === t2) + assert_equal(false, (t2..) === t1) + assert_equal(true, (t2..) === t2) + assert_equal(true, (t1...) === t1) + assert_equal(true, (t1...) === t2) + assert_equal(false, (t2...) === t1) + assert_equal(true, (t2...) === t2) + end + def test_eqq_non_iteratable k = Class.new do include Comparable @@ -772,21 +1165,38 @@ class TestRange < Test::Unit::TestCase end def test_size - assert_equal 42, (1..42).size - assert_equal 41, (1...42).size - assert_equal 6, (1...6.3).size - assert_equal 5, (1.1...6).size - assert_equal 42, (1..42).each.size + Enumerator.product([:to_i, :to_f, :to_r].repeated_permutation(2), [1, 10], [5, 5.5], [true, false]) do |(m1, m2), beg, ende, exclude_end| + r = Range.new(beg.send(m1), ende.send(m2), exclude_end) + iterable = true + yielded = [] + begin + r.each { yielded << _1 } + rescue TypeError + iterable = false + end + + if iterable + assert_equal(yielded.size, r.size, "failed on #{r}") + assert_equal(yielded.size, r.each.size, "failed on #{r}") + else + assert_raise(TypeError, "failed on #{r}") { r.size } + assert_raise(TypeError, "failed on #{r}") { r.each.size } + end + end + assert_nil ("a"..."z").size - assert_nil ("a"...).size - assert_nil (..."z").size # [Bug #18983] - assert_nil (nil...nil).size # [Bug #18983] - assert_equal Float::INFINITY, (1...).size - assert_equal Float::INFINITY, (1.0...).size - assert_equal Float::INFINITY, (...1).size - assert_equal Float::INFINITY, (...1.0).size - assert_nil ("a"...).size + assert_equal Float::INFINITY, (1..).size + assert_raise(TypeError) { (1.0..).size } + assert_raise(TypeError) { (1r..).size } + assert_nil ("a"..).size + + assert_raise(TypeError) { (..1).size } + assert_raise(TypeError) { (..1.0).size } + assert_raise(TypeError) { (..1r).size } + assert_raise(TypeError) { (..'z').size } + + assert_raise(TypeError) { (nil...nil).size } end def test_bsearch_typechecks_return_values @@ -810,9 +1220,6 @@ class TestRange < Test::Unit::TestCase assert_raise(TypeError) { (Rational(-1,2)..Rational(9,4)).bsearch } - assert_raise(TypeError) { - (BigDecimal('0.5')..BigDecimal('2.25')).bsearch - } end def test_bsearch_for_fixnum @@ -986,7 +1393,10 @@ class TestRange < Test::Unit::TestCase assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 100 }) assert_equal(bignum + 0, (bignum...bignum+ary.size).bsearch {|i| true }) assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| false }) + + assert_equal(bignum * 2 + 1, (0...).bsearch {|i| i > bignum * 2 }) assert_equal(bignum * 2 + 1, (bignum...).bsearch {|i| i > bignum * 2 }) + assert_equal(-bignum * 2 + 1, (...0).bsearch {|i| i > -bignum * 2 }) assert_equal(-bignum * 2 + 1, (...-bignum).bsearch {|i| i > -bignum * 2 }) assert_raise(TypeError) { ("a".."z").bsearch {} } @@ -1011,6 +1421,82 @@ class TestRange < Test::Unit::TestCase end def test_count + assert_equal 42, (1..42).count + assert_equal 41, (1...42).count + assert_equal 0, (42..1).count + assert_equal 0, (42...1).count + assert_equal 2**100, (1..2**100).count + assert_equal 6, (1...6.3).count + assert_equal 4, ('a'..'d').count + assert_equal 3, ('a'...'d').count + assert_equal(Float::INFINITY, (1..).count) + assert_equal(Float::INFINITY, (..1).count) + end + + def test_overlap? + assert_not_operator(0..2, :overlap?, -2..-1) + assert_not_operator(0..2, :overlap?, -2...0) + assert_operator(0..2, :overlap?, -1..0) + assert_operator(0..2, :overlap?, 1..2) + assert_operator(0..2, :overlap?, 2..3) + assert_not_operator(0..2, :overlap?, 3..4) + assert_not_operator(0...2, :overlap?, 2..3) + + assert_operator(..0, :overlap?, -1..0) + assert_operator(...0, :overlap?, -1..0) + assert_operator(..0, :overlap?, 0..1) + assert_operator(..0, :overlap?, ..1) + assert_not_operator(..0, :overlap?, 1..2) + assert_not_operator(...0, :overlap?, 0..1) + + assert_not_operator(0.., :overlap?, -2..-1) + assert_not_operator(0.., :overlap?, ...0) + assert_operator(0.., :overlap?, -1..0) + assert_operator(0.., :overlap?, ..0) + assert_operator(0.., :overlap?, 0..1) + assert_operator(0.., :overlap?, 1..2) + assert_operator(0.., :overlap?, 1..) + + assert_not_operator((1..3), :overlap?, ('a'..'d')) + assert_not_operator((1..), :overlap?, ('a'..)) + assert_not_operator((..1), :overlap?, (..'a')) + + assert_raise(TypeError) { (0..).overlap?(1) } + assert_raise(TypeError) { (0..).overlap?(nil) } + + assert_operator((1..3), :overlap?, (2..4)) + assert_operator((1...3), :overlap?, (2..3)) + assert_operator((2..3), :overlap?, (1..2)) + assert_operator((..3), :overlap?, (3..)) + assert_operator((nil..nil), :overlap?, (3..)) + assert_operator((nil...nil), :overlap?, (nil..)) + assert_operator((nil..nil), :overlap?, (..3)) + + assert_raise(TypeError) { (1..3).overlap?(1) } + + assert_not_operator((1..2), :overlap?, (2...2)) + assert_not_operator((2...2), :overlap?, (1..2)) + + assert_not_operator((4..1), :overlap?, (2..3)) + assert_not_operator((4..1), :overlap?, (..3)) + assert_not_operator((4..1), :overlap?, (2..)) + + assert_not_operator((1..4), :overlap?, (3..2)) + assert_not_operator((..4), :overlap?, (3..2)) + assert_not_operator((1..), :overlap?, (3..2)) + + assert_not_operator((4..5), :overlap?, (2..3)) + assert_not_operator((4..5), :overlap?, (2...4)) + + assert_not_operator((1..2), :overlap?, (3..4)) + assert_not_operator((1...3), :overlap?, (3..4)) + + assert_not_operator((4..5), :overlap?, (2..3)) + assert_not_operator((4..5), :overlap?, (2...4)) + + assert_not_operator((1..2), :overlap?, (3..4)) + assert_not_operator((1...3), :overlap?, (3..4)) + assert_not_operator((...3), :overlap?, (3..)) end end |