# Ruby Treasures 0.1
# Copyright (C) 2001 Paul Brannan <paul@atdesk.com>
# 
# You may distribute this software under the same terms as Ruby (see the file
# COPYING that was distributed with this library).
# 
require 'ds_test_helpers.rb'
require 'set'
requirelocal 'mixins/enumerable_test'
requirelocal 'mixins/comparable_test'

N = 25

class SetTest < DS_Test_Case

  include EnumerableTest
  include ComparableTest
  undef_method :test_each

  def initialize(*args)
    super(*args)
    @test_container     = Set
    @analgous_container = ExtendedArray
  end

  def test_misc
    DS_Test_Case.method_checked(:store, @test_container)
    DS_Test_Case.method_checked(:each, @test_container)
    DS_Test_Case.method_checked(:size, @test_container)
    DS_Test_Case.method_checked(:length, @test_container)
    for i in 0...N do
      a = generate_random_container(i, @analgous_container).uniq
      l = generate_container_from_analgous(a)
      assert_sets_equivalent(a, l)
      assert_sets_equivalent(l, a)
    end
  end

  def test_union_and_union_bang
    DS_Test_Case.method_checked(:union, @test_container)
    DS_Test_Case.method_checked(:union!, @test_container)
    DS_Test_Case.method_checked(:&, @test_container)
    for i in 0...N do
      a1 = generate_random_container(i + 1, @analgous_container).uniq
      a2 = generate_random_container(i, @analgous_container).uniq
      l1 = generate_container_from_analgous(a1)
      l2 = generate_container_from_analgous(a2)
      a1_union = a1 | a2
      a2_union = a2 | a1
      assert_sets_equivalent(a1_union, l1.union(a2))
      assert_sets_equivalent(a2_union, l2.union(a1))
      l1.union!(a2)
      l2.union!(a1)
      assert_sets_equivalent(a1_union, l1)
      assert_sets_equivalent(a2_union, l2)
    end
  end

  def test_intersect_and_intersect_bang
    DS_Test_Case.method_checked(:intersect, @test_container)
    DS_Test_Case.method_checked(:intersect!, @test_container)
    DS_Test_Case.method_checked(:|, @test_container)
    for i in 0...N do
      a1 = generate_random_container(i + 1, @analgous_container).uniq
      a2 = generate_random_container(i, @analgous_container).uniq
      l1 = generate_container_from_analgous(a1)
      l2 = generate_container_from_analgous(a2)
      a1_intersect = a1 & a2
      a2_intersect = a2 & a1
      assert_sets_equivalent(a1_intersect, l1.intersect(a2))
      assert_sets_equivalent(a2_intersect, l2.intersect(a1))
      l1.intersect!(a2)
      l2.intersect!(a1)
      assert_sets_equivalent(a1_intersect, l1)
      assert_sets_equivalent(a2_intersect, l2)
    end
  end

  def test_bracket_and_bracket_equals
    DS_Test_Case.method_checked(:[], @test_container)
    DS_Test_Case.method_checked(:[]=, @test_container)
    for i in 0...N do
      a = generate_random_container(i, @analgous_container).uniq
      h = Hash.new
      l = @test_container.new
      a.each do |item|
        x = rand(100)
        h[item] = x
        l[item] = x
        a.each do |item|
          assert_equal h[item], l[item]
        end
      end
    end
  end

  def test_self_bracket
    DS_Test_Case.class_method_checked(:[], @test_container)
    for i in 0...N do
      a = generate_random_container(i, @analgous_container).uniq
      l = @test_container[*a]
      assert_sets_equivalent(a, l)
    end
  end

  def test_clear
    DS_Test_Case.method_checked(:clear, @test_container)
    for i in 0...N do
      a = generate_random_container(i, @analgous_container).uniq
      l = generate_container_from_analgous(a)
      l.clear
      assert l.size == 0
      assert l.length == 0
      l.each do |i|
        assert false
      end
    end
  end

  def test_has
    DS_Test_Case.method_checked(:has?, @test_container)
    DS_Test_Case.method_checked(:has_key?, @test_container)
    for i in 0...N do
      a = generate_random_container(i, @analgous_container).uniq
      l = generate_container_from_analgous(a)
      a.each do |item|
        assert l.has?(item)
        assert l.has_key?(item)
        if not item.nil? then
          if a.index(item.succ) then
            assert l.has?(item.succ)
            assert l.has_key?(item.succ)
          else
            assert !l.has?(item.succ)
            assert !l.has_key?(item.succ)
          end
        end
      end
    end
  end

  def generate_container_from_analgous(a)
    l = Set.new
    a.each do |item|
      l.store(item)
    end
    l # return
  end

  def assert_sets_equivalent(set1, set2)
    assert_equal set1.size, set2.size
    assert_equal set1.length, set2.length
    set1.each do |item|
      assert set2.has?(item)
    end
  end
end

exit run_test(SetTest, Set)

