require 'rbtree'
require 'test/unit.rb'

class RBTreeTest < Test::Unit::TestCase
  unless method_defined?(:assert_raise)
    alias :assert_raise :assert_raises
  end
  
  def setup
    @rbtree = RBTree['Rhapsody', 'Italy', 'STRATOVARIUS', 'Finland',
                     'Blind Guardian', 'Germany', 'EDGUY', 'Germany']
  end
  
  def test_new
    assert_nothing_raised {
      RBTree.new
      RBTree.new('Gamma Ray')
      RBTree.new { 'Gamma Ray' }
    }
    assert_raise(ArgumentError) { RBTree.new('Gamma Ray') {} }
    assert_raise(ArgumentError) { RBTree.new('Gamma Ray', 'Gamma Ray') }
  end
  
  def test_aref
    assert_equal('Italy',   @rbtree['Rhapsody'])
    assert_equal('Finland', @rbtree['STRATOVARIUS'])
    assert_equal('Germany', @rbtree['Blind Guardian'])
    assert_equal('Germany', @rbtree['EDGUY'])
    
    assert_equal(nil, @rbtree['Gamma Ray'])
    @rbtree.default = 'Germany'
    assert_equal('Germany', @rbtree['Gamma Ray'])
  end
  
  def test_size
    assert_equal(4, @rbtree.size)
  end
  
  def test_create
    rbtree = RBTree[]
    assert_equal(0, rbtree.size)
    
    rbtree = RBTree[@rbtree]
    assert_equal(4, rbtree.size)
    assert_equal('Italy',   rbtree['Rhapsody'])
    assert_equal('Finland', rbtree['STRATOVARIUS'])
    assert_equal('Germany', rbtree['Blind Guardian'])
    assert_equal('Germany', rbtree['EDGUY'])
    
    rbtree = RBTree[RBTree.new('Gamma Ray')]
    assert_equal(nil, rbtree.default)
    rbtree = RBTree[RBTree.new { 'Gamma Ray' }]
    assert_equal(nil, rbtree.default_proc)

    @rbtree.default = 'Gamma Ray'
    assert_equal(nil, RBTree[@rbtree].default)
    @rbtree.readjust {|a,b| b <=> a }
    assert_equal(nil, RBTree[@rbtree].cmp_proc)
    
    assert_raise(ArgumentError) { RBTree['Gamma Ray'] }

    rbtree = RBTree[Hash['Rhapsody', 'Italy', 'STRATOVARIUS', 'Finland',
                         'Blind Guardian', 'Germany', 'EDGUY', 'Germany']]
    assert_equal(4, rbtree.size)
    assert_equal('Italy',   rbtree['Rhapsody'])
    assert_equal('Finland', rbtree['STRATOVARIUS'])
    assert_equal('Germany', rbtree['Blind Guardian'])
    assert_equal('Germany', rbtree['EDGUY'])
  end
  
  def test_clear
    @rbtree.clear
    assert_equal(0, @rbtree.size)
  end
  
  def test_aset
    @rbtree['Gamma Ray'] = 'Germany'
    assert_equal(5, @rbtree.size)
    assert_equal('Germany', @rbtree['Gamma Ray'])
    
    @rbtree['Rhapsody'] = 'Germany'
    assert_equal(5, @rbtree.size)
    assert_equal('Germany', @rbtree['Rhapsody'])
    
    
    key = 'Sonata Arctica'
    @rbtree[key] = 'Finland'
    cloned_key = @rbtree.last[0]
    assert_equal('Sonata Arctica', cloned_key)
    assert_not_same(key, cloned_key)
    assert_equal(true, cloned_key.frozen?)
    
    @rbtree['Sonata Arctica'] = 'Finland'
    assert_same(cloned_key, @rbtree.last[0])
    
    rbtree = RBTree.new
    key = ['Gamma Ray']
    rbtree[key] = 'Germany'
    assert_same(key, rbtree.first[0])
    rbtree[key] = 'Finland'
    assert_equal('Finland', rbtree[key])
  end
  
  def test_clone
    clone = @rbtree.clone
    assert_equal(4, @rbtree.size)
    assert_equal('Italy',   @rbtree['Rhapsody'])
    assert_equal('Finland', @rbtree['STRATOVARIUS'])
    assert_equal('Germany', @rbtree['Blind Guardian'])
    assert_equal('Germany', @rbtree['EDGUY'])
    
    rbtree = RBTree.new('Gamma Ray')
    clone = rbtree.clone
    assert_equal('Gamma Ray', clone.default)
    
    rbtree = RBTree.new { 'Gamma Ray' }
    clone = rbtree.clone
    assert_equal('Gamma Ray', clone.default)
    
    rbtree = RBTree.new
    rbtree.readjust {|a, b| a <=> b }
    clone = rbtree.clone
    assert_equal(rbtree.cmp_proc, clone.cmp_proc)
  end
  
  def test_default
    assert_equal(nil, @rbtree.default)
    
    rbtree = RBTree.new('Gamma Ray')
    assert_equal('Gamma Ray', rbtree.default)
    assert_equal('Gamma Ray', rbtree.default('Sonata Arctica'))
    assert_raise(ArgumentError) {
      rbtree.default('Gamma Ray', 'Sonata Arcitica')
    }
    
    rbtree = RBTree.new {|rbtree, key| @rbtree[key || 'Rhapsody'] }
    assert_equal('Italy', rbtree.default)
    assert_equal('Germany', rbtree.default('EDGUY'))
  end
  
  def test_set_default
    rbtree = RBTree.new { 'Gamma Ray' }
    rbtree.default = 'Gamma Ray'
    assert_equal('Gamma Ray', rbtree.default)
  end
  
  def test_default_proc
    rbtree = RBTree.new('Gamma Ray')
    assert_equal(nil, rbtree.default_proc)
    
    rbtree = RBTree.new { 'Gamma Ray' }
    assert_equal('Gamma Ray', rbtree.default_proc.call)
  end
  
  def test_equal
    assert_equal(@rbtree, @rbtree)
    assert_not_equal(@rbtree, nil)
    
    rbtree = RBTree['Rhapsody', 'Italy', 'STRATOVARIUS', 'Finland',
                    'Blind Guardian', 'Germany', 'EDGUY', 'Germany']
    assert_equal(@rbtree, rbtree)
    rbtree['STRATOVARIUS'] = 'Germany'
    assert_not_equal(@rbtree, rbtree)
    rbtree['STRATOVARIUS'] = 'Finland'
    rbtree['Gamma Ray'] = 'Germany'
    assert_not_equal(@rbtree, rbtree)
    @rbtree['Gamma Ray'] = 'Germany'
    assert_equal(@rbtree, rbtree)
    
    rbtree.default = 'Gamma Ray'
    assert_not_equal(@rbtree, rbtree)
    @rbtree.default = 'Gamma Ray'
    assert_equal(@rbtree, rbtree)
    
    a = RBTree.new('Gamma Ray')
    b = RBTree.new { 'Gamma Ray' }
    assert_not_equal(a, b)
    assert_equal(b, b.clone)
    
    a = RBTree.new
    b = RBTree.new
    a.readjust {|a, b| a <=> b }
    assert_not_equal(a, b)
    b.readjust(a.cmp_proc)
    assert_equal(a, b)
  end
  
  def test_fetch
    assert_equal('Italy',   @rbtree.fetch('Rhapsody'))
    assert_equal('Finland', @rbtree.fetch('STRATOVARIUS'))
    assert_equal('Germany', @rbtree.fetch('Blind Guardian'))
    assert_equal('Germany', @rbtree.fetch('EDGUY'))
    
    assert_raise(IndexError) { @rbtree.fetch('Sonata Arctica') }
    
    assert_equal('Finland', @rbtree.fetch('Sonata Arctica', 'Finland'))
    assert_equal('Finland', @rbtree.fetch('Sonata Arctica') { 'Finland' })
    assert_equal('Finland',
                 @rbtree.fetch('Sonata Arctica', 'Germany') { 'Finland' })
    
    assert_raise(ArgumentError) { @rbtree.fetch }
    assert_raise(ArgumentError) {
      @rbtree.fetch('Sonata Arctica', 'Finland', 'Finland')
    }
  end

  def test_index
    assert_equal('Blind Guardian', @rbtree.index('Germany'))
    assert_equal(nil, @rbtree.index('Sweden'))
  end

  def test_empty_p
    assert_equal(false, @rbtree.empty?)
    @rbtree.clear
    assert_equal(true, @rbtree.empty?)
  end
  
  def test_each
    ret = []
    @rbtree.each {|key, val| ret.push([key, val]) }
    assert_equal(4, ret.size)
    assert_equal(['Blind Guardian', 'Germany'], ret[0])
    assert_equal(['EDGUY',          'Germany'], ret[1])
    assert_equal(['Rhapsody',       'Italy'],   ret[2])
    assert_equal(['STRATOVARIUS',   'Finland'], ret[3])
    
    assert_raise(TypeError) {
      @rbtree.each { @rbtree['Gamma Ray'] = 'Germany' }
    }
    assert_equal(4, @rbtree.size)
  end

  def test_each_pair
    ret = []
    @rbtree.each_pair {|key, val| ret.push([key, val]) }
    assert_equal(4, ret.size)
    assert_equal(['Blind Guardian', 'Germany'], ret[0])
    assert_equal(['EDGUY',          'Germany'], ret[1])
    assert_equal(['Rhapsody',       'Italy'],   ret[2])
    assert_equal(['STRATOVARIUS',   'Finland'], ret[3])

    assert_raise(TypeError) {
      @rbtree.each_pair { @rbtree['Gamma Ray'] = 'Germany' }
    }
    assert_equal(4, @rbtree.size)
  end
  
  def test_each_key
    ret = []
    @rbtree.each_key {|val| ret.push(val) }
    assert_equal(4, ret.size)
    assert_equal('Blind Guardian', ret[0])
    assert_equal('EDGUY',          ret[1])
    assert_equal('Rhapsody',       ret[2])
    assert_equal('STRATOVARIUS',   ret[3])

    assert_raise(TypeError) {
      @rbtree.each_key { @rbtree['Gamma Ray'] = 'Germany' }
    }
    assert_equal(4, @rbtree.size)
  end
  
  def test_each_value
    ret = []
    @rbtree.each_value {|key| ret.push(key) }
    assert_equal(4, ret.size)
    assert_equal('Germany', ret[0])
    assert_equal('Germany', ret[1])
    assert_equal('Italy',   ret[2])
    assert_equal('Finland', ret[3])

    assert_raise(TypeError) {
      @rbtree.each_value { @rbtree['Gamma Ray'] = 'Germany' }
    }
    assert_equal(4, @rbtree.size)
  end

  def test_shift
    ret = @rbtree.shift
    assert_equal(3, @rbtree.size)
    assert_equal(['Blind Guardian', 'Germany'], ret)
    assert_equal(nil, @rbtree['Blind Guardian'])
    
    3.times { @rbtree.shift }
    assert_equal(0, @rbtree.size)
    assert_equal(nil, @rbtree.shift)
    @rbtree.default = 'Gamma Ray'
    assert_equal('Gamma Ray', @rbtree.shift)
    
    rbtree = RBTree.new { 'Gamma Ray' }
    assert_equal('Gamma Ray', rbtree.shift)
  end
  
  def test_pop
    ret = @rbtree.pop
    assert_equal(3, @rbtree.size)
    assert_equal(['STRATOVARIUS', 'Finland'], ret)
    assert_equal(nil, @rbtree['STRATOVARIUS'])
    
    3.times { @rbtree.pop }
    assert_equal(0, @rbtree.size)
    assert_equal(nil, @rbtree.pop)
    @rbtree.default = 'Gamma Ray'
    assert_equal('Gamma Ray', @rbtree.pop)
    
    rbtree = RBTree.new { 'Gamma Ray' }
    assert_equal('Gamma Ray', rbtree.pop)
  end
  
  def test_delete
    ret = @rbtree.delete('Rhapsody')
    assert_equal('Italy', ret)
    assert_equal(3, @rbtree.size)
    assert_equal(nil, @rbtree['Rhapsody'])
    
    assert_equal(nil, @rbtree.delete('Gamma Ray'))
    assert_equal('Sonata Arctica',
                 @rbtree.delete('Gamma Ray') { 'Sonata Arctica' })
  end
  
  def test_delete_if
    @rbtree.delete_if {|key, val| val == 'Germany' }
    assert_equal(2, @rbtree.size)
    assert_equal('Italy', @rbtree['Rhapsody'])
    assert_equal('Finland', @rbtree['STRATOVARIUS'])
    
    assert_raise(ArgumentError) {
      @rbtree.delete_if {|key, val| key == 'Rhapsody' or raise ArgumentError }
    }
    assert_equal(2, @rbtree.size)
    
    assert_raise(TypeError) {
      @rbtree.delete_if { @rbtree['Gamma Ray'] = 'Germany' }
    }
    assert_equal(2, @rbtree.size)
  end

  def test_reject_bang
    ret = @rbtree.reject! { false }
    assert_equal(nil, ret)
    assert_equal(4, @rbtree.size)
    
    ret = @rbtree.reject! {|key, val| val == 'Germany' }
    assert_same(@rbtree, ret)
    assert_equal(2, @rbtree.size)
    assert_equal('Italy', @rbtree['Rhapsody'])
    assert_equal('Finland', @rbtree['STRATOVARIUS'])
  end

  def test_reject
    ret = @rbtree.reject { false }
    assert_equal(nil, ret)
    assert_equal(4, @rbtree.size)
    
    ret = @rbtree.reject {|key, val| val == 'Germany' }
    assert_equal(2, ret.size)
    assert_equal('Italy', ret['Rhapsody'])
    assert_equal('Finland', ret['STRATOVARIUS'])
    assert_equal(4, @rbtree.size)
  end
  
  def test_select
    ret = @rbtree.select {|key, val| val == 'Germany' }
    assert_equal(['Blind Guardian', 'Germany'], ret[0])
    assert_equal(['EDGUY', 'Germany'], ret[1])
    assert_raise(ArgumentError) { @rbtree.select('STRATOVARIUS') }
  end

  def test_values_at
    ret = @rbtree.values_at('STRATOVARIUS', 'Blind Guardian', 'Gamma Ray')
    assert_equal('Finland', ret[0])
    assert_equal('Germany', ret[1])
    assert_equal(nil, ret[2])
  end
  
  def test_invert
    ret = @rbtree.invert
    assert_equal(RBTree, ret.class)
    assert_equal(3, ret.size)
    assert_equal('Rhapsody',     ret['Italy'])
    assert_equal('STRATOVARIUS', ret['Finland'])
    assert_equal('EDGUY',        ret['Germany'])
  end
  
  def test_update
    rbtree = RBTree.new
    rbtree['Gamma Ray'] = 'Germany'
    rbtree['Sonata Arctica'] = 'Finland'
    
    @rbtree.update(rbtree)
    assert_equal(6, @rbtree.size)
    assert_equal('Germany', @rbtree['Gamma Ray'])
    assert_equal('Finland', @rbtree['Sonata Arctica'])
    assert_equal('Italy',   @rbtree['Rhapsody'])
    assert_equal('Finland', @rbtree['STRATOVARIUS'])
    assert_equal('Germany', @rbtree['Blind Guardian'])
    assert_equal('Germany', @rbtree['EDGUY'])
    
    
    @rbtree.clear
    @rbtree['STRATOVARIUS'] = 'Fin'
    rbtree.clear
    rbtree['STRATOVARIUS'] = 'land'
    @rbtree['Sonata Arctica'] = 'Finland'
    
    @rbtree.update(rbtree) {|key, val1, val2|
      val1 + val2 if key == 'STRATOVARIUS'
    }
    assert_equal(2, @rbtree.size)
    assert_equal('Finland', @rbtree['STRATOVARIUS'])
    assert_equal('Finland', @rbtree['Sonata Arctica'])
    
    assert_raise(TypeError) { @rbtree.update('Gamma Ray') }
  end
  
  def test_merge
    rbtree = RBTree.new
    rbtree['Gamma Ray'] = 'Germany'
    rbtree['Sonata Arctica'] = 'Finland'
    
    ret = @rbtree.merge(rbtree)
    assert_equal(6, ret.size)
    assert_equal('Germany', ret['Gamma Ray'])
    assert_equal('Finland', ret['Sonata Arctica'])
    assert_equal('Italy',   ret['Rhapsody'])
    assert_equal('Finland', ret['STRATOVARIUS'])
    assert_equal('Germany', ret['Blind Guardian'])
    assert_equal('Germany', ret['EDGUY'])
    
    assert_equal(4, @rbtree.size)
  end
  
  def test_has_key
    assert_equal(true,  @rbtree.has_key?('STRATOVARIUS'))
    assert_equal(true,  @rbtree.has_key?('Blind Guardian'))
    assert_equal(true,  @rbtree.has_key?('Rhapsody'))
    assert_equal(true,  @rbtree.has_key?('EDGUY'))
    assert_equal(false, @rbtree.has_key?('Gamma Ray'))
  end
  
  def test_has_value
    assert_equal(true,  @rbtree.has_value?('Germany'))
    assert_equal(true,  @rbtree.has_value?('Italy'))
    assert_equal(true,  @rbtree.has_value?('Finland'))
    assert_equal(false, @rbtree.has_value?('Sweden'))
  end

  def test_keys
    ret = @rbtree.keys
    assert_equal(4, ret.size)
    assert_equal('Blind Guardian', ret[0])
    assert_equal('EDGUY',          ret[1])
    assert_equal('Rhapsody',       ret[2])
    assert_equal('STRATOVARIUS',   ret[3])
  end

  def test_values
    ret = @rbtree.values
    assert_equal(4, ret.size)
    assert_equal('Germany', ret[0])
    assert_equal('Germany', ret[1])
    assert_equal('Italy',   ret[2])
    assert_equal('Finland', ret[3])
  end

  def test_to_a
    ret = @rbtree.to_a
    assert_equal(Array, ret.class)
    assert_equal(4, ret.size)
    assert_equal(['Blind Guardian', 'Germany'], ret[0])
    assert_equal(['EDGUY',          'Germany'], ret[1])
    assert_equal(['Rhapsody',       'Italy'],   ret[2])
    assert_equal(['STRATOVARIUS',   'Finland'], ret[3])
  end

  def test_to_s
    assert_equal('Blind GuardianGermanyEDGUYGermanyRhapsodyItalySTRATOVARIUSFinland',
                 @rbtree.to_s)
  end
  
  def test_to_hash
    @rbtree.default = 'Gamma Ray'
    ret = @rbtree.to_hash
    
    assert_equal(Hash, ret.class)
    assert_equal('Gamma Ray', ret.default)
    assert_equal(4, ret.size)
    assert_equal('Germany', ret['Blind Guardian'])
    assert_equal('Germany', ret['EDGUY'])
    assert_equal('Italy',   ret['Rhapsody'])
    assert_equal('Finland', ret['STRATOVARIUS'])

    rbtree = RBTree.new { 'Gamma Ray' }
    ret = rbtree.to_hash
    if (ret.respond_to?(:default_proc))
      assert_equal(rbtree.default_proc, ret.default_proc)
    else
      assert_equal(rbtree.default_proc, ret.default)
    end
  end

  def test_to_rbtree
    assert_same(@rbtree, @rbtree.to_rbtree)
  end
  
  def test_inspect
    re = /#<RBTree: (\{.*\}), default=(.*), cmp_proc=(.*)>/
    
    @rbtree.default = 'Gamma Ray'
    @rbtree.readjust {|a, b| a <=> b}
    assert_match(re, @rbtree.inspect)
    match = re.match(@rbtree.inspect)
    tree, default, cmp_proc = match.to_a[1..-1]
    str = %({"Blind Guardian"=>"Germany", "EDGUY"=>"Germany", "Rhapsody"=>"Italy", "STRATOVARIUS"=>"Finland"})
    assert_equal(str, tree)
    assert_equal('"Gamma Ray"', default)
    assert_match(/#<Proc:\w+(@test.rb:\d+)?>/, cmp_proc)
    
    rbtree = RBTree.new
    assert_match(re, rbtree.inspect)
    match = re.match(rbtree.inspect)
    tree, default, cmp_proc = match.to_a[1..-1]
    assert_equal('{}', tree)
    assert_equal('nil', default)
    assert_equal('nil', cmp_proc)
    
    rbtree = RBTree.new
    rbtree['Gamma Ray'] = rbtree
    assert_match(re, rbtree.inspect)
    match = re.match(rbtree.inspect)
    assert_equal('{"Gamma Ray"=>#<RBTree: ...>}', match[1])
  end
  
  def test_lower_bound
    ret = @rbtree.lower_bound('Rhapsody')
    assert_equal(['Rhapsody', 'Italy'], ret)
    
    ret = @rbtree.lower_bound('Gamma Ray')
    assert_equal(['Rhapsody', 'Italy'], ret)
    
    ret = @rbtree.lower_bound('Sonata Arctica')
    assert_equal(nil, ret)
  end
  
  def test_upper_bound
    ret = @rbtree.upper_bound('Rhapsody')
    assert_equal(['Rhapsody', 'Italy'], ret)
    
    ret = @rbtree.upper_bound('Sonata Arctica')
    assert_equal(['STRATOVARIUS', 'Finland'], ret)
    
    ret = @rbtree.upper_bound('Avantasia')
    assert_equal(nil, ret)
  end
  
  def test_bound
    ret = @rbtree.bound('EDGUY', 'Rhapsody')
    assert_equal(2, ret.size)
    assert_equal('EDGUY', ret[0][0])
    assert_equal('Rhapsody', ret[1][0])
    
    ret = @rbtree.bound('STRATOVARIUS', 'STRATOVARIUS')
    assert_equal(1, ret.size)
    assert_equal('STRATOVARIUS', ret[0][0])
    
    ret = @rbtree.bound('Gamma Ray', 'Sonata Arctica')
    assert_equal(2, ret.size)
    assert_equal('Rhapsody', ret[0][0])
    assert_equal('STRATOVARIUS', ret[1][0])

    ret = @rbtree.bound('Gamma Ray', 'Helloween')
    assert_equal(0, ret.size)
    
    
    ret = @rbtree.bound('Angra', 'Avantasia')
    assert_equal(0, ret.size)
    
    ret = @rbtree.bound('Sonata Arctica', 'Yngwie Malmsteen')
    assert_equal(0, ret.size)
    
    ret = @rbtree.bound('Sonata Arctica', 'Avantasia')
    assert_equal(0, ret.size)
  end
  
  def test_bound_block
    ret = []
    @rbtree.bound('EDGUY', 'Rhapsody') {|key, val|
      ret.push(key)
    }
    assert_equal(2, ret.size)
    assert_equal('EDGUY', ret[0])
    assert_equal('Rhapsody', ret[1])
    
    assert_raise(TypeError) {
      @rbtree.bound('Blind Guardian', 'STRATOVARIUS') {
        @rbtree['Gamma Ray'] = 'Germany'
      }
    }
    assert_equal(4, @rbtree.size)
  end
  
  def test_first
    ret = @rbtree.first
    assert_equal(['Blind Guardian', 'Germany'], ret)
    
    rbtree = RBTree.new('Gamma Ray')
    assert_equal('Gamma Ray', rbtree.first)

    rbtree = RBTree.new { 'Gamma Ray' }
    assert_equal('Gamma Ray', rbtree.first)
  end

  def test_last
    ret = @rbtree.last
    assert_equal(['STRATOVARIUS', 'Finland'], ret)
    
    rbtree = RBTree.new('Gamma Ray')
    assert_equal('Gamma Ray', rbtree.last)

    rbtree = RBTree.new { 'Gamma Ray' }
    assert_equal('Gamma Ray', rbtree.last)
  end

  def test_readjust
    assert_equal(nil, @rbtree.cmp_proc)
    
    @rbtree.readjust {|a, b| a.reverse <=> b.reverse }
    assert_equal(4, @rbtree.size)
    ret = @rbtree.collect {|key, val| key }
    assert_equal('STRATOVARIUS',   ret[0])
    assert_equal('EDGUY',          ret[1])
    assert_equal('Blind Guardian', ret[2])
    assert_equal('Rhapsody',       ret[3])
    assert_not_equal(nil, @rbtree.cmp_proc)
    
    proc = Proc.new {|a,b| a.to_s <=> b.to_s }
    @rbtree.readjust(proc)
    assert_equal(4, @rbtree.size)
    ret = @rbtree.collect {|key, val| key }
    assert_equal('Blind Guardian', ret[0])
    assert_equal('EDGUY',          ret[1])
    assert_equal('Rhapsody',       ret[2])
    assert_equal('STRATOVARIUS',   ret[3])
    assert_equal(proc, @rbtree.cmp_proc)
    
    @rbtree[0] = nil
    assert_raise(TypeError) { @rbtree.readjust(nil) }
    assert_equal(5, @rbtree.size)
    assert_equal(proc, @rbtree.cmp_proc)
    
    @rbtree.delete(0)
    @rbtree.readjust(nil)
    assert_raise(TypeError) { @rbtree[0] = nil }
    
    
    rbtree = RBTree.new
    key = ['Angra']
    rbtree[key] = nil
    rbtree[['Gamma Ray']] = nil
    key[0] = 'Sonata Arcitica'
    
    ret = rbtree.collect {|key, val| key }
    assert_equal(['Sonata Arcitica'], ret[0])
    assert_equal(['Gamma Ray'], ret[1])
    rbtree.readjust
    ret = rbtree.collect {|key, val| key }
    assert_equal(['Gamma Ray'], ret[0])
    assert_equal(['Sonata Arcitica'], ret[1])
    
    
    assert_raise(TypeError) { @rbtree.readjust { 'Gamma Ray' } }
    assert_raise(TypeError) { @rbtree.readjust('Gamma Ray') }
    assert_raise(ArgumentError) {
      @rbtree.readjust(proc) {|a,b| a <=> b }
    }
    assert_raise(ArgumentError) { @rbtree.readjust(proc, proc) }
  end
  
  def test_replace
    rbtree = RBTree.new { 'Gamma Ray' }
    rbtree.readjust {|a, b| a <=> b}
    rbtree['Sonata Arctica'] = 'Finland'
    rbtree['Gamma Ray'] = 'Germany'
    
    @rbtree.replace(rbtree)
    assert_equal(2, @rbtree.size)
    assert_equal('Finland', @rbtree['Sonata Arctica'])
    assert_equal('Germany', @rbtree['Gamma Ray'])
    assert_equal(rbtree.cmp_proc, @rbtree.cmp_proc)
    
    rbtree.default = 'Gamma Ray'
    @rbtree.replace(rbtree)
    assert_equal(2, @rbtree.size)
    assert_equal('Finland', @rbtree['Sonata Arctica'])
    assert_equal('Germany', @rbtree['Gamma Ray'])
    assert_equal(rbtree.default, @rbtree.default)
    
    assert_raise(TypeError) { @rbtree.replace('Gamma Ray') }
  end
  
  def test_reverse_each
    ret = []
    @rbtree.reverse_each { |key, val| ret.push([key, val]) }
    assert_equal(4, ret.size)
    assert_equal(['STRATOVARIUS',   'Finland'], ret[0])
    assert_equal(['Rhapsody',       'Italy'],   ret[1])
    assert_equal(['EDGUY',          'Germany'], ret[2])
    assert_equal(['Blind Guardian', 'Germany'], ret[3])
  end
  
  def test_marshal
    assert_equal(@rbtree, Marshal.load(Marshal.dump(@rbtree)))
    
    @rbtree.default = 'Gamma Ray'
    assert_equal(@rbtree, Marshal.load(Marshal.dump(@rbtree)))
    
    assert_raise(TypeError) {
      Marshal.dump(RBTree.new { 'Gamma Ray' })
    }
    
    assert_raise(TypeError) {
      @rbtree.readjust {|a, b| a <=> b}
      Marshal.dump(@rbtree)
    }
  end
  
  begin
    require 'pp'
    
    def test_pp
      assert_equal(%(#<RBTree: {}, default=nil, cmp_proc=nil>\n),
                   PP.pp(RBTree[], ''))
      assert_equal(%(#<RBTree: {"a"=>"A", "b"=>"B"}, default=nil, cmp_proc=nil>\n),
                   PP.pp(RBTree['a', 'A', 'b', 'B'], ''))
      
      rbtree = RBTree[*('a'..'z').to_a]
      rbtree.default = 'a'
      rbtree.readjust {|a, b| a <=> b }
      expected = <<EOS
#<RBTree: {"a"=>"b",
  "c"=>"d",
  "e"=>"f",
  "g"=>"h",
  "i"=>"j",
  "k"=>"l",
  "m"=>"n",
  "o"=>"p",
  "q"=>"r",
  "s"=>"t",
  "u"=>"v",
  "w"=>"x",
  "y"=>"z"},
 default="a",
 cmp_proc=#{rbtree.cmp_proc}>
EOS
      assert_equal(expected, PP.pp(rbtree, ''))

      rbtree = RBTree[]
      rbtree[rbtree] = rbtree
      rbtree.default = rbtree
      expected = <<EOS
#<RBTree: {"#<RBTree: ...>"=>"#<RBTree: ...>"},
 default="#<RBTree: ...>",
 cmp_proc=nil>
EOS
      assert_equal(expected, PP.pp(rbtree, ''))
    end
  rescue LoadError
  end
end
