
$:.push(File::dirname($0))

load("test_prologue.rb")

# extend A
class RBA::A 

  def initialize
    @offset = nil
  end
  def s( o )
    @offset = o
  end
  def g
    return @offset
  end
  def m
    return @offset+a1
  end
  def call_a10_prot(f)
    a10_prot(f)
  end

private
  @offset

end

class XEdge < RBA::Edge
  def initialize
    super(RBA::Point.new(1,2), RBA::Point.new(3,4))
  end
end

class RBA::E
  def m 
    @m
  end
  def m=(x)
    @m = x
  end
  @m = nil
end

class Basic_TestClass < TestBase

  def test_FIRST

    GC.start 
    
    # all references of A are released now:
    ac0 = RBA::A::a0
    assert_equal( ac0, 0 )

    a = RBA::A.new_a(100)
    assert_equal( RBA::A::a0, ac0 + 1 )

    a = nil
    GC.start
    assert_equal( RBA::A::a0, ac0 )

    a = RBA::A.new
    assert_equal( RBA::A::a0, ac0 )  # delayed instantiation of detached objects - A is actually created if it is used first
    a.a2   # just check, if it can be called
    assert_equal( RBA::A::a0, ac0 + 1 )

    # open question: with ruby 1.8, aa is not deleted if the assert_equal is missing. Why?
    # maybe the GC does not like to be called that frequently?
    aa = a.dup
    assert_equal( RBA::A::a0, ac0 + 2 )

    aa = nil
    GC.start 

    if RUBY_VERSION >= "1.9.0"
      # GC works differently in >=1.9.x - but no leak (verified with valgrind)
      ac0 = RBA::A::a0
    else
      assert_equal( RBA::A::a0, ac0 + 1 )
    end

    a = nil
    GC.start

    if RUBY_VERSION >= "1.9.0"
      # GC works differently in >=1.9.x - but no leak (verified with valgrind)
      ac0 = RBA::A::a0
    else
      assert_equal( RBA::A::a0, ac0 )
    end

    a = RBA::A.new
    assert_equal( RBA::A::a0, ac0 )  # delayed instantiation of detached objects - A is actually created if it is used first
    a.a2   # just check, if it can be called
    assert_equal( RBA::A::a0, ac0 + 1 )

    # mix of getters, setters, predicates
    assert_equal( a.af, false )
    assert_equal( a.af(true), false )
    a.af = true
    assert_equal( a.af?, true )
    assert_equal( a.af?(true), true )

    # static and non-static methods can be mixed
    assert_equal( RBA::A.aa, "static_a" )
    assert_equal( a.aa, "a" )

    assert_equal( a.a1, 17 )
    a.a5 -5
    assert_equal( a.a1, -5 )
    a.a5 0x7fffffff
    assert_equal( a.a1, 0x7fffffff )
    a.a5 -0x80000000
    assert_equal( a.a1, -0x80000000 )

    assert_equal( a.a3("a"), 1 )
    assert_equal( a.a3("ab"), 2 )
    assert_equal( a.a3(""), 0 )

    assert_equal( a.a4([1]), 1.0 )
    assert_equal( a.a4([1, 125e-3]), 0.125 )
    assert_equal( a.a4([5, 1, -1.25]), -1.25 )

    arr = []
    a.a6 { |d| arr.push(d) } 
    assert_equal(arr, [5, 1, -1.25])

    arr = []
    a.a7 { |d| arr.push(d) } 
    assert_equal(arr, [5, 1, -1.25])

    arr = []
    a.a8 { |d| arr.push(d) } 
    assert_equal(arr, [5, 1, -1.25])

    a.destroy
    assert_equal( RBA::A::a0, ac0 )

    if !$leak_check 

      error_caught = false
      begin 
        a.a2  # object has been destroyed already
      rescue
        error_caught = true
      end
      assert_equal( error_caught, true )

      error_caught = false
      begin 
        a.destroy  # object has been destroyed already
      rescue
        error_caught = true
      end
      assert_equal( error_caught, true )

    end

    assert_equal( RBA::A::a0, ac0 )
    a = RBA::A::new_a( 55 )
    assert_equal( RBA::A::a0, ac0 + 1 )
    assert_equal( a.a1, 55 )
    assert_equal( a.a_vp1( a.a_vp2 ), "abc" )
    a.destroy
    assert_equal( RBA::A::a0, ac0 )

    a = RBA::A::new_a(0)
    assert_equal( a.a9a(5).to_s, "true" )
    assert_equal( a.a9a(4).to_s, "false" )
    assert_equal( a.a9b(true).to_s, "5" )
    assert_equal( a.a9b(0).to_s, "5" )
    assert_equal( a.a9b(1).to_s, "5" )
    assert_equal( a.a9b(false).to_s, "-5" )
    assert_equal( a.a9b(nil).to_s, "-5" )

  end

  def test_12

    a1 = RBA::A.new
    a1.a5( -15 )
    a2 = a1
    a3 = a2.dup

    assert_equal( a1.a1, -15 )
    assert_equal( a2.a1, -15 )
    assert_equal( a3.a1, -15 )

    a1.a5( 11 )
    a3.a5( -11 )
    
    assert_equal( a1.a1, 11 )
    assert_equal( a2.a1, 11 )
    assert_equal( a3.a1, -11 )

    assert_equal( a1.a10_d(5.2), "5.2" )
    assert_equal( a1.a10_f(5.7), "5.7" )
    x = RBA::Value.new(1.5)
    assert_equal( x.value.to_s, "1.5" )
    assert_equal( a1.a10_fptr(x), "6.5" )
    assert_equal( x.value.to_s, "6.5" )
    assert_equal( a1.a10_fptr(1), "6" )
    assert_equal( a1.a10_fptr(nil), "nil" )
    assert_equal( a1.a10_fptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "6.5" )
    assert_equal( x.value.to_s, "6.5" )
    x = RBA::Value.new(2.5)
    assert_equal( a1.a10_dptr(x), "8.5" )
    assert_equal( a1.a10_dptr(2), "8" )
    assert_equal( a1.a10_dptr(nil), "nil" )
    assert_equal( a1.a10_dptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "8.5" )
    assert_equal( x.value.to_s, "8.5" )
    x = RBA::Value.new(2)
    assert_equal( a1.a10_iptr(x), "9" )
    assert_equal( a1.a10_iptr(3), "10" )
    assert_equal( a1.a10_iptr(nil), "nil" )
    assert_equal( a1.a10_iptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "9" )
    assert_equal( x.value.to_s, "9" )
    x = RBA::Value.new(false)
    assert_equal( a1.a10_bptr(x), "true" )
    assert_equal( a1.a10_bptr(false), "true" )
    assert_equal( a1.a10_bptr(nil), "nil" )
    assert_equal( a1.a10_bptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "true" )
    assert_equal( x.value.to_s, "true" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_uiptr(x), "20" )
    assert_equal( a1.a10_uiptr(11), "21" )
    assert_equal( a1.a10_uiptr(nil), "nil" )
    assert_equal( a1.a10_uiptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "20" )
    assert_equal( x.value.to_s, "20" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_ulptr(x), "21" )
    assert_equal( a1.a10_ulptr(12), "23" )
    assert_equal( a1.a10_ulptr(nil), "nil" )
    assert_equal( a1.a10_ulptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "21" )
    assert_equal( x.value.to_s, "21" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_lptr(x), "22" )
    assert_equal( a1.a10_lptr(11), "23" )
    assert_equal( a1.a10_lptr(nil), "nil" )
    assert_equal( a1.a10_lptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "22" )
    assert_equal( x.value.to_s, "22" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_llptr(x), "23" )
    assert_equal( a1.a10_llptr(11), "24" )
    assert_equal( a1.a10_llptr(nil), "nil" )
    assert_equal( a1.a10_llptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "23" )
    assert_equal( x.value.to_s, "23" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_ullptr(x), "24" )
    assert_equal( a1.a10_ullptr(12), "26" )
    assert_equal( a1.a10_ullptr(nil), "nil" )
    assert_equal( a1.a10_ullptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "24" )
    assert_equal( x.value.to_s, "24" )
    x = RBA::Value.new("z")
    assert_equal( a1.a10_sptr(x), "zx" )
    assert_equal( a1.a10_sptr("a"), "ax" )
    assert_equal( a1.a10_sptr(nil), "nil" )
    assert_equal( a1.a10_sptr(RBA::Value.new), "nil" )
    assert_equal( x.to_s, "zx" )
    assert_equal( x.value.to_s, "zx" )
    begin
      # passing other objects than StringValue and a string fails
      assert_equal( a1.a10_sptr([]), "nil" )
      err = false
    rescue 
      err = true
    end
    assert_equal( err, true )

    assert_equal( a1.a10_cfptr(6.5), "6.5" )
    assert_equal( a1.a10_cfptr(nil), "nil" )
    assert_equal( a1.a10_cdptr(8.5), "8.5" )
    assert_equal( a1.a10_cdptr(nil), "nil" )
    assert_equal( a1.a10_ciptr(9), "9" )
    assert_equal( a1.a10_ciptr(nil), "nil" )
    assert_equal( a1.a10_cbptr(true), "true" )
    assert_equal( a1.a10_cbptr(nil), "nil" )
    assert_equal( a1.a10_cuiptr(20), "20" )
    assert_equal( a1.a10_cuiptr(nil), "nil" )
    assert_equal( a1.a10_culptr(21), "21" )
    assert_equal( a1.a10_culptr(nil), "nil" )
    assert_equal( a1.a10_clptr(22), "22" )
    assert_equal( a1.a10_clptr(nil), "nil" )
    assert_equal( a1.a10_cllptr(23), "23" )
    assert_equal( a1.a10_cllptr(nil), "nil" )
    assert_equal( a1.a10_cullptr(24), "24" )
    assert_equal( a1.a10_cullptr(nil), "nil" )
    assert_equal( a1.a10_csptr(nil), "nil" )
    assert_equal( a1.a10_csptr("x"), "x" )

    x = RBA::Value.new(1.5)
    assert_equal( a1.a10_fref(x), "11.5" )
    begin
      assert_equal( a1.a10_fref(nil), "nil" )
      err = false
    rescue 
      err = true
    end
    assert_equal( err, true )
    begin
      assert_equal( a1.a10_fref(RBA::Value.new), "nil" )
      err = false
    rescue 
      err = true
    end
    assert_equal( err, true )
    assert_equal( x.value.to_s, "11.5" )
    x = RBA::Value.new(2.5)
    assert_equal( a1.a10_dref(x), "13.5" )
    assert_equal( a1.a10_dref(2), "13" )
    assert_equal( x.value.to_s, "13.5" )
    x = RBA::Value.new(2)
    assert_equal( a1.a10_iref(x), "14" )
    assert_equal( a1.a10_iref(1), "13" )
    assert_equal( x.value.to_s, "14" )
    x = RBA::Value.new(false)
    assert_equal( a1.a10_bref(x), "true" )
    assert_equal( a1.a10_bref(false), "true" )
    assert_equal( x.value.to_s, "true" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_uiref(x), "24" )
    assert_equal( a1.a10_uiref(11), "25" )
    assert_equal( x.value.to_s, "24" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_ulref(x), "25" )
    assert_equal( a1.a10_ulref(12), "27" )
    assert_equal( x.value.to_s, "25" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_lref(x), "26" )
    assert_equal( a1.a10_lref(13), "29" )
    assert_equal( x.value.to_s, "26" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_llref(x), "27" )
    assert_equal( a1.a10_llref(14), "31" )
    assert_equal( x.value.to_s, "27" )
    x = RBA::Value.new(10)
    assert_equal( a1.a10_ullref(x), "28" )
    assert_equal( a1.a10_ullref(11), "29" )
    assert_equal( x.value.to_s, "28" )
    x = RBA::Value.new("x")
    assert_equal( a1.a10_sref(x), "xy" )
    assert_equal( a1.a10_sref("p"), "py" )
    assert_equal( x.value.to_s, "xy" )

    assert_equal( a1.a10_cfref(6.5), "6.5" )
    begin
      assert_equal( a1.a10_cfref(nil), "nil" )
      err = false
    rescue 
      err = true
    end
    assert_equal( err, true )
    assert_equal( a1.a10_cdref(8.5), "8.5" )
    assert_equal( a1.a10_ciref(9), "9" )
    assert_equal( a1.a10_cbref(true), "true" )
    assert_equal( a1.a10_cuiref(20), "20" )
    assert_equal( a1.a10_culref(21), "21" )
    assert_equal( a1.a10_clref(22), "22" )
    assert_equal( a1.a10_cllref(23), "23" )
    assert_equal( a1.a10_cullref(24), "24" )
    assert_equal( a1.a10_csref("x"), "x" )

  end

  def test_13

    b = RBA::B.new

    if !$leak_check 

      err_caught = false
      begin
        b.b7.a1 # cannot call non-const method on const reference
      rescue 
        err_caught = true
      end
      assert_equal( err_caught, true )

    end
      
    b.b7.a2 

    assert_equal( b.b1, 5 )
    assert_equal( b.b2, "" )
    b.b5( "xyz" )
    assert_equal( b.b2, "xyz" )
    assert_equal( b.b5a, "xyz" )
    b.b5b( "yx", "zz" )
    assert_equal( b.b2, "yxzz" )
    assert_equal( b.b5a, "yxzz" )

    arr = []

    err_caught = false

    if !$leak_check 

      begin
        b.b10 { |a| arr.push(a.a1) }  # b10 is a const iterator - cannot call a1 on it
      rescue 
        err_caught = true
      end
      assert_equal( err_caught, true )
      assert_equal(arr, [])

    end
   
    err_caught = false

    if !$leak_check 

      begin
        b.b10p { |a| arr.push(a.a1) }  # b10p is a const iterator - cannot call a1 on it
      rescue 
        err_caught = true
      end
      assert_equal( err_caught, true )
      assert_equal(arr, [])

    end
   
    arr = []
    b.b10 { |a| arr.push(a.dup.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.dup.b10 { |a| arr.push(a.dup.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b10 { |a| arr.push(a.a1c) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b10p { |a| arr.push(a.dup.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.dup.b10p { |a| arr.push(a.dup.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b10p { |a| arr.push(a.a1c) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b11 { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.dup.b11 { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b12 { |a| arr.push(a.a1) } 
    assert_equal(arr, [7100, 7121, 7144, 7169])

    arr = []
    b.dup.b12 { |a| arr.push(a.a1) } 
    assert_equal(arr, [7100, 7121, 7144, 7169])

    aarr = b.b16a 
    arr = []
    aarr.each { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    aarr = b.b16b 
    arr = []
    aarr.each { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    aarr = b.b16c 
    arr = []
    aarr.each { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    b.b17a( [ RBA::A.new_a( 101 ), RBA::A.new_a( -122 ) ] )
    arr = []
    b.b11 { |a| arr.push(a.a1) } 
    assert_equal(arr, [101, -122])

    b.b17a( [] )
    arr = []
    b.b11 { |a| arr.push(a.a1) } 
    assert_equal(arr, [])

    b.b17b( [ RBA::A.new_a( 102 ), RBA::A.new_a( -123 ) ] )
    arr = []
    b.b11 { |a| arr.push(a.a1) } 
    assert_equal(arr, [102, -123])

    b.b17c( [ RBA::A.new_a( 100 ), RBA::A.new_a( 121 ), RBA::A.new_a( 144 ) ] )
    arr = []
    b.b11 { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    if !$leak_check 

      arr = []
      begin
        b.b13 { |a| arr.push(a.a1) } 
      rescue 
        err_caught = true
      end
      assert_equal( err_caught, true )
      assert_equal(arr, [])

    end

    arr = []
    b.b13 { |a| arr.push(a.a1c) } 
    assert_equal(arr, [-3100, -3121])

    arr = []
    b.dup.b13 { |a| arr.push(a.a1c) } 
    assert_equal(arr, [-3100, -3121])

    arr = []
    b.b18 { |a| arr.push(a.a1c) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b18 { |a| arr.push(a.a1) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    b.b18b { |a| arr.push(a.a1c) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    # even though b18b returns a "const A &", calling a non-const method does not work
    # since A is a managed object and is not turned into a copy.
    err_caught = false
    begin 
      b.b18b { |a| arr.push(a.a1) } 
    rescue
      err_caught = true
    end
    assert_equal(arr, [])
    assert_equal(err_caught, true)

    arr = []
    b.b18c { |a| arr.push(a.a1c) } 
    assert_equal(arr, [100, 121, 144])

    arr = []
    # this does not work since b18c delivers a "const *" which cannot be used to call a non-const
    # method on
    err_caught = false
    begin 
      b.b18c { |a| arr.push(a.a1) } 
    rescue
      err_caught = true
    end
    assert_equal(arr, [])
    assert_equal(err_caught, true)

  end

  def test_13b

    b = RBA::B.new

    bb = RBA::B.new
    bb.b5("a")
    b.push_b(bb)

    bb = RBA::B.new
    bb.b5("y")
    b.push_b(bb)

    bb = RBA::B.new
    bb.b5("uu")
    b.push_b(bb)

    arr = []
    b.each_b_copy { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    b.each_b_copy { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) } 
    assert_equal(arr, ["ax", "yx", "uux"])

    arr = []
    b.each_b_copy { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    b.each_b_cref { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    # this works, since the "const B &" will be converted to a copy
    b.each_b_cref { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) } 
    assert_equal(arr, ["ax", "yx", "uux"])

    arr = []
    b.each_b_cref { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    b.each_b_cptr { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    # const references cannot be modified
    err_caught = false
    begin
      b.each_b_cptr { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) } 
    rescue 
      err_caught = true
    end
    assert_equal(err_caught, true)
    assert_equal(arr, [])

    arr = []
    b.each_b_cptr { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    b.each_b_ref { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["a", "y", "uu"])

    arr = []
    b.each_b_ref { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) } 
    assert_equal(arr, ["ax", "yx", "uux"])

    arr = []
    b.each_b_ref { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["ax", "yx", "uux"])

    arr = []
    b.each_b_ptr { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["ax", "yx", "uux"])

    arr = []
    b.each_b_ptr { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) } 
    assert_equal(arr, ["axx", "yxx", "uuxx"])

    arr = []
    b.each_b_ptr { |bb| arr.push(bb.b2) } 
    assert_equal(arr, ["axx", "yxx", "uuxx"])

  end

  def test_14

    a = RBA::A.new
    a.a5( 22 )

    b = RBA::B.new
    assert_equal( b.b3( a ), 22 )
    assert_equal( b.b4( a ), "b4_result: 22" )
    a.a5( -6 )
    assert_equal( b.b3( a ), -6 )
    assert_equal( b.b4( a ), "b4_result: -6" )
    assert_equal( b.b4( RBA::A.new ), "b4_result: 17" )

  end

  def test_15

    a = RBA::A_NC.new
    assert_equal( true, a.is_a?(RBA::A) )
    a.a5( 22 )

    b = RBA::B.new
    assert_equal( b.b3( a ), 22 )
    assert_equal( b.b4( a ), "b4_result: 22" )
    a.a5( -6 )
    assert_equal( b.b3( a ), -6 )
    assert_equal( b.b4( a ), "b4_result: -6" )
    assert_equal( b.b4( RBA::A_NC.new ), "b4_result: 17" )

  end

  class X < Data
  end
  class Y < Object
  end

  def test_16

    if $leak_check 
      return
    end

    # Test, if this throws an error (object of class X passed to A argument):
    begin
      b = RBA::B.new
      assert_equal( b.b4( X.new ), "b4_result: -6" )
      assert_equal( false, true )  # this must never hit
    rescue
      assert_equal( $!.to_s(), "allocator undefined for Basic_TestClass::X" );
    end
  
    # Test, if this throws an error (object of class X passed to A argument):
    begin
      b = RBA::B.new
      assert_equal( b.b4( Y.new ), "b4_result: -6" )
      assert_equal( false, true )  # this must never hit
    rescue
      assert_equal( $!.to_s(), "Unexpected object type (expected argument of class A, got Basic_TestClass::Y) in B::b4" );
    end
  
    # Test, if this throws an error (object of class X passed to A argument):
    begin
      b = RBA::B.new
      bb = RBA::B.new
      assert_equal( b.b4( bb ), "b4_result: -6" )
      assert_equal( false, true )  # this must never hit
    rescue
      assert_equal( $!.to_s(), "Unexpected object type (expected argument of class A, got RBA::B) in B::b4" );
    end
  
  end

  def test_17

    # test copies of objects being returned

    b = RBA::B.new

    a = b.b6( 1971 );
    assert_equal( a.a1, 1971 );
    assert_equal( b.b9( a ), 1971 );

    aa = b.b6( -61 );
    assert_equal( b.b9cref( aa ), -61 );
    assert_equal( a.a1, 1971 );
    assert_equal( b.b9( a ), 1971 );
    assert_equal( aa.a1, -61 );
    assert_equal( b.b9( aa ), -61 );

    aa.a5 98;
    a.a5 100;
    
    assert_equal( a.a1, 100 );
    assert_equal( b.b9( a ), 100 );
    assert_equal( aa.a1, 98 );
    assert_equal( b.b9( aa ), 98 );

  end

  def test_18

    # Test references to objects (returned by b.b7)

    b = RBA::B.new
    b.b8( 77 )
    assert_equal( b.b7.a1c, 77 );

    b.b8cref( 79 )
    assert_equal( b.b7.a1c, 79 );

    aref = b.b7
    err_caught = false

    if !$leak_check 

      begin 
        x = aref.a1 # cannot call non-const method on const reference (as delivered by b7)
      rescue
        err_caught = true
      end
      assert_equal( err_caught, true )
      assert_equal( aref.a1c, 79 );

    end

    b.b8( -1 )
    assert_equal( aref.a1c, -1 );

  end

  class C_IMP1 < RBA::C 
    def f(s)
      return 615
    end
  end

  class C_IMP2 < RBA::C 
    def f(s)
      return s.size
    end
  end

  class C_IMP3 < RBA::C 
  end

  def test_19

    c0 = RBA::C.new
    assert_equal( c0.g("x"), 1977 );

    c1 = C_IMP1.new
    assert_equal( c1.g("x"), 615 );

    c2 = C_IMP2.new
    assert_equal( c2.g("x"), 1 );
    assert_equal( c2.g(""), 0 );
    assert_equal( c2.g("abc"), 3 );
    assert_equal( c1.g("x"), 615 );

    c3 = C_IMP3.new
    assert_equal( c3.g("x"), 1977 );

    assert_equal( RBA::C.s1, 4451 );
    RBA::C.s2clr
    RBA::C.s2( 7.0 )
    assert_equal( RBA::C.s3( 5.5 ), "5.500" );

    arr = []
    RBA::C.each { |i| arr.push i }
    assert_equal( arr, [ 0, 1, 2, 3, 4, 5, 6 ] )

    assert_equal( C_IMP1.s1, 4451 );
    C_IMP1.s2( 1.0 )
    assert_equal( C_IMP1.s3( 1.5 ), "1.500" );

    arr = []
    C_IMP1.each { |i| arr.push i }
    assert_equal( arr, [ 0, 1, 2, 3, 4, 5, 6, 0 ] )

    assert_equal( C_IMP2.s1, 4451 );
    C_IMP2.s2( 2.0 )
    assert_equal( C_IMP2.s3( -1.5 ), "-1.500" );

    arr = []
    C_IMP2.each { |i| arr.push i }
    assert_equal( arr, [ 0, 1, 2, 3, 4, 5, 6, 0, 0, 1 ] )

  end

  def test_20

    b = RBA::B.new

    a1 = b.b14a( true )
    a2 = b.b14b
    assert_equal( a1.a1, 17 )
    assert_equal( a2.a1, 17 )
    a1.a5( 761 )
    assert_equal( a1.a1, 761 )
    assert_equal( a2.a1, 761 )

    a1 = b.b14a( false )
    assert_equal( a1, nil )
    
    assert_equal( b.b15( b.b14b ), true )
    assert_equal( b.b15( b.b14a( false ) ), false )
    assert_equal( b.b15( nil ), false )

  end

  def test_21

    # test client data binding to C++ objects 
    
    b = RBA::B.new
    
    b.b14b.s( 117 )
    assert_equal( b.b14b.g, 117 )

    n = 0
    b.b10_nc { |a| a.s( n ); n += 1 } 

    arr = []
    b.b10 { |a| arr.push( a.g ) }
    assert_equal( arr, [ 0, 1, 2 ] )

    arr = []
    b.b10p { |a| arr.push( a.g ) }
    assert_equal( arr, [ 0, 1, 2 ] )

  end

  def test_22

    # test client data binding to C++ objects 
    
    b = RBA::B.new
    
    assert_equal( b.b20a( 5.0 ), false )
    assert_equal( b.b20a( nil ), true )
    assert_equal( b.b20a( 1 ), false )
    assert_equal( b.b20a( "hallo" ), false )
    assert_equal( b.b20a( false ), false )
    assert_equal( b.b20a( true ), false )
    assert_equal( b.b20a( 10000000000000000 ), false )
    assert_equal( b.b20b( 5.0 ), true )
    assert_equal( b.b20b( nil ), false )
    assert_equal( b.b20b( 1 ), false )
    assert_equal( b.b20b( "hallo" ), false )
    assert_equal( b.b20b( false ), false )
    assert_equal( b.b20b( true ), false )
    # on 64 bit platforms this fits into a long value, therefore this test returns false:
    # assert_equal( b.b20b( 10000000000000000 ), false )
    assert_equal( b.b20c( 5.0 ), false )
    assert_equal( b.b20c( nil ), false )
    assert_equal( b.b20c( 1 ), true )
    assert_equal( b.b20c( "hallo" ), false )
    assert_equal( b.b20c( false ), false )
    assert_equal( b.b20c( true ), false )
    # on 64 bit platforms this fits into a long value, therefore this test returns true:
    # assert_equal( b.b20c( 10000000000000000 ), false )
    assert_equal( b.b20d( 5.0 ), false )
    assert_equal( b.b20d( nil ), false )
    assert_equal( b.b20d( 1 ), false )
    assert_equal( b.b20d( "hallo" ), true )
    assert_equal( b.b20d( false ), false )
    assert_equal( b.b20d( true ), false )
    assert_equal( b.b20d( 10000000000000000 ), false )
    assert_equal( b.b20e( 5.0 ), false )
    assert_equal( b.b20e( nil ), false )
    assert_equal( b.b20e( 1 ), false )
    assert_equal( b.b20e( "hallo" ), false )
    assert_equal( b.b20e( false ), true )
    assert_equal( b.b20e( true ), true )
    assert_equal( b.b20e( 10000000000000000 ), false )

    assert_equal( b.b21a( 50 ), "50" )
    assert_equal( b.b21a( true ), "true" )
    assert_equal( b.b21a( false ), "false" )
    assert_equal( b.b21a( "hallo" ), "hallo" )
    assert_equal( b.b21a( 5.5 ), "5.5" )
    assert_equal( b.b21a( nil ), "nil" )

    assert_equal( b.b21b( 50 ), 50.0 )
    assert_equal( b.b21b( true ), 1.0 )
    assert_equal( b.b21b( false ), 0.0 )
    assert_equal( b.b21b( 5.5 ), 5.5 )
    assert_equal( b.b21b( nil ), 0.0 )

    assert_equal( b.b21c( 50 ), 50 )
    assert_equal( b.b21c( true ), 1 )
    assert_equal( b.b21c( false ), 0 )
    assert_equal( b.b21c( 5.5 ), 5 )
    assert_equal( b.b21c( nil ), 0 )

    assert_equal( b.b22a( [ 1, "hallo", 5.5 ] ), 3 ) 
    assert_equal( b.b23a, [ 1, "hallo", 5.5 ] ) 
    a = [] 
    b.b24 { |x| a.push( x ) } 
    assert_equal( a, [ 1, "hallo", 5.5 ] ) 
    assert_equal( b.b22c, 5.5 )
    assert_equal( b.b22d, 5.5 )
    assert_equal( b.b22a( [ 1, "hallo" ] ), 2 ) 
    assert_equal( b.b23b, [ 1, "hallo" ] ) 
    assert_equal( b.b23d, [ 1, "hallo" ] ) 
    assert_equal( b.b23e, [ 1, "hallo" ] ) 
    assert_equal( b.b23e_null, nil ) 
    assert_equal( b.b23f, [ 1, "hallo" ] ) 
    assert_equal( b.b23f_null, nil ) 
    assert_equal( b.b22c, "hallo" )
    assert_equal( b.b22d, "hallo" )
    assert_equal( b.b22a( [ ] ), 0 ) 
    assert_equal( b.b23c, [ ] ) 
    a = [] 
    b.b24 { |x| a.push( x ) } 
    assert_equal( a, [ ] ) 
    assert_equal( b.b22b, nil )
    assert_equal( b.b22c, nil )
    assert_equal( b.b22d, nil )
    assert_equal( b.b22a( [ [ 1, "hallo" ], [ 10, 17, 20 ] ] ), 2 ) 
    assert_equal( b.b23a, [ [ 1, "hallo" ], [ 10, 17, 20 ] ] ) 
    a = [] 
    b.b24 { |x| a.push( x ) } 
    assert_equal( a, [ [ 1, "hallo" ], [ 10, 17, 20 ] ] ) 

    # ability to pass complex objects over tl::Variant:
    assert_equal( b.b22a( [ RBA::Box.new(RBA::Point.new(0, 0), RBA::Point.new(10, 20)) ] ), 1 ) 
    assert_equal( b.b22c.to_s, "(0,0;10,20)" )
    assert_equal( b.b22c.class.inspect, "RBA::Box" )

    # ability to pass complex objects over tl::Variant:
    assert_equal( b.b22a( [ RBA::DBox.new(RBA::DPoint.new(0, 0), RBA::DPoint.new(10, 20)) ] ), 1 ) 
    assert_equal( b.b22c.to_s, "(0,0;10,20)" )
    assert_equal( b.b22c.class.inspect, "RBA::DBox" )

    # ability to pass complex objects over tl::Variant:
    assert_equal( b.b22a( [ RBA::LayerInfo.new("hallo") ] ), 1 ) 
    assert_equal( b.b22c.to_s, "hallo" )
    assert_equal( b.b22c.class.inspect, "RBA::LayerInfo" )

  end

  def test_23

    b = RBA::B::new
    a = RBA::A::new

    assert_equal( b.bx, 17 )
    assert_equal( b.b30, 17 )
    assert_equal( b.bx( 5 ), "xz" )
    assert_equal( b.by( 5 ), "xz" )
    assert_equal( b.b31( 6 ), "xz" )
    assert_equal( b.b33( a ), "aref" )
    assert_equal( b.bx( a ), "aref" )
    assert_equal( b.bx( "a", 15 ), 20.5 )
    assert_equal( b.b32( "b", 25 ), 20.5 )

    err_caught = false
    begin 
      # invalid number of arguments
      assert_equal( b.by, "xz" )
    rescue
      err_caught = true
    end
    assert_equal( err_caught, true )

    err_caught = false
    begin 
      # invalid number of arguments
      assert_equal( b.bx( 1, 5, 7 ), "xz" )
    rescue
      err_caught = true
    end
    assert_equal( err_caught, true )

    b.destroy
    a.destroy

  end

  def test_24

    n0 = 0
    n1 = 0
    n2 = "" 

    # Events
    e = RBA::E.new
    e.m = 100

    e.s1 # no event installed
    assert_equal( 0, n0 )
    e.s2
    assert_equal( 0, n1 )
    e.s3
    assert_equal( "", n2 )

    assert_equal( 100, e.m )
    e.e0 { n0 += 1 }
    e.e1 { |x| n1 += x.m }
    e.e2 { |i,s| n2 += i.to_s + s; } 

    e.s1
    assert_equal( 1, n0 )
    e.s1
    assert_equal( 2, n0 )

    # using lambda
    p = lambda { n0 += 2 }
    e.e0(&p)
    e.s1
    assert_equal( 4, n0 )

    e.s2
    assert_equal( 100, n1 )
    e.m = 1
    e.s2
    assert_equal( 101, n1 )

    e.s3
    assert_equal( "18hallo", n2 )
    e.s3
    assert_equal( "18hallo18hallo", n2 )

    e.e0 { raise "X" }
    error_caught = false
    begin 
      e.s1
    rescue
      error_caught = true
    end
    assert_equal( error_caught, true )

    e.e0r { 5; }
    assert_equal( e.s1r("x"), 5 )
    e.e0r { |s| s.length + 2; }
    assert_equal( e.s1r("x"), 3 )
    assert_equal( e.s1r("abcxyz"), 8 )

  end

  def test_25

    # destruction of an instance via c++
    GC.start
    ac0 = RBA::A.a0 

    a = RBA::A::new
    a.create
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    RBA::A.a20(a)    # install static instance of A
    assert_equal(a.destroyed?, false)
    RBA::A.a20(nil) 
    assert_equal(RBA::A.a0, ac0)
    assert_equal(a.destroyed?, true)

    a = RBA::A::new
    a.create
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    RBA::A.a20(a)    # install static instance of A
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    RBA::A.a20(a)    # re-install static instance of A
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    
    # install another instance
    aa = RBA::A::new
    aa.create
    assert_equal(aa.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 2)
    RBA::A.a20(aa)    # install static instance of A

    # original one is destroyed now, only new instance remains
    assert_equal(a.destroyed?, true)
    assert_equal(aa.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    RBA::A.a20(nil)    # discard installed instance
    assert_equal(aa.destroyed, true)
    assert_equal(RBA::A.a0, ac0)

    # the same without create .. should work too, but not create an instance because of late 
    # instantiation in default ctor
    a = RBA::A::new
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0)
    RBA::A.a20(a)    # install static instance of A
    assert_equal(a.destroyed?, false)
    RBA::A.a20(nil) 
    assert_equal(RBA::A.a0, ac0)
    assert_equal(a.destroyed?, true)

  end

  def test_26

    # destruction of an instance via c++
    GC.start
    ac0 = RBA::A.a0 

    a = RBA::A::new
    a._create
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    RBA::A.a20(a)    # install static instance of A
    assert_equal(RBA::A.a20_get == nil, false)
    # release A instance -> will delete it
    # Note: overwriting the instance makes sure it's deleted (?)
    a = RBA::A.new()
    a._create
    a._destroy
    a = nil
    GC.start
    assert_equal(RBA::A.a0, ac0)
    assert_equal(RBA::A.a20_get == nil, true)

    a = RBA::A::new
    a._create
    assert_equal(a.destroyed?, false)
    assert_equal(RBA::A.a0, ac0 + 1)
    RBA::A.a20(a)    # install static instance of A
    assert_equal(RBA::A.a20_get == nil, false)
    a._unmanage
    # release A instance -> won't delete it since it is unmanaged
    # Note: overwriting the instance makes sure it's deleted (?)
    a = RBA::A.new()
    a._create
    a._destroy
    a = nil
    GC.start
    assert_equal(RBA::A.a0, ac0 + 1)
    assert_equal(RBA::A.a20_get == nil, false)

    a = RBA::A.a20_get
    a._manage
    # release A instance -> will be deleted since now it's managed again
    # Note: overwriting the instance makes sure it's deleted (?)
    a = RBA::A.new()
    a._create
    a._destroy
    a = nil
    GC.start
    assert_equal(RBA::A.a0, ac0)
    assert_equal(RBA::A.a20_get == nil, true)

  end

  def test_27

    # destruction of raw instances (non-gsi-enabled) via c++
    GC.start

    assert_equal(RBA::B.inst == nil, true)
    assert_equal(RBA::B.has_inst, false)

    b = RBA::B::new
    RBA::B.set_inst(b)
    assert_equal(RBA::B.has_inst, true)
    assert_equal(RBA::B.inst == b, false)
    assert_equal(RBA::B.inst.addr, b.addr)

    # new B instance -> will delete the old one
    # Note: overwriting the instance makes sure it's deleted (?)
    b = RBA::B.new()
    b._create
    b._destroy
    b = nil
    GC.start
    assert_equal(RBA::B.has_inst, false)

    b = RBA::B::new
    RBA::B.set_inst(b)
    b._unmanage
    ba = b.addr
    assert_equal(RBA::B.has_inst, true)
    assert_equal(RBA::B.inst == b, false)
    assert_equal(RBA::B.inst.addr, b.addr)

    # new B instance -> will not delete the old one (since we made it unmanaged)
    # Note: overwriting the instance makes sure it's deleted (?)
    b = RBA::B.new()
    b._create
    b._destroy
    b = nil
    GC.start
    assert_equal(RBA::B.has_inst, true)
    assert_equal(RBA::B.inst.addr, ba)

    # Make it managed again
    RBA::B.inst._manage

    # new B instance -> will delete the old one (since we made it managed again)
    # Note: overwriting the instance makes sure it's deleted (?)
    b = RBA::B.new()
    b._create
    b._destroy
    b = nil
    GC.start
    assert_equal(RBA::B.has_inst, false)

  end

  def test_30

    # some basic tests for the *Value boxing classes

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 17.5
    assert_equal(val.value, 17.5)
    assert_equal(val.to_s, "17.5")
    val.value += 1
    assert_equal(val.to_s, "18.5")
    val = RBA::Value::new(5)
    assert_equal(val.value, 5)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 17.5
    assert_equal(val.value, 17.5)
    assert_equal(val.to_s, "17.5")
    val.value += 1
    assert_equal(val.to_s, "18.5")
    val = RBA::Value::new(5)
    assert_equal(val.value, 5)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = true
    assert_equal(val.value, true)
    assert_equal(val.to_s, "true")
    val = RBA::Value::new(true)
    assert_equal(val.value, true)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 17
    assert_equal(val.value, 17)
    assert_equal(val.to_s, "17")
    val.value += 1
    assert_equal(val.to_s, "18")
    val = RBA::Value::new(5)
    assert_equal(val.value, 5)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 17
    assert_equal(val.value, 17)
    assert_equal(val.to_s, "17")
    val.value += 1
    assert_equal(val.to_s, "18")
    val = RBA::Value::new(5)
    assert_equal(val.value, 5)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 17
    assert_equal(val.value, 17)
    assert_equal(val.to_s, "17")
    val.value += 1
    assert_equal(val.to_s, "18")
    val = RBA::Value::new(5)
    assert_equal(val.value, 5)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 2700000000
    assert_equal(val.value, 2700000000)
    assert_equal(val.to_s, "2700000000")
    val.value += 1
    assert_equal(val.to_s, "2700000001")
    val = RBA::Value::new(500000000)
    assert_equal(val.value, 500000000)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 170000000000
    assert_equal(val.to_s, "170000000000")
    assert_equal(val.value, 170000000000)
    val.value += 1
    assert_equal(val.to_s, "170000000001")
    val = RBA::Value::new(50000000000)
    assert_equal(val.value, 50000000000)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.to_s, "nil")
    assert_equal(val.value, nil)
    val.value = 170000000000
    assert_equal(val.value, 170000000000)
    assert_equal(val.to_s, "170000000000")
    val.value += 1
    assert_equal(val.to_s, "170000000001")
    val = RBA::Value::new(50000000000)
    assert_equal(val.value, 50000000000)
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

    val = RBA::Value::new
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")
    val.value = "abc"
    assert_equal(val.value, "abc")
    assert_equal(val.to_s, "abc")
    val.value += "x"
    assert_equal(val.to_s, "abcx")
    val = RBA::Value::new("uv")
    assert_equal(val.value, "uv")
    val.value = nil
    assert_equal(val.value, nil)
    assert_equal(val.to_s, "nil")

  end

  def test_31

    # some basic tests with derived and base classes

    RBA::X.init
    RBA::Y.init
    x = RBA::X.new("hallo")
    assert_equal(true, x.is_a?(RBA::X))
    assert_equal(false, x.is_a?(RBA::A))
    assert_equal(false, x.is_a?(RBA::Y))
    assert_equal("hallo", x.s)
    assert_equal("RBT_X", x.cls_name)
    cxp = RBA::X.x_cptr
    assert_equal("RBT_X::a", cxp.s)
    begin 
      cxp.s = "x"
      error_caught = false
    rescue
      error_caught = true
    end
    assert_equal(true, error_caught)
    xp = RBA::X.x_ptr
    assert_equal("RBT_X::a", xp.s)
    xp.s = "x"
    assert_equal("x", xp.s)

    y = RBA::Y.new("hallo")
    assert_equal(true, y.is_a?(RBA::X))
    assert_equal(false, y.is_a?(RBA::A))
    assert_equal(true, y.is_a?(RBA::Y))
    assert_equal("hallo", y.s)
    assert_equal("RBT_Y", y.cls_name)
    assert_equal(5, y.i)
    cyp = RBA::Y.y_cptr
    assert_equal("RBT_Y::a", cyp.s)
    assert_equal("RBT_Y", cyp.cls_name)
    begin 
      cyp.s = "y"
      error_caught = false
    rescue
      error_caught = true
    end
    assert_equal(true, error_caught)
    yp = RBA::Y.y_ptr
    assert_equal("RBT_Y", yp.cls_name)
    assert_equal("RBT_Y::a", yp.s)
    yp.s = "y"
    assert_equal("y", yp.s)
    assert_equal(1, yp.i)
    yp.s = "abc"
    assert_equal(3, yp.i)
    assert_equal("RBA::Y", yp.class.to_s)

  end

  def test_32

    # run test only if we have Qt bindings 
    if !RBA.constants.find { |x| x == :QStringPair }
      return
    end

    # QPair<String, String>
    p = RBA::QStringPair.new
    p.first = "a"
    p.second = "b"
    assert_equal("a", p.first)
    assert_equal("b", p.second)
    pp = p.dup
    assert_equal("a", pp.first)
    assert_equal("b", pp.second)
    pp.first = "u"
    assert_equal("a", p.first)
    assert_equal("b", p.second)
    assert_equal("u", pp.first)
    assert_equal("b", pp.second)
    assert_equal(pp == p, false)
    assert_equal(pp != p, true)
    pp = RBA::QStringPair.new("a", "b")
    assert_equal("a", pp.first)
    assert_equal("b", pp.second)
    assert_equal(pp == p, true)
    assert_equal(pp != p, false)

  end

  def test_33

    # run test only if we have Qt bindings 
    if !RBA.constants.find { |x| x == :QByteArrayPair }
      return
    end

    # QPair<QByteArray, QByteArray>
    p = RBA::QByteArrayPair.new
    p.first = "a"
    p.second = "b"
    assert_equal("a", p.first)
    assert_equal("b", p.second)
    pp = p.dup
    assert_equal("a", pp.first)
    assert_equal("b", pp.second)
    pp.first = "u"
    assert_equal("a", p.first)
    assert_equal("b", p.second)
    assert_equal("u", pp.first)
    assert_equal("b", pp.second)
    assert_equal(pp == p, false)
    assert_equal(pp != p, true)
    pp = RBA::QByteArrayPair.new("a", "b")
    assert_equal("a", pp.first)
    assert_equal("b", pp.second)
    assert_equal(pp == p, true)
    assert_equal(pp != p, false)

  end

  def test_34

    # run test only if we have Qt bindings 
    if !RBA.constants.find { |x| x == :QDialog }
      return
    end

    # QDialog and QWidget
    # Hint: QApplication creates some leaks (FT, GTK). Hence it must not be used in the leak_check case ..
    if !$leak_check 

      # Note: Qt4.8.5/GTK+ seems not to like creating an QApplication object twice.
      # hence we do so only once.
      $app_inst ||= RBA::QApplication.new_app

      qd = RBA::QDialog.new
      RBA::QApplication.setActiveWindow(qd)
      assert_equal(RBA::QApplication.activeWindow.inspect, qd.inspect)
      assert_equal("RBA::QDialog", RBA::QApplication.activeWindow.class.to_s)
      assert_equal($app_inst.object_id, RBA::QApplication.instance.object_id)
      qd._destroy
      assert_equal(RBA::QApplication.activeWindow.inspect, "nil")

      qd = RBA::QDialog.new
      RBA::QApplication.setActiveWindow(qd)
      assert_equal(RBA::QApplication.activeWindow.inspect, qd.inspect)
      assert_equal("RBA::QDialog", RBA::QApplication.activeWindow.class.to_s)
      assert_equal($app_inst.object_id, RBA::QApplication.instance.object_id)
      qd._destroy
      assert_equal(RBA::QApplication.activeWindow.inspect, "nil")

    end

  end

  def test_35

    # vectors of pointers

    RBA::X.init
    RBA::Y.init
    vx = RBA::X.vx
    assert_equal(2, vx.size)
    assert_equal("RBT_X::a", vx[0].s)
    assert_equal("RBT_X::b", vx[1].s)

    vx_ptr = RBA::X.vx_ptr
    vx_cptr = RBA::X.vx_cptr
    assert_equal(2, vx_ptr.size)
    assert_equal(2, vx_cptr.size)
    assert_equal("RBA::X", vx_ptr[0].class.to_s)
    assert_equal("RBA::X", vx_ptr[1].class.to_s)

    begin 
      vx_cptr[0].s = "y"
      error_caught = false
    rescue
      error_caught = true
    end
    assert_equal(true, error_caught)

    vx_ptr[0].s = "u"
    assert_equal("u", vx_cptr[0].s)
    assert_equal("RBT_X::a", vx[0].s)
    assert_equal("RBT_X::b", vx[1].s)

    vy0_ptr = RBA::Y.vy0_ptr
    assert_equal(1, vy0_ptr.size)
    assert_equal("nil", vy0_ptr[0].inspect)

    vy_ptr = RBA::Y.vy_ptr
    vy_cptr = RBA::Y.vy_cptr
    assert_equal(2, vy_ptr.size)
    assert_equal(2, vy_cptr.size)
    assert_equal("RBA::Y", vy_ptr[0].class.to_s)
    assert_equal("RBA::Y", vy_ptr[1].class.to_s)

    begin 
      vy_cptr[0].s = "y"
      error_caught = false
    rescue
      error_caught = true
    end
    assert_equal(true, error_caught)

    vy_ptr[0].s = "uvw"
    assert_equal("uvw", vy_cptr[0].s)
    assert_equal(3, vy_cptr[0].i)

    vy_ptr = RBA::Y.vyasx_ptr
    vy_cptr = RBA::Y.vyasx_cptr
    assert_equal(2, vy_ptr.size)
    assert_equal(2, vy_cptr.size)
    assert_equal("RBA::Y", vy_ptr[0].class.to_s)
    assert_equal("RBA::Y", vy_ptr[1].class.to_s)

    begin 
      vy_cptr[0].s = "y"
      error_caught = false
    rescue
      error_caught = true
    end
    assert_equal(true, error_caught)

    vy_ptr[0].s = "uvw"
    assert_equal("uvw", vy_cptr[0].s)
    assert_equal(3, vy_cptr[0].i)

    y = RBA::Y.new("")
    yc = y.vx_dyn_count
    y.vx_dyn_make
    assert_equal(yc + 1, y.vx_dyn_count)
    y.vx_dyn_destroy
    assert_equal(yc, y.vx_dyn_count)

    y.vx_dyn_make
    assert_equal(yc + 1, y.vx_dyn_count)
    yy = y.vx_dyn
    assert_equal(1, yy.size)
    assert_equal("RBA::Y", yy[0].class.to_s)
    assert_equal(true, yy[0] != nil)
    yy[0].destroy
    assert_equal(true, yy[0].destroyed?)
    assert_equal(yc, y.vx_dyn_count)

    y.vx_dyn_make
    assert_equal(yc + 1, y.vx_dyn_count)
    yy = y.vx_dyn
    assert_equal(1, yy.size)
    assert_equal("RBA::Y", yy[0].class.to_s)
    assert_equal(true, yy[0] != nil)
    y.vx_dyn_destroy
    assert_equal(true, yy[0].destroyed?)
    assert_equal(yc, y.vx_dyn_count)

  end

  def test_36

    x = XEdge.new
    assert_equal("XEdge", x.class.inspect)
    assert_equal("(1,2;3,4)", x.to_s)

  end

  def test_37

    # protected methods
    ok = false
    a = RBA::A.new
    e = ""
    begin
      a.a10_prot # cannot be called - is protected
      ok = true
    rescue => ex
      e = ex.to_s
    end
    assert_equal(e =~ /^protected method `a10_prot' called/, 0)
    assert_equal(ok, false)
    assert_equal(a.call_a10_prot(1.25), "1.25")

  end

  def test_38

    # mixed const / non-const reference and events
    ec = RBA::E.ic
    assert_equal(ec.is_const_object?, true)
    enc = RBA::E.inc
    # Now, ec has turned into a non-const reference as well!
    # This is strange but is a consequence of the unique C++/Ruby binding and there can 
    # only be a non-const or const ruby object!
    assert_equal(ec.is_const_object?, false)
    assert_equal(enc.is_const_object?, false)

    # the "true reference" is a not copy since E is derived from ObjectBase
    ec.x = 15
    assert_equal(ec.x, 15);
    ec2 = RBA::E.ic
    assert_equal(ec2.x, 15);
    ec2 = RBA::E.icref
    assert_equal(ec2.x, 15);
    ec2.x = 17
    assert_equal(ec2.x, 17);
    assert_equal(ec.x, 17);
    assert_equal(ec2.is_const_object?, false) # because it's a copy

    # the "true reference" is a not copy since E is derived from ObjectBase
    enc2 = RBA::E.incref
    assert_equal(enc2.x, 17);
    enc2.x = 19
    assert_equal(enc2.x, 19);
    assert_equal(ec.x, 19);  # because the non-const reference by incref is not a copy

  end

  def test_39

    # mixed const / non-const reference and events
    fc = RBA::F.ic
    assert_equal(fc.is_const_object?, true)
    fnc = RBA::F.inc
    # In contrase to E, the fc reference is not touched because F is not derived
    # from ObjectBase
    assert_equal(fc.is_const_object?, true)
    assert_equal(fnc.is_const_object?, false)

    # the "true reference" is a copy
    fnc.x = 15
    assert_equal(fc.x, 15);
    fc2 = RBA::F.ic
    assert_equal(fc2.x, 15);
    fc2 = RBA::F.icref
    assert_equal(fc2.x, 15);
    fc2.x = 17
    assert_equal(fc2.x, 17);
    assert_equal(fc.x, 15);
    assert_equal(fc2.is_const_object?, false) # because it's a copy

    # the "true reference" is a copy
    fnc2 = RBA::F.incref
    assert_equal(fnc2.x, 15);
    fnc2.x = 19
    assert_equal(fnc2.x, 19);
    assert_equal(fc.x, 19);  # because the non-const reference by incref is not a copy

  end

  def test_40

    # optional arguments
    g = RBA::G.new

    assert_equal(g.iv, 0)
    g.set_iva(2)
    assert_equal(g.iv, 2)
    g.set_ivb(3)
    assert_equal(g.iv, 3)
    g.set_ivb
    assert_equal(g.iv, 1)
    g.set_sv1a("hello")
    assert_equal(g.sv, "hello")

    failed = false
    begin
      g.set_sv1a
    rescue 
      failed = true
    end
    assert_equal(failed, true)

    g.set_sv1b("world")
    assert_equal(g.sv, "world")
    g.set_sv1b
    assert_equal(g.sv, "value")
    g.set_sv2a("hello")
    assert_equal(g.sv, "hello")

    failed = false
    begin
      g.set_sv2a
    rescue 
      failed = true
    end
    assert_equal(failed, true)

    g.set_sv2b("world")
    assert_equal(g.sv, "world")
    g.set_sv2b
    assert_equal(g.sv, "value")

    g.set_vva(17, "c")
    assert_equal(g.iv, 17)
    assert_equal(g.sv, "c")

    failed = false
    begin
      g.set_svva
    rescue 
      failed = true
    end
    assert_equal(failed, true)

    failed = false
    begin
      g.set_svva(11)
    rescue 
      failed = true
    end
    assert_equal(failed, true)

    g.set_vvb(11)
    assert_equal(g.iv, 11)
    assert_equal(g.sv, "value")
    g.set_vvb(10, "nil")
    assert_equal(g.iv, 10)
    assert_equal(g.sv, "nil")

    failed = false
    begin
      g.set_svvb
    rescue 
      failed = true
    end
    assert_equal(failed, true)

    g.set_vvc(11)
    assert_equal(g.iv, 11)
    assert_equal(g.sv, "value")
    g.set_vvc
    assert_equal(g.iv, 1)
    assert_equal(g.sv, "value")
    g.set_vvc(17, "nil")
    assert_equal(g.iv, 17)
    assert_equal(g.sv, "nil")

  end

  def test_41

    # maps 
    b = RBA::B.new

    b.insert_map1(1, "hello")
    assert_equal(b.map1.inspect, "{1=>\"hello\"}")

    b.map1 = {}
    b.insert_map1(2, "hello")
    assert_equal(b.map1_cref.inspect, "{2=>\"hello\"}")

    b.map1 = {}
    b.insert_map1(3, "hello")
    assert_equal(b.map1_cptr.inspect, "{3=>\"hello\"}")

    b.map1 = {}
    b.insert_map1(4, "hello")
    assert_equal(b.map1_ref.inspect, "{4=>\"hello\"}")

    b.map1 = {}
    b.insert_map1(5, "hello")
    assert_equal(b.map1_ptr.inspect, "{5=>\"hello\"}")

    assert_equal(b.map1_cptr_null == nil, true);
    assert_equal(b.map1_ptr_null == nil, true);

    begin
      b.map1 = { 42 => 1, -17 => true }
      error = nil
    rescue => ex
      error = ex.message.split("\n")[0]
    end
    if error == "can't convert Fixnum into String"
      # Ok
    elsif error == "no implicit conversion of Fixnum into String"
      # Ok 
    else
      assert_equal(error, "")
    end
    b.map1 = { 42 => "1", -17 => "true" }
    assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"1\"}")

    b.map1 = {}
    b.set_map1_cref({ 42 => "2", -17 => "true" })
    assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"2\"}")

    b.map1 = {}
    b.set_map1_cptr({ 42 => "3", -17 => "true" })
    assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"3\"}")

    b.map1 = {}
    b.set_map1_cptr(nil)
    assert_equal(b.map1.inspect, "{}")

    b.map1 = {}
    b.set_map1_cptr(nil)
    assert_equal(b.map1.inspect, "{}")

    b.map1 = {}
    b.set_map1_ref({ 42 => "4", -17 => "true" })
    assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"4\"}")

    b.map1 = {}
    b.set_map1_ptr({ 42 => "5", -17 => "true" })
    assert_equal(b.map1.inspect, "{-17=>\"true\", 42=>\"5\"}")

    b.map1 = {}
    b.set_map1_ptr(nil)
    assert_equal(b.map1.inspect, "{}")

    b.map2 = {}
    b.map2 = { 'xy' => 1, -17 => true }
    assert_equal(b.map2.inspect, "{-17=>true, \"xy\"=>1}")

    assert_equal(b.map2_null == nil, true)

  end

  class Z_IMP1 < RBA::Z 
    def f(x)
      return x.cls_name()
    end
  end

  class Z_IMP2 < RBA::Z 
    def f(x)
      return x.class.to_s()
    end
  end

  const_defined?(:Z_IMP3) && remove_const(:Z_IMP3)
  class Z_IMP3 < RBA::Z 
    alias f_org f
    def f(x)
      return self.f_org(x) + "*"
    end
  end

  def test_42

    # virtual functions and sub-classes 
    z = RBA::Z.new
    assert_equal(z.f(nil), "(nil)")
    assert_equal(z.f(RBA::X.new("hello")), "hello")

    z1 = Z_IMP1::new
    assert_equal(z1.f(RBA::X.new("a")), "RBT_X")
    assert_equal(z1.f(RBA::Y.new("b")), "RBT_Y")
    assert_equal(z1.f_with_x("a"), "RBT_X")
    assert_equal(z1.f_with_y("b"), "RBT_Y")
    assert_equal(z1.f_with_yy("b"), "RBT_YY")

    z2 = Z_IMP2::new
    assert_equal(z2.f(RBA::X.new("1")), "RBA::X")
    assert_equal(z2.f(RBA::Y.new("2")), "RBA::Y")
    assert_equal(z2.f_with_x("1"), "RBA::X")
    assert_equal(z2.f_with_y("2"), "RBA::Y")
    assert_equal(z2.f_with_yy("3"), "RBA::Y")

    z1 = Z_IMP3::new
    assert_equal(z1.f(RBA::X.new("x")), "x*")
    assert_equal(z1.f(RBA::Y.new("y")), "y*")
    assert_equal(z1.f_with_x("x"), "x*")
    assert_equal(z1.f_with_y("y"), "y*")
    assert_equal(z1.f_with_yy("yy"), "yy*")

  end

end

load("test_epilogue.rb")

