1require 'test/unit'
2require 'delegate'
3require 'timeout'
4require 'bigdecimal'
5require_relative 'envutil'
6
7class TestRange < Test::Unit::TestCase
8  def test_range_string
9    # XXX: Is this really the test of Range?
10    assert_equal([], ("a" ... "a").to_a)
11    assert_equal(["a"], ("a" .. "a").to_a)
12    assert_equal(["a"], ("a" ... "b").to_a)
13    assert_equal(["a", "b"], ("a" .. "b").to_a)
14  end
15
16  def test_range_numeric_string
17    assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]")
18    assert_equal(["6", "7"], ("6"..."8").to_a)
19    assert_equal(["9", "10"], ("9".."10").to_a)
20    assert_equal(["09", "10"], ("09".."10").to_a, "[ruby-dev:39361]")
21    assert_equal(["9", "10"], (SimpleDelegator.new("9").."10").to_a)
22    assert_equal(["9", "10"], ("9"..SimpleDelegator.new("10")).to_a)
23  end
24
25  def test_range_symbol
26    assert_equal([:a, :b], (:a .. :b).to_a)
27  end
28
29  def test_evaluation_order
30    arr = [1,2]
31    r = (arr.shift)..(arr.shift)
32    assert_equal(1..2, r, "[ruby-dev:26383]")
33  end
34
35  class DuckRange
36    def initialize(b,e,excl=false)
37      @begin = b
38      @end = e
39      @excl = excl
40    end
41    attr_reader :begin, :end
42
43    def exclude_end?
44      @excl
45    end
46  end
47
48  def test_duckrange
49    assert_equal("bc", "abcd"[DuckRange.new(1,2)])
50  end
51
52  def test_min
53    assert_equal(1, (1..2).min)
54    assert_equal(nil, (2..1).min)
55    assert_equal(1, (1...2).min)
56
57    assert_equal(1.0, (1.0..2.0).min)
58    assert_equal(nil, (2.0..1.0).min)
59    assert_equal(1, (1.0...2.0).min)
60
61    assert_equal(0, (0..0).min)
62    assert_equal(nil, (0...0).min)
63  end
64
65  def test_max
66    assert_equal(2, (1..2).max)
67    assert_equal(nil, (2..1).max)
68    assert_equal(1, (1...2).max)
69
70    assert_equal(2.0, (1.0..2.0).max)
71    assert_equal(nil, (2.0..1.0).max)
72    assert_raise(TypeError) { (1.0...2.0).max }
73    assert_raise(TypeError) { (1...1.5).max }
74    assert_raise(TypeError) { (1.5...2).max }
75
76    assert_equal(-0x80000002, ((-0x80000002)...(-0x80000001)).max)
77
78    assert_equal(0, (0..0).max)
79    assert_equal(nil, (0...0).max)
80  end
81
82  def test_initialize_twice
83    r = eval("1..2")
84    assert_raise(NameError) { r.instance_eval { initialize 3, 4 } }
85  end
86
87  def test_uninitialized_range
88    r = Range.allocate
89    s = Marshal.dump(r)
90    r = Marshal.load(s)
91    assert_nothing_raised { r.instance_eval { initialize 5, 6} }
92  end
93
94  def test_bad_value
95    assert_raise(ArgumentError) { (1 .. :a) }
96  end
97
98  def test_exclude_end
99    assert(!((0..1).exclude_end?))
100    assert((0...1).exclude_end?)
101  end
102
103  def test_eq
104    r = (0..1)
105    assert(r == r)
106    assert(r == (0..1))
107    assert(r != 0)
108    assert(r != (1..2))
109    assert(r != (0..2))
110    assert(r != (0...1))
111    subclass = Class.new(Range)
112    assert(r == subclass.new(0,1))
113  end
114
115  def test_eql
116    r = (0..1)
117    assert(r.eql?(r))
118    assert(r.eql?(0..1))
119    assert(!r.eql?(0))
120    assert(!r.eql?(1..2))
121    assert(!r.eql?(0..2))
122    assert(!r.eql?(0...1))
123    subclass = Class.new(Range)
124    assert(r.eql?(subclass.new(0,1)))
125  end
126
127  def test_hash
128    assert((0..1).hash.is_a?(Fixnum))
129  end
130
131  def test_step
132    a = []
133    (0..10).step {|x| a << x }
134    assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)
135
136    a = []
137    (0..10).step(2) {|x| a << x }
138    assert_equal([0, 2, 4, 6, 8, 10], a)
139
140    assert_raise(ArgumentError) { (0..10).step(-1) { } }
141    assert_raise(ArgumentError) { (0..10).step(0) { } }
142
143    a = []
144    ("a" .. "z").step(2) {|x| a << x }
145    assert_equal(%w(a c e g i k m o q s u w y), a)
146
147    a = []
148    ("a" .. "z").step(2**32) {|x| a << x }
149    assert_equal(["a"], a)
150
151    a = []
152    (2**32-1 .. 2**32+1).step(2) {|x| a << x }
153    assert_equal([4294967295, 4294967297], a)
154    zero = (2**32).coerce(0).first
155    assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }
156
157    o1 = Object.new
158    o2 = Object.new
159    def o1.<=>(x); -1; end
160    def o2.<=>(x); 0; end
161    assert_raise(TypeError) { (o1..o2).step(1) { } }
162
163    class << o1; self; end.class_eval do
164      define_method(:succ) { o2 }
165    end
166    a = []
167    (o1..o2).step(1) {|x| a << x }
168    assert_equal([o1, o2], a)
169
170    a = []
171    (o1...o2).step(1) {|x| a << x }
172    assert_equal([o1], a)
173
174    assert_nothing_raised("[ruby-dev:34557]") { (0..2).step(0.5) {|x| } }
175
176    a = []
177    (0..2).step(0.5) {|x| a << x }
178    assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)
179
180    a = []
181    (0x40000000..0x40000002).step(0.5) {|x| a << x }
182    assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)
183
184    o = Object.new
185    def o.to_int() 1 end
186    assert_nothing_raised("[ruby-dev:34558]") { (0..2).step(o) {|x| } }
187  end
188
189  def test_step_ruby_core_35753
190    assert_equal(6, (1...6.3).step.to_a.size)
191    assert_equal(5, (1.1...6).step.to_a.size)
192    assert_equal(5, (1...6).step(1.1).to_a.size)
193    assert_equal(3, (1.0...5.4).step(1.5).to_a.size)
194    assert_equal(3, (1.0...5.5).step(1.5).to_a.size)
195    assert_equal(4, (1.0...5.6).step(1.5).to_a.size)
196  end
197
198  def test_each
199    a = []
200    (0..10).each {|x| a << x }
201    assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)
202
203    o1 = Object.new
204    o2 = Object.new
205    def o1.setcmp(v) @cmpresult = v end
206    o1.setcmp(-1)
207    def o1.<=>(x); @cmpresult; end
208    def o2.setcmp(v) @cmpresult = v end
209    o2.setcmp(0)
210    def o2.<=>(x); @cmpresult; end
211    class << o1; self; end.class_eval do
212      define_method(:succ) { o2 }
213    end
214
215    r1 = (o1..o2)
216    r2 = (o1...o2)
217
218    a = []
219    r1.each {|x| a << x }
220    assert_equal([o1, o2], a)
221
222    a = []
223    r2.each {|x| a << x }
224    assert_equal([o1], a)
225
226    o2.setcmp(1)
227
228    a = []
229    r1.each {|x| a << x }
230    assert_equal([o1], a)
231
232    o2.setcmp(nil)
233
234    a = []
235    r1.each {|x| a << x }
236    assert_equal([o1], a)
237
238    o1.setcmp(nil)
239
240    a = []
241    r2.each {|x| a << x }
242    assert_equal([], a)
243  end
244
245  def test_begin_end
246    assert_equal(0, (0..1).begin)
247    assert_equal(1, (0..1).end)
248  end
249
250  def test_first_last
251    assert_equal([0, 1, 2], (0..10).first(3))
252    assert_equal([8, 9, 10], (0..10).last(3))
253  end
254
255  def test_to_s
256    assert_equal("0..1", (0..1).to_s)
257    assert_equal("0...1", (0...1).to_s)
258  end
259
260  def test_inspect
261    assert_equal("0..1", (0..1).inspect)
262    assert_equal("0...1", (0...1).inspect)
263  end
264
265  def test_eqq
266    assert((0..10) === 5)
267    assert(!((0..10) === 11))
268  end
269
270  def test_include
271    assert(("a".."z").include?("c"))
272    assert(!(("a".."z").include?("5")))
273    assert(("a"..."z").include?("y"))
274    assert(!(("a"..."z").include?("z")))
275    assert(!(("a".."z").include?("cc")))
276    assert((0...10).include?(5))
277  end
278
279  def test_cover
280    assert(("a".."z").cover?("c"))
281    assert(!(("a".."z").cover?("5")))
282    assert(("a"..."z").cover?("y"))
283    assert(!(("a"..."z").cover?("z")))
284    assert(("a".."z").cover?("cc"))
285  end
286
287  def test_beg_len
288    o = Object.new
289    assert_raise(TypeError) { [][o] }
290    class << o; attr_accessor :begin end
291    o.begin = -10
292    assert_raise(TypeError) { [][o] }
293    class << o; attr_accessor :end end
294    o.end = 0
295    assert_raise(NoMethodError) { [][o] }
296    def o.exclude_end=(v) @exclude_end = v end
297    def o.exclude_end?() @exclude_end end
298    o.exclude_end = false
299    assert_nil([0][o])
300    assert_raise(RangeError) { [0][o] = 1 }
301    o.begin = 10
302    o.end = 10
303    assert_nil([0][o])
304    o.begin = 0
305    assert_equal([0], [0][o])
306    o.begin = 2
307    o.end = 0
308    assert_equal([], [0, 1, 2][o])
309  end
310
311  class CyclicRange < Range
312    def <=>(other); true; end
313  end
314  def test_cyclic_range_inspect
315    o = CyclicRange.allocate
316    o.instance_eval { initialize(o, 1) }
317    assert_equal("(... .. ...)..1", o.inspect)
318  end
319
320  def test_comparison_when_recursive
321    x = CyclicRange.allocate; x.send(:initialize, x, 1)
322    y = CyclicRange.allocate; y.send(:initialize, y, 1)
323    Timeout.timeout(1) {
324      assert x == y
325      assert x.eql? y
326    }
327
328    z = CyclicRange.allocate; z.send(:initialize, z, :another)
329    Timeout.timeout(1) {
330      assert x != z
331      assert !x.eql?(z)
332    }
333
334    x = CyclicRange.allocate
335    y = CyclicRange.allocate
336    x.send(:initialize, y, 1)
337    y.send(:initialize, x, 1)
338    Timeout.timeout(1) {
339      assert x == y
340      assert x.eql?(y)
341    }
342
343    x = CyclicRange.allocate
344    z = CyclicRange.allocate
345    x.send(:initialize, z, 1)
346    z.send(:initialize, x, :other)
347    Timeout.timeout(1) {
348      assert x != z
349      assert !x.eql?(z)
350    }
351  end
352
353  def test_size
354    assert_equal 42, (1..42).size
355    assert_equal 41, (1...42).size
356    assert_equal 6, (1...6.3).size
357    assert_equal 5, (1.1...6).size
358    assert_equal 42, (1..42).each.size
359  end
360
361  def test_bsearch_typechecks_return_values
362    assert_raise(TypeError) do
363      (1..42).bsearch{ "not ok" }
364    end
365    assert_equal (1..42).bsearch{}, (1..42).bsearch{false}
366  end
367
368  def test_bsearch_with_no_block
369    enum = (42...666).bsearch
370    assert_nil enum.size
371    assert_equal 200, enum.each{|x| x >= 200 }
372  end
373
374  def test_bsearch_for_other_numerics
375    assert_raise(TypeError) {
376      (Rational(-1,2)..Rational(9,4)).bsearch
377    }
378    assert_raise(TypeError) {
379      (BigDecimal('0.5')..BigDecimal('2.25')).bsearch
380    }
381  end
382
383  def test_bsearch_for_fixnum
384    ary = [3, 4, 7, 9, 12]
385    assert_equal(0, (0...ary.size).bsearch {|i| ary[i] >= 2 })
386    assert_equal(1, (0...ary.size).bsearch {|i| ary[i] >= 4 })
387    assert_equal(2, (0...ary.size).bsearch {|i| ary[i] >= 6 })
388    assert_equal(3, (0...ary.size).bsearch {|i| ary[i] >= 8 })
389    assert_equal(4, (0...ary.size).bsearch {|i| ary[i] >= 10 })
390    assert_equal(nil, (0...ary.size).bsearch {|i| ary[i] >= 100 })
391    assert_equal(0, (0...ary.size).bsearch {|i| true })
392    assert_equal(nil, (0...ary.size).bsearch {|i| false })
393
394    ary = [0, 100, 100, 100, 200]
395    assert_equal(1, (0...ary.size).bsearch {|i| ary[i] >= 100 })
396  end
397
398  def test_bsearch_for_float
399    inf = Float::INFINITY
400    assert_in_delta(10.0, (0.0...100.0).bsearch {|x| x > 0 && Math.log(x / 10) >= 0 }, 0.0001)
401    assert_in_delta(10.0, (0.0...inf).bsearch {|x| x > 0 && Math.log(x / 10) >= 0 }, 0.0001)
402    assert_in_delta(-10.0, (-inf..100.0).bsearch {|x| x >= 0 || Math.log(-x / 10) < 0 }, 0.0001)
403    assert_in_delta(10.0, (-inf..inf).bsearch {|x| x > 0 && Math.log(x / 10) >= 0 }, 0.0001)
404    assert_equal(nil, (-inf..5).bsearch {|x| x > 0 && Math.log(x / 10) >= 0 }, 0.0001)
405
406    assert_in_delta(10.0, (-inf.. 10).bsearch {|x| x > 0 && Math.log(x / 10) >= 0 }, 0.0001)
407    assert_equal(nil,     (-inf...10).bsearch {|x| x > 0 && Math.log(x / 10) >= 0 }, 0.0001)
408
409    assert_equal(nil, (-inf..inf).bsearch { false })
410    assert_equal(-inf, (-inf..inf).bsearch { true })
411
412    assert_equal(inf, (0..inf).bsearch {|x| x == inf })
413    assert_equal(nil, (0...inf).bsearch {|x| x == inf })
414
415    v = (-inf..0).bsearch {|x| x != -inf }
416    assert_operator(-Float::MAX, :>=, v)
417    assert_operator(-inf, :<, v)
418
419    v = (0.0..1.0).bsearch {|x| x > 0 } # the nearest positive value to 0.0
420    assert_in_delta(0, v, 0.0001)
421    assert_operator(0, :<, v)
422    assert_equal(0.0, (-1.0..0.0).bsearch {|x| x >= 0 })
423    assert_equal(nil, (-1.0...0.0).bsearch {|x| x >= 0 })
424
425    v = (0..Float::MAX).bsearch {|x| x >= Float::MAX }
426    assert_in_delta(Float::MAX, v)
427    assert_equal(nil, v.infinite?)
428
429    v = (0..inf).bsearch {|x| x >= Float::MAX }
430    assert_in_delta(Float::MAX, v)
431    assert_equal(nil, v.infinite?)
432
433    v = (-Float::MAX..0).bsearch {|x| x > -Float::MAX }
434    assert_operator(-Float::MAX, :<, v)
435    assert_equal(nil, v.infinite?)
436
437    v = (-inf..0).bsearch {|x| x >= -Float::MAX }
438    assert_in_delta(-Float::MAX, v)
439    assert_equal(nil, v.infinite?)
440
441    v = (-inf..0).bsearch {|x| x > -Float::MAX }
442    assert_operator(-Float::MAX, :<, v)
443    assert_equal(nil, v.infinite?)
444
445    assert_in_delta(1.0, (0.0..inf).bsearch {|x| Math.log(x) >= 0 })
446    assert_in_delta(7.0, (0.0..10).bsearch {|x| 7.0 - x })
447  end
448
449  def check_bsearch_values(range, search)
450    from, to = range.begin, range.end
451    cmp = range.exclude_end? ? :< : :<=
452
453    # (0) trivial test
454    r = Range.new(to, from, range.exclude_end?).bsearch do |x|
455      fail "#{to}, #{from}, #{range.exclude_end?}, #{x}"
456    end
457    assert_equal nil, r
458
459    r = (to...to).bsearch do
460      fail
461    end
462    assert_equal nil, r
463
464    # prepare for others
465    yielded = []
466    r = range.bsearch do |val|
467      yielded << val
468      val >= search
469    end
470
471    # (1) log test
472    max = case from
473          when Float then 65
474          when Integer then Math.log(to-from+(range.exclude_end? ? 0 : 1), 2).to_i + 1
475          end
476    assert yielded.size <= max
477
478    # (2) coverage test
479    expect =  if search < from
480                from
481              elsif search.send(cmp, to)
482                search
483              else
484                nil
485              end
486    assert_equal expect, r
487
488    # (3) uniqueness test
489    assert_equal nil, yielded.uniq!
490
491    # (4) end of range test
492    case
493    when range.exclude_end?
494      assert !yielded.include?(to)
495      assert r != to
496    when search >= to
497      assert yielded.include?(to)
498      assert_equal search == to ? to : nil, r
499    end
500
501    # start of range test
502    if search <= from
503      assert yielded.include?(from)
504      assert_equal from, r
505    end
506
507    # (5) out of range test
508    yielded.each do |val|
509      assert from <= val && val.send(cmp, to)
510    end
511  end
512
513  def test_range_bsearch_for_floats
514    ints   = [-1 << 100, -123456789, -42, -1, 0, 1, 42, 123456789, 1 << 100]
515    floats = [-Float::INFINITY, -Float::MAX, -42.0, -4.2, -Float::EPSILON, -Float::MIN, 0.0, Float::MIN, Float::EPSILON, Math::PI, 4.2, 42.0, Float::MAX, Float::INFINITY]
516
517    [ints, floats].each do |values|
518      values.combination(2).to_a.product(values).each do |(from, to), search|
519        check_bsearch_values(from..to, search)
520        check_bsearch_values(from...to, search)
521      end
522    end
523  end
524
525  def test_bsearch_for_bignum
526    bignum = 2**100
527    ary = [3, 4, 7, 9, 12]
528    assert_equal(bignum + 0, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 2 })
529    assert_equal(bignum + 1, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 4 })
530    assert_equal(bignum + 2, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 6 })
531    assert_equal(bignum + 3, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 8 })
532    assert_equal(bignum + 4, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 10 })
533    assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 100 })
534    assert_equal(bignum + 0, (bignum...bignum+ary.size).bsearch {|i| true })
535    assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| false })
536
537    assert_raise(TypeError) { ("a".."z").bsearch {} }
538  end
539
540  def test_bsearch_with_mathn
541    assert_separately ['-r', 'mathn'], %q{
542      msg = '[ruby-core:25740]'
543      answer = (1..(1 << 100)).bsearch{|x|
544        assert_predicate(x, :integer?, msg)
545        x >= 42
546      }
547      assert_equal(42, answer, msg)
548    }
549  end
550end
551