summaryrefslogtreecommitdiff
path: root/jni/ruby/test/ruby/test_module.rb
diff options
context:
space:
mode:
Diffstat (limited to 'jni/ruby/test/ruby/test_module.rb')
-rw-r--r--jni/ruby/test/ruby/test_module.rb2032
1 files changed, 2032 insertions, 0 deletions
diff --git a/jni/ruby/test/ruby/test_module.rb b/jni/ruby/test/ruby/test_module.rb
new file mode 100644
index 0000000..2f3e5c2
--- /dev/null
+++ b/jni/ruby/test/ruby/test_module.rb
@@ -0,0 +1,2032 @@
+require 'test/unit'
+require 'pp'
+
+$m0 = Module.nesting
+
+class TestModule < Test::Unit::TestCase
+ def _wrap_assertion
+ yield
+ end
+
+ def assert_method_defined?(klass, mid, message="")
+ message = build_message(message, "#{klass}\##{mid} expected to be defined.")
+ _wrap_assertion do
+ klass.method_defined?(mid) or
+ raise Test::Unit::AssertionFailedError, message, caller(3)
+ end
+ end
+
+ def assert_method_not_defined?(klass, mid, message="")
+ message = build_message(message, "#{klass}\##{mid} expected to not be defined.")
+ _wrap_assertion do
+ klass.method_defined?(mid) and
+ raise Test::Unit::AssertionFailedError, message, caller(3)
+ end
+ end
+
+ def setup
+ @verbose = $VERBOSE
+ $VERBOSE = nil
+ end
+
+ def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_LT_0
+ assert_equal true, String < Object
+ assert_equal false, Object < String
+ assert_nil String < Array
+ assert_equal true, Array < Enumerable
+ assert_equal false, Enumerable < Array
+ assert_nil Proc < Comparable
+ assert_nil Comparable < Proc
+ end
+
+ def test_GT_0
+ assert_equal false, String > Object
+ assert_equal true, Object > String
+ assert_nil String > Array
+ assert_equal false, Array > Enumerable
+ assert_equal true, Enumerable > Array
+ assert_nil Comparable > Proc
+ assert_nil Proc > Comparable
+ end
+
+ def test_CMP_0
+ assert_equal(-1, (String <=> Object))
+ assert_equal 1, (Object <=> String)
+ assert_nil(Array <=> String)
+ end
+
+ ExpectedException = NoMethodError
+
+ # Support stuff
+
+ module Mixin
+ MIXIN = 1
+ def mixin
+ end
+ end
+
+ module User
+ USER = 2
+ include Mixin
+ def user
+ end
+ end
+
+ module Other
+ def other
+ end
+ end
+
+ class AClass
+ def AClass.cm1
+ "cm1"
+ end
+ def AClass.cm2
+ cm1 + "cm2" + cm3
+ end
+ def AClass.cm3
+ "cm3"
+ end
+
+ private_class_method :cm1, "cm3"
+
+ def aClass
+ :aClass
+ end
+
+ def aClass1
+ :aClass1
+ end
+
+ def aClass2
+ :aClass2
+ end
+
+ private :aClass1
+ protected :aClass2
+ end
+
+ class BClass < AClass
+ def bClass1
+ :bClass1
+ end
+
+ private
+
+ def bClass2
+ :bClass2
+ end
+
+ protected
+ def bClass3
+ :bClass3
+ end
+ end
+
+ class CClass < BClass
+ def self.cClass
+ end
+ end
+
+ MyClass = AClass.clone
+ class MyClass
+ public_class_method :cm1
+ end
+
+ # -----------------------------------------------------------
+
+ def test_CMP # '<=>'
+ assert_equal( 0, Mixin <=> Mixin)
+ assert_equal(-1, User <=> Mixin)
+ assert_equal( 1, Mixin <=> User)
+
+ assert_equal( 0, Object <=> Object)
+ assert_equal(-1, String <=> Object)
+ assert_equal( 1, Object <=> String)
+ end
+
+ def test_GE # '>='
+ assert_operator(Mixin, :>=, User)
+ assert_operator(Mixin, :>=, Mixin)
+ assert_not_operator(User, :>=, Mixin)
+
+ assert_operator(Object, :>=, String)
+ assert_operator(String, :>=, String)
+ assert_not_operator(String, :>=, Object)
+ end
+
+ def test_GT # '>'
+ assert_operator(Mixin, :>, User)
+ assert_not_operator(Mixin, :>, Mixin)
+ assert_not_operator(User, :>, Mixin)
+
+ assert_operator(Object, :>, String)
+ assert_not_operator(String, :>, String)
+ assert_not_operator(String, :>, Object)
+ end
+
+ def test_LE # '<='
+ assert_operator(User, :<=, Mixin)
+ assert_operator(Mixin, :<=, Mixin)
+ assert_not_operator(Mixin, :<=, User)
+
+ assert_operator(String, :<=, Object)
+ assert_operator(String, :<=, String)
+ assert_not_operator(Object, :<=, String)
+ end
+
+ def test_LT # '<'
+ assert_operator(User, :<, Mixin)
+ assert_not_operator(Mixin, :<, Mixin)
+ assert_not_operator(Mixin, :<, User)
+
+ assert_operator(String, :<, Object)
+ assert_not_operator(String, :<, String)
+ assert_not_operator(Object, :<, String)
+ end
+
+ def test_VERY_EQUAL # '==='
+ assert_operator(Object, :===, self)
+ assert_operator(Test::Unit::TestCase, :===, self)
+ assert_operator(TestModule, :===, self)
+ assert_not_operator(String, :===, self)
+ end
+
+ def test_ancestors
+ assert_equal([User, Mixin], User.ancestors)
+ assert_equal([Mixin], Mixin.ancestors)
+
+ ancestors = Object.ancestors
+ mixins = ancestors - [Object, Kernel, BasicObject]
+ mixins << JSON::Ext::Generator::GeneratorMethods::String if defined?(JSON::Ext::Generator::GeneratorMethods::String)
+ assert_equal([Object, Kernel, BasicObject], ancestors - mixins)
+ assert_equal([String, Comparable, Object, Kernel, BasicObject], String.ancestors - mixins)
+ end
+
+ CLASS_EVAL = 2
+ @@class_eval = 'b'
+
+ def test_class_eval
+ Other.class_eval("CLASS_EVAL = 1")
+ assert_equal(1, Other::CLASS_EVAL)
+ assert_include(Other.constants, :CLASS_EVAL)
+ assert_equal(2, Other.class_eval { CLASS_EVAL })
+
+ Other.class_eval("@@class_eval = 'a'")
+ assert_equal('a', Other.class_variable_get(:@@class_eval))
+ assert_equal('b', Other.class_eval { @@class_eval })
+
+ Other.class_eval do
+ module_function
+
+ def class_eval_test
+ "foo"
+ end
+ end
+ assert_equal("foo", Other.class_eval_test)
+
+ assert_equal([Other], Other.class_eval { |*args| args })
+ end
+
+ def test_const_defined?
+ assert_operator(Math, :const_defined?, :PI)
+ assert_operator(Math, :const_defined?, "PI")
+ assert_not_operator(Math, :const_defined?, :IP)
+ assert_not_operator(Math, :const_defined?, "IP")
+ end
+
+ def each_bad_constants(m, &b)
+ [
+ "#<Class:0x7b8b718b>",
+ ":Object",
+ "",
+ ":",
+ ["String::", "[Bug #7573]"],
+ "\u3042",
+ "Name?",
+ ].each do |name, msg|
+ expected = "wrong constant name %s" % quote(name)
+ msg = "#{msg}#{': ' if msg}wrong constant name #{name.dump}"
+ assert_raise_with_message(NameError, expected, "#{msg} to #{m}") do
+ yield name
+ end
+ end
+ end
+
+ def test_bad_constants_get
+ each_bad_constants("get") {|name|
+ Object.const_get name
+ }
+ end
+
+ def test_bad_constants_defined
+ each_bad_constants("defined?") {|name|
+ Object.const_defined? name
+ }
+ end
+
+ def test_leading_colons
+ assert_equal Object, AClass.const_get('::Object')
+ end
+
+ def test_const_get
+ assert_equal(Math::PI, Math.const_get("PI"))
+ assert_equal(Math::PI, Math.const_get(:PI))
+
+ n = Object.new
+ def n.to_str; @count = defined?(@count) ? @count + 1 : 1; "PI"; end
+ def n.count; @count; end
+ assert_equal(Math::PI, Math.const_get(n))
+ assert_equal(1, n.count)
+ end
+
+ def test_nested_get
+ assert_equal Other, Object.const_get([self.class, Other].join('::'))
+ assert_equal User::USER, self.class.const_get([User, 'USER'].join('::'))
+ end
+
+ def test_nested_get_symbol
+ const = [self.class, Other].join('::').to_sym
+ assert_raise(NameError) {Object.const_get(const)}
+
+ const = [User, 'USER'].join('::').to_sym
+ assert_raise(NameError) {self.class.const_get(const)}
+ end
+
+ def test_nested_get_const_missing
+ classes = []
+ klass = Class.new {
+ define_singleton_method(:const_missing) { |name|
+ classes << name
+ klass
+ }
+ }
+ klass.const_get("Foo::Bar::Baz")
+ assert_equal [:Foo, :Bar, :Baz], classes
+ end
+
+ def test_nested_get_bad_class
+ assert_raise(TypeError) do
+ self.class.const_get([User, 'USER', 'Foo'].join('::'))
+ end
+ end
+
+ def test_nested_defined
+ assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')])
+ assert_send([self.class, :const_defined?, 'User::USER'])
+ assert_not_send([self.class, :const_defined?, 'User::Foo'])
+ end
+
+ def test_nested_defined_symbol
+ const = [self.class, Other].join('::').to_sym
+ assert_raise(NameError) {Object.const_defined?(const)}
+
+ const = [User, 'USER'].join('::').to_sym
+ assert_raise(NameError) {self.class.const_defined?(const)}
+ end
+
+ def test_nested_defined_bad_class
+ assert_raise(TypeError) do
+ self.class.const_defined?('User::USER::Foo')
+ end
+ end
+
+ def test_const_set
+ assert_not_operator(Other, :const_defined?, :KOALA)
+ Other.const_set(:KOALA, 99)
+ assert_operator(Other, :const_defined?, :KOALA)
+ assert_equal(99, Other::KOALA)
+ Other.const_set("WOMBAT", "Hi")
+ assert_equal("Hi", Other::WOMBAT)
+
+ n = Object.new
+ def n.to_str; @count = defined?(@count) ? @count + 1 : 1; "HOGE"; end
+ def n.count; @count; end
+ def n.count=(v); @count=v; end
+ assert_not_operator(Other, :const_defined?, :HOGE)
+ Other.const_set(n, 999)
+ assert_equal(1, n.count)
+ n.count = 0
+ assert_equal(999, Other.const_get(n))
+ assert_equal(1, n.count)
+ n.count = 0
+ assert_equal(true, Other.const_defined?(n))
+ assert_equal(1, n.count)
+ end
+
+ def test_constants
+ assert_equal([:MIXIN], Mixin.constants)
+ assert_equal([:MIXIN, :USER], User.constants.sort)
+ end
+
+ def test_self_initialize_copy
+ bug9535 = '[ruby-dev:47989] [Bug #9535]'
+ m = Module.new do
+ def foo
+ :ok
+ end
+ initialize_copy(self)
+ end
+ assert_equal(:ok, Object.new.extend(m).foo, bug9535)
+ end
+
+ def test_initialize_copy_empty
+ bug9813 = '[ruby-dev:48182] [Bug #9813]'
+ m = Module.new do
+ def x
+ end
+ const_set(:X, 1)
+ @x = 2
+ end
+ assert_equal([:x], m.instance_methods)
+ assert_equal([:@x], m.instance_variables)
+ assert_equal([:X], m.constants)
+ m.module_eval do
+ initialize_copy(Module.new)
+ end
+ assert_empty(m.instance_methods, bug9813)
+ assert_empty(m.instance_variables, bug9813)
+ assert_empty(m.constants, bug9813)
+ end
+
+ def test_dup
+ bug6454 = '[ruby-core:45132]'
+
+ a = Module.new
+ Other.const_set :BUG6454, a
+ b = a.dup
+ Other.const_set :BUG6454_dup, b
+
+ assert_equal "TestModule::Other::BUG6454_dup", b.inspect, bug6454
+ end
+
+ def test_dup_anonymous
+ bug6454 = '[ruby-core:45132]'
+
+ a = Module.new
+ original = a.inspect
+
+ b = a.dup
+
+ assert_not_equal original, b.inspect, bug6454
+ end
+
+ def test_public_include
+ assert_nothing_raised('#8846') do
+ Module.new.include(Module.new { def foo; end }).instance_methods == [:foo]
+ end
+ end
+
+ def test_include_toplevel
+ assert_separately([], <<-EOS)
+ Mod = Module.new {def foo; :include_foo end}
+ TOPLEVEL_BINDING.eval('include Mod')
+
+ assert_equal(:include_foo, TOPLEVEL_BINDING.eval('foo'))
+ assert_equal([Object, Mod], Object.ancestors.slice(0, 2))
+ EOS
+ end
+
+ def test_included_modules
+ assert_equal([], Mixin.included_modules)
+ assert_equal([Mixin], User.included_modules)
+
+ mixins = Object.included_modules - [Kernel]
+ mixins << JSON::Ext::Generator::GeneratorMethods::String if defined?(JSON::Ext::Generator::GeneratorMethods::String)
+ assert_equal([Kernel], Object.included_modules - mixins)
+ assert_equal([Comparable, Kernel], String.included_modules - mixins)
+ end
+
+ def test_instance_methods
+ assert_equal([:user], User.instance_methods(false))
+ assert_equal([:user, :mixin].sort, User.instance_methods(true).sort)
+ assert_equal([:mixin], Mixin.instance_methods)
+ assert_equal([:mixin], Mixin.instance_methods(true))
+ assert_equal([:cClass], (class << CClass; self; end).instance_methods(false))
+ assert_equal([], (class << BClass; self; end).instance_methods(false))
+ assert_equal([:cm2], (class << AClass; self; end).instance_methods(false))
+ # Ruby 1.8 feature change:
+ # #instance_methods includes protected methods.
+ #assert_equal([:aClass], AClass.instance_methods(false))
+ assert_equal([:aClass, :aClass2], AClass.instance_methods(false).sort)
+ assert_equal([:aClass, :aClass2],
+ (AClass.instance_methods(true) - Object.instance_methods(true)).sort)
+ end
+
+ def test_method_defined?
+ assert_method_not_defined?(User, :wombat)
+ assert_method_defined?(User, :user)
+ assert_method_defined?(User, :mixin)
+ assert_method_not_defined?(User, :wombat)
+ assert_method_defined?(User, :user)
+ assert_method_defined?(User, :mixin)
+ end
+
+ def module_exec_aux
+ Proc.new do
+ def dynamically_added_method_3; end
+ end
+ end
+ def module_exec_aux_2(&block)
+ User.module_exec(&block)
+ end
+
+ def test_module_exec
+ User.module_exec do
+ def dynamically_added_method_1; end
+ end
+ assert_method_defined?(User, :dynamically_added_method_1)
+
+ block = Proc.new do
+ def dynamically_added_method_2; end
+ end
+ User.module_exec(&block)
+ assert_method_defined?(User, :dynamically_added_method_2)
+
+ User.module_exec(&module_exec_aux)
+ assert_method_defined?(User, :dynamically_added_method_3)
+
+ module_exec_aux_2 do
+ def dynamically_added_method_4; end
+ end
+ assert_method_defined?(User, :dynamically_added_method_4)
+ end
+
+ def test_module_eval
+ User.module_eval("MODULE_EVAL = 1")
+ assert_equal(1, User::MODULE_EVAL)
+ assert_include(User.constants, :MODULE_EVAL)
+ User.instance_eval("remove_const(:MODULE_EVAL)")
+ assert_not_include(User.constants, :MODULE_EVAL)
+ end
+
+ def test_name
+ assert_equal("Fixnum", Fixnum.name)
+ assert_equal("TestModule::Mixin", Mixin.name)
+ assert_equal("TestModule::User", User.name)
+ end
+
+ def test_classpath
+ m = Module.new
+ n = Module.new
+ m.const_set(:N, n)
+ assert_nil(m.name)
+ assert_nil(n.name)
+ assert_equal([:N], m.constants)
+ m.module_eval("module O end")
+ assert_equal([:N, :O], m.constants)
+ m.module_eval("class C; end")
+ assert_equal([:N, :O, :C], m.constants)
+ assert_nil(m::N.name)
+ assert_match(/\A#<Module:.*>::O\z/, m::O.name)
+ assert_match(/\A#<Module:.*>::C\z/, m::C.name)
+ self.class.const_set(:M, m)
+ prefix = self.class.name + "::M::"
+ assert_equal(prefix+"N", m.const_get(:N).name)
+ assert_equal(prefix+"O", m.const_get(:O).name)
+ assert_equal(prefix+"C", m.const_get(:C).name)
+ end
+
+ def test_private_class_method
+ assert_raise(ExpectedException) { AClass.cm1 }
+ assert_raise(ExpectedException) { AClass.cm3 }
+ assert_equal("cm1cm2cm3", AClass.cm2)
+ end
+
+ def test_private_instance_methods
+ assert_equal([:aClass1], AClass.private_instance_methods(false))
+ assert_equal([:bClass2], BClass.private_instance_methods(false))
+ assert_equal([:aClass1, :bClass2],
+ (BClass.private_instance_methods(true) -
+ Object.private_instance_methods(true)).sort)
+ end
+
+ def test_protected_instance_methods
+ assert_equal([:aClass2], AClass.protected_instance_methods)
+ assert_equal([:bClass3], BClass.protected_instance_methods(false))
+ assert_equal([:bClass3, :aClass2].sort,
+ (BClass.protected_instance_methods(true) -
+ Object.protected_instance_methods(true)).sort)
+ end
+
+ def test_public_class_method
+ assert_equal("cm1", MyClass.cm1)
+ assert_equal("cm1cm2cm3", MyClass.cm2)
+ assert_raise(ExpectedException) { eval "MyClass.cm3" }
+ end
+
+ def test_public_instance_methods
+ assert_equal([:aClass], AClass.public_instance_methods(false))
+ assert_equal([:bClass1], BClass.public_instance_methods(false))
+ end
+
+ def test_s_constants
+ c1 = Module.constants
+ Object.module_eval "WALTER = 99"
+ c2 = Module.constants
+ assert_equal([:WALTER], c2 - c1)
+
+ assert_equal([], Module.constants(true))
+ assert_equal([], Module.constants(false))
+
+ src = <<-INPUT
+ ary = Module.constants
+ module M
+ WALTER = 99
+ end
+ class Module
+ include M
+ end
+ p Module.constants - ary, Module.constants(true), Module.constants(false)
+ INPUT
+ assert_in_out_err([], src, %w([:M] [:WALTER] []), [])
+
+ klass = Class.new do
+ const_set(:X, 123)
+ end
+ assert_equal(false, klass.class_eval { Module.constants }.include?(:X))
+ end
+
+ module M1
+ $m1 = Module.nesting
+ module M2
+ $m2 = Module.nesting
+ end
+ end
+
+ def test_s_nesting
+ assert_equal([], $m0)
+ assert_equal([TestModule::M1, TestModule], $m1)
+ assert_equal([TestModule::M1::M2,
+ TestModule::M1, TestModule], $m2)
+ end
+
+ def test_s_new
+ m = Module.new
+ assert_instance_of(Module, m)
+ end
+
+ def test_freeze
+ m = Module.new
+ m.freeze
+ assert_raise(RuntimeError) do
+ m.module_eval do
+ def foo; end
+ end
+ end
+ end
+
+ def test_attr_obsoleted_flag
+ c = Class.new
+ c.class_eval do
+ def initialize
+ @foo = :foo
+ @bar = :bar
+ end
+ attr :foo, true
+ attr :bar, false
+ end
+ o = c.new
+ assert_equal(true, o.respond_to?(:foo))
+ assert_equal(true, o.respond_to?(:foo=))
+ assert_equal(true, o.respond_to?(:bar))
+ assert_equal(false, o.respond_to?(:bar=))
+ end
+
+ def test_const_get_evaled
+ c1 = Class.new
+ c2 = Class.new(c1)
+
+ eval("c1::Foo = :foo")
+ assert_equal(:foo, c1::Foo)
+ assert_equal(:foo, c2::Foo)
+ assert_equal(:foo, c2.const_get(:Foo))
+ assert_raise(NameError) { c2.const_get(:Foo, false) }
+
+ eval("c1::Foo = :foo")
+ assert_raise(NameError) { c1::Bar }
+ assert_raise(NameError) { c2::Bar }
+ assert_raise(NameError) { c2.const_get(:Bar) }
+ assert_raise(NameError) { c2.const_get(:Bar, false) }
+ assert_raise(NameError) { c2.const_get("Bar", false) }
+ assert_raise(NameError) { c2.const_get("BaR11", false) }
+ assert_raise(NameError) { Object.const_get("BaR11", false) }
+
+ c1.instance_eval do
+ def const_missing(x)
+ x
+ end
+ end
+
+ assert_equal(:Bar, c1::Bar)
+ assert_equal(:Bar, c2::Bar)
+ assert_equal(:Bar, c2.const_get(:Bar))
+ assert_equal(:Bar, c2.const_get(:Bar, false))
+ assert_equal(:Bar, c2.const_get("Bar"))
+ assert_equal(:Bar, c2.const_get("Bar", false))
+
+ v = c2.const_get("Bar11", false)
+ assert_equal("Bar11".to_sym, v)
+
+ assert_raise(NameError) { c1.const_get(:foo) }
+ end
+
+ def test_const_set_invalid_name
+ c1 = Class.new
+ assert_raise_with_message(NameError, /foo/) { c1.const_set(:foo, :foo) }
+ assert_raise_with_message(NameError, /bar/) { c1.const_set("bar", :foo) }
+ assert_raise_with_message(TypeError, /1/) { c1.const_set(1, :foo) }
+ assert_nothing_raised(NameError) { c1.const_set("X\u{3042}", :foo) }
+ assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-16be"), :foo) }
+ assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-16le"), :foo) }
+ assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-32be"), :foo) }
+ assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-32le"), :foo) }
+ cx = EnvUtil.labeled_class("X\u{3042}")
+ EnvUtil.with_default_internal(Encoding::UTF_8) {
+ assert_raise_with_message(TypeError, /X\u{3042}/) { c1.const_set(cx, :foo) }
+ }
+ end
+
+ def test_const_get_invalid_name
+ c1 = Class.new
+ assert_raise(NameError) { c1.const_get(:foo) }
+ bug5084 = '[ruby-dev:44200]'
+ assert_raise(TypeError, bug5084) { c1.const_get(1) }
+ bug7574 = '[ruby-dev:46749]'
+ assert_raise_with_message(NameError, "wrong constant name \"String\\u0000\"", bug7574) {
+ Object.const_get("String\0")
+ }
+ end
+
+ def test_const_defined_invalid_name
+ c1 = Class.new
+ assert_raise(NameError) { c1.const_defined?(:foo) }
+ bug5084 = '[ruby-dev:44200]'
+ assert_raise(TypeError, bug5084) { c1.const_defined?(1) }
+ bug7574 = '[ruby-dev:46749]'
+ assert_raise_with_message(NameError, "wrong constant name \"String\\u0000\"", bug7574) {
+ Object.const_defined?("String\0")
+ }
+ end
+
+ def test_const_get_no_inherited
+ bug3422 = '[ruby-core:30719]'
+ assert_in_out_err([], <<-INPUT, %w[1 NameError A], [], bug3422)
+ BasicObject::A = 1
+ puts [true, false].map {|inh|
+ begin
+ Object.const_get(:A, inh)
+ rescue NameError => e
+ [e.class, e.name]
+ end
+ }
+ INPUT
+ end
+
+ def test_const_get_inherited
+ bug3423 = '[ruby-core:30720]'
+ assert_in_out_err([], <<-INPUT, %w[NameError A NameError A], [], bug3423)
+ module Foo; A = 1; end
+ class Object; include Foo; end
+ class Bar; include Foo; end
+
+ puts [Object, Bar].map {|klass|
+ begin
+ klass.const_get(:A, false)
+ rescue NameError => e
+ [e.class, e.name]
+ end
+ }
+ INPUT
+ end
+
+ def test_const_in_module
+ bug3423 = '[ruby-core:37698]'
+ assert_in_out_err([], <<-INPUT, %w[ok], [], bug3423)
+ module LangModuleSpecInObject
+ module LangModuleTop
+ end
+ end
+ include LangModuleSpecInObject
+ module LangModuleTop
+ end
+ puts "ok" if LangModuleSpecInObject::LangModuleTop == LangModuleTop
+ INPUT
+
+ bug5264 = '[ruby-core:39227]'
+ assert_in_out_err([], <<-'INPUT', [], [], bug5264)
+ class A
+ class X; end
+ end
+ class B < A
+ module X; end
+ end
+ INPUT
+ end
+
+ def test_class_variable_get
+ c = Class.new
+ c.class_eval('@@foo = :foo')
+ assert_equal(:foo, c.class_variable_get(:@@foo))
+ assert_raise(NameError) { c.class_variable_get(:@@bar) } # c.f. instance_variable_get
+ assert_raise(NameError) { c.class_variable_get(:'@@') }
+ assert_raise(NameError) { c.class_variable_get('@@') }
+ assert_raise(NameError) { c.class_variable_get(:foo) }
+ assert_raise(NameError) { c.class_variable_get("bar") }
+ assert_raise(TypeError) { c.class_variable_get(1) }
+
+ n = Object.new
+ def n.to_str; @count = defined?(@count) ? @count + 1 : 1; "@@foo"; end
+ def n.count; @count; end
+ assert_equal(:foo, c.class_variable_get(n))
+ assert_equal(1, n.count)
+ end
+
+ def test_class_variable_set
+ c = Class.new
+ c.class_variable_set(:@@foo, :foo)
+ assert_equal(:foo, c.class_eval('@@foo'))
+ assert_raise(NameError) { c.class_variable_set(:'@@', 1) }
+ assert_raise(NameError) { c.class_variable_set('@@', 1) }
+ assert_raise(NameError) { c.class_variable_set(:foo, 1) }
+ assert_raise(NameError) { c.class_variable_set("bar", 1) }
+ assert_raise(TypeError) { c.class_variable_set(1, 1) }
+
+ n = Object.new
+ def n.to_str; @count = defined?(@count) ? @count + 1 : 1; "@@foo"; end
+ def n.count; @count; end
+ c.class_variable_set(n, :bar)
+ assert_equal(:bar, c.class_eval('@@foo'))
+ assert_equal(1, n.count)
+ end
+
+ def test_class_variable_defined
+ c = Class.new
+ c.class_eval('@@foo = :foo')
+ assert_equal(true, c.class_variable_defined?(:@@foo))
+ assert_equal(false, c.class_variable_defined?(:@@bar))
+ assert_raise(NameError) { c.class_variable_defined?(:'@@') }
+ assert_raise(NameError) { c.class_variable_defined?('@@') }
+ assert_raise(NameError) { c.class_variable_defined?(:foo) }
+ assert_raise(NameError) { c.class_variable_defined?("bar") }
+ assert_raise(TypeError) { c.class_variable_defined?(1) }
+ n = Object.new
+ def n.to_str; @count = defined?(@count) ? @count + 1 : 1; "@@foo"; end
+ def n.count; @count; end
+ assert_equal(true, c.class_variable_defined?(n))
+ assert_equal(1, n.count)
+ end
+
+ def test_remove_class_variable
+ c = Class.new
+ c.class_eval('@@foo = :foo')
+ c.class_eval { remove_class_variable(:@@foo) }
+ assert_equal(false, c.class_variable_defined?(:@@foo))
+ end
+
+ def test_export_method
+ m = Module.new
+ assert_raise(NameError) do
+ m.instance_eval { public(:foo) }
+ end
+ end
+
+ def test_attr
+ assert_in_out_err([], <<-INPUT, %w(:ok nil), /warning: private attribute\?$/)
+ $VERBOSE = true
+ c = Class.new
+ c.instance_eval do
+ private
+ attr_reader :foo
+ end
+ o = c.new
+ o.foo rescue p(:ok)
+ p(o.instance_eval { foo })
+ INPUT
+
+ c = Class.new
+ assert_raise(NameError) do
+ c.instance_eval { attr_reader :"." }
+ end
+ end
+
+ def test_undef
+ c = Class.new
+ assert_raise(NameError) do
+ c.instance_eval { undef_method(:foo) }
+ end
+
+ m = Module.new
+ assert_raise(NameError) do
+ m.instance_eval { undef_method(:foo) }
+ end
+
+ o = Object.new
+ assert_raise(NameError) do
+ class << o; self; end.instance_eval { undef_method(:foo) }
+ end
+
+ %w(object_id __send__ initialize).each do |n|
+ assert_in_out_err([], <<-INPUT, [], %r"warning: undefining `#{n}' may cause serious problems$")
+ $VERBOSE = false
+ Class.new.instance_eval { undef_method(:#{n}) }
+ INPUT
+ end
+ end
+
+ def test_alias
+ m = Module.new
+ assert_raise(NameError) do
+ m.class_eval { alias foo bar }
+ end
+
+ assert_in_out_err([], <<-INPUT, %w(2), /discarding old foo$/)
+ $VERBOSE = true
+ c = Class.new
+ c.class_eval do
+ def foo; 1; end
+ def bar; 2; end
+ end
+ c.class_eval { alias foo bar }
+ p c.new.foo
+ INPUT
+ end
+
+ def test_mod_constants
+ m = Module.new
+ m.const_set(:Foo, :foo)
+ assert_equal([:Foo], m.constants(true))
+ assert_equal([:Foo], m.constants(false))
+ m.instance_eval { remove_const(:Foo) }
+ end
+
+ class Bug9413
+ class << self
+ Foo = :foo
+ end
+ end
+
+ def test_singleton_constants
+ bug9413 = '[ruby-core:59763] [Bug #9413]'
+ c = Bug9413.singleton_class
+ assert_include(c.constants(true), :Foo, bug9413)
+ assert_include(c.constants(false), :Foo, bug9413)
+ end
+
+ def test_frozen_module
+ m = Module.new
+ m.freeze
+ assert_raise(RuntimeError) do
+ m.instance_eval { undef_method(:foo) }
+ end
+ end
+
+ def test_frozen_class
+ c = Class.new
+ c.freeze
+ assert_raise(RuntimeError) do
+ c.instance_eval { undef_method(:foo) }
+ end
+ end
+
+ def test_frozen_singleton_class
+ klass = Class.new
+ o = klass.new
+ c = class << o; self; end
+ c.freeze
+ assert_raise_with_message(RuntimeError, /frozen/) do
+ c.instance_eval { undef_method(:foo) }
+ end
+ klass.class_eval do
+ def self.foo
+ end
+ end
+ end
+
+ def test_method_defined
+ c = Class.new
+ c.class_eval do
+ def foo; end
+ def bar; end
+ def baz; end
+ public :foo
+ protected :bar
+ private :baz
+ end
+
+ assert_equal(true, c.public_method_defined?(:foo))
+ assert_equal(false, c.public_method_defined?(:bar))
+ assert_equal(false, c.public_method_defined?(:baz))
+
+ assert_equal(false, c.protected_method_defined?(:foo))
+ assert_equal(true, c.protected_method_defined?(:bar))
+ assert_equal(false, c.protected_method_defined?(:baz))
+
+ assert_equal(false, c.private_method_defined?(:foo))
+ assert_equal(false, c.private_method_defined?(:bar))
+ assert_equal(true, c.private_method_defined?(:baz))
+ end
+
+ def test_top_public_private
+ assert_in_out_err([], <<-INPUT, %w([:foo] [:bar]), [])
+ private
+ def foo; :foo; end
+ public
+ def bar; :bar; end
+ p self.private_methods.grep(/^foo$|^bar$/)
+ p self.methods.grep(/^foo$|^bar$/)
+ INPUT
+ end
+
+ def test_append_features
+ t = nil
+ m = Module.new
+ m.module_eval do
+ def foo; :foo; end
+ end
+ class << m; self; end.class_eval do
+ define_method(:append_features) do |mod|
+ t = mod
+ super(mod)
+ end
+ end
+
+ m2 = Module.new
+ m2.module_eval { include(m) }
+ assert_equal(m2, t)
+
+ o = Object.new
+ o.extend(m2)
+ assert_equal(true, o.respond_to?(:foo))
+ end
+
+ def test_append_features_raise
+ m = Module.new
+ m.module_eval do
+ def foo; :foo; end
+ end
+ class << m; self; end.class_eval do
+ define_method(:append_features) {|mod| raise }
+ end
+
+ m2 = Module.new
+ assert_raise(RuntimeError) do
+ m2.module_eval { include(m) }
+ end
+
+ o = Object.new
+ o.extend(m2)
+ assert_equal(false, o.respond_to?(:foo))
+ end
+
+ def test_append_features_type_error
+ assert_raise(TypeError) do
+ Module.new.instance_eval { append_features(1) }
+ end
+ end
+
+ def test_included
+ m = Module.new
+ m.module_eval do
+ def foo; :foo; end
+ end
+ class << m; self; end.class_eval do
+ define_method(:included) {|mod| raise }
+ end
+
+ m2 = Module.new
+ assert_raise(RuntimeError) do
+ m2.module_eval { include(m) }
+ end
+
+ o = Object.new
+ o.extend(m2)
+ assert_equal(true, o.respond_to?(:foo))
+ end
+
+ def test_cyclic_include
+ m1 = Module.new
+ m2 = Module.new
+ m1.instance_eval { include(m2) }
+ assert_raise(ArgumentError) do
+ m2.instance_eval { include(m1) }
+ end
+ end
+
+ def test_include_p
+ m = Module.new
+ c1 = Class.new
+ c1.instance_eval { include(m) }
+ c2 = Class.new(c1)
+ assert_equal(true, c1.include?(m))
+ assert_equal(true, c2.include?(m))
+ assert_equal(false, m.include?(m))
+ end
+
+ def test_send
+ a = AClass.new
+ assert_equal(:aClass, a.__send__(:aClass))
+ assert_equal(:aClass1, a.__send__(:aClass1))
+ assert_equal(:aClass2, a.__send__(:aClass2))
+ b = BClass.new
+ assert_equal(:aClass, b.__send__(:aClass))
+ assert_equal(:aClass1, b.__send__(:aClass1))
+ assert_equal(:aClass2, b.__send__(:aClass2))
+ assert_equal(:bClass1, b.__send__(:bClass1))
+ assert_equal(:bClass2, b.__send__(:bClass2))
+ assert_equal(:bClass3, b.__send__(:bClass3))
+ end
+
+
+ def test_nonascii_name
+ c = eval("class ::C\u{df}; self; end")
+ assert_equal("C\u{df}", c.name, '[ruby-core:24600]')
+ c = eval("class C\u{df}; self; end")
+ assert_equal("TestModule::C\u{df}", c.name, '[ruby-core:24600]')
+ end
+
+ def test_method_added
+ memo = []
+ mod = Module.new do
+ mod = self
+ (class << self ; self ; end).class_eval do
+ define_method :method_added do |sym|
+ memo << sym
+ memo << mod.instance_methods(false)
+ memo << (mod.instance_method(sym) rescue nil)
+ end
+ end
+ def f
+ end
+ alias g f
+ attr_reader :a
+ attr_writer :a
+ end
+ assert_equal :f, memo.shift
+ assert_equal [:f], memo.shift, '[ruby-core:25536]'
+ assert_equal mod.instance_method(:f), memo.shift
+ assert_equal :g, memo.shift
+ assert_equal [:f, :g], memo.shift
+ assert_equal mod.instance_method(:f), memo.shift
+ assert_equal :a, memo.shift
+ assert_equal [:f, :g, :a], memo.shift
+ assert_equal mod.instance_method(:a), memo.shift
+ assert_equal :a=, memo.shift
+ assert_equal [:f, :g, :a, :a=], memo.shift
+ assert_equal mod.instance_method(:a=), memo.shift
+ end
+
+ def test_method_undefined
+ added = []
+ undefed = []
+ removed = []
+ mod = Module.new do
+ mod = self
+ def f
+ end
+ (class << self ; self ; end).class_eval do
+ define_method :method_added do |sym|
+ added << sym
+ end
+ define_method :method_undefined do |sym|
+ undefed << sym
+ end
+ define_method :method_removed do |sym|
+ removed << sym
+ end
+ end
+ end
+ assert_method_defined?(mod, :f)
+ mod.module_eval do
+ undef :f
+ end
+ assert_equal [], added
+ assert_equal [:f], undefed
+ assert_equal [], removed
+ end
+
+ def test_method_removed
+ added = []
+ undefed = []
+ removed = []
+ mod = Module.new do
+ mod = self
+ def f
+ end
+ (class << self ; self ; end).class_eval do
+ define_method :method_added do |sym|
+ added << sym
+ end
+ define_method :method_undefined do |sym|
+ undefed << sym
+ end
+ define_method :method_removed do |sym|
+ removed << sym
+ end
+ end
+ end
+ assert_method_defined?(mod, :f)
+ mod.module_eval do
+ remove_method :f
+ end
+ assert_equal [], added
+ assert_equal [], undefed
+ assert_equal [:f], removed
+ end
+
+ def test_method_redefinition
+ feature2155 = '[ruby-dev:39400]'
+
+ line = __LINE__+4
+ stderr = EnvUtil.verbose_warning do
+ Module.new do
+ def foo; end
+ def foo; end
+ end
+ end
+ assert_match(/:#{line}: warning: method redefined; discarding old foo/, stderr)
+ assert_match(/:#{line-1}: warning: previous definition of foo/, stderr, feature2155)
+
+ assert_warning '' do
+ Module.new do
+ def foo; end
+ alias bar foo
+ def foo; end
+ end
+ end
+
+ assert_warning '' do
+ Module.new do
+ def foo; end
+ alias bar foo
+ alias bar foo
+ end
+ end
+
+ line = __LINE__+4
+ stderr = EnvUtil.verbose_warning do
+ Module.new do
+ define_method(:foo) do end
+ def foo; end
+ end
+ end
+ assert_match(/:#{line}: warning: method redefined; discarding old foo/, stderr)
+ assert_match(/:#{line-1}: warning: previous definition of foo/, stderr, feature2155)
+
+ assert_warning '' do
+ Module.new do
+ define_method(:foo) do end
+ alias bar foo
+ alias bar foo
+ end
+ end
+
+ assert_warning('', '[ruby-dev:39397]') do
+ Module.new do
+ module_function
+ def foo; end
+ module_function :foo
+ end
+ end
+
+ assert_warning '' do
+ Module.new do
+ def foo; end
+ undef foo
+ end
+ end
+ end
+
+ def test_protected_singleton_method
+ klass = Class.new
+ x = klass.new
+ class << x
+ protected
+
+ def foo
+ end
+ end
+ assert_raise(NoMethodError) do
+ x.foo
+ end
+ klass.send(:define_method, :bar) do
+ x.foo
+ end
+ assert_nothing_raised do
+ x.bar
+ end
+ y = klass.new
+ assert_raise(NoMethodError) do
+ y.bar
+ end
+ end
+
+ def test_uninitialized_toplevel_constant
+ bug3123 = '[ruby-dev:40951]'
+ e = assert_raise(NameError) {eval("Bug3123", TOPLEVEL_BINDING)}
+ assert_not_match(/Object::/, e.message, bug3123)
+ end
+
+ def test_attr_inherited_visibility
+ bug3406 = '[ruby-core:30638]'
+ c = Class.new do
+ class << self
+ private
+ def attr_accessor(*); super; end
+ end
+ attr_accessor :x
+ end.new
+ assert_nothing_raised(bug3406) {c.x = 1}
+ assert_equal(1, c.x, bug3406)
+ end
+
+ def test_attr_writer_with_no_arguments
+ bug8540 = "[ruby-core:55543]"
+ c = Class.new do
+ attr_writer :foo
+ end
+ assert_raise(ArgumentError, bug8540) { c.new.send :foo= }
+ end
+
+ def test_private_constant
+ c = Class.new
+ c.const_set(:FOO, "foo")
+ assert_equal("foo", c::FOO)
+ c.private_constant(:FOO)
+ assert_raise(NameError) { c::FOO }
+ assert_equal("foo", c.class_eval("FOO"))
+ assert_equal("foo", c.const_get("FOO"))
+ $VERBOSE, verbose = nil, $VERBOSE
+ c.const_set(:FOO, "foo")
+ $VERBOSE = verbose
+ assert_raise(NameError) { c::FOO }
+ end
+
+ def test_private_constant2
+ c = Class.new
+ c.const_set(:FOO, "foo")
+ c.const_set(:BAR, "bar")
+ assert_equal("foo", c::FOO)
+ assert_equal("bar", c::BAR)
+ c.private_constant(:FOO, :BAR)
+ assert_raise(NameError) { c::FOO }
+ assert_raise(NameError) { c::BAR }
+ assert_equal("foo", c.class_eval("FOO"))
+ assert_equal("bar", c.class_eval("BAR"))
+ end
+
+ def test_private_constant_with_no_args
+ assert_in_out_err([], <<-RUBY, [], ["-:3: warning: private_constant with no argument is just ignored"])
+ $-w = true
+ class X
+ private_constant
+ end
+ RUBY
+ end
+
+ class PrivateClass
+ end
+ private_constant :PrivateClass
+
+ def test_define_module_under_private_constant
+ assert_raise(NameError) do
+ eval %q{class TestModule::PrivateClass; end}
+ end
+ assert_raise(NameError) do
+ eval %q{module TestModule::PrivateClass::TestModule; end}
+ end
+ eval %q{class PrivateClass; end}
+ eval %q{module PrivateClass::TestModule; end}
+ assert_instance_of(Module, PrivateClass::TestModule)
+ PrivateClass.class_eval { remove_const(:TestModule) }
+ end
+
+ def test_public_constant
+ c = Class.new
+ c.const_set(:FOO, "foo")
+ assert_equal("foo", c::FOO)
+ c.private_constant(:FOO)
+ assert_raise(NameError) { c::FOO }
+ assert_equal("foo", c.class_eval("FOO"))
+ c.public_constant(:FOO)
+ assert_equal("foo", c::FOO)
+ end
+
+ def test_constants_with_private_constant
+ assert_not_include(::TestModule.constants, :PrivateClass)
+ end
+
+ def test_toplevel_private_constant
+ src = <<-INPUT
+ class Object
+ private_constant :Object
+ end
+ p Object
+ begin
+ p ::Object
+ rescue
+ p :ok
+ end
+ INPUT
+ assert_in_out_err([], src, %w(Object :ok), [])
+ end
+
+ def test_private_constants_clear_inlinecache
+ bug5702 = '[ruby-dev:44929]'
+ src = <<-INPUT
+ class A
+ C = :Const
+ def self.get_C
+ A::C
+ end
+ # fill cache
+ A.get_C
+ private_constant :C, :D rescue nil
+ begin
+ A.get_C
+ rescue NameError
+ puts "A.get_C"
+ end
+ end
+ INPUT
+ assert_in_out_err([], src, %w(A.get_C), [], bug5702)
+ end
+
+ def test_constant_lookup_in_method_defined_by_class_eval
+ src = <<-INPUT
+ class A
+ B = 42
+ end
+
+ A.class_eval do
+ def self.f
+ B
+ end
+
+ def f
+ B
+ end
+ end
+
+ begin
+ A.f
+ rescue NameError
+ puts "A.f"
+ end
+ begin
+ A.new.f
+ rescue NameError
+ puts "A.new.f"
+ end
+ INPUT
+ assert_in_out_err([], src, %w(A.f A.new.f), [])
+ end
+
+ def test_constant_lookup_in_toplevel_class_eval
+ src = <<-INPUT
+ module X
+ A = 123
+ end
+ begin
+ X.class_eval { A }
+ rescue NameError => e
+ puts e
+ end
+ INPUT
+ assert_in_out_err([], src, ["uninitialized constant A"], [])
+ end
+
+ def test_constant_lookup_in_module_in_class_eval
+ src = <<-INPUT
+ class A
+ B = 42
+ end
+
+ A.class_eval do
+ module C
+ begin
+ B
+ rescue NameError
+ puts "NameError"
+ end
+ end
+ end
+ INPUT
+ assert_in_out_err([], src, ["NameError"], [])
+ end
+
+ module M0
+ def m1; [:M0] end
+ end
+ module M1
+ def m1; [:M1, *super] end
+ end
+ module M2
+ def m1; [:M2, *super] end
+ end
+ M3 = Module.new do
+ def m1; [:M3, *super] end
+ end
+ module M4
+ def m1; [:M4, *super] end
+ end
+ class C
+ def m1; end
+ end
+ class C0 < C
+ include M0
+ prepend M1
+ def m1; [:C0, *super] end
+ end
+ class C1 < C0
+ prepend M2, M3
+ include M4
+ def m1; [:C1, *super] end
+ end
+
+ def test_prepend
+ obj = C0.new
+ expected = [:M1,:C0,:M0]
+ assert_equal(expected, obj.m1)
+ obj = C1.new
+ expected = [:M2,:M3,:C1,:M4,:M1,:C0,:M0]
+ assert_equal(expected, obj.m1)
+ end
+
+ def test_public_prepend
+ assert_nothing_raised('#8846') do
+ Class.new.prepend(Module.new)
+ end
+ end
+
+ def test_prepend_inheritance
+ bug6654 = '[ruby-core:45914]'
+ a = labeled_module("a")
+ b = labeled_module("b") {include a}
+ c = labeled_class("c") {prepend b}
+ assert_operator(c, :<, b, bug6654)
+ assert_operator(c, :<, a, bug6654)
+ bug8357 = '[ruby-core:54736] [Bug #8357]'
+ b = labeled_module("b") {prepend a}
+ c = labeled_class("c") {include b}
+ assert_operator(c, :<, b, bug8357)
+ assert_operator(c, :<, a, bug8357)
+ bug8357 = '[ruby-core:54742] [Bug #8357]'
+ assert_kind_of(b, c.new, bug8357)
+ end
+
+ def test_prepend_instance_methods
+ bug6655 = '[ruby-core:45915]'
+ assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655)
+ end
+
+ def test_prepend_singleton_methods
+ o = Object.new
+ o.singleton_class.class_eval {prepend Module.new}
+ assert_equal([], o.singleton_methods)
+ end
+
+ def test_prepend_remove_method
+ c = Class.new do
+ prepend Module.new {def foo; end}
+ end
+ assert_raise(NameError) do
+ c.class_eval do
+ remove_method(:foo)
+ end
+ end
+ c.class_eval do
+ def foo; end
+ end
+ removed = nil
+ c.singleton_class.class_eval do
+ define_method(:method_removed) {|id| removed = id}
+ end
+ assert_nothing_raised(NoMethodError, NameError, '[Bug #7843]') do
+ c.class_eval do
+ remove_method(:foo)
+ end
+ end
+ assert_equal(:foo, removed)
+ end
+
+ def test_prepend_class_ancestors
+ bug6658 = '[ruby-core:45919]'
+ m = labeled_module("m")
+ c = labeled_class("c") {prepend m}
+ assert_equal([m, c], c.ancestors[0, 2], bug6658)
+
+ bug6662 = '[ruby-dev:45868]'
+ c2 = labeled_class("c2", c)
+ anc = c2.ancestors
+ assert_equal([c2, m, c, Object], anc[0..anc.index(Object)], bug6662)
+ end
+
+ def test_prepend_module_ancestors
+ bug6659 = '[ruby-dev:45861]'
+ m0 = labeled_module("m0") {def x; [:m0, *super] end}
+ m1 = labeled_module("m1") {def x; [:m1, *super] end; prepend m0}
+ m2 = labeled_module("m2") {def x; [:m2, *super] end; prepend m1}
+ c0 = labeled_class("c0") {def x; [:c0] end}
+ c1 = labeled_class("c1") {def x; [:c1] end; prepend m2}
+ c2 = labeled_class("c2", c0) {def x; [:c2, *super] end; include m2}
+
+ assert_equal([m0, m1], m1.ancestors, bug6659)
+
+ bug6662 = '[ruby-dev:45868]'
+ assert_equal([m0, m1, m2], m2.ancestors, bug6662)
+ assert_equal([m0, m1, m2, c1], c1.ancestors[0, 4], bug6662)
+ assert_equal([:m0, :m1, :m2, :c1], c1.new.x)
+ assert_equal([c2, m0, m1, m2, c0], c2.ancestors[0, 5], bug6662)
+ assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x)
+
+ m3 = labeled_module("m3") {include m1; prepend m1}
+ assert_equal([m3, m0, m1], m3.ancestors)
+ m3 = labeled_module("m3") {prepend m1; include m1}
+ assert_equal([m0, m1, m3], m3.ancestors)
+ m3 = labeled_module("m3") {prepend m1; prepend m1}
+ assert_equal([m0, m1, m3], m3.ancestors)
+ m3 = labeled_module("m3") {include m1; include m1}
+ assert_equal([m3, m0, m1], m3.ancestors)
+ end
+
+ def labeled_module(name, &block)
+ EnvUtil.labeled_module(name, &block)
+ end
+
+ def labeled_class(name, superclass = Object, &block)
+ EnvUtil.labeled_class(name, superclass, &block)
+ end
+
+ def test_prepend_instance_methods_false
+ bug6660 = '[ruby-dev:45863]'
+ assert_equal([:m1], Class.new{ prepend Module.new; def m1; end }.instance_methods(false), bug6660)
+ assert_equal([:m1], Class.new(Class.new{def m2;end}){ prepend Module.new; def m1; end }.instance_methods(false), bug6660)
+ end
+
+ def test_cyclic_prepend
+ bug7841 = '[ruby-core:52205] [Bug #7841]'
+ m1 = Module.new
+ m2 = Module.new
+ m1.instance_eval { prepend(m2) }
+ assert_raise(ArgumentError, bug7841) do
+ m2.instance_eval { prepend(m1) }
+ end
+ end
+
+ def test_prepend_optmethod
+ bug7983 = '[ruby-dev:47124] [Bug #7983]'
+ assert_separately [], %{
+ module M
+ def /(other)
+ to_f / other
+ end
+ end
+ Fixnum.send(:prepend, M)
+ assert_equal(0.5, 1 / 2, "#{bug7983}")
+ }
+ assert_equal(0, 1 / 2)
+ end
+
+ def test_prepend_visibility
+ bug8005 = '[ruby-core:53106] [Bug #8005]'
+ c = Class.new do
+ prepend Module.new {}
+ def foo() end
+ protected :foo
+ end
+ a = c.new
+ assert_respond_to a, [:foo, true], bug8005
+ assert_nothing_raised(NoMethodError, bug8005) {a.send :foo}
+ end
+
+ def test_prepend_visibility_inherited
+ bug8238 = '[ruby-core:54105] [Bug #8238]'
+ assert_separately [], <<-"end;", timeout: 20
+ class A
+ def foo() A; end
+ private :foo
+ end
+ class B < A
+ public :foo
+ prepend Module.new
+ end
+ assert_equal(A, B.new.foo, "#{bug8238}")
+ end;
+ end
+
+ def test_prepend_included_modules
+ bug8025 = '[ruby-core:53158] [Bug #8025]'
+ mixin = labeled_module("mixin")
+ c = labeled_module("c") {prepend mixin}
+ im = c.included_modules
+ assert_not_include(im, c, bug8025)
+ assert_include(im, mixin, bug8025)
+ c1 = labeled_class("c1") {prepend mixin}
+ c2 = labeled_class("c2", c1)
+ im = c2.included_modules
+ assert_not_include(im, c1, bug8025)
+ assert_not_include(im, c2, bug8025)
+ assert_include(im, mixin, bug8025)
+ end
+
+ def test_prepend_super_in_alias
+ bug7842 = '[Bug #7842]'
+
+ p = labeled_module("P") do
+ def m; "P"+super; end
+ end
+ a = labeled_class("A") do
+ def m; "A"; end
+ end
+ b = labeled_class("B", a) do
+ def m; "B"+super; end
+ alias m2 m
+ prepend p
+ alias m3 m
+ end
+ assert_equal("BA", b.new.m2, bug7842)
+ assert_equal("PBA", b.new.m3, bug7842)
+ end
+
+ def test_include_super_in_alias
+ bug9236 = '[Bug #9236]'
+
+ fun = labeled_module("Fun") do
+ def hello
+ orig_hello
+ end
+ end
+
+ m1 = labeled_module("M1") do
+ def hello
+ 'hello!'
+ end
+ end
+
+ m2 = labeled_module("M2") do
+ def hello
+ super
+ end
+ end
+
+ foo = labeled_class("Foo") do
+ include m1
+ include m2
+
+ alias orig_hello hello
+ include fun
+ end
+
+ assert_equal('hello!', foo.new.hello, bug9236)
+ end
+
+ def test_prepend_call_super
+ assert_separately([], <<-'end;') #do
+ bug10847 = '[ruby-core:68093] [Bug #10847]'
+ module M; end
+ Float.prepend M
+ assert_nothing_raised(SystemStackError, bug10847) do
+ 0.3.numerator
+ end
+ end;
+ end
+
+ def test_class_variables
+ m = Module.new
+ m.class_variable_set(:@@foo, 1)
+ m2 = Module.new
+ m2.send(:include, m)
+ m2.class_variable_set(:@@bar, 2)
+ assert_equal([:@@foo], m.class_variables)
+ assert_equal([:@@bar, :@@foo], m2.class_variables)
+ assert_equal([:@@bar, :@@foo], m2.class_variables(true))
+ assert_equal([:@@bar], m2.class_variables(false))
+ end
+
+ Bug6891 = '[ruby-core:47241]'
+
+ def test_extend_module_with_protected_method
+ list = []
+
+ x = Class.new {
+ @list = list
+
+ extend Module.new {
+ protected
+
+ def inherited(klass)
+ @list << "protected"
+ super(klass)
+ end
+ }
+
+ extend Module.new {
+ def inherited(klass)
+ @list << "public"
+ super(klass)
+ end
+ }
+ }
+
+ assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)}
+ assert_equal(['public', 'protected'], list)
+ end
+
+ def test_extend_module_with_protected_bmethod
+ list = []
+
+ x = Class.new {
+ extend Module.new {
+ protected
+
+ define_method(:inherited) do |klass|
+ list << "protected"
+ super(klass)
+ end
+ }
+
+ extend Module.new {
+ define_method(:inherited) do |klass|
+ list << "public"
+ super(klass)
+ end
+ }
+ }
+
+ assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)}
+ assert_equal(['public', 'protected'], list)
+ end
+
+ def test_invalid_attr
+ %W[
+ foo?
+ @foo
+ @@foo
+ $foo
+ \u3042$
+ ].each do |name|
+ assert_raise_with_message(NameError, /#{Regexp.quote(quote(name))}/) do
+ Module.new { attr_accessor name.to_sym }
+ end
+ end
+ end
+
+ private def quote(name)
+ encoding = Encoding.default_internal || Encoding.default_external
+ (name.encoding == encoding || name.ascii_only?) ? name : name.inspect
+ end
+
+ class AttrTest
+ class << self
+ attr_accessor :cattr
+ end
+ attr_accessor :iattr
+ def ivar
+ @ivar
+ end
+ end
+
+ def test_uninitialized_instance_variable
+ a = AttrTest.new
+ assert_warning(/instance variable @ivar not initialized/) do
+ assert_nil(a.ivar)
+ end
+ a.instance_variable_set(:@ivar, 42)
+ assert_warning '' do
+ assert_equal(42, a.ivar)
+ end
+
+ name = "@\u{5909 6570}"
+ assert_warning(/instance variable #{name} not initialized/) do
+ val = EnvUtil.with_default_external(Encoding::UTF_8) {
+ a.instance_eval(name)
+ }
+ assert_nil(val)
+ end
+ end
+
+ def test_uninitialized_attr
+ a = AttrTest.new
+ assert_warning '' do
+ assert_nil(a.iattr)
+ end
+ a.iattr = 42
+ assert_warning '' do
+ assert_equal(42, a.iattr)
+ end
+ end
+
+ def test_uninitialized_attr_class
+ assert_warning '' do
+ assert_nil(AttrTest.cattr)
+ end
+ AttrTest.cattr = 42
+ assert_warning '' do
+ assert_equal(42, AttrTest.cattr)
+ end
+ end
+
+ def test_uninitialized_attr_non_object
+ a = Class.new(Array) do
+ attr_accessor :iattr
+ end.new
+ assert_warning '' do
+ assert_nil(a.iattr)
+ end
+ a.iattr = 42
+ assert_warning '' do
+ assert_equal(42, a.iattr)
+ end
+ end
+
+ def test_remove_const
+ m = Module.new
+ assert_raise(NameError){ m.instance_eval { remove_const(:__FOO__) } }
+ end
+
+ def test_private_top_methods
+ assert_top_method_is_private(:include)
+ assert_top_method_is_private(:public)
+ assert_top_method_is_private(:private)
+ assert_top_method_is_private(:define_method)
+ end
+
+ module PrivateConstantReopen
+ PRIVATE_CONSTANT = true
+ private_constant :PRIVATE_CONSTANT
+ end
+
+ def test_private_constant_reopen
+ assert_raise(NameError) do
+ eval <<-EOS, TOPLEVEL_BINDING
+ module TestModule::PrivateConstantReopen::PRIVATE_CONSTANT
+ end
+ EOS
+ end
+ assert_raise(NameError) do
+ eval <<-EOS, TOPLEVEL_BINDING
+ class TestModule::PrivateConstantReopen::PRIVATE_CONSTANT
+ end
+ EOS
+ end
+ end
+
+ def test_singleton_class_ancestors
+ feature8035 = '[ruby-core:53171]'
+ obj = Object.new
+ assert_equal [obj.singleton_class, Object], obj.singleton_class.ancestors.first(2), feature8035
+
+ mod = Module.new
+ obj.extend mod
+ assert_equal [obj.singleton_class, mod, Object], obj.singleton_class.ancestors.first(3)
+
+ obj = Object.new
+ obj.singleton_class.send :prepend, mod
+ assert_equal [mod, obj.singleton_class, Object], obj.singleton_class.ancestors.first(3)
+ end
+
+ def test_visibility_by_public_class_method
+ bug8284 = '[ruby-core:54404] [Bug #8284]'
+ assert_raise(NoMethodError) {Object.define_method}
+ Module.new.public_class_method(:define_method)
+ assert_raise(NoMethodError, bug8284) {Object.define_method}
+ end
+
+ def test_include_module_with_constants_invalidates_method_cache
+ assert_in_out_err([], <<-RUBY, %w(123 456), [])
+ A = 123
+
+ class Foo
+ def self.a
+ A
+ end
+ end
+
+ module M
+ A = 456
+ end
+
+ puts Foo.a
+ Foo.send(:include, M)
+ puts Foo.a
+ RUBY
+ end
+
+ def test_return_value_of_define_method
+ retvals = []
+ Class.new.class_eval do
+ retvals << define_method(:foo){}
+ retvals << define_method(:bar, instance_method(:foo))
+ end
+ assert_equal :foo, retvals[0]
+ assert_equal :bar, retvals[1]
+ end
+
+ def test_return_value_of_define_singleton_method
+ retvals = []
+ Class.new do
+ retvals << define_singleton_method(:foo){}
+ retvals << define_singleton_method(:bar, method(:foo))
+ end
+ assert_equal :foo, retvals[0]
+ assert_equal :bar, retvals[1]
+ end
+
+ def test_prepend_gc
+ assert_separately [], %{
+ module Foo
+ end
+ class Object
+ prepend Foo
+ end
+ GC.start # make created T_ICLASS old (or remembered shady)
+ class Object # add methods into T_ICLASS (need WB if it is old)
+ def foo; end
+ attr_reader :bar
+ end
+ 1_000_000.times{''} # cause GC
+ }
+ end
+
+ def test_inspect_segfault
+ bug_10282 = '[ruby-core:65214] [Bug #10282]'
+ assert_separately [], <<-RUBY
+ module ShallowInspect
+ def shallow_inspect
+ "foo"
+ end
+ end
+
+ module InspectIsShallow
+ include ShallowInspect
+ alias_method :inspect, :shallow_inspect
+ end
+
+ class A
+ end
+
+ A.prepend InspectIsShallow
+
+ expect = "#<Method: A(Object)#inspect(shallow_inspect)>"
+ assert_equal expect, A.new.method(:inspect).inspect, "#{bug_10282}"
+ RUBY
+ end
+
+ private
+
+ def assert_top_method_is_private(method)
+ assert_separately [], %{
+ methods = singleton_class.private_instance_methods(false)
+ assert_include(methods, :#{method}, ":#{method} should be private")
+
+ assert_raise_with_message(NoMethodError, "private method `#{method}' called for main:Object") {
+ self.#{method}
+ }
+ }
+ end
+end