aboutsummaryrefslogtreecommitdiffstats
path: root/spec/ruby/core/basicobject
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/basicobject')
-rw-r--r--spec/ruby/core/basicobject/__id__spec.rb6
-rw-r--r--spec/ruby/core/basicobject/__send___spec.rb10
-rw-r--r--spec/ruby/core/basicobject/basicobject_spec.rb87
-rw-r--r--spec/ruby/core/basicobject/equal_spec.rb52
-rw-r--r--spec/ruby/core/basicobject/equal_value_spec.rb10
-rw-r--r--spec/ruby/core/basicobject/fixtures/classes.rb33
-rw-r--r--spec/ruby/core/basicobject/fixtures/common.rb9
-rw-r--r--spec/ruby/core/basicobject/fixtures/remove_method_missing.rb9
-rw-r--r--spec/ruby/core/basicobject/fixtures/singleton_method.rb10
-rw-r--r--spec/ruby/core/basicobject/initialize_spec.rb13
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb180
-rw-r--r--spec/ruby/core/basicobject/instance_exec_spec.rb107
-rw-r--r--spec/ruby/core/basicobject/method_missing_spec.rb39
-rw-r--r--spec/ruby/core/basicobject/not_equal_spec.rb53
-rw-r--r--spec/ruby/core/basicobject/not_spec.rb11
-rw-r--r--spec/ruby/core/basicobject/singleton_method_added_spec.rb86
-rw-r--r--spec/ruby/core/basicobject/singleton_method_removed_spec.rb24
-rw-r--r--spec/ruby/core/basicobject/singleton_method_undefined_spec.rb24
18 files changed, 763 insertions, 0 deletions
diff --git a/spec/ruby/core/basicobject/__id__spec.rb b/spec/ruby/core/basicobject/__id__spec.rb
new file mode 100644
index 0000000000..fba9ed3b34
--- /dev/null
+++ b/spec/ruby/core/basicobject/__id__spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/kernel/object_id', __FILE__)
+
+describe "BasicObject#__id__" do
+ it_behaves_like :object_id, :__id__, BasicObject
+end
diff --git a/spec/ruby/core/basicobject/__send___spec.rb b/spec/ruby/core/basicobject/__send___spec.rb
new file mode 100644
index 0000000000..f25339fac7
--- /dev/null
+++ b/spec/ruby/core/basicobject/__send___spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/basicobject/send', __FILE__)
+
+describe "BasicObject#__send__" do
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:__send__)
+ end
+
+ it_behaves_like(:basicobject_send, :__send__)
+end
diff --git a/spec/ruby/core/basicobject/basicobject_spec.rb b/spec/ruby/core/basicobject/basicobject_spec.rb
new file mode 100644
index 0000000000..f58c17a0c0
--- /dev/null
+++ b/spec/ruby/core/basicobject/basicobject_spec.rb
@@ -0,0 +1,87 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/common', __FILE__)
+
+describe "BasicObject" do
+ it "raises NoMethodError for nonexistent methods after #method_missing is removed" do
+ script = fixture __FILE__, "remove_method_missing.rb"
+ ruby_exe(script).chomp.should == "NoMethodError"
+ end
+
+ it "raises NameError when referencing built-in constants" do
+ lambda { class BasicObjectSpecs::BOSubclass; Kernel; end }.should raise_error(NameError)
+ end
+
+ it "does not define built-in constants (according to const_defined?)" do
+ BasicObject.const_defined?(:Kernel).should be_false
+ end
+
+ it "does not define built-in constants (according to defined?)" do
+ BasicObjectSpecs::BOSubclass.kernel_defined?.should be_nil
+ end
+
+ it "includes itself in its list of constants" do
+ BasicObject.constants.should include(:BasicObject)
+ end
+end
+
+describe "BasicObject metaclass" do
+ before :each do
+ @meta = class << BasicObject; self; end
+ end
+
+ it "is an instance of Class" do
+ @meta.should be_an_instance_of(Class)
+ end
+
+ it "has Class as superclass" do
+ @meta.superclass.should equal(Class)
+ end
+
+ it "contains methods for the BasicObject class" do
+ @meta.class_eval do
+ def rubyspec_test_method() :test end
+ end
+
+ BasicObject.rubyspec_test_method.should == :test
+ end
+end
+
+describe "BasicObject instance metaclass" do
+ before :each do
+ @object = BasicObject.new
+ @meta = class << @object; self; end
+ end
+
+ it "is an instance of Class" do
+ @meta.should be_an_instance_of(Class)
+ end
+
+ it "has BasicObject as superclass" do
+ @meta.superclass.should equal(BasicObject)
+ end
+
+ it "contains methods defined for the BasicObject instance" do
+ @meta.class_eval do
+ def test_method() :test end
+ end
+
+ @object.test_method.should == :test
+ end
+end
+
+describe "BasicObject subclass" do
+ it "contains Kernel methods when including Kernel" do
+ obj = BasicObjectSpecs::BOSubclass.new
+
+ obj.instance_variable_set(:@test, :value)
+ obj.instance_variable_get(:@test).should == :value
+
+ obj.respond_to?(:hash).should == true
+ end
+
+ describe "BasicObject references" do
+ it "can refer to BasicObject from within itself" do
+ lambda { BasicObject::BasicObject }.should_not raise_error
+ end
+ end
+end
diff --git a/spec/ruby/core/basicobject/equal_spec.rb b/spec/ruby/core/basicobject/equal_spec.rb
new file mode 100644
index 0000000000..8120df836f
--- /dev/null
+++ b/spec/ruby/core/basicobject/equal_spec.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/kernel/equal', __FILE__)
+
+describe "BasicObject#equal?" do
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:equal?)
+ end
+
+ it_behaves_like :object_equal, :equal?
+
+ it "is unaffected by overriding __id__" do
+ o1 = mock("object")
+ o2 = mock("object")
+ def o1.__id__; 10; end
+ def o2.__id__; 10; end
+ o1.equal?(o2).should be_false
+ end
+
+ it "is unaffected by overriding object_id" do
+ o1 = mock("object")
+ o1.stub!(:object_id).and_return(10)
+ o2 = mock("object")
+ o2.stub!(:object_id).and_return(10)
+ o1.equal?(o2).should be_false
+ end
+
+ it "is unaffected by overriding ==" do
+ # different objects, overriding == to return true
+ o1 = mock("object")
+ o1.stub!(:==).and_return(true)
+ o2 = mock("object")
+ o1.equal?(o2).should be_false
+
+ # same objects, overriding == to return false
+ o3 = mock("object")
+ o3.stub!(:==).and_return(false)
+ o3.equal?(o3).should be_true
+ end
+
+ it "is unaffected by overriding eql?" do
+ # different objects, overriding eql? to return true
+ o1 = mock("object")
+ o1.stub!(:eql?).and_return(true)
+ o2 = mock("object")
+ o1.equal?(o2).should be_false
+
+ # same objects, overriding eql? to return false
+ o3 = mock("object")
+ o3.stub!(:eql?).and_return(false)
+ o3.equal?(o3).should be_true
+ end
+end
diff --git a/spec/ruby/core/basicobject/equal_value_spec.rb b/spec/ruby/core/basicobject/equal_value_spec.rb
new file mode 100644
index 0000000000..7d67634884
--- /dev/null
+++ b/spec/ruby/core/basicobject/equal_value_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/kernel/equal', __FILE__)
+
+describe "BasicObject#==" do
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:==)
+ end
+
+ it_behaves_like :object_equal, :==
+end
diff --git a/spec/ruby/core/basicobject/fixtures/classes.rb b/spec/ruby/core/basicobject/fixtures/classes.rb
new file mode 100644
index 0000000000..d1785afe31
--- /dev/null
+++ b/spec/ruby/core/basicobject/fixtures/classes.rb
@@ -0,0 +1,33 @@
+module BasicObjectSpecs
+ class IVars
+ def initialize
+ @secret = 99
+ end
+ end
+
+ module InstExec
+ def self.included(base)
+ base.instance_exec { @@count = 2 }
+ end
+ end
+
+ module InstExecIncluded
+ include InstExec
+ end
+
+ module InstEvalCVar
+ instance_eval { @@count = 2 }
+ end
+
+ class InstEvalConst
+ INST_EVAL_CONST_X = 2
+ end
+
+ module InstEvalOuter
+ module Inner
+ obj = InstEvalConst.new
+ X_BY_STR = obj.instance_eval("INST_EVAL_CONST_X") rescue nil
+ X_BY_BLOCK = obj.instance_eval { INST_EVAL_CONST_X } rescue nil
+ end
+ end
+end
diff --git a/spec/ruby/core/basicobject/fixtures/common.rb b/spec/ruby/core/basicobject/fixtures/common.rb
new file mode 100644
index 0000000000..3447a3a5e7
--- /dev/null
+++ b/spec/ruby/core/basicobject/fixtures/common.rb
@@ -0,0 +1,9 @@
+module BasicObjectSpecs
+ class BOSubclass < BasicObject
+ def self.kernel_defined?
+ defined?(Kernel)
+ end
+
+ include ::Kernel
+ end
+end
diff --git a/spec/ruby/core/basicobject/fixtures/remove_method_missing.rb b/spec/ruby/core/basicobject/fixtures/remove_method_missing.rb
new file mode 100644
index 0000000000..095b982d3a
--- /dev/null
+++ b/spec/ruby/core/basicobject/fixtures/remove_method_missing.rb
@@ -0,0 +1,9 @@
+class BasicObject
+ remove_method :method_missing
+end
+
+begin
+ Object.new.test_method
+rescue NoMethodError => e
+ puts e.class.name
+end
diff --git a/spec/ruby/core/basicobject/fixtures/singleton_method.rb b/spec/ruby/core/basicobject/fixtures/singleton_method.rb
new file mode 100644
index 0000000000..0e00e035fa
--- /dev/null
+++ b/spec/ruby/core/basicobject/fixtures/singleton_method.rb
@@ -0,0 +1,10 @@
+module BasicObjectSpecs
+ class SingletonMethod
+ def self.singleton_method_added name
+ ScratchPad.record [:singleton_method_added, name]
+ end
+
+ def self.singleton_method_to_alias
+ end
+ end
+end
diff --git a/spec/ruby/core/basicobject/initialize_spec.rb b/spec/ruby/core/basicobject/initialize_spec.rb
new file mode 100644
index 0000000000..7e6680df61
--- /dev/null
+++ b/spec/ruby/core/basicobject/initialize_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "BasicObject#initialize" do
+ it "is a private instance method" do
+ BasicObject.should have_private_instance_method(:initialize)
+ end
+
+ it "does not accept arguments" do
+ lambda {
+ BasicObject.new("This", "makes it easier", "to call super", "from other constructors")
+ }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
new file mode 100644
index 0000000000..3898e96b8b
--- /dev/null
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -0,0 +1,180 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "BasicObject#instance_eval" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:instance_eval)
+ end
+
+ it "sets self to the receiver in the context of the passed block" do
+ a = BasicObject.new
+ a.instance_eval { self }.equal?(a).should be_true
+ end
+
+ it "evaluates strings" do
+ a = BasicObject.new
+ a.instance_eval('self').equal?(a).should be_true
+ end
+
+ it "expects a block with no arguments" do
+ lambda { "hola".instance_eval }.should raise_error(ArgumentError)
+ end
+
+ it "takes no arguments with a block" do
+ lambda { "hola".instance_eval(4, 5) {|a,b| a + b } }.should raise_error(ArgumentError)
+ end
+
+ it "yields the object to the block" do
+ "hola".instance_eval {|o| ScratchPad.record o }
+ ScratchPad.recorded.should == "hola"
+ end
+
+ it "returns the result of the block" do
+ "hola".instance_eval { :result }.should == :result
+ end
+
+ it "only binds the eval to the receiver" do
+ f = Object.new
+ f.instance_eval do
+ def foo
+ 1
+ end
+ end
+ f.foo.should == 1
+ lambda { Object.new.foo }.should raise_error(NoMethodError)
+ end
+
+ it "preserves self in the original block when passed a block argument" do
+ prc = proc { self }
+
+ old_self = prc.call
+
+ new_self = Object.new
+ new_self.instance_eval(&prc).should == new_self
+
+ prc.call.should == old_self
+ end
+
+ # TODO: This should probably be replaced with a "should behave like" that uses
+ # the many scoping/binding specs from kernel/eval_spec, since most of those
+ # behaviors are the same for instance_eval. See also module_eval/class_eval.
+
+ it "binds self to the receiver" do
+ s = "hola"
+ (s == s.instance_eval { self }).should be_true
+ o = mock('o')
+ (o == o.instance_eval("self")).should be_true
+ end
+
+ it "executes in the context of the receiver" do
+ "Ruby-fu".instance_eval { size }.should == 7
+ "hola".instance_eval("size").should == 4
+ Object.class_eval { "hola".instance_eval("to_s") }.should == "hola"
+ Object.class_eval { "Ruby-fu".instance_eval{ to_s } }.should == "Ruby-fu"
+
+ end
+
+ it "has access to receiver's instance variables" do
+ BasicObjectSpecs::IVars.new.instance_eval { @secret }.should == 99
+ BasicObjectSpecs::IVars.new.instance_eval("@secret").should == 99
+ end
+
+ it "treats block-local variables as local to the block" do
+ prc = instance_eval <<-CODE
+ proc do |x, prc|
+ if x
+ n = 2
+ else
+ n = 1
+ prc.call(true, prc)
+ n
+ end
+ end
+ CODE
+
+ prc.call(false, prc).should == 1
+ end
+
+ it "sets class variables in the receiver" do
+ BasicObjectSpecs::InstEvalCVar.class_variables.should include(:@@count)
+ BasicObjectSpecs::InstEvalCVar.send(:class_variable_get, :@@count).should == 2
+ end
+
+ it "makes the receiver metaclass the scoped class when used with a string" do
+ obj = Object.new
+ obj.instance_eval %{
+ class B; end
+ B
+ }
+ obj.singleton_class.const_get(:B).should be_an_instance_of(Class)
+ end
+
+ it "gets constants in the receiver if a string given" do
+ BasicObjectSpecs::InstEvalOuter::Inner::X_BY_STR.should == 2
+ end
+
+ it "doesn't get constants in the receiver if a block given" do
+ BasicObjectSpecs::InstEvalOuter::Inner::X_BY_BLOCK.should be_nil
+ end
+
+ it "raises a TypeError when defining methods on an immediate" do
+ lambda do
+ 1.instance_eval { def foo; end }
+ end.should raise_error(TypeError)
+ lambda do
+ :foo.instance_eval { def foo; end }
+ end.should raise_error(TypeError)
+ end
+
+quarantine! do # Not clean, leaves cvars lying around to break other specs
+ it "scopes class var accesses in the caller when called on a Fixnum" do
+ # Fixnum can take instance vars
+ Fixnum.class_eval "@@__tmp_instance_eval_spec = 1"
+ (defined? @@__tmp_instance_eval_spec).should be_nil
+
+ @@__tmp_instance_eval_spec = 2
+ 1.instance_eval { @@__tmp_instance_eval_spec }.should == 2
+ Fixnum.__send__(:remove_class_variable, :@@__tmp_instance_eval_spec)
+ end
+end
+
+ it "raises a TypeError when defining methods on numerics" do
+ lambda do
+ (1.0).instance_eval { def foo; end }
+ end.should raise_error(TypeError)
+ lambda do
+ (1 << 64).instance_eval { def foo; end }
+ end.should raise_error(TypeError)
+ end
+
+ it "evaluates procs originating from methods" do
+ def meth(arg); arg; end
+
+ m = method(:meth)
+ obj = Object.new
+
+ obj.instance_eval(&m).should == obj
+ end
+
+ it "evaluates string with given filename and linenumber" do
+ err = begin
+ Object.new.instance_eval("raise", "a_file", 10)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[0..1].should == ["a_file", "10"]
+ end
+
+ it "evaluates string with given filename and negative linenumber" do
+ err = begin
+ Object.new.instance_eval("\n\nraise\n", "b_file", -100)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[0..1].should == ["b_file", "-98"]
+ end
+end
diff --git a/spec/ruby/core/basicobject/instance_exec_spec.rb b/spec/ruby/core/basicobject/instance_exec_spec.rb
new file mode 100644
index 0000000000..f41af6f64f
--- /dev/null
+++ b/spec/ruby/core/basicobject/instance_exec_spec.rb
@@ -0,0 +1,107 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+describe "BasicObject#instance_exec" do
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:instance_exec)
+ end
+
+ it "sets self to the receiver in the context of the passed block" do
+ a = BasicObject.new
+ a.instance_exec { self }.equal?(a).should be_true
+ end
+
+ it "passes arguments to the block" do
+ a = BasicObject.new
+ a.instance_exec(1) { |b| b }.should equal(1)
+ end
+
+ it "raises a LocalJumpError unless given a block" do
+ lambda { "hola".instance_exec }.should raise_error(LocalJumpError)
+ end
+
+ it "has an arity of -1" do
+ Object.new.method(:instance_exec).arity.should == -1
+ end
+
+ it "accepts arguments with a block" do
+ lambda { "hola".instance_exec(4, 5) { |a,b| a + b } }.should_not raise_error
+ end
+
+ it "doesn't pass self to the block as an argument" do
+ "hola".instance_exec { |o| o }.should be_nil
+ end
+
+ it "passes any arguments to the block" do
+ Object.new.instance_exec(1,2) {|one, two| one + two}.should == 3
+ end
+
+ it "only binds the exec to the receiver" do
+ f = Object.new
+ f.instance_exec do
+ def foo
+ 1
+ end
+ end
+ f.foo.should == 1
+ lambda { Object.new.foo }.should raise_error(NoMethodError)
+ end
+
+ # TODO: This should probably be replaced with a "should behave like" that uses
+ # the many scoping/binding specs from kernel/eval_spec, since most of those
+ # behaviors are the same for instance_exec. See also module_eval/class_eval.
+
+ it "binds self to the receiver" do
+ s = "hola"
+ (s == s.instance_exec { self }).should == true
+ end
+
+ it "binds the block's binding self to the receiver" do
+ s = "hola"
+ (s == s.instance_exec { eval "self", binding }).should == true
+ end
+
+ it "executes in the context of the receiver" do
+ "Ruby-fu".instance_exec { size }.should == 7
+ Object.class_eval { "Ruby-fu".instance_exec{ to_s } }.should == "Ruby-fu"
+ end
+
+ it "has access to receiver's instance variables" do
+ BasicObjectSpecs::IVars.new.instance_exec { @secret }.should == 99
+ end
+
+ it "sets class variables in the receiver" do
+ BasicObjectSpecs::InstExec.class_variables.should include(:@@count)
+ BasicObjectSpecs::InstExec.send(:class_variable_get, :@@count).should == 2
+ end
+
+ it "raises a TypeError when defining methods on an immediate" do
+ lambda do
+ 1.instance_exec { def foo; end }
+ end.should raise_error(TypeError)
+ lambda do
+ :foo.instance_exec { def foo; end }
+ end.should raise_error(TypeError)
+ end
+
+quarantine! do # Not clean, leaves cvars lying around to break other specs
+ it "scopes class var accesses in the caller when called on a Fixnum" do
+ # Fixnum can take instance vars
+ Fixnum.class_eval "@@__tmp_instance_exec_spec = 1"
+ (defined? @@__tmp_instance_exec_spec).should == nil
+
+ @@__tmp_instance_exec_spec = 2
+ 1.instance_exec { @@__tmp_instance_exec_spec }.should == 2
+ Fixnum.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
+ end
+end
+
+ it "raises a TypeError when defining methods on numerics" do
+ lambda do
+ (1.0).instance_exec { def foo; end }
+ end.should raise_error(TypeError)
+ lambda do
+ (1 << 64).instance_exec { def foo; end }
+ end.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/core/basicobject/method_missing_spec.rb b/spec/ruby/core/basicobject/method_missing_spec.rb
new file mode 100644
index 0000000000..eea45a8ddc
--- /dev/null
+++ b/spec/ruby/core/basicobject/method_missing_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../shared/basicobject/method_missing', __FILE__)
+
+describe "BasicObject#method_missing" do
+ it "is a private method" do
+ BasicObject.should have_private_instance_method(:method_missing)
+ end
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_class, nil, BasicObject
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_instance, nil, BasicObject
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_defined_module, nil, KernelSpecs::ModuleMM
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_module, nil, KernelSpecs::ModuleNoMM
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_defined_class, nil, KernelSpecs::ClassMM
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_class, nil, KernelSpecs::ClassNoMM
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_defined_instance, nil, KernelSpecs::ClassMM
+end
+
+describe "BasicObject#method_missing" do
+ it_behaves_like :method_missing_instance, nil, KernelSpecs::ClassNoMM
+end
diff --git a/spec/ruby/core/basicobject/not_equal_spec.rb b/spec/ruby/core/basicobject/not_equal_spec.rb
new file mode 100644
index 0000000000..9177380154
--- /dev/null
+++ b/spec/ruby/core/basicobject/not_equal_spec.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "BasicObject#!=" do
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:'!=')
+ end
+
+ it "returns true if other is not identical to self" do
+ a = BasicObject.new
+ b = BasicObject.new
+ (a != b).should be_true
+ end
+
+ it "returns true if other is an Object" do
+ a = BasicObject.new
+ b = Object.new
+ (a != b).should be_true
+ end
+
+ it "returns false if other is identical to self" do
+ a = BasicObject.new
+ (a != a).should be_false
+ end
+
+ it "dispatches to #==" do
+ a = mock("not_equal")
+ b = BasicObject.new
+ a.should_receive(:==).and_return(true)
+
+ (a != b).should be_false
+ end
+
+ describe "when invoked using Kernel#send" do
+ it "returns true if other is not identical to self" do
+ a = Object.new
+ b = Object.new
+ a.send(:!=, b).should be_true
+ end
+
+ it "returns false if other is identical to self" do
+ a = Object.new
+ a.send(:!=, a).should be_false
+ end
+
+ it "dispatches to #==" do
+ a = mock("not_equal")
+ b = Object.new
+ a.should_receive(:==).and_return(true)
+
+ a.send(:!=, b).should be_false
+ end
+ end
+end
diff --git a/spec/ruby/core/basicobject/not_spec.rb b/spec/ruby/core/basicobject/not_spec.rb
new file mode 100644
index 0000000000..f02b31edb2
--- /dev/null
+++ b/spec/ruby/core/basicobject/not_spec.rb
@@ -0,0 +1,11 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "BasicObject#!" do
+ it "is a public instance method" do
+ BasicObject.should have_public_instance_method(:'!')
+ end
+
+ it "returns false" do
+ (!BasicObject.new).should be_false
+ end
+end
diff --git a/spec/ruby/core/basicobject/singleton_method_added_spec.rb b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
new file mode 100644
index 0000000000..7622798dee
--- /dev/null
+++ b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
@@ -0,0 +1,86 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/singleton_method', __FILE__)
+
+describe "BasicObject#singleton_method_added" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "is a private method" do
+ BasicObject.should have_private_instance_method(:singleton_method_added)
+ end
+
+ it "is called when a singleton method is defined on an object" do
+ obj = BasicObject.new
+
+ def obj.singleton_method_added(name)
+ ScratchPad.record [:singleton_method_added, name]
+ end
+
+ def obj.new_singleton_method
+ end
+
+ ScratchPad.recorded.should == [:singleton_method_added, :new_singleton_method]
+ end
+
+ it "is not called for instance methods" do
+ ScratchPad.record []
+
+ Module.new do
+ def self.singleton_method_added(name)
+ ScratchPad << name
+ end
+
+ def new_instance_method
+ end
+ end
+
+ ScratchPad.recorded.should_not include(:new_instance_method)
+ end
+
+ it "is called when a singleton method is defined on a module" do
+ class BasicObjectSpecs::SingletonMethod
+ def self.new_method_on_self
+ end
+ end
+ ScratchPad.recorded.should == [:singleton_method_added, :new_method_on_self]
+ end
+
+ it "is called when a method is defined in the singleton class" do
+ class BasicObjectSpecs::SingletonMethod
+ class << self
+ def new_method_on_singleton
+ end
+ end
+ end
+ ScratchPad.recorded.should == [:singleton_method_added, :new_method_on_singleton]
+ end
+
+ it "is called when a method is defined with alias_method in the singleton class" do
+ class BasicObjectSpecs::SingletonMethod
+ class << self
+ alias_method :new_method_on_singleton_with_alias_method, :singleton_method_to_alias
+ end
+ end
+ ScratchPad.recorded.should == [:singleton_method_added, :new_method_on_singleton_with_alias_method]
+ end
+
+ it "is called when a method is defined with syntax alias in the singleton class" do
+ class BasicObjectSpecs::SingletonMethod
+ class << self
+ alias new_method_on_singleton_with_syntax_alias singleton_method_to_alias
+ end
+ end
+ ScratchPad.recorded.should == [:singleton_method_added, :new_method_on_singleton_with_syntax_alias]
+ end
+
+ it "is called when define_method is used in the singleton class" do
+ class BasicObjectSpecs::SingletonMethod
+ class << self
+ define_method :new_method_with_define_method do
+ end
+ end
+ end
+ ScratchPad.recorded.should == [:singleton_method_added, :new_method_with_define_method]
+ end
+end
diff --git a/spec/ruby/core/basicobject/singleton_method_removed_spec.rb b/spec/ruby/core/basicobject/singleton_method_removed_spec.rb
new file mode 100644
index 0000000000..406f4a888e
--- /dev/null
+++ b/spec/ruby/core/basicobject/singleton_method_removed_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "BasicObject#singleton_method_removed" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "is a private method" do
+ BasicObject.should have_private_instance_method(:singleton_method_removed)
+ end
+
+ it "is called when a method is removed on self" do
+ klass = Class.new
+ def klass.singleton_method_removed(name)
+ ScratchPad.record [:singleton_method_removed, name]
+ end
+ def klass.singleton_method_to_remove
+ end
+ class << klass
+ remove_method :singleton_method_to_remove
+ end
+ ScratchPad.recorded.should == [:singleton_method_removed, :singleton_method_to_remove]
+ end
+end
diff --git a/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb b/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb
new file mode 100644
index 0000000000..4f33cc5dbe
--- /dev/null
+++ b/spec/ruby/core/basicobject/singleton_method_undefined_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+describe "BasicObject#singleton_method_undefined" do
+ before :each do
+ ScratchPad.clear
+ end
+
+ it "is a private method" do
+ BasicObject.should have_private_instance_method(:singleton_method_undefined)
+ end
+
+ it "is called when a method is removed on self" do
+ klass = Class.new
+ def klass.singleton_method_undefined(name)
+ ScratchPad.record [:singleton_method_undefined, name]
+ end
+ def klass.singleton_method_to_undefine
+ end
+ class << klass
+ undef_method :singleton_method_to_undefine
+ end
+ ScratchPad.recorded.should == [:singleton_method_undefined, :singleton_method_to_undefine]
+ end
+end