# $Id: tc_array.rb,v 1.5 2002/12/10 13:29:16 knu Exp $

require 'test/unit'
begin
  require 'features/ruby18/array'
rescue LoadError; end

class TC_Array < Test::Unit::TestCase
  def test_s_new
    assert_equal([], Array.new)

    # copy constructor
    assert_equal([1, 2], Array.new([1, 2]))

    # repeat
    assert_equal([nil, nil, nil], Array.new(3))
    assert_equal([1, 1], Array.new(2, 1))

    # by function
    assert_equal([0, 2, 4, 6, 8], Array.new(5) {|i| i * 2 })
  end

  def test_fetch
    a = [1, 2, 3, 4, 5]

    assert_equal(3, a.fetch(2))
    assert_equal(4, a.fetch(-2))
    assert_equal(3, a.fetch(2, 0))
    assert_equal(4, a.fetch(-2, 0))
    assert_equal(0, a.fetch(5, 0))
    assert_equal(0, a.fetch(-6, 0))

    assert_equal(-5, a.fetch(5) { |i| -i })
    assert_equal(6, a.fetch(-6) { |i| -i })

    assert_raises(IndexError) { a.fetch(5) }
    assert_raises(IndexError) { a.fetch(-6) }
    assert_raises(ArgumentError) { a.fetch(5, 0) { |i| -1 } }

    # XXX: suggested
    #assert_raises(ArgumentError) { a.fetch(2, 0) { |i| -1 } }
  end

  def test_fill
    # shouldn't break the case where no block is given
    assert_equal([1, 0, 0, 0, 5], [1, 2, 3, 4, 5].fill(0, 1, 3))

    # wrong number of arguments
    assert_raises(ArgumentError) { [1, 2, 3].fill(0, 1, 2) { |i| i } }

    # make sure it is destructive
    a = [1, 2, 3, 4, 5]
    assert_same(a, a.fill(1) { |i| i + 5 })
    assert_equal([1, 6, 7, 8, 9], a)

    # no argument
    assert_equal([5, 6, 7, 8, 9], [1, 2, 3, 4, 5].fill() { |i| i + 5 })

    # 1 argument (integer)
    assert_equal([1, 2, 7, 8, 9], [1, 2, 3, 4, 5].fill(2) { |i| i + 5 })
    assert_equal([1, 2, 3, 8, 9], [1, 2, 3, 4, 5].fill(-2) { |i| i + 5 })
    assert_equal([5, 6, 7, 8, 9], [1, 2, 3, 4, 5].fill(-7) { |i| i + 5 })
    assert_equal([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].fill(5) { |i| i + 5 })

    # 1 argument (range)
    assert_raises(RangeError) { [1, 2, 3, 4, 5].fill(-8..2) { |i| i + 5 } }

    assert_equal([1, 6, 7, 4, 5], [1, 2, 3, 4, 5].fill(1..2) { |i| i + 5 })
    assert_equal([1, 6, 3, 4, 5], [1, 2, 3, 4, 5].fill(1...2) { |i| i + 5 })
    assert_equal([1, 6, 7, 8, 5], [1, 2, 3, 4, 5].fill(1..-2) { |i| i + 5 })
    assert_equal([1, 6, 7, 4, 5], [1, 2, 3, 4, 5].fill(1...-2) { |i| i + 5 })
    assert_equal([1, 2, 7, 8, 5], [1, 2, 3, 4, 5].fill(-3..3) { |i| i + 5 })
    assert_equal([1, 2, 7, 4, 5], [1, 2, 3, 4, 5].fill(-3...3) { |i| i + 5 })
    assert_equal([1, 6, 7, 8, 5], [1, 2, 3, 4, 5].fill(-4..-2) { |i| i + 5 })
    assert_equal([1, 6, 7, 4, 5], [1, 2, 3, 4, 5].fill(-4...-2) { |i| i + 5 })
    assert_equal([1, 2, 7, 8, 9, 10, 11, 12], [1, 2, 3, 4, 5].fill(2...8) { |i| i + 5 })
    assert_equal([1, 2, 3, 4, 5, nil, 11, 12], [1, 2, 3, 4, 5].fill(6..7) { |i| i + 5 })

    # 2 arguments
    assert_equal([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].fill(3, 0) { |i| i + 5 })
    assert_equal([1, 6, 7, 8, 5], [1, 2, 3, 4, 5].fill(1, 3) { |i| i + 5 })
    assert_equal([1, 2, 7, 8, 9, 10], [1, 2, 3, 4, 5].fill(-3, 4) { |i| i + 5 })
    assert_equal([1, 2, 3, 4, 5, nil, 11, 12], [1, 2, 3, 4, 5].fill(6, 2) { |i| i + 5 })
  end

  def test_insert
    a = [0, 4]

    assert_raises(ArgumentError) { a.insert() }
    assert_raises(ArgumentError) { a.insert(1) }

    b = a.insert(1, 1, 2, 3)

    assert_same(a, b)
    assert_equal([0, 1, 2, 3, 4], b)
  end

  def test_select
    assert_equal([], [1,2,3,4,5].select())

    assert_equal([2,3], [1,2,3,4,5].select(1,2))

    assert_equal([2,4], [1,2,3,4,5].select {|x| x % 2 == 0})
  end

  def test_zip
    a = [1,2,3]

    assert_raises(TypeError) { a.zip(4,5,6) }

    assert_equal([[1], [2], [3]], a.zip)
    assert_equal([[1,4], [2,5], [3,nil]], a.zip([4,5]))
    assert_equal([[1,4], [2,5], [3,6]], a.zip([4,5,6]))
    assert_equal([[1,4], [2,5], [3,6]], a.zip([4,5,6,7]))
    assert_equal([[1,4,7], [2,5,8], [3,6,9]], a.zip([4,5,6], [7,8,9]))
  end

  def test_transpose
    assert_raises(TypeError) { [1].transpose }
    assert_raises(TypeError) { [[1], 2].transpose }

    assert_raises(IndexError) { [[1], []].transpose }
    assert_raises(IndexError) { [[1], [2,3]].transpose }

    a = []
    b = a.transpose
    assert_equal([], b)
    assert_not_same(a, b)

    assert_equal([[1,2,3]], [[1],[2],[3]].transpose)
    assert_equal([[1,2,3], [4,5,6]], [[1,4],[2,5],[3,6]].transpose)
  end

  class TestArraySub < Array
  end

  def test_x_subclass
    ary = TestArraySub.new
    assert_equal(TestArraySub, ary.class)
    
    ary << 1 << 2 << 3
    assert_equal([1, 2, 3], ary)
    assert_equal(TestArraySub, ary.class)

    ary = TestArraySub.new(ary.select {|e| e % 2 == 1 })
    assert_equal([1, 3], ary)
    assert_equal(TestArraySub, ary.class)
  end
end
