2015-12-16 00:07:31 -05:00
|
|
|
# frozen_string_literal: false
|
2012-08-02 07:34:19 -04:00
|
|
|
require 'test/unit'
|
|
|
|
|
|
|
|
class TestRefinement < Test::Unit::TestCase
|
2015-03-04 21:56:03 -05:00
|
|
|
module Sandbox
|
|
|
|
BINDING = binding
|
|
|
|
end
|
|
|
|
|
2012-08-02 07:34:19 -04:00
|
|
|
class Foo
|
|
|
|
def x
|
|
|
|
return "Foo#x"
|
|
|
|
end
|
|
|
|
|
|
|
|
def y
|
|
|
|
return "Foo#y"
|
|
|
|
end
|
|
|
|
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 11:05:45 -05:00
|
|
|
def a
|
|
|
|
return "Foo#a"
|
|
|
|
end
|
|
|
|
|
2012-08-02 07:34:19 -04:00
|
|
|
def call_x
|
|
|
|
return x
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooExt
|
|
|
|
refine Foo do
|
|
|
|
def x
|
|
|
|
return "FooExt#x"
|
|
|
|
end
|
|
|
|
|
|
|
|
def y
|
|
|
|
return "FooExt#y " + super
|
|
|
|
end
|
|
|
|
|
|
|
|
def z
|
|
|
|
return "FooExt#z"
|
|
|
|
end
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 11:05:45 -05:00
|
|
|
|
|
|
|
def a
|
|
|
|
return "FooExt#a"
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooExt2
|
|
|
|
refine Foo do
|
|
|
|
def x
|
|
|
|
return "FooExt2#x"
|
|
|
|
end
|
|
|
|
|
|
|
|
def y
|
|
|
|
return "FooExt2#y " + super
|
|
|
|
end
|
|
|
|
|
|
|
|
def z
|
|
|
|
return "FooExt2#z"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class FooSub < Foo
|
|
|
|
def x
|
|
|
|
return "FooSub#x"
|
|
|
|
end
|
|
|
|
|
|
|
|
def y
|
|
|
|
return "FooSub#y " + super
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-10-15 18:59:38 -04:00
|
|
|
class FooExtClient
|
2012-12-06 10:12:36 -05:00
|
|
|
using TestRefinement::FooExt
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2016-10-15 18:59:38 -04:00
|
|
|
begin
|
2016-10-15 18:59:39 -04:00
|
|
|
def self.map_x_on(foo)
|
|
|
|
[foo].map(&:x)[0]
|
|
|
|
end
|
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.invoke_x_on(foo)
|
|
|
|
return foo.x
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.invoke_y_on(foo)
|
|
|
|
return foo.y
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.invoke_z_on(foo)
|
|
|
|
return foo.z
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.send_z_on(foo)
|
|
|
|
return foo.send(:z)
|
|
|
|
end
|
2012-11-02 20:09:26 -04:00
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.method_z(foo)
|
|
|
|
return foo.method(:z)
|
|
|
|
end
|
2012-11-02 20:09:26 -04:00
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.invoke_call_x_on(foo)
|
|
|
|
return foo.call_x
|
|
|
|
end
|
2016-10-22 22:03:56 -04:00
|
|
|
|
|
|
|
def self.return_proc(&block)
|
|
|
|
block
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
2016-10-15 18:59:38 -04:00
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2016-10-15 18:59:38 -04:00
|
|
|
class TestRefinement::FooExtClient2
|
2012-12-06 10:12:36 -05:00
|
|
|
using TestRefinement::FooExt
|
|
|
|
using TestRefinement::FooExt2
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2016-10-15 18:59:38 -04:00
|
|
|
begin
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.invoke_y_on(foo)
|
|
|
|
return foo.y
|
|
|
|
end
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 11:05:45 -05:00
|
|
|
|
|
|
|
def self.invoke_a_on(foo)
|
|
|
|
return foo.a
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
2016-10-15 18:59:38 -04:00
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
|
|
|
def test_override
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#x", foo.x)
|
|
|
|
assert_equal("FooExt#x", FooExtClient.invoke_x_on(foo))
|
|
|
|
assert_equal("Foo#x", foo.x)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_super
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#y", foo.y)
|
|
|
|
assert_equal("FooExt#y Foo#y", FooExtClient.invoke_y_on(foo))
|
|
|
|
assert_equal("Foo#y", foo.y)
|
|
|
|
end
|
|
|
|
|
2012-12-07 22:36:58 -05:00
|
|
|
def test_super_not_chained
|
2012-08-02 07:34:19 -04:00
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#y", foo.y)
|
2012-12-07 22:36:58 -05:00
|
|
|
assert_equal("FooExt2#y Foo#y", FooExtClient2.invoke_y_on(foo))
|
2012-08-02 07:34:19 -04:00
|
|
|
assert_equal("Foo#y", foo.y)
|
|
|
|
end
|
|
|
|
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 11:05:45 -05:00
|
|
|
def test_using_same_class_refinements
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#a", foo.a)
|
|
|
|
assert_equal("FooExt#a", FooExtClient2.invoke_a_on(foo))
|
|
|
|
assert_equal("Foo#a", foo.a)
|
|
|
|
end
|
|
|
|
|
2012-08-02 07:34:19 -04:00
|
|
|
def test_new_method
|
|
|
|
foo = Foo.new
|
|
|
|
assert_raise(NoMethodError) { foo.z }
|
|
|
|
assert_equal("FooExt#z", FooExtClient.invoke_z_on(foo))
|
|
|
|
assert_raise(NoMethodError) { foo.z }
|
|
|
|
end
|
|
|
|
|
2012-12-10 08:02:54 -05:00
|
|
|
module RespondTo
|
|
|
|
class Super
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Sub < Super
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine Sub do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-10-19 04:02:17 -04:00
|
|
|
def test_send_should_use_refinements
|
2012-11-02 20:09:26 -04:00
|
|
|
foo = Foo.new
|
|
|
|
assert_raise(NoMethodError) { foo.send(:z) }
|
2016-10-19 04:02:17 -04:00
|
|
|
assert_equal("FooExt#z", FooExtClient.send_z_on(foo))
|
2012-11-02 20:09:26 -04:00
|
|
|
assert_raise(NoMethodError) { foo.send(:z) }
|
2012-12-10 08:02:54 -05:00
|
|
|
|
|
|
|
assert_equal(true, RespondTo::Sub.new.respond_to?(:foo))
|
2012-11-02 20:09:26 -04:00
|
|
|
end
|
|
|
|
|
2012-12-09 03:48:34 -05:00
|
|
|
def test_method_should_not_use_refinements
|
2012-11-02 20:09:26 -04:00
|
|
|
foo = Foo.new
|
2012-12-09 03:48:34 -05:00
|
|
|
assert_raise(NameError) { foo.method(:z) }
|
|
|
|
assert_raise(NameError) { FooExtClient.method_z(foo) }
|
|
|
|
assert_raise(NameError) { foo.method(:z) }
|
2012-11-02 20:09:26 -04:00
|
|
|
end
|
|
|
|
|
2012-08-02 07:34:19 -04:00
|
|
|
def test_no_local_rebinding
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#x", foo.call_x)
|
|
|
|
assert_equal("Foo#x", FooExtClient.invoke_call_x_on(foo))
|
|
|
|
assert_equal("Foo#x", foo.call_x)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_subclass_is_prior
|
|
|
|
sub = FooSub.new
|
|
|
|
assert_equal("FooSub#x", sub.x)
|
|
|
|
assert_equal("FooSub#x", FooExtClient.invoke_x_on(sub))
|
|
|
|
assert_equal("FooSub#x", sub.x)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_super_in_subclass
|
|
|
|
sub = FooSub.new
|
|
|
|
assert_equal("FooSub#y Foo#y", sub.y)
|
|
|
|
# not "FooSub#y FooExt#y Foo#y"
|
|
|
|
assert_equal("FooSub#y Foo#y", FooExtClient.invoke_y_on(sub))
|
|
|
|
assert_equal("FooSub#y Foo#y", sub.y)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_new_method_on_subclass
|
|
|
|
sub = FooSub.new
|
|
|
|
assert_raise(NoMethodError) { sub.z }
|
|
|
|
assert_equal("FooExt#z", FooExtClient.invoke_z_on(sub))
|
|
|
|
assert_raise(NoMethodError) { sub.z }
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_module_eval
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#x", foo.x)
|
2012-12-07 10:49:21 -05:00
|
|
|
assert_equal("Foo#x", FooExt.module_eval { foo.x })
|
|
|
|
assert_equal("Foo#x", FooExt.module_eval("foo.x"))
|
2012-08-02 07:34:19 -04:00
|
|
|
assert_equal("Foo#x", foo.x)
|
|
|
|
end
|
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
def test_instance_eval_without_refinement
|
2012-08-02 07:34:19 -04:00
|
|
|
foo = Foo.new
|
|
|
|
ext_client = FooExtClient.new
|
|
|
|
assert_equal("Foo#x", foo.x)
|
2012-12-06 10:12:36 -05:00
|
|
|
assert_equal("Foo#x", ext_client.instance_eval { foo.x })
|
2012-08-02 07:34:19 -04:00
|
|
|
assert_equal("Foo#x", foo.x)
|
|
|
|
end
|
|
|
|
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
module IntegerSlashExt
|
|
|
|
refine Integer do
|
2012-12-06 10:12:36 -05:00
|
|
|
def /(other) quo(other) end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-02 07:34:19 -04:00
|
|
|
def test_override_builtin_method
|
|
|
|
assert_equal(0, 1 / 2)
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
assert_equal(Rational(1, 2), eval_using(IntegerSlashExt, "1 / 2"))
|
2012-08-02 07:34:19 -04:00
|
|
|
assert_equal(0, 1 / 2)
|
|
|
|
end
|
|
|
|
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
module IntegerPlusExt
|
|
|
|
refine Integer do
|
2012-12-06 10:12:36 -05:00
|
|
|
def self.method_added(*args); end
|
2013-12-19 23:44:09 -05:00
|
|
|
def +(other) "overridden" end
|
2012-12-06 10:12:36 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-11-06 23:09:51 -05:00
|
|
|
def test_override_builtin_method_with_method_added
|
|
|
|
assert_equal(3, 1 + 2)
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
assert_equal("overridden", eval_using(IntegerPlusExt, "1 + 2"))
|
2012-11-06 23:09:51 -05:00
|
|
|
assert_equal(3, 1 + 2)
|
|
|
|
end
|
|
|
|
|
2012-08-02 07:34:19 -04:00
|
|
|
def test_return_value_of_refine
|
|
|
|
mod = nil
|
|
|
|
result = nil
|
2014-03-05 08:27:22 -05:00
|
|
|
Module.new {
|
2012-08-02 07:34:19 -04:00
|
|
|
result = refine(Object) {
|
|
|
|
mod = self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert_equal mod, result
|
|
|
|
end
|
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
module RefineSameClass
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
REFINEMENT1 = refine(Integer) {
|
2012-12-06 10:12:36 -05:00
|
|
|
def foo; return "foo" end
|
|
|
|
}
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
REFINEMENT2 = refine(Integer) {
|
2012-12-06 10:12:36 -05:00
|
|
|
def bar; return "bar" end
|
|
|
|
}
|
|
|
|
REFINEMENT3 = refine(String) {
|
|
|
|
def baz; return "baz" end
|
2012-08-02 07:34:19 -04:00
|
|
|
}
|
2012-12-06 10:12:36 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_same_class_twice
|
|
|
|
assert_equal("foo", eval_using(RefineSameClass, "1.foo"))
|
|
|
|
assert_equal("bar", eval_using(RefineSameClass, "1.bar"))
|
|
|
|
assert_equal(RefineSameClass::REFINEMENT1, RefineSameClass::REFINEMENT2)
|
|
|
|
assert_not_equal(RefineSameClass::REFINEMENT1, RefineSameClass::REFINEMENT3)
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
|
|
|
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
module IntegerFooExt
|
|
|
|
refine Integer do
|
2012-12-07 10:49:21 -05:00
|
|
|
def foo; "foo"; end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-12-09 03:48:34 -05:00
|
|
|
def test_respond_to_should_not_use_refinements
|
2012-08-02 07:34:19 -04:00
|
|
|
assert_equal(false, 1.respond_to?(:foo))
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
assert_equal(false, eval_using(IntegerFooExt, "1.respond_to?(:foo)"))
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
module StringCmpExt
|
|
|
|
refine String do
|
|
|
|
def <=>(other) return 0 end
|
|
|
|
end
|
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
module ArrayEachExt
|
|
|
|
refine Array do
|
|
|
|
def each
|
|
|
|
super do |i|
|
|
|
|
yield 2 * i
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
|
|
|
end
|
2012-12-06 10:12:36 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_builtin_method_no_local_rebinding
|
|
|
|
assert_equal(false, eval_using(StringCmpExt, '"1" >= "2"'))
|
|
|
|
assert_equal(1, eval_using(ArrayEachExt, "[1, 2, 3].min"))
|
2012-08-02 07:34:19 -04:00
|
|
|
end
|
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
module RefinePrependedClass
|
|
|
|
module M1
|
2012-08-06 22:44:24 -04:00
|
|
|
def foo
|
|
|
|
super << :m1
|
|
|
|
end
|
2012-12-07 10:49:21 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
class C
|
|
|
|
prepend M1
|
2012-08-06 22:44:24 -04:00
|
|
|
|
|
|
|
def foo
|
|
|
|
[:c]
|
|
|
|
end
|
2012-12-07 10:49:21 -05:00
|
|
|
end
|
2012-08-02 07:34:19 -04:00
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
module M2
|
|
|
|
refine C do
|
2012-09-27 05:53:24 -04:00
|
|
|
def foo
|
2012-12-07 10:49:21 -05:00
|
|
|
super << :m2
|
2012-09-27 05:53:24 -04:00
|
|
|
end
|
|
|
|
end
|
2012-12-07 10:49:21 -05:00
|
|
|
end
|
2012-09-27 05:53:24 -04:00
|
|
|
end
|
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
def test_refine_prepended_class
|
|
|
|
x = eval_using(RefinePrependedClass::M2,
|
|
|
|
"TestRefinement::RefinePrependedClass::C.new.foo")
|
|
|
|
assert_equal([:c, :m1, :m2], x)
|
2012-09-27 05:53:24 -04:00
|
|
|
end
|
|
|
|
|
2016-09-23 07:46:33 -04:00
|
|
|
module RefineModule
|
|
|
|
module M
|
|
|
|
def foo
|
|
|
|
"M#foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
def bar
|
|
|
|
"M#bar"
|
|
|
|
end
|
|
|
|
|
|
|
|
def baz
|
|
|
|
"M#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class C
|
|
|
|
include M
|
|
|
|
|
|
|
|
def baz
|
|
|
|
"#{super} C#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M2
|
|
|
|
refine M do
|
2012-09-28 22:21:27 -04:00
|
|
|
def foo
|
2016-09-23 07:46:33 -04:00
|
|
|
"M@M2#foo"
|
2012-09-28 22:21:27 -04:00
|
|
|
end
|
2016-09-23 07:46:33 -04:00
|
|
|
|
|
|
|
def bar
|
|
|
|
"#{super} M@M2#bar"
|
2012-09-28 22:21:27 -04:00
|
|
|
end
|
2016-09-23 07:46:33 -04:00
|
|
|
|
|
|
|
def baz
|
|
|
|
"#{super} M@M2#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using M2
|
|
|
|
|
|
|
|
def self.call_foo
|
|
|
|
C.new.foo
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.call_bar
|
|
|
|
C.new.bar
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.call_baz
|
|
|
|
C.new.baz
|
2012-12-07 10:49:21 -05:00
|
|
|
end
|
2012-09-28 02:48:20 -04:00
|
|
|
end
|
|
|
|
|
2016-09-23 07:46:33 -04:00
|
|
|
def test_refine_module
|
|
|
|
assert_equal("M@M2#foo", RefineModule.call_foo)
|
|
|
|
assert_equal("M#bar M@M2#bar", RefineModule.call_bar)
|
|
|
|
assert_equal("M#baz C#baz", RefineModule.call_baz)
|
|
|
|
end
|
|
|
|
|
2012-09-27 05:53:24 -04:00
|
|
|
def test_refine_neither_class_nor_module
|
|
|
|
assert_raise(TypeError) do
|
|
|
|
Module.new {
|
|
|
|
refine Object.new do
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
assert_raise(TypeError) do
|
|
|
|
Module.new {
|
|
|
|
refine 123 do
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
assert_raise(TypeError) do
|
|
|
|
Module.new {
|
|
|
|
refine "foo" do
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2012-09-28 22:21:27 -04:00
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
def test_refine_in_class
|
|
|
|
assert_raise(NoMethodError) do
|
|
|
|
Class.new {
|
Use Integer instead of Fixnum and Bignum.
* object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c,
lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb,
lib/rubygems/specification.rb, lib/uri/generic.rb,
bootstraptest/test_eval.rb, basictest/test.rb,
test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb,
test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb,
test/csv/test_data_converters.rb, test/date/test_date.rb,
test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb,
test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb,
test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb,
test/ruby/test_bignum.rb, test/ruby/test_case.rb,
test/ruby/test_class.rb, test/ruby/test_complex.rb,
test/ruby/test_enum.rb, test/ruby/test_eval.rb,
test/ruby/test_iseq.rb, test/ruby/test_literal.rb,
test/ruby/test_math.rb, test/ruby/test_module.rb,
test/ruby/test_numeric.rb, test/ruby/test_range.rb,
test/ruby/test_rational.rb, test/ruby/test_refinement.rb,
test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb,
test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb,
test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-17 09:15:57 -04:00
|
|
|
refine Integer do
|
2012-12-07 10:49:21 -05:00
|
|
|
def foo
|
|
|
|
"c"
|
|
|
|
end
|
2012-09-28 22:21:27 -04:00
|
|
|
end
|
2012-12-07 10:49:21 -05:00
|
|
|
}
|
|
|
|
end
|
2012-09-28 22:21:27 -04:00
|
|
|
end
|
|
|
|
|
2012-11-11 01:14:16 -05:00
|
|
|
def test_main_using
|
2013-07-31 05:29:40 -04:00
|
|
|
assert_in_out_err([], <<-INPUT, %w(:C :M), [])
|
2012-11-11 01:14:16 -05:00
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
:C
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
:M
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
c = C.new
|
|
|
|
p c.foo
|
|
|
|
using M
|
|
|
|
p c.foo
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
def test_main_using_is_private
|
|
|
|
assert_raise(NoMethodError) do
|
2015-03-04 21:56:03 -05:00
|
|
|
eval("self.using Module.new", Sandbox::BINDING)
|
2012-12-07 10:49:21 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-11-11 01:14:16 -05:00
|
|
|
def test_no_kernel_using
|
|
|
|
assert_raise(NoMethodError) do
|
|
|
|
using Module.new
|
2012-09-28 22:21:27 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
class UsingClass
|
|
|
|
end
|
|
|
|
|
2012-09-28 22:21:27 -04:00
|
|
|
def test_module_using_class
|
|
|
|
assert_raise(TypeError) do
|
2015-03-04 21:56:03 -05:00
|
|
|
eval("using TestRefinement::UsingClass", Sandbox::BINDING)
|
2012-09-28 22:21:27 -04:00
|
|
|
end
|
|
|
|
end
|
2012-10-08 10:56:08 -04:00
|
|
|
|
2012-10-30 10:58:47 -04:00
|
|
|
def test_refine_without_block
|
|
|
|
c1 = Class.new
|
2013-10-09 11:17:20 -04:00
|
|
|
assert_raise_with_message(ArgumentError, "no block given") {
|
2012-10-30 10:58:47 -04:00
|
|
|
Module.new do
|
|
|
|
refine c1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end
|
2012-11-01 01:45:28 -04:00
|
|
|
|
2012-11-02 04:53:06 -04:00
|
|
|
module Inspect
|
|
|
|
module M
|
2016-05-01 23:35:52 -04:00
|
|
|
Integer = refine(Integer) {}
|
2012-11-02 04:53:06 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_inspect
|
2016-05-01 23:35:52 -04:00
|
|
|
assert_equal("#<refinement:Integer@TestRefinement::Inspect::M>",
|
|
|
|
Inspect::M::Integer.inspect)
|
2012-11-02 04:53:06 -04:00
|
|
|
end
|
2012-11-10 21:42:04 -05:00
|
|
|
|
2012-11-10 23:45:31 -05:00
|
|
|
def test_using_method_cache
|
2013-07-31 05:29:40 -04:00
|
|
|
assert_in_out_err([], <<-INPUT, %w(:M1 :M2), [])
|
2012-11-10 23:45:31 -05:00
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
"original"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M1
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
:M1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M2
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
:M2
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
c = C.new
|
|
|
|
using M1
|
|
|
|
p c.foo
|
|
|
|
using M2
|
|
|
|
p c.foo
|
|
|
|
INPUT
|
|
|
|
end
|
2012-11-13 04:05:18 -05:00
|
|
|
|
2012-12-07 10:49:21 -05:00
|
|
|
module RedefineRefinedMethod
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
"original"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
"refined"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class C
|
2016-02-19 02:58:09 -05:00
|
|
|
EnvUtil.suppress_warning do
|
|
|
|
def foo
|
|
|
|
"redefined"
|
|
|
|
end
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_redefine_refined_method
|
2012-12-07 10:49:21 -05:00
|
|
|
x = eval_using(RedefineRefinedMethod::M,
|
|
|
|
"TestRefinement::RedefineRefinedMethod::C.new.foo")
|
|
|
|
assert_equal("refined", x)
|
|
|
|
end
|
|
|
|
|
|
|
|
module StringExt
|
|
|
|
refine String do
|
|
|
|
def foo
|
|
|
|
"foo"
|
|
|
|
end
|
|
|
|
end
|
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 08:08:41 -05:00
|
|
|
end
|
2012-12-06 10:12:36 -05:00
|
|
|
|
2012-12-07 21:37:16 -05:00
|
|
|
module RefineScoping
|
|
|
|
refine String do
|
|
|
|
def foo
|
|
|
|
"foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
def RefineScoping.call_in_refine_block
|
|
|
|
"".foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.call_outside_refine_block
|
|
|
|
"".foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_scoping
|
|
|
|
assert_equal("foo", RefineScoping.call_in_refine_block)
|
|
|
|
assert_raise(NoMethodError) do
|
|
|
|
RefineScoping.call_outside_refine_block
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module StringRecursiveLength
|
|
|
|
refine String do
|
|
|
|
def recursive_length
|
|
|
|
if empty?
|
|
|
|
0
|
2012-12-19 20:52:47 -05:00
|
|
|
else
|
2012-12-07 21:37:16 -05:00
|
|
|
self[1..-1].recursive_length + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_recursion
|
|
|
|
x = eval_using(StringRecursiveLength, "'foo'.recursive_length")
|
|
|
|
assert_equal(3, x)
|
|
|
|
end
|
|
|
|
|
|
|
|
module ToJSON
|
|
|
|
refine Integer do
|
|
|
|
def to_json; to_s; end
|
|
|
|
end
|
|
|
|
|
|
|
|
refine Array do
|
|
|
|
def to_json; "[" + map { |i| i.to_json }.join(",") + "]" end
|
|
|
|
end
|
|
|
|
|
|
|
|
refine Hash do
|
|
|
|
def to_json; "{" + map { |k, v| k.to_s.dump + ":" + v.to_json }.join(",") + "}" end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_mutual_recursion
|
|
|
|
x = eval_using(ToJSON, "[{1=>2}, {3=>4}].to_json")
|
|
|
|
assert_equal('[{"1":2},{"3":4}]', x)
|
|
|
|
end
|
|
|
|
|
2012-12-07 22:06:13 -05:00
|
|
|
def test_refine_with_proc
|
|
|
|
assert_raise(ArgumentError) do
|
|
|
|
Module.new {
|
|
|
|
refine(String, &Proc.new {})
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-12-08 08:35:12 -05:00
|
|
|
def test_using_in_module
|
|
|
|
assert_raise(RuntimeError) do
|
2015-03-04 21:56:03 -05:00
|
|
|
eval(<<-EOF, Sandbox::BINDING)
|
2012-12-08 08:35:12 -05:00
|
|
|
$main = self
|
|
|
|
module M
|
|
|
|
end
|
|
|
|
module M2
|
|
|
|
$main.send(:using, M)
|
|
|
|
end
|
|
|
|
EOF
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_using_in_method
|
|
|
|
assert_raise(RuntimeError) do
|
2015-03-04 21:56:03 -05:00
|
|
|
eval(<<-EOF, Sandbox::BINDING)
|
2012-12-08 08:35:12 -05:00
|
|
|
$main = self
|
|
|
|
module M
|
|
|
|
end
|
2015-03-04 21:56:03 -05:00
|
|
|
class C
|
|
|
|
def call_using_in_method
|
|
|
|
$main.send(:using, M)
|
|
|
|
end
|
2012-12-08 08:35:12 -05:00
|
|
|
end
|
2015-03-04 21:56:03 -05:00
|
|
|
C.new.call_using_in_method
|
2012-12-08 08:35:12 -05:00
|
|
|
EOF
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 11:05:45 -05:00
|
|
|
module IncludeIntoRefinement
|
|
|
|
class C
|
|
|
|
def bar
|
|
|
|
return "C#bar"
|
|
|
|
end
|
|
|
|
|
|
|
|
def baz
|
|
|
|
return "C#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Mixin
|
|
|
|
def foo
|
|
|
|
return "Mixin#foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
def bar
|
|
|
|
return super << " Mixin#bar"
|
|
|
|
end
|
|
|
|
|
|
|
|
def baz
|
|
|
|
return super << " Mixin#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine C do
|
|
|
|
include Mixin
|
|
|
|
|
|
|
|
def baz
|
|
|
|
return super << " M#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-04 21:56:03 -05:00
|
|
|
eval <<-EOF, Sandbox::BINDING
|
* fix the behavior when a module is included into a refinement.
This change is a little tricky, so it might be better to prohibit
module inclusion to refinements.
* include/ruby/ruby.h (RMODULE_INCLUDED_INTO_REFINEMENT): new flag
to represent that a module (iclass) is included into a refinement.
* class.c (include_modules_at): set RMODULE_INCLUDED_INTO_REFINEMENT
if klass is a refinement.
* eval.c (rb_mod_refine): set the superclass of a refinement to the
refined class for super.
* eval.c (rb_using_refinement): skip the above superclass (the
refined class) when creating iclasses for refinements. Otherwise,
`using Refinement1; using Refinement2' creates iclasses:
<Refinement2> -> <RefinedClass> -> <Refinement1> -> RefinedClass,
where <Module> is an iclass for Module, so RefinedClass is
searched before Refinement1. The correct iclasses should be
<Refinement2> -> <Refinement1> -> RefinedClass.
* vm_insnhelper.c (vm_search_normal_superclass): if klass is an
iclass for a refinement, use the refinement's superclass instead
of the iclass's superclass. Otherwise, multiple refinements are
searched by super. For example, if a refinement Refinement2
includes a module M (i.e., Refinement2 -> <M> -> RefinedClass,
and if refinements iclasses are <Refinement2> -> <M>' ->
<Refinement1> -> RefinedClass, then super in <Refinement2> should
use Refinement2's superclass <M> instead of <Refinement2>'s
superclass <M>'.
* vm_insnhelper.c (vm_search_super_method): do not raise a
NotImplementError if current_defind_class is a module included
into a refinement. Because of the change of
vm_search_normal_superclass(), the receiver might not be an
instance of the module('s iclass).
* test/ruby/test_refinement.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38298 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-10 11:05:45 -05:00
|
|
|
using TestRefinement::IncludeIntoRefinement::M
|
|
|
|
|
|
|
|
module TestRefinement::IncludeIntoRefinement::User
|
|
|
|
def self.invoke_foo_on(x)
|
|
|
|
x.foo
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_bar_on(x)
|
|
|
|
x.bar
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_baz_on(x)
|
|
|
|
x.baz
|
|
|
|
end
|
|
|
|
end
|
|
|
|
EOF
|
|
|
|
|
|
|
|
def test_include_into_refinement
|
|
|
|
x = IncludeIntoRefinement::C.new
|
|
|
|
assert_equal("Mixin#foo", IncludeIntoRefinement::User.invoke_foo_on(x))
|
|
|
|
assert_equal("C#bar Mixin#bar",
|
|
|
|
IncludeIntoRefinement::User.invoke_bar_on(x))
|
|
|
|
assert_equal("C#baz Mixin#baz M#baz",
|
|
|
|
IncludeIntoRefinement::User.invoke_baz_on(x))
|
|
|
|
end
|
|
|
|
|
2012-12-11 11:48:21 -05:00
|
|
|
module PrependIntoRefinement
|
|
|
|
class C
|
|
|
|
def bar
|
|
|
|
return "C#bar"
|
|
|
|
end
|
|
|
|
|
|
|
|
def baz
|
|
|
|
return "C#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Mixin
|
|
|
|
def foo
|
|
|
|
return "Mixin#foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
def bar
|
|
|
|
return super << " Mixin#bar"
|
|
|
|
end
|
|
|
|
|
|
|
|
def baz
|
|
|
|
return super << " Mixin#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine C do
|
|
|
|
prepend Mixin
|
|
|
|
|
|
|
|
def baz
|
|
|
|
return super << " M#baz"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-04 21:56:03 -05:00
|
|
|
eval <<-EOF, Sandbox::BINDING
|
2012-12-11 11:48:21 -05:00
|
|
|
using TestRefinement::PrependIntoRefinement::M
|
|
|
|
|
|
|
|
module TestRefinement::PrependIntoRefinement::User
|
|
|
|
def self.invoke_foo_on(x)
|
|
|
|
x.foo
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_bar_on(x)
|
|
|
|
x.bar
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_baz_on(x)
|
|
|
|
x.baz
|
|
|
|
end
|
|
|
|
end
|
|
|
|
EOF
|
|
|
|
|
|
|
|
def test_prepend_into_refinement
|
|
|
|
x = PrependIntoRefinement::C.new
|
|
|
|
assert_equal("Mixin#foo", PrependIntoRefinement::User.invoke_foo_on(x))
|
|
|
|
assert_equal("C#bar Mixin#bar",
|
|
|
|
PrependIntoRefinement::User.invoke_bar_on(x))
|
|
|
|
assert_equal("C#baz M#baz Mixin#baz",
|
|
|
|
PrependIntoRefinement::User.invoke_baz_on(x))
|
|
|
|
end
|
|
|
|
|
2015-08-31 04:07:59 -04:00
|
|
|
PrependAfterRefine_CODE = <<-EOC
|
2012-12-12 04:35:50 -05:00
|
|
|
module PrependAfterRefine
|
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
"original"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
"refined"
|
|
|
|
end
|
|
|
|
|
|
|
|
def bar
|
|
|
|
"refined"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Mixin
|
|
|
|
def foo
|
|
|
|
"mixin"
|
|
|
|
end
|
|
|
|
|
|
|
|
def bar
|
|
|
|
"mixin"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class C
|
|
|
|
prepend Mixin
|
|
|
|
end
|
|
|
|
end
|
2015-08-31 04:07:59 -04:00
|
|
|
EOC
|
|
|
|
eval PrependAfterRefine_CODE
|
|
|
|
|
|
|
|
def test_prepend_after_refine_wb_miss
|
2016-06-28 23:45:23 -04:00
|
|
|
if /\A(arm|mips)/ =~ RUBY_PLATFORM
|
|
|
|
skip "too slow cpu"
|
|
|
|
end
|
2015-08-31 04:07:59 -04:00
|
|
|
assert_normal_exit %Q{
|
|
|
|
GC.stress = true
|
|
|
|
10.times{
|
|
|
|
#{PrependAfterRefine_CODE}
|
|
|
|
undef PrependAfterRefine
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
2012-12-12 04:35:50 -05:00
|
|
|
|
|
|
|
def test_prepend_after_refine
|
|
|
|
x = eval_using(PrependAfterRefine::M,
|
|
|
|
"TestRefinement::PrependAfterRefine::C.new.foo")
|
|
|
|
assert_equal("refined", x)
|
|
|
|
assert_equal("mixin", TestRefinement::PrependAfterRefine::C.new.foo)
|
|
|
|
y = eval_using(PrependAfterRefine::M,
|
|
|
|
"TestRefinement::PrependAfterRefine::C.new.bar")
|
|
|
|
assert_equal("refined", y)
|
|
|
|
assert_equal("mixin", TestRefinement::PrependAfterRefine::C.new.bar)
|
|
|
|
end
|
|
|
|
|
2013-02-23 23:36:00 -05:00
|
|
|
module SuperInBlock
|
|
|
|
class C
|
|
|
|
def foo(*args)
|
|
|
|
[:foo, *args]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module R
|
|
|
|
refine C do
|
|
|
|
def foo(*args)
|
|
|
|
tap do
|
|
|
|
return super(:ref, *args)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_super_in_block
|
|
|
|
bug7925 = '[ruby-core:52750] [Bug #7925]'
|
|
|
|
x = eval_using(SuperInBlock::R,
|
|
|
|
"TestRefinement:: SuperInBlock::C.new.foo(#{bug7925.dump})")
|
|
|
|
assert_equal([:foo, :ref, bug7925], x, bug7925)
|
|
|
|
end
|
|
|
|
|
2013-06-12 10:33:59 -04:00
|
|
|
module ModuleUsing
|
|
|
|
using FooExt
|
|
|
|
|
|
|
|
def self.invoke_x_on(foo)
|
|
|
|
return foo.x
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_y_on(foo)
|
|
|
|
return foo.y
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_z_on(foo)
|
|
|
|
return foo.z
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.send_z_on(foo)
|
|
|
|
return foo.send(:z)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.method_z(foo)
|
|
|
|
return foo.method(:z)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_call_x_on(foo)
|
|
|
|
return foo.call_x
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_module_using
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("Foo#x", foo.x)
|
|
|
|
assert_equal("Foo#y", foo.y)
|
|
|
|
assert_raise(NoMethodError) { foo.z }
|
|
|
|
assert_equal("FooExt#x", ModuleUsing.invoke_x_on(foo))
|
|
|
|
assert_equal("FooExt#y Foo#y", ModuleUsing.invoke_y_on(foo))
|
|
|
|
assert_equal("FooExt#z", ModuleUsing.invoke_z_on(foo))
|
|
|
|
assert_equal("Foo#x", foo.x)
|
|
|
|
assert_equal("Foo#y", foo.y)
|
|
|
|
assert_raise(NoMethodError) { foo.z }
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_module_using_in_method
|
|
|
|
assert_raise(RuntimeError) do
|
|
|
|
Module.new.send(:using, FooExt)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_module_using_invalid_self
|
|
|
|
assert_raise(RuntimeError) do
|
2015-03-04 21:56:03 -05:00
|
|
|
eval <<-EOF, Sandbox::BINDING
|
2013-06-12 10:33:59 -04:00
|
|
|
module TestRefinement::TestModuleUsingInvalidSelf
|
|
|
|
Module.new.send(:using, TestRefinement::FooExt)
|
|
|
|
end
|
|
|
|
EOF
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-30 23:57:16 -04:00
|
|
|
class Bar
|
|
|
|
end
|
|
|
|
|
|
|
|
module BarExt
|
|
|
|
refine Bar do
|
|
|
|
def x
|
|
|
|
return "BarExt#x"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooBarExt
|
|
|
|
include FooExt
|
|
|
|
include BarExt
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooBarExtClient
|
|
|
|
using FooBarExt
|
|
|
|
|
|
|
|
def self.invoke_x_on(foo)
|
|
|
|
return foo.x
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_module_inclusion
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("FooExt#x", FooBarExtClient.invoke_x_on(foo))
|
|
|
|
bar = Bar.new
|
|
|
|
assert_equal("BarExt#x", FooBarExtClient.invoke_x_on(bar))
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooFoo2Ext
|
|
|
|
include FooExt
|
|
|
|
include FooExt2
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooFoo2ExtClient
|
|
|
|
using FooFoo2Ext
|
|
|
|
|
|
|
|
def self.invoke_x_on(foo)
|
|
|
|
return foo.x
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoke_y_on(foo)
|
|
|
|
return foo.y
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_module_inclusion2
|
|
|
|
foo = Foo.new
|
|
|
|
assert_equal("FooExt2#x", FooFoo2ExtClient.invoke_x_on(foo))
|
|
|
|
assert_equal("FooExt2#y Foo#y", FooFoo2ExtClient.invoke_y_on(foo))
|
|
|
|
end
|
|
|
|
|
2013-08-06 03:15:18 -04:00
|
|
|
def test_eval_scoping
|
|
|
|
assert_in_out_err([], <<-INPUT, ["HELLO WORLD", "dlrow olleh", "HELLO WORLD"], [])
|
|
|
|
module M
|
|
|
|
refine String do
|
|
|
|
def upcase
|
|
|
|
reverse
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
puts "hello world".upcase
|
|
|
|
puts eval(%{using M; "hello world".upcase})
|
|
|
|
puts "hello world".upcase
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_eval_with_binding_scoping
|
2015-03-04 21:56:03 -05:00
|
|
|
assert_in_out_err([], <<-INPUT, ["HELLO WORLD", "dlrow olleh", "dlrow olleh"], [])
|
2013-08-06 03:15:18 -04:00
|
|
|
module M
|
|
|
|
refine String do
|
|
|
|
def upcase
|
|
|
|
reverse
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
puts "hello world".upcase
|
2015-03-04 21:56:03 -05:00
|
|
|
b = binding
|
|
|
|
puts eval(%{using M; "hello world".upcase}, b)
|
|
|
|
puts eval(%{"hello world".upcase}, b)
|
2013-08-06 03:15:18 -04:00
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2013-09-07 02:44:31 -04:00
|
|
|
def test_case_dispatch_is_aware_of_refinements
|
|
|
|
assert_in_out_err([], <<-RUBY, ["refinement used"], [])
|
|
|
|
module RefineSymbol
|
|
|
|
refine Symbol do
|
|
|
|
def ===(other)
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using RefineSymbol
|
|
|
|
|
|
|
|
case :a
|
|
|
|
when :b
|
|
|
|
puts "refinement used"
|
|
|
|
else
|
|
|
|
puts "refinement not used"
|
|
|
|
end
|
|
|
|
RUBY
|
|
|
|
end
|
|
|
|
|
2013-09-09 03:56:02 -04:00
|
|
|
def test_refine_after_using
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug8880 = '[ruby-core:57079] [Bug #8880]'
|
|
|
|
module Test
|
|
|
|
refine(String) do
|
|
|
|
end
|
|
|
|
end
|
|
|
|
using Test
|
|
|
|
def t
|
|
|
|
'Refinements are broken!'.chop!
|
|
|
|
end
|
|
|
|
t
|
|
|
|
module Test
|
|
|
|
refine(String) do
|
|
|
|
def chop!
|
|
|
|
self.sub!(/broken/, 'fine')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert_equal('Refinements are fine!', t, bug8880)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2013-09-09 23:39:31 -04:00
|
|
|
def test_instance_methods
|
|
|
|
bug8881 = '[ruby-core:57080] [Bug #8881]'
|
|
|
|
assert_not_include(Foo.instance_methods(false), :z, bug8881)
|
|
|
|
assert_not_include(FooSub.instance_methods(true), :z, bug8881)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_method_defined
|
|
|
|
assert_not_send([Foo, :method_defined?, :z])
|
|
|
|
assert_not_send([FooSub, :method_defined?, :z])
|
|
|
|
end
|
|
|
|
|
2013-09-29 21:49:21 -04:00
|
|
|
def test_undef_refined_method
|
|
|
|
bug8966 = '[ruby-core:57466] [Bug #8966]'
|
|
|
|
|
|
|
|
assert_in_out_err([], <<-INPUT, ["NameError"], [], bug8966)
|
|
|
|
module Foo
|
|
|
|
refine Object do
|
|
|
|
def foo
|
|
|
|
puts "foo"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using Foo
|
|
|
|
|
|
|
|
class Object
|
|
|
|
begin
|
|
|
|
undef foo
|
|
|
|
rescue Exception => e
|
|
|
|
p e.class
|
|
|
|
end
|
|
|
|
end
|
|
|
|
INPUT
|
|
|
|
|
|
|
|
assert_in_out_err([], <<-INPUT, ["NameError"], [], bug8966)
|
|
|
|
module Foo
|
|
|
|
refine Object do
|
|
|
|
def foo
|
|
|
|
puts "foo"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# without `using Foo'
|
|
|
|
|
|
|
|
class Object
|
|
|
|
begin
|
|
|
|
undef foo
|
|
|
|
rescue Exception => e
|
|
|
|
p e.class
|
|
|
|
end
|
|
|
|
end
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2013-10-17 04:44:26 -04:00
|
|
|
def test_refine_undefed_method_and_call
|
|
|
|
assert_in_out_err([], <<-INPUT, ["NoMethodError"], [])
|
|
|
|
class Foo
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
|
|
|
|
undef foo
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooExt
|
|
|
|
refine Foo do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
Foo.new.foo
|
|
|
|
rescue => e
|
|
|
|
p e.class
|
|
|
|
end
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_undefed_method_and_send
|
|
|
|
assert_in_out_err([], <<-INPUT, ["NoMethodError"], [])
|
|
|
|
class Foo
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
|
|
|
|
undef foo
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooExt
|
|
|
|
refine Foo do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
Foo.new.send(:foo)
|
|
|
|
rescue => e
|
|
|
|
p e.class
|
|
|
|
end
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2014-02-13 09:44:41 -05:00
|
|
|
def test_adding_private_method
|
|
|
|
bug9452 = '[ruby-core:60111] [Bug #9452]'
|
|
|
|
|
|
|
|
assert_in_out_err([], <<-INPUT, ["Success!", "NoMethodError"], [], bug9452)
|
|
|
|
module R
|
|
|
|
refine Object do
|
|
|
|
def m
|
|
|
|
puts "Success!"
|
|
|
|
end
|
|
|
|
|
|
|
|
private(:m)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using R
|
|
|
|
|
|
|
|
m
|
|
|
|
42.m rescue p($!.class)
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_making_private_method_public
|
|
|
|
bug9452 = '[ruby-core:60111] [Bug #9452]'
|
|
|
|
|
|
|
|
assert_in_out_err([], <<-INPUT, ["Success!", "Success!"], [], bug9452)
|
|
|
|
class Object
|
|
|
|
private
|
|
|
|
def m
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module R
|
|
|
|
refine Object do
|
|
|
|
def m
|
|
|
|
puts "Success!"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using R
|
|
|
|
m
|
|
|
|
42.m
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2014-08-02 21:43:10 -04:00
|
|
|
def test_refine_basic_object
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10106 = '[ruby-core:64166] [Bug #10106]'
|
|
|
|
module RefinementBug
|
|
|
|
refine BasicObject do
|
|
|
|
def foo
|
|
|
|
1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise(NoMethodError, bug10106) {Object.new.foo}
|
|
|
|
end;
|
2015-01-08 03:05:03 -05:00
|
|
|
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10707 = '[ruby-core:67389] [Bug #10707]'
|
|
|
|
module RefinementBug
|
|
|
|
refine BasicObject do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert(methods, bug10707)
|
|
|
|
assert_raise(NameError, bug10707) {method(:foo)}
|
|
|
|
end;
|
2014-08-02 21:43:10 -04:00
|
|
|
end
|
|
|
|
|
2015-01-08 02:31:45 -05:00
|
|
|
def test_change_refined_new_method_visibility
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10706 = '[ruby-core:67387] [Bug #10706]'
|
|
|
|
module RefinementBug
|
|
|
|
refine Object do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise(NameError, bug10706) {private(:foo)}
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2015-01-12 02:45:49 -05:00
|
|
|
def test_alias_refined_method
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10731 = '[ruby-core:67523] [Bug #10731]'
|
|
|
|
|
|
|
|
class C
|
|
|
|
end
|
|
|
|
|
|
|
|
module RefinementBug
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
|
|
|
|
def bar
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise(NameError, bug10731) do
|
|
|
|
class C
|
|
|
|
alias foo bar
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2015-01-15 07:35:00 -05:00
|
|
|
def test_singleton_method_should_not_use_refinements
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10744 = '[ruby-core:67603] [Bug #10744]'
|
|
|
|
|
|
|
|
class C
|
|
|
|
end
|
|
|
|
|
|
|
|
module RefinementBug
|
|
|
|
refine C.singleton_class do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise(NameError, bug10744) { C.singleton_method(:foo) }
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2015-01-18 01:57:34 -05:00
|
|
|
def test_refined_method_defined
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10753 = '[ruby-core:67656] [Bug #10753]'
|
|
|
|
|
|
|
|
c = Class.new do
|
|
|
|
def refined_public; end
|
|
|
|
def refined_protected; end
|
|
|
|
def refined_private; end
|
|
|
|
|
|
|
|
public :refined_public
|
|
|
|
protected :refined_protected
|
|
|
|
private :refined_private
|
|
|
|
end
|
|
|
|
|
|
|
|
m = Module.new do
|
|
|
|
refine(c) do
|
|
|
|
def refined_public; end
|
|
|
|
def refined_protected; end
|
|
|
|
def refined_private; end
|
|
|
|
|
|
|
|
public :refined_public
|
|
|
|
protected :refined_protected
|
|
|
|
private :refined_private
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using m
|
|
|
|
|
|
|
|
assert_equal(true, c.public_method_defined?(:refined_public), bug10753)
|
|
|
|
assert_equal(false, c.public_method_defined?(:refined_protected), bug10753)
|
|
|
|
assert_equal(false, c.public_method_defined?(:refined_private), bug10753)
|
|
|
|
|
|
|
|
assert_equal(false, c.protected_method_defined?(:refined_public), bug10753)
|
|
|
|
assert_equal(true, c.protected_method_defined?(:refined_protected), bug10753)
|
|
|
|
assert_equal(false, c.protected_method_defined?(:refined_private), bug10753)
|
|
|
|
|
|
|
|
assert_equal(false, c.private_method_defined?(:refined_public), bug10753)
|
|
|
|
assert_equal(false, c.private_method_defined?(:refined_protected), bug10753)
|
|
|
|
assert_equal(true, c.private_method_defined?(:refined_private), bug10753)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_undefined_refined_method_defined
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10753 = '[ruby-core:67656] [Bug #10753]'
|
|
|
|
|
|
|
|
c = Class.new
|
|
|
|
|
|
|
|
m = Module.new do
|
|
|
|
refine(c) do
|
|
|
|
def undefined_refined_public; end
|
|
|
|
def undefined_refined_protected; end
|
|
|
|
def undefined_refined_private; end
|
|
|
|
public :undefined_refined_public
|
|
|
|
protected :undefined_refined_protected
|
|
|
|
private :undefined_refined_private
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using m
|
|
|
|
|
|
|
|
assert_equal(false, c.public_method_defined?(:undefined_refined_public), bug10753)
|
|
|
|
assert_equal(false, c.public_method_defined?(:undefined_refined_protected), bug10753)
|
|
|
|
assert_equal(false, c.public_method_defined?(:undefined_refined_private), bug10753)
|
|
|
|
|
|
|
|
assert_equal(false, c.protected_method_defined?(:undefined_refined_public), bug10753)
|
|
|
|
assert_equal(false, c.protected_method_defined?(:undefined_refined_protected), bug10753)
|
|
|
|
assert_equal(false, c.protected_method_defined?(:undefined_refined_private), bug10753)
|
|
|
|
|
|
|
|
assert_equal(false, c.private_method_defined?(:undefined_refined_public), bug10753)
|
|
|
|
assert_equal(false, c.private_method_defined?(:undefined_refined_protected), bug10753)
|
|
|
|
assert_equal(false, c.private_method_defined?(:undefined_refined_private), bug10753)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2015-02-03 01:26:48 -05:00
|
|
|
def test_remove_refined_method
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10765 = '[ruby-core:67722] [Bug #10765]'
|
|
|
|
|
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
"C#foo"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module RefinementBug
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
"RefinementBug#foo"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using RefinementBug
|
|
|
|
|
|
|
|
class C
|
|
|
|
remove_method :foo
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_equal("RefinementBug#foo", C.new.foo, bug10765)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_remove_undefined_refined_method
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
bug10765 = '[ruby-core:67722] [Bug #10765]'
|
|
|
|
|
|
|
|
class C
|
|
|
|
end
|
|
|
|
|
|
|
|
module RefinementBug
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using RefinementBug
|
|
|
|
|
|
|
|
assert_raise(NameError, bug10765) {
|
|
|
|
class C
|
|
|
|
remove_method :foo
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2015-02-04 02:45:29 -05:00
|
|
|
module NotIncludeSuperclassMethod
|
|
|
|
class X
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Y < X
|
|
|
|
end
|
|
|
|
|
|
|
|
module Bar
|
|
|
|
refine Y do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_instance_methods_not_include_superclass_method
|
|
|
|
bug10826 = '[ruby-dev:48854] [Bug #10826]'
|
|
|
|
assert_not_include(NotIncludeSuperclassMethod::Y.instance_methods(false),
|
|
|
|
:foo, bug10826)
|
|
|
|
assert_include(NotIncludeSuperclassMethod::Y.instance_methods(true),
|
|
|
|
:foo, bug10826)
|
|
|
|
end
|
|
|
|
|
2015-02-09 21:40:21 -05:00
|
|
|
def test_undef_original_method
|
|
|
|
assert_in_out_err([], <<-INPUT, ["NoMethodError"], [])
|
|
|
|
module NoPlus
|
|
|
|
refine String do
|
|
|
|
undef +
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using NoPlus
|
|
|
|
"a" + "b" rescue p($!.class)
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2017-01-18 00:23:53 -05:00
|
|
|
def test_undef_prepended_method
|
|
|
|
bug13096 = '[ruby-core:78944] [Bug #13096]'
|
|
|
|
klass = EnvUtil.labeled_class("X") do
|
|
|
|
def foo; end
|
|
|
|
end
|
|
|
|
klass.prepend(Module.new)
|
|
|
|
ext = EnvUtil.labeled_module("Ext") do
|
|
|
|
refine klass do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert_nothing_raised(NameError, bug13096) do
|
|
|
|
klass.class_eval do
|
|
|
|
undef :foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-02-22 02:05:14 -05:00
|
|
|
def test_call_refined_method_in_duplicate_module
|
|
|
|
bug10885 = '[ruby-dev:48878]'
|
|
|
|
assert_in_out_err([], <<-INPUT, [], [], bug10885)
|
|
|
|
module M
|
|
|
|
refine Object do
|
|
|
|
def raise
|
|
|
|
# do nothing
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class << self
|
|
|
|
using M
|
|
|
|
def m0
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using M
|
|
|
|
def M.m1
|
|
|
|
raise
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
M.dup.m0
|
|
|
|
M.dup.m1
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2015-05-06 09:49:57 -04:00
|
|
|
def test_check_funcall_undefined
|
|
|
|
bug11117 = '[ruby-core:69064] [Bug #11117]'
|
|
|
|
|
|
|
|
x = Class.new
|
|
|
|
Module.new do
|
|
|
|
refine x do
|
|
|
|
def to_regexp
|
|
|
|
//
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_nothing_raised(NoMethodError, bug11117) {
|
|
|
|
assert_nil(Regexp.try_convert(x.new))
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2015-05-07 23:11:35 -04:00
|
|
|
def test_funcall_inherited
|
|
|
|
bug11117 = '[ruby-core:69064] [Bug #11117]'
|
|
|
|
|
|
|
|
Module.new {refine(Dir) {def to_s; end}}
|
|
|
|
x = Class.new(Dir).allocate
|
|
|
|
assert_nothing_raised(NoMethodError, bug11117) {
|
|
|
|
x.inspect
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2015-05-26 09:16:18 -04:00
|
|
|
def test_alias_refined_method2
|
|
|
|
bug11182 = '[ruby-core:69360]'
|
|
|
|
assert_in_out_err([], <<-INPUT, ["C"], [], bug11182)
|
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
puts "C"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine C do
|
|
|
|
def foo
|
2015-08-10 21:33:32 -04:00
|
|
|
puts "Refined C"
|
2015-05-26 09:16:18 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class D < C
|
|
|
|
alias bar foo
|
|
|
|
end
|
|
|
|
|
|
|
|
using M
|
|
|
|
D.new.bar
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2015-11-09 10:57:07 -05:00
|
|
|
def test_reopen_refinement_module
|
|
|
|
assert_separately([], <<-"end;")
|
|
|
|
$VERBOSE = nil
|
|
|
|
class C
|
|
|
|
end
|
|
|
|
|
|
|
|
module R
|
|
|
|
refine C do
|
|
|
|
def m
|
|
|
|
:foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using R
|
|
|
|
assert_equal(:foo, C.new.m)
|
|
|
|
|
|
|
|
module R
|
|
|
|
refine C do
|
|
|
|
def m
|
|
|
|
:bar
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-11-09 17:25:10 -05:00
|
|
|
assert_equal(:bar, C.new.m, "[ruby-core:71423] [Bug #11672]")
|
2015-11-09 10:57:07 -05:00
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2015-11-19 19:17:25 -05:00
|
|
|
module MixedUsing1
|
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
:orig_foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module R1
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
[:R1, super]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module_function
|
|
|
|
|
|
|
|
def foo
|
|
|
|
[:foo, C.new.foo]
|
|
|
|
end
|
|
|
|
|
|
|
|
using R1
|
|
|
|
|
|
|
|
def bar
|
|
|
|
[:bar, C.new.foo]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module MixedUsing2
|
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
:orig_foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module R1
|
|
|
|
refine C do
|
|
|
|
def foo
|
|
|
|
[:R1_foo, super]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module R2
|
|
|
|
refine C do
|
|
|
|
def bar
|
|
|
|
[:R2_bar, C.new.foo]
|
|
|
|
end
|
|
|
|
|
|
|
|
using R1
|
|
|
|
|
|
|
|
def baz
|
|
|
|
[:R2_baz, C.new.foo]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using R2
|
|
|
|
module_function
|
|
|
|
def f1; C.new.bar; end
|
|
|
|
def f2; C.new.baz; end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_mixed_using
|
|
|
|
assert_equal([:foo, :orig_foo], MixedUsing1.foo)
|
|
|
|
assert_equal([:bar, [:R1, :orig_foo]], MixedUsing1.bar)
|
|
|
|
|
|
|
|
assert_equal([:R2_bar, :orig_foo], MixedUsing2.f1)
|
|
|
|
assert_equal([:R2_baz, [:R1_foo, :orig_foo]], MixedUsing2.f2)
|
|
|
|
end
|
|
|
|
|
2015-12-12 10:08:52 -05:00
|
|
|
module MethodMissing
|
|
|
|
class Foo
|
|
|
|
end
|
|
|
|
|
|
|
|
module Bar
|
|
|
|
refine Foo do
|
|
|
|
def method_missing(mid, *args)
|
|
|
|
"method_missing refined"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using Bar
|
|
|
|
|
|
|
|
def self.call_undefined_method
|
|
|
|
Foo.new.foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_method_missing
|
|
|
|
assert_raise(NoMethodError) do
|
|
|
|
MethodMissing.call_undefined_method
|
|
|
|
end
|
|
|
|
end
|
2016-09-07 12:15:46 -04:00
|
|
|
|
2016-09-07 12:15:45 -04:00
|
|
|
module VisibleRefinements
|
|
|
|
module RefA
|
|
|
|
refine Object do
|
|
|
|
def in_ref_a
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module RefB
|
|
|
|
refine Object do
|
|
|
|
def in_ref_b
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module RefC
|
|
|
|
using RefA
|
2016-09-07 12:15:46 -04:00
|
|
|
|
2016-09-07 12:15:45 -04:00
|
|
|
refine Object do
|
|
|
|
def in_ref_c
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Foo
|
|
|
|
using RefB
|
2016-09-08 03:49:02 -04:00
|
|
|
USED_MODS = Module.used_modules
|
2016-09-07 12:15:45 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
module Bar
|
|
|
|
using RefC
|
2016-09-08 03:49:02 -04:00
|
|
|
USED_MODS = Module.used_modules
|
2016-09-07 12:15:45 -04:00
|
|
|
end
|
2016-09-07 12:15:46 -04:00
|
|
|
|
2016-09-07 12:15:45 -04:00
|
|
|
module Combined
|
|
|
|
using RefA
|
|
|
|
using RefB
|
2016-09-08 03:49:02 -04:00
|
|
|
USED_MODS = Module.used_modules
|
2016-09-07 12:15:45 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-08 03:49:02 -04:00
|
|
|
def test_used_modules
|
2016-09-07 12:15:45 -04:00
|
|
|
ref = VisibleRefinements
|
2016-09-08 03:49:02 -04:00
|
|
|
assert_equal [], Module.used_modules
|
|
|
|
assert_equal [ref::RefB], ref::Foo::USED_MODS
|
|
|
|
assert_equal [ref::RefC], ref::Bar::USED_MODS
|
|
|
|
assert_equal [ref::RefB, ref::RefA], ref::Combined::USED_MODS
|
2016-09-07 12:15:45 -04:00
|
|
|
end
|
2015-12-12 10:08:52 -05:00
|
|
|
|
2016-09-08 00:44:51 -04:00
|
|
|
def test_warn_setconst_in_refinmenet
|
|
|
|
bug10103 = '[ruby-core:64143] [Bug #10103]'
|
|
|
|
warnings = [
|
|
|
|
"-:3: warning: not defined at the refinement, but at the outer class/module",
|
|
|
|
"-:4: warning: not defined at the refinement, but at the outer class/module"
|
|
|
|
]
|
|
|
|
assert_in_out_err([], <<-INPUT, [], warnings, bug10103)
|
|
|
|
module M
|
|
|
|
refine String do
|
|
|
|
FOO = 123
|
|
|
|
@@foo = 456
|
|
|
|
end
|
|
|
|
end
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2016-10-15 18:59:39 -04:00
|
|
|
def test_symbol_proc
|
|
|
|
assert_equal("FooExt#x", FooExtClient.map_x_on(Foo.new))
|
2016-10-22 22:03:56 -04:00
|
|
|
assert_equal("Foo#x", FooExtClient.return_proc(&:x).(Foo.new))
|
2016-10-15 18:59:39 -04:00
|
|
|
end
|
|
|
|
|
2017-03-18 10:22:15 -04:00
|
|
|
def test_symbol_proc_with_block
|
|
|
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
|
|
|
bug = '[ruby-core:80219] [Bug #13325]'
|
|
|
|
begin;
|
|
|
|
module M
|
|
|
|
refine Class.new do
|
|
|
|
end
|
|
|
|
end
|
|
|
|
class C
|
|
|
|
def call(a, x, &b)
|
|
|
|
b.call(a, &x)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
o = C.new
|
|
|
|
r = nil
|
|
|
|
x = ->(z){r = z}
|
|
|
|
assert_equal(42, o.call(42, x, &:tap))
|
|
|
|
assert_equal(42, r)
|
|
|
|
using M
|
|
|
|
r = nil
|
|
|
|
assert_equal(42, o.call(42, x, &:tap), bug)
|
|
|
|
assert_equal(42, r, bug)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2016-11-04 22:57:40 -04:00
|
|
|
module AliasInSubclass
|
|
|
|
class C
|
|
|
|
def foo
|
|
|
|
:original
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class D < C
|
|
|
|
alias bar foo
|
|
|
|
end
|
|
|
|
|
|
|
|
module M
|
|
|
|
refine D do
|
|
|
|
def bar
|
|
|
|
:refined
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_alias_in_subclass
|
|
|
|
assert_equal(:refined,
|
|
|
|
eval_using(AliasInSubclass::M, "AliasInSubclass::D.new.bar"))
|
|
|
|
end
|
|
|
|
|
2016-11-10 09:18:52 -05:00
|
|
|
def test_refine_with_prepend
|
|
|
|
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
|
|
|
|
begin;
|
|
|
|
bug = '[ruby-core:78073] [Bug #12920]'
|
|
|
|
Integer.prepend(Module.new)
|
|
|
|
Module.new do
|
|
|
|
refine Integer do
|
|
|
|
define_method(:+) {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert_kind_of(Time, Time.now, bug)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2016-12-08 00:16:33 -05:00
|
|
|
def test_public_in_refine
|
|
|
|
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
|
|
|
|
begin;
|
|
|
|
bug12729 = '[ruby-core:77161] [Bug #12729]'
|
|
|
|
|
|
|
|
class Cow
|
|
|
|
private
|
|
|
|
def moo() "Moo"; end
|
|
|
|
end
|
|
|
|
|
|
|
|
module PublicCows
|
|
|
|
refine(Cow) {
|
|
|
|
public :moo
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
using PublicCows
|
|
|
|
assert_equal("Moo", Cow.new.moo, bug12729)
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2017-02-18 20:27:52 -05:00
|
|
|
module SuperToModule
|
|
|
|
class Parent
|
|
|
|
end
|
|
|
|
|
|
|
|
class Child < Parent
|
|
|
|
end
|
|
|
|
|
|
|
|
module FooBar
|
|
|
|
refine Parent do
|
|
|
|
def to_s
|
|
|
|
"Parent"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
refine Child do
|
|
|
|
def to_s
|
|
|
|
super + " -> Child"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
using FooBar
|
|
|
|
def Child.test
|
|
|
|
new.to_s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_super_to_module
|
|
|
|
bug = '[ruby-core:79588] [Bug #13227]'
|
|
|
|
assert_equal("Parent -> Child", SuperToModule::Child.test, bug)
|
|
|
|
end
|
|
|
|
|
2017-03-24 23:23:43 -04:00
|
|
|
def test_include_refinement
|
|
|
|
bug = '[ruby-core:79632] [Bug #13236] cannot include refinement module'
|
|
|
|
r = nil
|
|
|
|
m = Module.new do
|
|
|
|
r = refine(String) {def test;:ok end}
|
|
|
|
end
|
|
|
|
assert_raise_with_message(ArgumentError, /refinement/, bug) do
|
|
|
|
m.module_eval {include r}
|
|
|
|
end
|
|
|
|
assert_raise_with_message(ArgumentError, /refinement/, bug) do
|
|
|
|
m.module_eval {prepend r}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-29 08:42:42 -04:00
|
|
|
class ParentDefiningPrivateMethod
|
|
|
|
private
|
|
|
|
def some_inherited_method
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module MixinDefiningPrivateMethod
|
|
|
|
private
|
|
|
|
def some_included_method
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class SomeChildClassToRefine < ParentDefiningPrivateMethod
|
|
|
|
include MixinDefiningPrivateMethod
|
|
|
|
|
|
|
|
private
|
|
|
|
def some_method
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_refine_inherited_method_with_visibility_changes
|
|
|
|
Module.new do
|
|
|
|
refine(SomeChildClassToRefine) do
|
|
|
|
def some_inherited_method; end
|
|
|
|
def some_included_method; end
|
|
|
|
def some_method; end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
obj = SomeChildClassToRefine.new
|
|
|
|
|
|
|
|
assert_raise_with_message(NoMethodError, /private/) do
|
|
|
|
obj.some_inherited_method
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise_with_message(NoMethodError, /private/) do
|
|
|
|
obj.some_included_method
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise_with_message(NoMethodError, /private/) do
|
|
|
|
obj.some_method
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-08-17 10:58:11 -04:00
|
|
|
def test_refined_method_alias_warning
|
|
|
|
c = Class.new do
|
|
|
|
def t; :t end
|
|
|
|
def f; :f end
|
|
|
|
end
|
|
|
|
Module.new do
|
|
|
|
refine(c) do
|
|
|
|
alias foo t
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assert_warning('', '[ruby-core:82385] [Bug #13817] refined method is not redefined') do
|
|
|
|
c.class_eval do
|
|
|
|
alias foo f
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-30 08:26:23 -04:00
|
|
|
def test_using_wrong_argument
|
|
|
|
bug = '[ruby-dev:50270] [Bug #13956]'
|
|
|
|
pattern = /expected Module/
|
|
|
|
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
|
|
|
|
bug = ""#{bug.dump}
|
|
|
|
pattern = /#{pattern}/
|
|
|
|
begin;
|
|
|
|
assert_raise_with_message(TypeError, pattern, bug) {
|
|
|
|
using(1) do end
|
|
|
|
}
|
|
|
|
end;
|
|
|
|
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
|
|
|
|
bug = ""#{bug.dump}
|
|
|
|
pattern = /#{pattern}/
|
|
|
|
begin;
|
|
|
|
assert_raise_with_message(TypeError, pattern, bug) {
|
|
|
|
Module.new {using(1) {}}
|
|
|
|
}
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
|
2017-09-17 22:27:13 -04:00
|
|
|
class ToString
|
|
|
|
c = self
|
|
|
|
using Module.new {refine(c) {def to_s; "ok"; end}}
|
|
|
|
def string
|
|
|
|
"#{self}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_tostring
|
|
|
|
assert_equal("ok", ToString.new.string)
|
|
|
|
assert_predicate(ToString.new.taint.string, :tainted?)
|
|
|
|
end
|
|
|
|
|
2017-09-30 22:24:11 -04:00
|
|
|
class ToSymbol
|
|
|
|
c = self
|
|
|
|
using Module.new {refine(c) {def intern; "<#{upcase}>"; end}}
|
|
|
|
def symbol
|
|
|
|
:"#{@string}"
|
|
|
|
end
|
|
|
|
def initialize(string)
|
|
|
|
@string = string
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_dsym_literal
|
|
|
|
assert_equal(:foo, ToSymbol.new("foo").symbol)
|
|
|
|
end
|
|
|
|
|
2017-11-29 03:39:47 -05:00
|
|
|
def test_unused_refinement_for_module
|
|
|
|
bug14068 = '[ruby-core:83613] [Bug #14068]'
|
|
|
|
assert_in_out_err([], <<-INPUT, ["M1#foo"], [], bug14068)
|
|
|
|
module M1
|
|
|
|
def foo
|
|
|
|
puts "M1#foo"
|
|
|
|
end
|
|
|
|
end
|
2017-11-29 03:39:48 -05:00
|
|
|
|
2017-11-29 03:39:47 -05:00
|
|
|
module M2
|
|
|
|
end
|
2017-11-29 03:39:48 -05:00
|
|
|
|
2017-11-29 03:39:47 -05:00
|
|
|
module UnusedRefinement
|
|
|
|
refine(M2) do
|
|
|
|
def foo
|
|
|
|
puts "M2#foo"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-11-29 03:39:48 -05:00
|
|
|
|
2017-11-29 03:39:47 -05:00
|
|
|
include M1
|
|
|
|
include M2
|
|
|
|
foo()
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2017-12-02 05:54:39 -05:00
|
|
|
def test_refining_module_repeatedly
|
|
|
|
bug14070 = '[ruby-core:83617] [Bug #14070]'
|
|
|
|
assert_in_out_err([], <<-INPUT, ["ok"], [], bug14070)
|
|
|
|
1000.times do
|
|
|
|
Class.new do
|
|
|
|
include Enumerable
|
|
|
|
end
|
|
|
|
|
|
|
|
Module.new do
|
|
|
|
refine Enumerable do
|
|
|
|
def foo
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
puts "ok"
|
|
|
|
INPUT
|
|
|
|
end
|
|
|
|
|
2012-12-06 10:12:36 -05:00
|
|
|
private
|
|
|
|
|
|
|
|
def eval_using(mod, s)
|
2015-03-04 21:56:03 -05:00
|
|
|
eval("using #{mod}; #{s}", Sandbox::BINDING)
|
2012-12-06 10:12:36 -05:00
|
|
|
end
|
2012-09-27 05:53:24 -04:00
|
|
|
end
|