New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Range#eql? checks that start and end of range are same using MethodNames.EQL #3960

Closed
wants to merge 9 commits into
base: master
from

Conversation

Projects
None yet
4 participants
@monkstone
Contributor

monkstone commented Jun 9, 2016

Just be clear checks start of one range is same numeric type as start of second and end of one range is same numeric type as end of second.

@enebo

This comment has been minimized.

Show comment
Hide comment
@enebo

enebo Jun 9, 2016

Member

@monkstone @kares You have fixed the compat in this case but you could go a little further. I see in MRI that it dispatches to begin.eql?(other.begin) + same for end. In theory, definiing a new eql? on an arbrtrary type (for begin or end) could still work whereas this PR will assume it has to be a builtin numeric type.

Since these are new checks and we were not checking at all this PR could break existing code.

Member

enebo commented Jun 9, 2016

@monkstone @kares You have fixed the compat in this case but you could go a little further. I see in MRI that it dispatches to begin.eql?(other.begin) + same for end. In theory, definiing a new eql? on an arbrtrary type (for begin or end) could still work whereas this PR will assume it has to be a builtin numeric type.

Since these are new checks and we were not checking at all this PR could break existing code.

@monkstone

This comment has been minimized.

Show comment
Hide comment
@monkstone

monkstone Jun 9, 2016

Contributor

I had kind of assumed that it is numeric equalInternal that is anomalous, and that's why I came up with this PR, all falls through to original logic unless there is an obvious mismatch in the numeric type. I don't think I'm up to the job if it goes deeper than that.

Contributor

monkstone commented Jun 9, 2016

I had kind of assumed that it is numeric equalInternal that is anomalous, and that's why I came up with this PR, all falls through to original logic unless there is an obvious mismatch in the numeric type. I don't think I'm up to the job if it goes deeper than that.

@monkstone

This comment has been minimized.

Show comment
Hide comment
@monkstone

monkstone Jun 10, 2016

Contributor

@enebo you are right of course just check this out:-

class Xs                # represent a string of 'x's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'x' * @length
  end
end

class Ys                # represent a string of 'y's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Ys.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'y' * @length
  end
end

fred = (Xs.new(3)..Xs.new(5))

ted = (Ys.new(3)..Ys.new(5))

puts fred.eql?(ted)

yields false MRI ruby true jruby http://ruby-doc.org/core-2.2.0/Range.html I'll happily close this PR and suggest @kares removes beginner tag

Contributor

monkstone commented Jun 10, 2016

@enebo you are right of course just check this out:-

class Xs                # represent a string of 'x's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'x' * @length
  end
end

class Ys                # represent a string of 'y's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Ys.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'y' * @length
  end
end

fred = (Xs.new(3)..Xs.new(5))

ted = (Ys.new(3)..Ys.new(5))

puts fred.eql?(ted)

yields false MRI ruby true jruby http://ruby-doc.org/core-2.2.0/Range.html I'll happily close this PR and suggest @kares removes beginner tag

@enebo

This comment has been minimized.

Show comment
Hide comment
@enebo

enebo Jun 10, 2016

Member

@monkstone if there is not a test for this in ruby/spec then maybe you could pr spec for this.

Also really all you need to do is something like:

invokedynamic(context, begin, MethodNames.OP_EQL, other.begin).isTrue()

So you could still take a quick stab at convering the instanceof stuff to that?

Member

enebo commented Jun 10, 2016

@monkstone if there is not a test for this in ruby/spec then maybe you could pr spec for this.

Also really all you need to do is something like:

invokedynamic(context, begin, MethodNames.OP_EQL, other.begin).isTrue()

So you could still take a quick stab at convering the instanceof stuff to that?

@monkstone

This comment has been minimized.

Show comment
Hide comment
@monkstone

monkstone Jun 10, 2016

Contributor
# frozen_string_literal: false
gem 'minitest' # don't use bundled minitest
require 'delegate'
require 'timeout'
require 'bigdecimal'
require 'minitest/autorun'
require 'minitest/pride'

# Custom Range classes Xs and Ys
class Xs # represent a string of 'x's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'x' * @length
  end
end

class Ys # represent a string of 'y's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Ys.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'y' * @length
  end
end

class TestRange < Minitest::Test
  def test_new
    assert_equal((0..2), Range.new(0, 2))
    assert_equal((0..2), Range.new(0, 2, false))
    assert_equal((0...2), Range.new(0, 2, true))
  end

  def test_range_string
    # XXX: Is this really the test of Range?
    assert_equal([], ("a" ... "a").to_a)
    assert_equal(["a"], ("a" .. "a").to_a)
    assert_equal(["a"], ("a" ... "b").to_a)
    assert_equal(["a", "b"], ("a" .. "b").to_a)
  end

  def test_range_numeric_string
    assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]")
    assert_equal(["6", "7"], ("6"..."8").to_a)
    assert_equal(["9", "10"], ("9".."10").to_a)
    assert_equal(["09", "10"], ("09".."10").to_a, "[ruby-dev:39361]")
    assert_equal(["9", "10"], (SimpleDelegator.new("9").."10").to_a)
    assert_equal(["9", "10"], ("9"..SimpleDelegator.new("10")).to_a)
  end

  def test_range_symbol
    assert_equal([:a, :b], (:a .. :b).to_a)
  end

  def test_evaluation_order
    arr = [1,2]
    r = (arr.shift)..(arr.shift)
    assert_equal(1..2, r, "[ruby-dev:26383]")
  end

  class DuckRange
    def initialize(b,e,excl=false)
      @begin = b
      @end = e
      @excl = excl
    end
    attr_reader :begin, :end

    def exclude_end?
      @excl
    end
  end

  def test_duckrange
    assert_equal("bc", "abcd"[DuckRange.new(1,2)])
  end

  def test_min
    assert_equal(1, (1..2).min)
    assert_equal(nil, (2..1).min)
    assert_equal(1, (1...2).min)

    assert_equal(1.0, (1.0..2.0).min)
    assert_equal(nil, (2.0..1.0).min)
    assert_equal(1, (1.0...2.0).min)

    assert_equal(0, (0..0).min)
    assert_equal(nil, (0...0).min)

    assert_equal([0,1,2], (0..10).min(3))
    assert_equal([0,1], (0..1).min(3))
  end

  def test_max
    assert_equal(2, (1..2).max)
    assert_equal(nil, (2..1).max)
    assert_equal(1, (1...2).max)

    assert_equal(2.0, (1.0..2.0).max)
    assert_equal(nil, (2.0..1.0).max)
    assert_raises(TypeError) { (1.0...2.0).max }
    assert_raises(TypeError) { (1...1.5).max }
    assert_raises(TypeError) { (1.5...2).max }

    assert_equal(-0x80000002, ((-0x80000002)...(-0x80000001)).max)

    assert_equal(0, (0..0).max)
    assert_equal(nil, (0...0).max)

    assert_equal([10,9,8], (0..10).max(3))
    assert_equal([9,8,7], (0...10).max(3))
  end

  def test_initialize_twice
    r = eval("1..2")
    assert_raises(NameError) { r.instance_eval { initialize 3, 4 } }
    assert_raises(NameError) { r.instance_eval { initialize_copy 3..4 } }
  end

  def test_uninitialized_range
    r = Range.allocate
    s = Marshal.dump(r)
    r = Marshal.load(s)
    assert_silent { r.instance_eval { initialize 5, 6} }
  end

  def test_bad_value
    assert_raises(ArgumentError) { (1 .. :a) }
  end

  def test_exclude_end
    refute_predicate(0..1, :exclude_end?)
    assert_predicate(0...1, :exclude_end?)
  end

  def test_eq
    r = (0..1)
    assert_equal(r, r)
    assert_equal(r, (0..1))
    refute_equal(r, 0)
    refute_equal(r, (1..2))
    refute_equal(r, (0..2))
    refute_equal(r, (0...1))
    subclass = Class.new(Range)
    assert_equal(r, subclass.new(0,1))
  end

  def test_eql
    r = (0..1)
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, 0..1)
    refute_operator(r, :eql?, 0..1.0)
    refute_operator(r, :eql?, 0)
    refute_operator(r, :eql?, 1..2)
    refute_operator(r, :eql?, 0..2)
    refute_operator(r, :eql?, 0...1)
    subclass = Class.new(Range)
    assert_operator(r, :eql?, subclass.new(0,1))
  end

  def test_custom_range_eql
    r = (Xs.new(3)..Xs.new(5))
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, (Xs.new(3)..Xs.new(5)))
    refute_operator(r, :eql?, (Ys.new(3)..Ys.new(5)))
    assert_operator(r, :eql?, subclass.new(Xs.new(3), Xs.new(5)))
  end

  def test_hash
    assert_kind_of(Fixnum, (0..1).hash)
    assert_equal((0..1).hash, (0..1).hash)
    refute_equal((0..1).hash, (0...1).hash)
  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)

    a = []
    (0..10).step(2) {|x| a << x }
    assert_equal([0, 2, 4, 6, 8, 10], a)

    assert_raises(ArgumentError) { (0..10).step(-1) { } }
    assert_raises(ArgumentError) { (0..10).step(0) { } }

    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)

    a = []
    ("a" .. "z").step(2**32) {|x| a << x }
    assert_equal(["a"], a)

    a = []
    (2**32-1 .. 2**32+1).step(2) {|x| a << x }
    assert_equal([4294967295, 4294967297], a)
    zero = (2**32).coerce(0).first
    assert_raises(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }

    o1 = Object.new
    o2 = Object.new
    def o1.<=>(x); -1; end
    def o2.<=>(x); 0; end
    assert_raises(TypeError) { (o1..o2).step(1) { } }

    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end
    a = []
    (o1..o2).step(1) {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    (o1...o2).step(1) {|x| a << x }
    assert_equal([o1], a)

    assert_silent { (0..2).step(0.5) {|x| } } # ("[ruby-dev:34557]")

    a = []
    (0..2).step(0.5) {|x| a << x }
    assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)

    a = []
    (0x40000000..0x40000002).step(0.5) {|x| a << x }
    assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)

    o = Object.new
    def o.to_int() 1 end
    assert_silent { (0..2).step(o) {|x| } } # ("[ruby-dev:34558]")
  end

  def test_step_ruby_core_35753
    assert_equal(6, (1...6.3).step.to_a.size)
    assert_equal(5, (1.1...6).step.to_a.size)
    assert_equal(5, (1...6).step(1.1).to_a.size)
    assert_equal(3, (1.0...5.4).step(1.5).to_a.size)
    assert_equal(3, (1.0...5.5).step(1.5).to_a.size)
    assert_equal(4, (1.0...5.6).step(1.5).to_a.size)
  end

  def test_each
    a = []
    (0..10).each {|x| a << x }
    assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)

    o1 = Object.new
    o2 = Object.new
    def o1.setcmp(v) @cmpresult = v end
    o1.setcmp(-1)
    def o1.<=>(x); @cmpresult; end
    def o2.setcmp(v) @cmpresult = v end
    o2.setcmp(0)
    def o2.<=>(x); @cmpresult; end
    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end

    r1 = (o1..o2)
    r2 = (o1...o2)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    r2.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(1)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(nil)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o1.setcmp(nil)

    a = []
    r2.each {|x| a << x }
    assert_equal([], a)
  end

  def test_begin_end
    assert_equal(0, (0..1).begin)
    assert_equal(1, (0..1).end)
    assert_equal(1, (0...1).end)
  end

  def test_first_last
    assert_equal([0, 1, 2], (0..10).first(3))
    assert_equal([8, 9, 10], (0..10).last(3))
    assert_equal(0, (0..10).first)
    assert_equal(10, (0..10).last)
    assert_equal("a", ("a".."c").first)
    assert_equal("c", ("a".."c").last)
    assert_equal(0, (2..0).last)

    assert_equal([0, 1, 2], (0...10).first(3))
    assert_equal([7, 8, 9], (0...10).last(3))
    assert_equal(0, (0...10).first)
    assert_equal(10, (0...10).last)
    assert_equal("a", ("a"..."c").first)
    assert_equal("c", ("a"..."c").last)
    assert_equal(0, (2...0).last)
  end

  def test_to_s
    assert_equal("0..1", (0..1).to_s)
    assert_equal("0...1", (0...1).to_s)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").to_s, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).to_s, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.to_s, :tainted?, bug11767)
  end

  def test_inspect
    assert_equal("0..1", (0..1).inspect)
    assert_equal("0...1", (0...1).inspect)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").inspect, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).inspect, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.inspect, :tainted?, bug11767)
  end

  def test_eqq
    assert_operator(0..10, :===, 5)
    refute_operator(0..10, :===, 11)
  end

  def test_eqq_time
    skip "TypeError: can't iterate from Time jruby"
    bug11113 = '[ruby-core:69052] [Bug #11113]'
    t = Time.now
    assert_silent {
    assert_operator(t..(t + 10), :===, t + 5)
    }
  end

  def test_include
    assert_includes("a".."z", "c")
    refute_includes("a".."z", "5")
    assert_includes("a"..."z", "y")
    refute_includes("a"..."z", "z")
    refute_includes("a".."z", "cc")
    assert_includes(0...10, 5)
  end

  def test_cover
    assert_operator("a".."z", :cover?, "c")
    refute_operator("a".."z", :cover?, "5")
    assert_operator("a"..."z", :cover?, "y")
    refute_operator("a"..."z", :cover?, "z")
    assert_operator("a".."z", :cover?, "cc")
  end

  def test_beg_len
    o = Object.new
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :begin end
    o.begin = -10
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :end end
    o.end = 0
    assert_raises(NoMethodError) { [][o] }
    def o.exclude_end=(v) @exclude_end = v end
    def o.exclude_end?() @exclude_end end
    o.exclude_end = false
    assert_nil([0][o])
    assert_raises(RangeError) { [0][o] = 1 }
    o.begin = 10
    o.end = 10
    assert_nil([0][o])
    o.begin = 0
    assert_equal([0], [0][o])
    o.begin = 2
    o.end = 0
    assert_equal([], [0, 1, 2][o])
  end
end

The modified jruby fails above test same as MRI ruby with custom test
Expected xxx..xxxxx to be eql? xxx..xxxxx so may'be we are now OK!!!

@kares @enebo
Will attempt to translate to Test/Unit

Contributor

monkstone commented Jun 10, 2016

# frozen_string_literal: false
gem 'minitest' # don't use bundled minitest
require 'delegate'
require 'timeout'
require 'bigdecimal'
require 'minitest/autorun'
require 'minitest/pride'

# Custom Range classes Xs and Ys
class Xs # represent a string of 'x's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Xs.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'x' * @length
  end
end

class Ys # represent a string of 'y's
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def succ
    Ys.new(@length + 1)
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
  def inspect
    'y' * @length
  end
end

class TestRange < Minitest::Test
  def test_new
    assert_equal((0..2), Range.new(0, 2))
    assert_equal((0..2), Range.new(0, 2, false))
    assert_equal((0...2), Range.new(0, 2, true))
  end

  def test_range_string
    # XXX: Is this really the test of Range?
    assert_equal([], ("a" ... "a").to_a)
    assert_equal(["a"], ("a" .. "a").to_a)
    assert_equal(["a"], ("a" ... "b").to_a)
    assert_equal(["a", "b"], ("a" .. "b").to_a)
  end

  def test_range_numeric_string
    assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]")
    assert_equal(["6", "7"], ("6"..."8").to_a)
    assert_equal(["9", "10"], ("9".."10").to_a)
    assert_equal(["09", "10"], ("09".."10").to_a, "[ruby-dev:39361]")
    assert_equal(["9", "10"], (SimpleDelegator.new("9").."10").to_a)
    assert_equal(["9", "10"], ("9"..SimpleDelegator.new("10")).to_a)
  end

  def test_range_symbol
    assert_equal([:a, :b], (:a .. :b).to_a)
  end

  def test_evaluation_order
    arr = [1,2]
    r = (arr.shift)..(arr.shift)
    assert_equal(1..2, r, "[ruby-dev:26383]")
  end

  class DuckRange
    def initialize(b,e,excl=false)
      @begin = b
      @end = e
      @excl = excl
    end
    attr_reader :begin, :end

    def exclude_end?
      @excl
    end
  end

  def test_duckrange
    assert_equal("bc", "abcd"[DuckRange.new(1,2)])
  end

  def test_min
    assert_equal(1, (1..2).min)
    assert_equal(nil, (2..1).min)
    assert_equal(1, (1...2).min)

    assert_equal(1.0, (1.0..2.0).min)
    assert_equal(nil, (2.0..1.0).min)
    assert_equal(1, (1.0...2.0).min)

    assert_equal(0, (0..0).min)
    assert_equal(nil, (0...0).min)

    assert_equal([0,1,2], (0..10).min(3))
    assert_equal([0,1], (0..1).min(3))
  end

  def test_max
    assert_equal(2, (1..2).max)
    assert_equal(nil, (2..1).max)
    assert_equal(1, (1...2).max)

    assert_equal(2.0, (1.0..2.0).max)
    assert_equal(nil, (2.0..1.0).max)
    assert_raises(TypeError) { (1.0...2.0).max }
    assert_raises(TypeError) { (1...1.5).max }
    assert_raises(TypeError) { (1.5...2).max }

    assert_equal(-0x80000002, ((-0x80000002)...(-0x80000001)).max)

    assert_equal(0, (0..0).max)
    assert_equal(nil, (0...0).max)

    assert_equal([10,9,8], (0..10).max(3))
    assert_equal([9,8,7], (0...10).max(3))
  end

  def test_initialize_twice
    r = eval("1..2")
    assert_raises(NameError) { r.instance_eval { initialize 3, 4 } }
    assert_raises(NameError) { r.instance_eval { initialize_copy 3..4 } }
  end

  def test_uninitialized_range
    r = Range.allocate
    s = Marshal.dump(r)
    r = Marshal.load(s)
    assert_silent { r.instance_eval { initialize 5, 6} }
  end

  def test_bad_value
    assert_raises(ArgumentError) { (1 .. :a) }
  end

  def test_exclude_end
    refute_predicate(0..1, :exclude_end?)
    assert_predicate(0...1, :exclude_end?)
  end

  def test_eq
    r = (0..1)
    assert_equal(r, r)
    assert_equal(r, (0..1))
    refute_equal(r, 0)
    refute_equal(r, (1..2))
    refute_equal(r, (0..2))
    refute_equal(r, (0...1))
    subclass = Class.new(Range)
    assert_equal(r, subclass.new(0,1))
  end

  def test_eql
    r = (0..1)
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, 0..1)
    refute_operator(r, :eql?, 0..1.0)
    refute_operator(r, :eql?, 0)
    refute_operator(r, :eql?, 1..2)
    refute_operator(r, :eql?, 0..2)
    refute_operator(r, :eql?, 0...1)
    subclass = Class.new(Range)
    assert_operator(r, :eql?, subclass.new(0,1))
  end

  def test_custom_range_eql
    r = (Xs.new(3)..Xs.new(5))
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, (Xs.new(3)..Xs.new(5)))
    refute_operator(r, :eql?, (Ys.new(3)..Ys.new(5)))
    assert_operator(r, :eql?, subclass.new(Xs.new(3), Xs.new(5)))
  end

  def test_hash
    assert_kind_of(Fixnum, (0..1).hash)
    assert_equal((0..1).hash, (0..1).hash)
    refute_equal((0..1).hash, (0...1).hash)
  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)

    a = []
    (0..10).step(2) {|x| a << x }
    assert_equal([0, 2, 4, 6, 8, 10], a)

    assert_raises(ArgumentError) { (0..10).step(-1) { } }
    assert_raises(ArgumentError) { (0..10).step(0) { } }

    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)

    a = []
    ("a" .. "z").step(2**32) {|x| a << x }
    assert_equal(["a"], a)

    a = []
    (2**32-1 .. 2**32+1).step(2) {|x| a << x }
    assert_equal([4294967295, 4294967297], a)
    zero = (2**32).coerce(0).first
    assert_raises(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }

    o1 = Object.new
    o2 = Object.new
    def o1.<=>(x); -1; end
    def o2.<=>(x); 0; end
    assert_raises(TypeError) { (o1..o2).step(1) { } }

    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end
    a = []
    (o1..o2).step(1) {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    (o1...o2).step(1) {|x| a << x }
    assert_equal([o1], a)

    assert_silent { (0..2).step(0.5) {|x| } } # ("[ruby-dev:34557]")

    a = []
    (0..2).step(0.5) {|x| a << x }
    assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)

    a = []
    (0x40000000..0x40000002).step(0.5) {|x| a << x }
    assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)

    o = Object.new
    def o.to_int() 1 end
    assert_silent { (0..2).step(o) {|x| } } # ("[ruby-dev:34558]")
  end

  def test_step_ruby_core_35753
    assert_equal(6, (1...6.3).step.to_a.size)
    assert_equal(5, (1.1...6).step.to_a.size)
    assert_equal(5, (1...6).step(1.1).to_a.size)
    assert_equal(3, (1.0...5.4).step(1.5).to_a.size)
    assert_equal(3, (1.0...5.5).step(1.5).to_a.size)
    assert_equal(4, (1.0...5.6).step(1.5).to_a.size)
  end

  def test_each
    a = []
    (0..10).each {|x| a << x }
    assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)

    o1 = Object.new
    o2 = Object.new
    def o1.setcmp(v) @cmpresult = v end
    o1.setcmp(-1)
    def o1.<=>(x); @cmpresult; end
    def o2.setcmp(v) @cmpresult = v end
    o2.setcmp(0)
    def o2.<=>(x); @cmpresult; end
    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end

    r1 = (o1..o2)
    r2 = (o1...o2)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    r2.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(1)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(nil)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o1.setcmp(nil)

    a = []
    r2.each {|x| a << x }
    assert_equal([], a)
  end

  def test_begin_end
    assert_equal(0, (0..1).begin)
    assert_equal(1, (0..1).end)
    assert_equal(1, (0...1).end)
  end

  def test_first_last
    assert_equal([0, 1, 2], (0..10).first(3))
    assert_equal([8, 9, 10], (0..10).last(3))
    assert_equal(0, (0..10).first)
    assert_equal(10, (0..10).last)
    assert_equal("a", ("a".."c").first)
    assert_equal("c", ("a".."c").last)
    assert_equal(0, (2..0).last)

    assert_equal([0, 1, 2], (0...10).first(3))
    assert_equal([7, 8, 9], (0...10).last(3))
    assert_equal(0, (0...10).first)
    assert_equal(10, (0...10).last)
    assert_equal("a", ("a"..."c").first)
    assert_equal("c", ("a"..."c").last)
    assert_equal(0, (2...0).last)
  end

  def test_to_s
    assert_equal("0..1", (0..1).to_s)
    assert_equal("0...1", (0...1).to_s)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").to_s, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).to_s, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.to_s, :tainted?, bug11767)
  end

  def test_inspect
    assert_equal("0..1", (0..1).inspect)
    assert_equal("0...1", (0...1).inspect)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").inspect, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).inspect, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.inspect, :tainted?, bug11767)
  end

  def test_eqq
    assert_operator(0..10, :===, 5)
    refute_operator(0..10, :===, 11)
  end

  def test_eqq_time
    skip "TypeError: can't iterate from Time jruby"
    bug11113 = '[ruby-core:69052] [Bug #11113]'
    t = Time.now
    assert_silent {
    assert_operator(t..(t + 10), :===, t + 5)
    }
  end

  def test_include
    assert_includes("a".."z", "c")
    refute_includes("a".."z", "5")
    assert_includes("a"..."z", "y")
    refute_includes("a"..."z", "z")
    refute_includes("a".."z", "cc")
    assert_includes(0...10, 5)
  end

  def test_cover
    assert_operator("a".."z", :cover?, "c")
    refute_operator("a".."z", :cover?, "5")
    assert_operator("a"..."z", :cover?, "y")
    refute_operator("a"..."z", :cover?, "z")
    assert_operator("a".."z", :cover?, "cc")
  end

  def test_beg_len
    o = Object.new
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :begin end
    o.begin = -10
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :end end
    o.end = 0
    assert_raises(NoMethodError) { [][o] }
    def o.exclude_end=(v) @exclude_end = v end
    def o.exclude_end?() @exclude_end end
    o.exclude_end = false
    assert_nil([0][o])
    assert_raises(RangeError) { [0][o] = 1 }
    o.begin = 10
    o.end = 10
    assert_nil([0][o])
    o.begin = 0
    assert_equal([0], [0][o])
    o.begin = 2
    o.end = 0
    assert_equal([], [0, 1, 2][o])
  end
end

The modified jruby fails above test same as MRI ruby with custom test
Expected xxx..xxxxx to be eql? xxx..xxxxx so may'be we are now OK!!!

@kares @enebo
Will attempt to translate to Test/Unit

@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Jun 11, 2016

Member

👍 najs ... btw. test-unit 3.x JRuby's using should have most of the minitest asserts, if smt's missing idd should be fairly simple to add it into test_helper.rb ... so that you do not have to convert stuff over.

Member

kares commented Jun 11, 2016

👍 najs ... btw. test-unit 3.x JRuby's using should have most of the minitest asserts, if smt's missing idd should be fairly simple to add it into test_helper.rb ... so that you do not have to convert stuff over.

@monkstone

This comment has been minimized.

Show comment
Hide comment
@monkstone

monkstone Jun 11, 2016

Contributor
# frozen_string_literal: false
gem 'minitest' # don't use bundled minitest
require 'delegate'
require 'timeout'
require 'bigdecimal'
require 'minitest/autorun'
require 'minitest/pride'

# Custom Range classes Xs and Ys
class Custom 
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def eql?(other)
    inspect.eql? other.inspect
  end
  def inspect
    'custom'
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
end

class Xs < Custom # represent a string of 'x's
  def succ
    Xs.new(@length + 1)
  end
  def inspect
    'x' * @length
  end
end

class Ys < Custom # represent a string of 'y's
  def succ
    Ys.new(@length + 1)
  end
  def inspect
    'y' * @length
  end
end

class TestRange < Minitest::Test
  def test_new
    assert_equal((0..2), Range.new(0, 2))
    assert_equal((0..2), Range.new(0, 2, false))
    assert_equal((0...2), Range.new(0, 2, true))
  end

  def test_range_string
    # XXX: Is this really the test of Range?
    assert_equal([], ("a" ... "a").to_a)
    assert_equal(["a"], ("a" .. "a").to_a)
    assert_equal(["a"], ("a" ... "b").to_a)
    assert_equal(["a", "b"], ("a" .. "b").to_a)
  end

  def test_range_numeric_string
    assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]")
    assert_equal(["6", "7"], ("6"..."8").to_a)
    assert_equal(["9", "10"], ("9".."10").to_a)
    assert_equal(["09", "10"], ("09".."10").to_a, "[ruby-dev:39361]")
    assert_equal(["9", "10"], (SimpleDelegator.new("9").."10").to_a)
    assert_equal(["9", "10"], ("9"..SimpleDelegator.new("10")).to_a)
  end

  def test_range_symbol
    assert_equal([:a, :b], (:a .. :b).to_a)
  end

  def test_evaluation_order
    arr = [1,2]
    r = (arr.shift)..(arr.shift)
    assert_equal(1..2, r, "[ruby-dev:26383]")
  end

  class DuckRange
    def initialize(b,e,excl=false)
      @begin = b
      @end = e
      @excl = excl
    end
    attr_reader :begin, :end

    def exclude_end?
      @excl
    end
  end

  def test_duckrange
    assert_equal("bc", "abcd"[DuckRange.new(1,2)])
  end

  def test_min
    assert_equal(1, (1..2).min)
    assert_equal(nil, (2..1).min)
    assert_equal(1, (1...2).min)

    assert_equal(1.0, (1.0..2.0).min)
    assert_equal(nil, (2.0..1.0).min)
    assert_equal(1, (1.0...2.0).min)

    assert_equal(0, (0..0).min)
    assert_equal(nil, (0...0).min)

    assert_equal([0,1,2], (0..10).min(3))
    assert_equal([0,1], (0..1).min(3))
  end

  def test_max
    assert_equal(2, (1..2).max)
    assert_equal(nil, (2..1).max)
    assert_equal(1, (1...2).max)

    assert_equal(2.0, (1.0..2.0).max)
    assert_equal(nil, (2.0..1.0).max)
    assert_raises(TypeError) { (1.0...2.0).max }
    assert_raises(TypeError) { (1...1.5).max }
    assert_raises(TypeError) { (1.5...2).max }

    assert_equal(-0x80000002, ((-0x80000002)...(-0x80000001)).max)

    assert_equal(0, (0..0).max)
    assert_equal(nil, (0...0).max)

    assert_equal([10,9,8], (0..10).max(3))
    assert_equal([9,8,7], (0...10).max(3))
  end

  def test_initialize_twice
    r = eval("1..2")
    assert_raises(NameError) { r.instance_eval { initialize 3, 4 } }
    assert_raises(NameError) { r.instance_eval { initialize_copy 3..4 } }
  end

  def test_uninitialized_range
    r = Range.allocate
    s = Marshal.dump(r)
    r = Marshal.load(s)
    assert_silent { r.instance_eval { initialize 5, 6} }
  end

  def test_bad_value
    assert_raises(ArgumentError) { (1 .. :a) }
  end

  def test_exclude_end
    refute_predicate(0..1, :exclude_end?)
    assert_predicate(0...1, :exclude_end?)
  end

  def test_eq
    r = (0..1)
    assert_equal(r, r)
    assert_equal(r, (0..1))
    refute_equal(r, 0)
    refute_equal(r, (1..2))
    refute_equal(r, (0..2))
    refute_equal(r, (0...1))
    subclass = Class.new(Range)
    assert_equal(r, subclass.new(0,1))
  end

  def test_eql
    r = (0..1)
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, 0..1)
    refute_operator(r, :eql?, 0..1.0)
    refute_operator(r, :eql?, 0)
    refute_operator(r, :eql?, 1..2)
    refute_operator(r, :eql?, 0..2)
    refute_operator(r, :eql?, 0...1)
    subclass = Class.new(Range)

    assert_operator(r, :eql?, subclass.new(0,1))
  end

  def test_custom_range_eql
    r = (Xs.new(3)..Xs.new(5))
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, (Xs.new(3)..Xs.new(5)))
    refute_operator(r, :eql?, (Ys.new(3)..Ys.new(5)))
    subclass = Class.new(Range)
    assert_equal(r, subclass.new(Xs.new(3), Xs.new(5)))    
  end

  def test_hash
    assert_kind_of(Fixnum, (0..1).hash)
    assert_equal((0..1).hash, (0..1).hash)
    refute_equal((0..1).hash, (0...1).hash)
  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)

    a = []
    (0..10).step(2) {|x| a << x }
    assert_equal([0, 2, 4, 6, 8, 10], a)

    assert_raises(ArgumentError) { (0..10).step(-1) { } }
    assert_raises(ArgumentError) { (0..10).step(0) { } }

    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)

    a = []
    ("a" .. "z").step(2**32) {|x| a << x }
    assert_equal(["a"], a)

    a = []
    (2**32-1 .. 2**32+1).step(2) {|x| a << x }
    assert_equal([4294967295, 4294967297], a)
    zero = (2**32).coerce(0).first
    assert_raises(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }

    o1 = Object.new
    o2 = Object.new
    def o1.<=>(x); -1; end
    def o2.<=>(x); 0; end
    assert_raises(TypeError) { (o1..o2).step(1) { } }

    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end
    a = []
    (o1..o2).step(1) {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    (o1...o2).step(1) {|x| a << x }
    assert_equal([o1], a)

    assert_silent { (0..2).step(0.5) {|x| } } # ("[ruby-dev:34557]")

    a = []
    (0..2).step(0.5) {|x| a << x }
    assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)

    a = []
    (0x40000000..0x40000002).step(0.5) {|x| a << x }
    assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)

    o = Object.new
    def o.to_int() 1 end
    assert_silent { (0..2).step(o) {|x| } } # ("[ruby-dev:34558]")
  end

  def test_step_ruby_core_35753
    assert_equal(6, (1...6.3).step.to_a.size)
    assert_equal(5, (1.1...6).step.to_a.size)
    assert_equal(5, (1...6).step(1.1).to_a.size)
    assert_equal(3, (1.0...5.4).step(1.5).to_a.size)
    assert_equal(3, (1.0...5.5).step(1.5).to_a.size)
    assert_equal(4, (1.0...5.6).step(1.5).to_a.size)
  end

  def test_each
    a = []
    (0..10).each {|x| a << x }
    assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)

    o1 = Object.new
    o2 = Object.new
    def o1.setcmp(v) @cmpresult = v end
    o1.setcmp(-1)
    def o1.<=>(x); @cmpresult; end
    def o2.setcmp(v) @cmpresult = v end
    o2.setcmp(0)
    def o2.<=>(x); @cmpresult; end
    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end

    r1 = (o1..o2)
    r2 = (o1...o2)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    r2.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(1)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(nil)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o1.setcmp(nil)

    a = []
    r2.each {|x| a << x }
    assert_equal([], a)
  end

  def test_begin_end
    assert_equal(0, (0..1).begin)
    assert_equal(1, (0..1).end)
    assert_equal(1, (0...1).end)
  end

  def test_first_last
    assert_equal([0, 1, 2], (0..10).first(3))
    assert_equal([8, 9, 10], (0..10).last(3))
    assert_equal(0, (0..10).first)
    assert_equal(10, (0..10).last)
    assert_equal("a", ("a".."c").first)
    assert_equal("c", ("a".."c").last)
    assert_equal(0, (2..0).last)

    assert_equal([0, 1, 2], (0...10).first(3))
    assert_equal([7, 8, 9], (0...10).last(3))
    assert_equal(0, (0...10).first)
    assert_equal(10, (0...10).last)
    assert_equal("a", ("a"..."c").first)
    assert_equal("c", ("a"..."c").last)
    assert_equal(0, (2...0).last)
  end

  def test_to_s
    assert_equal("0..1", (0..1).to_s)
    assert_equal("0...1", (0...1).to_s)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").to_s, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).to_s, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.to_s, :tainted?, bug11767)
  end

  def test_inspect
    assert_equal("0..1", (0..1).inspect)
    assert_equal("0...1", (0...1).inspect)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").inspect, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).inspect, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.inspect, :tainted?, bug11767)
  end

  def test_eqq
    assert_operator(0..10, :===, 5)
    refute_operator(0..10, :===, 11)
  end

  def test_eqq_time
    skip "TypeError: can't iterate from Time jruby"
    bug11113 = '[ruby-core:69052] [Bug #11113]'
    t = Time.now
    assert_silent {
    assert_operator(t..(t + 10), :===, t + 5)
    }
  end

  def test_include
    assert_includes("a".."z", "c")
    refute_includes("a".."z", "5")
    assert_includes("a"..."z", "y")
    refute_includes("a"..."z", "z")
    refute_includes("a".."z", "cc")
    assert_includes(0...10, 5)
  end

  def test_cover
    assert_operator("a".."z", :cover?, "c")
    refute_operator("a".."z", :cover?, "5")
    assert_operator("a"..."z", :cover?, "y")
    refute_operator("a"..."z", :cover?, "z")
    assert_operator("a".."z", :cover?, "cc")
  end

  def test_beg_len
    o = Object.new
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :begin end
    o.begin = -10
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :end end
    o.end = 0
    assert_raises(NoMethodError) { [][o] }
    def o.exclude_end=(v) @exclude_end = v end
    def o.exclude_end?() @exclude_end end
    o.exclude_end = false
    assert_nil([0][o])
    assert_raises(RangeError) { [0][o] = 1 }
    o.begin = 10
    o.end = 10
    assert_nil([0][o])
    o.begin = 0
    assert_equal([0], [0][o])
    o.begin = 2
    o.end = 0
    assert_equal([], [0, 1, 2][o])
  end
end

@kares @enebo fixed the test now passes all

Contributor

monkstone commented Jun 11, 2016

# frozen_string_literal: false
gem 'minitest' # don't use bundled minitest
require 'delegate'
require 'timeout'
require 'bigdecimal'
require 'minitest/autorun'
require 'minitest/pride'

# Custom Range classes Xs and Ys
class Custom 
  include Comparable
  attr :length
  def initialize(n)
    @length = n
  end
  def eql?(other)
    inspect.eql? other.inspect
  end
  def inspect
    'custom'
  end
  def <=>(other)
    @length <=> other.length
  end
  def to_s
    sprintf "%2d #{inspect}", @length
  end
end

class Xs < Custom # represent a string of 'x's
  def succ
    Xs.new(@length + 1)
  end
  def inspect
    'x' * @length
  end
end

class Ys < Custom # represent a string of 'y's
  def succ
    Ys.new(@length + 1)
  end
  def inspect
    'y' * @length
  end
end

class TestRange < Minitest::Test
  def test_new
    assert_equal((0..2), Range.new(0, 2))
    assert_equal((0..2), Range.new(0, 2, false))
    assert_equal((0...2), Range.new(0, 2, true))
  end

  def test_range_string
    # XXX: Is this really the test of Range?
    assert_equal([], ("a" ... "a").to_a)
    assert_equal(["a"], ("a" .. "a").to_a)
    assert_equal(["a"], ("a" ... "b").to_a)
    assert_equal(["a", "b"], ("a" .. "b").to_a)
  end

  def test_range_numeric_string
    assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]")
    assert_equal(["6", "7"], ("6"..."8").to_a)
    assert_equal(["9", "10"], ("9".."10").to_a)
    assert_equal(["09", "10"], ("09".."10").to_a, "[ruby-dev:39361]")
    assert_equal(["9", "10"], (SimpleDelegator.new("9").."10").to_a)
    assert_equal(["9", "10"], ("9"..SimpleDelegator.new("10")).to_a)
  end

  def test_range_symbol
    assert_equal([:a, :b], (:a .. :b).to_a)
  end

  def test_evaluation_order
    arr = [1,2]
    r = (arr.shift)..(arr.shift)
    assert_equal(1..2, r, "[ruby-dev:26383]")
  end

  class DuckRange
    def initialize(b,e,excl=false)
      @begin = b
      @end = e
      @excl = excl
    end
    attr_reader :begin, :end

    def exclude_end?
      @excl
    end
  end

  def test_duckrange
    assert_equal("bc", "abcd"[DuckRange.new(1,2)])
  end

  def test_min
    assert_equal(1, (1..2).min)
    assert_equal(nil, (2..1).min)
    assert_equal(1, (1...2).min)

    assert_equal(1.0, (1.0..2.0).min)
    assert_equal(nil, (2.0..1.0).min)
    assert_equal(1, (1.0...2.0).min)

    assert_equal(0, (0..0).min)
    assert_equal(nil, (0...0).min)

    assert_equal([0,1,2], (0..10).min(3))
    assert_equal([0,1], (0..1).min(3))
  end

  def test_max
    assert_equal(2, (1..2).max)
    assert_equal(nil, (2..1).max)
    assert_equal(1, (1...2).max)

    assert_equal(2.0, (1.0..2.0).max)
    assert_equal(nil, (2.0..1.0).max)
    assert_raises(TypeError) { (1.0...2.0).max }
    assert_raises(TypeError) { (1...1.5).max }
    assert_raises(TypeError) { (1.5...2).max }

    assert_equal(-0x80000002, ((-0x80000002)...(-0x80000001)).max)

    assert_equal(0, (0..0).max)
    assert_equal(nil, (0...0).max)

    assert_equal([10,9,8], (0..10).max(3))
    assert_equal([9,8,7], (0...10).max(3))
  end

  def test_initialize_twice
    r = eval("1..2")
    assert_raises(NameError) { r.instance_eval { initialize 3, 4 } }
    assert_raises(NameError) { r.instance_eval { initialize_copy 3..4 } }
  end

  def test_uninitialized_range
    r = Range.allocate
    s = Marshal.dump(r)
    r = Marshal.load(s)
    assert_silent { r.instance_eval { initialize 5, 6} }
  end

  def test_bad_value
    assert_raises(ArgumentError) { (1 .. :a) }
  end

  def test_exclude_end
    refute_predicate(0..1, :exclude_end?)
    assert_predicate(0...1, :exclude_end?)
  end

  def test_eq
    r = (0..1)
    assert_equal(r, r)
    assert_equal(r, (0..1))
    refute_equal(r, 0)
    refute_equal(r, (1..2))
    refute_equal(r, (0..2))
    refute_equal(r, (0...1))
    subclass = Class.new(Range)
    assert_equal(r, subclass.new(0,1))
  end

  def test_eql
    r = (0..1)
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, 0..1)
    refute_operator(r, :eql?, 0..1.0)
    refute_operator(r, :eql?, 0)
    refute_operator(r, :eql?, 1..2)
    refute_operator(r, :eql?, 0..2)
    refute_operator(r, :eql?, 0...1)
    subclass = Class.new(Range)

    assert_operator(r, :eql?, subclass.new(0,1))
  end

  def test_custom_range_eql
    r = (Xs.new(3)..Xs.new(5))
    assert_operator(r, :eql?, r)
    assert_operator(r, :eql?, (Xs.new(3)..Xs.new(5)))
    refute_operator(r, :eql?, (Ys.new(3)..Ys.new(5)))
    subclass = Class.new(Range)
    assert_equal(r, subclass.new(Xs.new(3), Xs.new(5)))    
  end

  def test_hash
    assert_kind_of(Fixnum, (0..1).hash)
    assert_equal((0..1).hash, (0..1).hash)
    refute_equal((0..1).hash, (0...1).hash)
  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)

    a = []
    (0..10).step(2) {|x| a << x }
    assert_equal([0, 2, 4, 6, 8, 10], a)

    assert_raises(ArgumentError) { (0..10).step(-1) { } }
    assert_raises(ArgumentError) { (0..10).step(0) { } }

    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)

    a = []
    ("a" .. "z").step(2**32) {|x| a << x }
    assert_equal(["a"], a)

    a = []
    (2**32-1 .. 2**32+1).step(2) {|x| a << x }
    assert_equal([4294967295, 4294967297], a)
    zero = (2**32).coerce(0).first
    assert_raises(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }

    o1 = Object.new
    o2 = Object.new
    def o1.<=>(x); -1; end
    def o2.<=>(x); 0; end
    assert_raises(TypeError) { (o1..o2).step(1) { } }

    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end
    a = []
    (o1..o2).step(1) {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    (o1...o2).step(1) {|x| a << x }
    assert_equal([o1], a)

    assert_silent { (0..2).step(0.5) {|x| } } # ("[ruby-dev:34557]")

    a = []
    (0..2).step(0.5) {|x| a << x }
    assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)

    a = []
    (0x40000000..0x40000002).step(0.5) {|x| a << x }
    assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)

    o = Object.new
    def o.to_int() 1 end
    assert_silent { (0..2).step(o) {|x| } } # ("[ruby-dev:34558]")
  end

  def test_step_ruby_core_35753
    assert_equal(6, (1...6.3).step.to_a.size)
    assert_equal(5, (1.1...6).step.to_a.size)
    assert_equal(5, (1...6).step(1.1).to_a.size)
    assert_equal(3, (1.0...5.4).step(1.5).to_a.size)
    assert_equal(3, (1.0...5.5).step(1.5).to_a.size)
    assert_equal(4, (1.0...5.6).step(1.5).to_a.size)
  end

  def test_each
    a = []
    (0..10).each {|x| a << x }
    assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a)

    o1 = Object.new
    o2 = Object.new
    def o1.setcmp(v) @cmpresult = v end
    o1.setcmp(-1)
    def o1.<=>(x); @cmpresult; end
    def o2.setcmp(v) @cmpresult = v end
    o2.setcmp(0)
    def o2.<=>(x); @cmpresult; end
    class << o1; self; end.class_eval do
      define_method(:succ) { o2 }
    end

    r1 = (o1..o2)
    r2 = (o1...o2)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1, o2], a)

    a = []
    r2.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(1)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o2.setcmp(nil)

    a = []
    r1.each {|x| a << x }
    assert_equal([o1], a)

    o1.setcmp(nil)

    a = []
    r2.each {|x| a << x }
    assert_equal([], a)
  end

  def test_begin_end
    assert_equal(0, (0..1).begin)
    assert_equal(1, (0..1).end)
    assert_equal(1, (0...1).end)
  end

  def test_first_last
    assert_equal([0, 1, 2], (0..10).first(3))
    assert_equal([8, 9, 10], (0..10).last(3))
    assert_equal(0, (0..10).first)
    assert_equal(10, (0..10).last)
    assert_equal("a", ("a".."c").first)
    assert_equal("c", ("a".."c").last)
    assert_equal(0, (2..0).last)

    assert_equal([0, 1, 2], (0...10).first(3))
    assert_equal([7, 8, 9], (0...10).last(3))
    assert_equal(0, (0...10).first)
    assert_equal(10, (0...10).last)
    assert_equal("a", ("a"..."c").first)
    assert_equal("c", ("a"..."c").last)
    assert_equal(0, (2...0).last)
  end

  def test_to_s
    assert_equal("0..1", (0..1).to_s)
    assert_equal("0...1", (0...1).to_s)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").to_s, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).to_s, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.to_s, :tainted?, bug11767)
  end

  def test_inspect
    assert_equal("0..1", (0..1).inspect)
    assert_equal("0...1", (0...1).inspect)

    bug11767 = '[ruby-core:71811] [Bug #11767]'
    assert_predicate(("0".taint.."1").inspect, :tainted?, bug11767)
    assert_predicate(("0".."1".taint).inspect, :tainted?, bug11767)
    assert_predicate(("0".."1").taint.inspect, :tainted?, bug11767)
  end

  def test_eqq
    assert_operator(0..10, :===, 5)
    refute_operator(0..10, :===, 11)
  end

  def test_eqq_time
    skip "TypeError: can't iterate from Time jruby"
    bug11113 = '[ruby-core:69052] [Bug #11113]'
    t = Time.now
    assert_silent {
    assert_operator(t..(t + 10), :===, t + 5)
    }
  end

  def test_include
    assert_includes("a".."z", "c")
    refute_includes("a".."z", "5")
    assert_includes("a"..."z", "y")
    refute_includes("a"..."z", "z")
    refute_includes("a".."z", "cc")
    assert_includes(0...10, 5)
  end

  def test_cover
    assert_operator("a".."z", :cover?, "c")
    refute_operator("a".."z", :cover?, "5")
    assert_operator("a"..."z", :cover?, "y")
    refute_operator("a"..."z", :cover?, "z")
    assert_operator("a".."z", :cover?, "cc")
  end

  def test_beg_len
    o = Object.new
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :begin end
    o.begin = -10
    assert_raises(TypeError) { [][o] }
    class << o; attr_accessor :end end
    o.end = 0
    assert_raises(NoMethodError) { [][o] }
    def o.exclude_end=(v) @exclude_end = v end
    def o.exclude_end?() @exclude_end end
    o.exclude_end = false
    assert_nil([0][o])
    assert_raises(RangeError) { [0][o] = 1 }
    o.begin = 10
    o.end = 10
    assert_nil([0][o])
    o.begin = 0
    assert_equal([0], [0][o])
    o.begin = 2
    o.end = 0
    assert_equal([], [0, 1, 2][o])
  end
end

@kares @enebo fixed the test now passes all

@monkstone monkstone changed the title from Fix Range#eql? that checks that start and end of range are same numeric type to Fix Range#eql? that checks that start and end of range are same using Method.EQL Jun 11, 2016

@monkstone monkstone changed the title from Fix Range#eql? that checks that start and end of range are same using Method.EQL to Fix Range#eql? checks that start and end of range are same using MethodNames.EQL Jun 11, 2016

@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Jun 13, 2016

Member

I usually do not add cases under test/mri/ruby ... since its easy to overwrite with a new Ruby version.
instead would either add ruby-specs or just move the test-case into a JRuby specific test/jruby/...
@enebo is it fine to do new test methods under test/mri/ruby ?

Member

kares commented Jun 13, 2016

I usually do not add cases under test/mri/ruby ... since its easy to overwrite with a new Ruby version.
instead would either add ruby-specs or just move the test-case into a JRuby specific test/jruby/...
@enebo is it fine to do new test methods under test/mri/ruby ?

@enebo

This comment has been minimized.

Show comment
Hide comment
@enebo

enebo Jun 13, 2016

Member

@kares I end up asking @headius to commit back to MRI since he has a commit bit but I agree that these tests would probably be better added as specs. @monkstone sorry we are not messing with you :)

Member

enebo commented Jun 13, 2016

@kares I end up asking @headius to commit back to MRI since he has a commit bit but I agree that these tests would probably be better added as specs. @monkstone sorry we are not messing with you :)

@monkstone

This comment has been minimized.

Show comment
Hide comment
@monkstone

monkstone Jun 13, 2016

Contributor

@enebo @kares I've reverted mri test (perhaps not by approved github way) and modified spec test as best I could, I've gone off rspec completely and favour minitest seems to make much more sense to me and on the odd occasion has behaved more correctly than rspec (which I since mistrust).

Contributor

monkstone commented Jun 13, 2016

@enebo @kares I've reverted mri test (perhaps not by approved github way) and modified spec test as best I could, I've gone off rspec completely and favour minitest seems to make much more sense to me and on the odd occasion has behaved more correctly than rspec (which I since mistrust).

@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Jun 13, 2016

Member

@monkstone do not see no spec changes except for an empty space change. you could have just moved the new test case into a (new) test_range.rb under: https://github.com/jruby/jruby/tree/master/test/jruby

Member

kares commented Jun 13, 2016

@monkstone do not see no spec changes except for an empty space change. you could have just moved the new test case into a (new) test_range.rb under: https://github.com/jruby/jruby/tree/master/test/jruby

Show outdated Hide outdated spec/ruby/core/range/eql_spec.rb
(0.5..2.4).send(@method, Range.new(0.5, 2.4)).should == true
(0xffff..0xfffff).send(@method, 0xffff..0xfffff).should == true
(0xffff..0xfffff).send(@method, Range.new(0xffff,0xfffff)).should == true
(Xs.new(3)..Xs.new(5)).send(@method, Range.new(Xs.new(3), Xs.new(5)).should == true

This comment has been minimized.

@kares

kares Jun 13, 2016

Member

missed a closing ) here

@kares

kares Jun 13, 2016

Member

missed a closing ) here

monkstone added some commits Jun 13, 2016

@monkstone

This comment has been minimized.

Show comment
Hide comment
@monkstone

monkstone Jun 14, 2016

Contributor

@kares @enebo I can't get on with mspec (at all), it doesn't seem to work correctly in my hands yet it seems that the above test is passing on travis. So to make permanent changes to ruby spec can someone else do it. I'm sure it would be more encouraging to contributors to have simpler standalone test per class/module etc ruby-spec is a confusing behemoth with lots of indirection (a lot like rspec and rails etc).

Contributor

monkstone commented Jun 14, 2016

@kares @enebo I can't get on with mspec (at all), it doesn't seem to work correctly in my hands yet it seems that the above test is passing on travis. So to make permanent changes to ruby spec can someone else do it. I'm sure it would be more encouraging to contributors to have simpler standalone test per class/module etc ruby-spec is a confusing behemoth with lots of indirection (a lot like rspec and rails etc).

@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Jun 14, 2016

Member

did some commit squashing and pushed your commits to master those LICENSE block formatting changes are really annoying - watch out for them next time, please. thanks for the hard work!

Member

kares commented Jun 14, 2016

did some commit squashing and pushed your commits to master those LICENSE block formatting changes are really annoying - watch out for them next time, please. thanks for the hard work!

@enebo

This comment has been minimized.

Show comment
Hide comment
@enebo

enebo Jun 14, 2016

Member

@monkstone thanks for going the extra mile for us. :)

Member

enebo commented Jun 14, 2016

@monkstone thanks for going the extra mile for us. :)

@eregon

This comment has been minimized.

Show comment
Hide comment
@eregon

eregon Jun 15, 2016

Member

Just a note, if the commit are just pushed and rebased, it would be useful to have a back link to this PR (in one of the commit messages) 😃

Member

eregon commented Jun 15, 2016

Just a note, if the commit are just pushed and rebased, it would be useful to have a back link to this PR (in one of the commit messages) 😃

@eregon

This comment has been minimized.

Show comment
Hide comment
@eregon

eregon Jun 27, 2016

Member

Please review the specs before they come in master, this one just duplicated a shared spec and had no namespacing whatsoever.

Member

eregon commented Jun 27, 2016

Please review the specs before they come in master, this one just duplicated a shared spec and had no namespacing whatsoever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment