Skip to content

Commit

Permalink
Merge branch 'master' into simple_instance_of
Browse files Browse the repository at this point in the history
Conflicts:
	doc/todo.txt
	lib/rr/double_definitions/strategies/double_injection/any_instance_of_class.rb
  • Loading branch information
Brian Takita committed Aug 23, 2010
2 parents fc0f182 + ec477f2 commit 0af78d3
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 119 deletions.
2 changes: 1 addition & 1 deletion doc/todo.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
any_instance_of should use the DoubleInjection strategies.
Replace usage of PrototypeSubject in the instance DoubleBinding process with a Class-based DoubleBinding process.
DoubleInjection binds to the class instead of the eigenclass.
DoubleInjection binds to the class instead of the eigenclass.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Instance < DoubleInjectionStrategy
protected
def do_call
double_injection = Injections::DoubleInjection.find_or_create(
subject, method_name, (class << subject; self; end)
(class << subject; self; end), method_name
)
Double.new(double_injection, definition)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ def do_call
end

def add_double_to_instance(instance, *args)
double_injection = Injections::DoubleInjection.find_or_create(
instance, method_name, (class << instance; self; end)
)
double_injection = Injections::DoubleInjection.find_or_create((class << instance; self; end), method_name)
Double.new(double_injection, definition)
#####
if args.last.is_a?(ProcFromBlock)
Expand Down
80 changes: 46 additions & 34 deletions lib/rr/injections/double_injection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,90 @@ module Injections
# has Argument Expectations and Times called Expectations.
class DoubleInjection < Injection
extend(Module.new do
def find_or_create(subject, method_name, subject_class = (class << subject; self; end))
instances[subject][method_name.to_sym] ||= begin
new(subject, method_name.to_sym, subject_class).bind
def find_or_create(subject_class, method_name)
instances[subject_class][method_name.to_sym] ||= begin
new(subject_class, method_name.to_sym).bind
end
end

def find(subject, method_name)
instances[subject] && instances[subject][method_name.to_sym]
def find_or_create_by_subject(subject, method_name)
find_or_create(class << subject; self; end, method_name)
end

def exists?(subject, method_name)
!!find(subject, method_name)
def find(subject_class, method_name)
instances[subject_class] && instances[subject_class][method_name.to_sym]
end

def find_by_subject(subject, method_name)
find(class << subject; self; end, method_name)
end

def exists?(subject_class, method_name)
!!find(subject_class, method_name)
end

def exists_by_subject?(subject, method_name)
exists?((class << subject; self; end), method_name)
end

def dispatch_method(subject, method_name, arguments, block)
if exists?(subject, method_name)
find(subject, method_name.to_sym).dispatch_method(subject, arguments, block)
subject_class = (class << subject; self; end)
if exists?(subject_class, method_name)
find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, block)
else
new(subject, method_name.to_sym).dispatch_original_method(subject, arguments, block)
new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, block)
end
end

def reset
instances.each do |subject, method_double_map|
SingletonMethodAddedInjection.find(subject) && SingletonMethodAddedInjection.find(subject).reset
instances.each do |subject_class, method_double_map|
SingletonMethodAddedInjection.find(subject_class) && SingletonMethodAddedInjection.find(subject_class).reset
method_double_map.keys.each do |method_name|
reset_double(subject, method_name)
reset_double(subject_class, method_name)
end
Injections::DoubleInjection.instances.delete(subject) if Injections::DoubleInjection.instances.has_key?(subject)
Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances.has_key?(subject_class)
end
end

def verify(*subjects)
subjects = subjects.empty? ?
subject_classes = subjects.empty? ?
Injections::DoubleInjection.instances.keys :
subjects
subjects.each do |subject|
instances.include?(subject) &&
instances[subject].keys.each do |method_name|
verify_double(subject, method_name)
subjects.map {|subject| class << subject; self; end}
subject_classes.each do |subject_class|
instances.include?(subject_class) &&
instances[subject_class].keys.each do |method_name|
verify_double(subject_class, method_name)
end &&
instances.delete(subject)
instances.delete(subject_class)
end
end

# Verifies the DoubleInjection for the passed in subject and method_name.
def verify_double(subject, method_name)
Injections::DoubleInjection.find(subject, method_name).verify
def verify_double(subject_class, method_name)
Injections::DoubleInjection.find(subject_class, method_name).verify
ensure
reset_double subject, method_name
reset_double subject_class, method_name
end

# Resets the DoubleInjection for the passed in subject and method_name.
def reset_double(subject, method_name)
double_injection = Injections::DoubleInjection.instances[subject].delete(method_name)
def reset_double(subject_class, method_name)
double_injection = Injections::DoubleInjection.instances[subject_class].delete(method_name)
double_injection.reset
Injections::DoubleInjection.instances.delete(subject) if Injections::DoubleInjection.instances[subject].empty?
Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances[subject_class].empty?
end

def instances
@instances ||= HashWithObjectIdKey.new do |hash, subject|
hash.set_with_object_id(subject, {})
@instances ||= HashWithObjectIdKey.new do |hash, subject_object|
hash.set_with_object_id(subject_object, {})
end
end
end)

attr_reader :subject, :subject_class, :method_name, :doubles
attr_reader :subject_class, :method_name, :doubles

MethodArguments = Struct.new(:arguments, :block)

def initialize(subject, method_name, subject_class=(class << subject; self; end))
@subject = subject
def initialize(subject_class, method_name)
@subject_class = subject_class
@method_name = method_name.to_sym
@doubles = []
Expand All @@ -96,8 +108,8 @@ def bind
if subject_has_method_defined?(method_name)
bind_method_with_alias
else
Injections::MethodMissingInjection.find_or_create(subject)
Injections::SingletonMethodAddedInjection.find_or_create(subject)
Injections::MethodMissingInjection.find_or_create(subject_class)
Injections::SingletonMethodAddedInjection.find_or_create(subject_class)
bind_method_that_self_destructs_and_delegates_to_method_missing
end
self
Expand Down
9 changes: 4 additions & 5 deletions lib/rr/injections/method_missing_injection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ module RR
module Injections
class MethodMissingInjection < Injection
extend(Module.new do
def find_or_create(subject)
instances[subject] ||= begin
new(subject).bind
def find_or_create(subject_class)
instances[subject_class] ||= begin
new(subject_class).bind
end
end

Expand All @@ -14,8 +14,7 @@ def exists?(subject)
end)

attr_reader :subject_class
def initialize(subject, subject_class=(class << subject; self; end))
@subject = subject
def initialize(subject_class)
@subject_class = subject_class
@placeholder_method_defined = false
end
Expand Down
17 changes: 8 additions & 9 deletions lib/rr/injections/singleton_method_added_injection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ module RR
module Injections
class SingletonMethodAddedInjection < Injection
extend(Module.new do
def find_or_create(subject)
instances[subject] ||= begin
new(subject).bind
def find_or_create(subject_class)
instances[subject_class] ||= begin
new(subject_class).bind
end
end

Expand All @@ -17,9 +17,8 @@ def exists?(subject)
end
end)

attr_reader :subject, :subject_class
def initialize(subject, subject_class=(class << subject; self; end))
@subject = subject
attr_reader :subject_class
def initialize(subject_class)
@subject_class = subject_class
@placeholder_method_defined = false
end
Expand All @@ -37,11 +36,11 @@ def singleton_method_added(method_name)

memoized_original_method_alias_name = original_method_alias_name
subject_class.__send__(:alias_method, original_method_alias_name, :singleton_method_added)
memoized_subject = subject
memoized_subject_class = subject_class
memoized_original_method_alias_name = original_method_alias_name
subject_class.__send__(:define_method, :singleton_method_added) do |method_name_arg|
if Injections::DoubleInjection.exists?(memoized_subject, method_name_arg)
Injections::DoubleInjection.find_or_create(memoized_subject, method_name_arg).send(:deferred_bind_method)
if Injections::DoubleInjection.exists?(memoized_subject_class, method_name_arg)
Injections::DoubleInjection.find_or_create(memoized_subject_class, method_name_arg).send(:deferred_bind_method)
end
__send__(memoized_original_method_alias_name, method_name_arg)
end
Expand Down
8 changes: 4 additions & 4 deletions lib/rr/method_dispatches/method_missing_dispatch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def initialize(subject, method_name, args, block)
end

def call
if Injections::DoubleInjection.exists?(subject, method_name)
if Injections::DoubleInjection.exists_by_subject?(subject, method_name)
@double = find_double_to_attempt

if double
Expand All @@ -33,7 +33,7 @@ def call
end

def call_original_method
Injections::DoubleInjection.find_or_create(subject, method_name).dispatch_method_delegates_to_dispatch_original_method do
Injections::DoubleInjection.find_or_create_by_subject(subject, method_name).dispatch_method_delegates_to_dispatch_original_method do
call_original_method_missing
end
end
Expand All @@ -45,7 +45,7 @@ def call_implementation
double.method_call(args)
call_original_method
else
if double_injection = Injections::DoubleInjection.find(subject, method_name)
if double_injection = Injections::DoubleInjection.find_by_subject(subject, method_name)
double_injection.bind_method
# The DoubleInjection takes care of calling double.method_call
subject.__send__(method_name, *args, &block)
Expand All @@ -56,7 +56,7 @@ def call_implementation
end

def double_injection
Injections::DoubleInjection.find_or_create(subject, method_name)
Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rr/recorded_calls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def match_error(spy_verification)
attr_accessor :ordered_index

def double_injection_exists_error(spy_verification)
unless Injections::DoubleInjection.exists?(spy_verification.subject, spy_verification.method_name)
unless Injections::DoubleInjection.exists_by_subject?(spy_verification.subject, spy_verification.method_name)
RR::Errors::SpyVerificationErrors::DoubleInjectionNotFoundError.new(
"A Double Injection for the subject and method call:\n" <<
"#{spy_verification.subject.inspect}\n" <<
Expand Down
10 changes: 5 additions & 5 deletions lib/rr/space.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def space
end
end

extend(Module.new do
class << self
def instance
@instance ||= new
end
Expand All @@ -17,7 +17,7 @@ def instance
def method_missing(method_name, *args, &block)
instance.__send__(method_name, *args, &block)
end
end)
end

attr_reader :ordered_doubles, :recorded_calls
attr_accessor :trim_backtrace
Expand Down Expand Up @@ -68,12 +68,12 @@ def reset

# Verifies the DoubleInjection for the passed in subject and method_name.
def verify_double(subject, method_name)
Injections::DoubleInjection.verify_double(subject, method_name)
Injections::DoubleInjection.verify_double(class << subject; self; end, method_name)
end

# Resets the DoubleInjection for the passed in subject and method_name.
def reset_double(subject, method_name)
Injections::DoubleInjection.reset_double(subject, method_name)
Injections::DoubleInjection.reset_double(class << subject; self; end, method_name)
end

def record_call(subject, method_name, arguments, block)
Expand All @@ -93,7 +93,7 @@ def reset_ordered_doubles
end

def reset_method_missing_injections
Injections::MethodMissingInjection.instances.each do |subject, injection|
Injections::MethodMissingInjection.instances.each do |subject_class, injection|
injection.reset
end
Injections::MethodMissingInjection.instances.clear
Expand Down
8 changes: 4 additions & 4 deletions spec/rr/adapters/rr_methods_space_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module Adapters

describe "#rr_verify" do
it "verifies and deletes the double_injections" do
double_1 = ::RR::Injections::DoubleInjection.find_or_create(subject_1, method_name)
double_1 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name)
double_1_verify_calls = 0
double_1_reset_calls = 0
(
Expand All @@ -34,7 +34,7 @@ class << double_1;
double_1_reset_calls += 1
end
end
double_2 = ::RR::Injections::DoubleInjection.find_or_create(subject_2, method_name)
double_2 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name)
double_2_verify_calls = 0
double_2_reset_calls = 0
( class << double_2; self; end).class_eval do
Expand Down Expand Up @@ -73,14 +73,14 @@ class << double_1;
end

it "resets all double_injections" do
double_1 = ::RR::Injections::DoubleInjection.find_or_create(subject_1, method_name)
double_1 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_1, method_name)
double_1_reset_calls = 0
( class << double_1; self; end).class_eval do
define_method(:reset) do ||
double_1_reset_calls += 1
end
end
double_2 = ::RR::Injections::DoubleInjection.find_or_create(subject_2, method_name)
double_2 = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject_2, method_name)
double_2_reset_calls = 0
( class << double_2; self; end).class_eval do
define_method(:reset) do ||
Expand Down
2 changes: 1 addition & 1 deletion spec/rr/double_injection/double_injection_verify_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module Injections
@subject = Object.new
@method_name = :foobar
subject.methods.should_not include(method_name.to_s)
@double_injection = ::RR::Injections::DoubleInjection.find_or_create(subject, method_name)
@double_injection = ::RR::Injections::DoubleInjection.find_or_create_by_subject(subject, method_name)
end

it "verifies each double was met" do
Expand Down
Loading

0 comments on commit 0af78d3

Please sign in to comment.