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