require 'test/unit' require 'cgen/cshadow'

class EmptyBase

include CShadow

end

class EBSub_1 < EmptyBase

shadow_attr_accessor :x => "int x"

end

class EBSub_1_1 < EBSub_1 end

class EBSub_2 < EmptyBase end

class EBSub_2_2 < EBSub_2

shadow_attr_accessor :x => "int x"

end

class Base

include CShadow
shadow_attr_reader :x => 'int x'
shadow_attr_writer :y => 'int y'
shadow_attr_accessor :obj => Array
shadow_attr_accessor :nonpersistent, :np => Object

end

class Sub_1 < Base

shadow_attr :z => 'int zzz'

end

class Sub_2 < Base

attr_reader :ruby_reader
attr_writer :ruby_writer

end

module Mod_For_Sub_3

class Sub_3 < Base
  # Make sure the nested class name bug isn't biting today.
end

end

class Sub_4 < Base

private :x
protected :y=

end

class OtherBase

include CShadow
shadow_library Base
shadow_attr_accessor :str => "char *pchar"

end

class OtherFile < OtherBase

shadow_library_file "OtherFile"
shadow_attr_accessor :x => "double x"

end

class CompileTimeTestCase < Test::Unit::TestCase

def test_conflict
  assert_raises(NameError) {
    Sub_2.class_eval {
      shadow_attr "y" => 'char * yy'
    }
  }
  assert_raises(NameError) {
    Sub_2.class_eval {
      shadow_attr :y => 'char * yy'
    }
  }
  assert_raises(NameError) {
    Sub_2.class_eval {
      shadow_attr :yy => 'char * y'
    }
  }

  # Checking overwrite by attr_*
  assert_raises(NameError) {
    Sub_2.class_eval {
      attr_accessor :y
    }
  }
  assert_raises(NameError) {
    Sub_2.class_eval {
      attr_reader :y
    }
  }
  assert_raises(NameError) {
    Sub_2.class_eval {
      attr_writer :y
    }
  }

  # Checking overwrite by shadow_attr_*
  assert_raises(NameError) {
    Sub_2.class_eval {
     shadow_attr_reader :ruby_writer => Object
    }
  }
  assert_raises(NameError) {
    Sub_2.class_eval {
     shadow_attr_writer :ruby_reader => Object
    }
  }
end

end

require 'ftools' dir = File.join("tmp", RUBY_VERSION) File.mkpath dir Dir.chdir dir

EmptyBase.commit Base.commit # do not commit OtherBase

METHOD_MISSING_ERROR =

RUBY_VERSION.to_f >= 1.7 ?
  NoMethodError :
  NameError

class EmptyBaseTestCase < Test::Unit::TestCase

def test_empty_base
  ebs1 = EBSub_1.new
  ebs2 = EBSub_2.new
  ebs11 = EBSub_1_1.new
  ebs22 = EBSub_2_2.new

  ebs1.x = 3
  ebs11.x = 4
  ebs22.x = 5

  assert_raises(METHOD_MISSING_ERROR) {
    ebs2.x = 6
  }

  assert_equal(3, ebs1.x)
  assert_equal(4, ebs11.x)
  assert_equal(5, ebs22.x)
end

end

class BaseTestCase < Test::Unit::TestCase

def test_limited_access
  b = Sub_1.new

  assert_raises(METHOD_MISSING_ERROR) {
    b.x = 1
  }
  assert_equal(0, b.x)

  b.y = 2
  assert_raises(METHOD_MISSING_ERROR) {
    b.y
  }

  assert_raises(METHOD_MISSING_ERROR) {
    b.z = 3
  }
  assert_raises(METHOD_MISSING_ERROR) {
    b.z
  }
end

def test_inherit
  b = Sub_1.new

  # test inheritance of attr initializers
  assert_equal(nil, b.obj)

  # test inheritance of attr dump/load code
  b.obj = [1,2,3]
  assert_equal([1,2,3], Marshal.load(Marshal.dump(b)).obj)
end

def test_marshal
  b = Base.new
  b.obj = [1, {:foo => "foo"}, "bar"]
  b.instance_eval {@z=3}
  bb = Marshal.load(Marshal.dump(b))
  assert_equal(bb.obj, b.obj)
  assert_equal(bb.instance_eval{@z}, b.instance_eval{@z})
end

def test_nonpersistence
  b = Base.new
  assert_equal(nil, b.np)
  b.np = [4,5,6]
  assert_equal([4,5,6], b.np)
  bb = Marshal.load(Marshal.dump(b))
  assert_equal(nil, bb.np)
end

def test_protect
  a = Base.new
  b = Sub_4.new
  assert_nothing_raised {a.x; a.y = 2}
  assert_raises(METHOD_MISSING_ERROR) {
    b.x
  }
  assert_raises(METHOD_MISSING_ERROR) {
    b.y = 2
  }
end

def test_reflection
  names = Sub_1.shadow_attrs.collect { |attr| attr.var.to_s }.sort
  assert_equal(['np', 'obj', 'x', 'y', 'z'], names)
end

end

class OtherBaseTestCase < Test::Unit::TestCase

def test_sharing_library
  ob = OtherBase.new
  ob.str = "fred"
  assert_equal("fred", ob.str)

  ob = OtherFile.new
  ob.x = 1.2
  assert_equal(1.2, ob.x)      
end

end

begin

require 'yaml'
module Kernel
  undef :y # else conflict with checking :y is undefined above
end
CShadow.allow_yaml

rescue Exception => e

$stderr.puts "Could not load yaml : #{e.inspect}"

else

class YamlTest < Test::Unit::TestCase

  def test_yaml
    base = Base.new
    base.obj = [1,2,3]
    base.np = "456"

    base2 = YAML.load(YAML.dump(base))

    assert_equal(base.obj, base2.obj)
    assert_equal(nil, base2.np)
  end

end

end