Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Extract and improve method definer to report blocks as arguments

  • Loading branch information...
commit 714a48324bee463ab7c32f9b42610d4936d5ab4d 1 parent 36e8816
Josep M. Bach authored November 29, 2010
24  lib/hijacker.rb
... ...
@@ -1,6 +1,7 @@
1 1
 require 'drb'
2 2
 require 'trollop'
3 3
 require 'hijacker/exceptions'
  4
+require 'hijacker/method_definer'
4 5
 require 'hijacker/config'
5 6
 require 'hijacker/handler'
6 7
 
@@ -10,6 +11,9 @@ module Hijacker
10 11
   REJECTED_METHODS = (Object.instance_methods | Module.methods | %w{__original_[\w\d]+})
11 12
   FORBIDDEN_CLASSES = [Array, Hash, String, Fixnum, Float, Numeric, Symbol, Proc, Class, Object, Module]
12 13
 
  14
+  extend MethodDefiner # declares `define_hijacked`
  15
+  private :define_hijacked
  16
+
13 17
   class << self
14 18
 
15 19
     def spying(*args, &block)
@@ -94,26 +98,6 @@ def guess_class_methods_from(object)
94 98
       end
95 99
     end
96 100
 
97  
-    def define_hijacked(methods, receiver, uri)
98  
-      methods.each do |met|
99  
-        receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
100  
-        receiver.send(:undef_method, :"#{met}")
101  
-        writer = (met =~ /=$/)
102  
-        receiver.class_eval <<EOS
103  
-          def #{met}(#{writer ? 'arg' : '*args, &blk'})
104  
-            begin
105  
-              __original_#{met}(#{writer ? 'arg' : '*args, &blk'}).tap do |retval|
106  
-                Hijacker.register :#{met}, #{writer ? '[arg]' : 'args' }, retval, nil, self, #{uri.inspect}
107  
-              end
108  
-            rescue=>error
109  
-              Hijacker.register :#{met}, #{writer ? '[arg]' : 'args' }, nil, error, self, #{uri.inspect}
110  
-              raise error
111  
-            end
112  
-          end
113  
-EOS
114  
-      end
115  
-    end
116  
-
117 101
   end
118 102
 
119 103
 end
27  lib/hijacker/method_definer.rb
... ...
@@ -0,0 +1,27 @@
  1
+module Hijacker
  2
+  module MethodDefiner
  3
+
  4
+    def define_hijacked(methods, receiver, uri)
  5
+      methods.each do |met|
  6
+        receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
  7
+        receiver.send(:undef_method, :"#{met}")
  8
+        writer = (met =~ /=$/)
  9
+        receiver.class_eval <<EOS
  10
+          def #{met}(#{writer ? 'arg' : '*args, &blk'})
  11
+            _args = #{writer ? '[arg]' : 'args'}
  12
+            _args += [blk] if block_given?
  13
+            begin
  14
+              __original_#{met}(#{writer ? 'arg' : '*args, &blk'}).tap do |retval|
  15
+                Hijacker.register :#{met}, _args, retval, nil, self, #{uri.inspect}
  16
+              end
  17
+            rescue=>error
  18
+              Hijacker.register :#{met}, _args, nil, error, self, #{uri.inspect}
  19
+              raise error
  20
+            end
  21
+          end
  22
+EOS
  23
+      end
  24
+    end
  25
+
  26
+  end
  27
+end
115  spec/hijacker/method_definer_spec.rb
... ...
@@ -0,0 +1,115 @@
  1
+require 'spec_helper'
  2
+
  3
+module Hijacker
  4
+  describe MethodDefiner do
  5
+
  6
+    describe "#define_hijacked" do
  7
+      let(:receiver) do
  8
+        class SomeClass
  9
+          def foo
  10
+            7
  11
+          end
  12
+          def bar(a, b)
  13
+            a + b
  14
+          end
  15
+          def baz=(value)
  16
+            @baz = value
  17
+          end
  18
+          def method_with_block(argument)
  19
+            yield if block_given?
  20
+          end
  21
+          def method_that_raises
  22
+            raise StandardError, "Something went wrong"
  23
+          end
  24
+        end
  25
+        SomeClass
  26
+      end
  27
+
  28
+      before(:each) do
  29
+        Hijacker.stub(:register)
  30
+      end
  31
+
  32
+      after(:each) do
  33
+        Hijacker.restore(receiver)
  34
+      end
  35
+
  36
+      it 'saves original methods on the receiver' do
  37
+        Hijacker.send(:define_hijacked, [:foo, :bar], receiver, nil)
  38
+        instance = receiver.new 
  39
+        instance.should respond_to(:__original_foo, :__original_bar)
  40
+        instance.should_not respond_to(:__original_baz)
  41
+      end
  42
+
  43
+      it 'creates aliased methods' do
  44
+        Hijacker.send(:define_hijacked, [:foo, :baz=], receiver, nil)
  45
+        instance = receiver.new
  46
+
  47
+        instance.should_receive(:__original_foo).once
  48
+        instance.foo
  49
+        instance.should_not_receive(:__original_bar)
  50
+        instance.bar(9,10)
  51
+        instance.should_receive(:__original_baz=)
  52
+        instance.baz = 3
  53
+      end
  54
+
  55
+      describe "registering method calls" do
  56
+        context "with no arguments" do
  57
+          it "registers the method call" do
  58
+            Hijacker.send(:define_hijacked, [:foo], receiver, nil)
  59
+            instance = receiver.new
  60
+            Hijacker.should_receive(:register).with :foo,
  61
+                                                    [],
  62
+                                                    7,
  63
+                                                    nil,
  64
+                                                    instance,
  65
+                                                    nil
  66
+            instance.foo.should == 7
  67
+          end
  68
+        end
  69
+        context "with arguments" do
  70
+          it "registers the method call" do
  71
+            Hijacker.send(:define_hijacked, [:bar], receiver, nil)
  72
+            instance = receiver.new
  73
+            Hijacker.should_receive(:register).with :bar,
  74
+                                                    [1,2],
  75
+                                                    3,
  76
+                                                    nil,
  77
+                                                    instance,
  78
+                                                    nil
  79
+            instance.bar(1,2).should == 3
  80
+          end
  81
+        end
  82
+        context "with arguments and a block" do
  83
+          it "registers the method call" do
  84
+            Hijacker.send(:define_hijacked, [:method_with_block], receiver, nil)
  85
+            instance = receiver.new
  86
+            Hijacker.should_receive(:register).with :method_with_block,
  87
+                                                    [1,kind_of(Proc)],
  88
+                                                    3,
  89
+                                                    nil,
  90
+                                                    instance,
  91
+                                                    nil
  92
+            instance.method_with_block(1) do
  93
+              3
  94
+            end.should == 3
  95
+          end
  96
+        end
  97
+        context "raising an exception" do
  98
+          it "registers the method call" do
  99
+            Hijacker.send(:define_hijacked, [:method_that_raises], receiver, nil)
  100
+            instance = receiver.new
  101
+            Hijacker.should_receive(:register).with :method_that_raises,
  102
+                                                    [],
  103
+                                                    nil,
  104
+                                                    kind_of(StandardError),
  105
+                                                    instance,
  106
+                                                    nil
  107
+            expect {
  108
+              instance.method_that_raises
  109
+            }.to raise_error(StandardError)
  110
+          end
  111
+        end
  112
+      end
  113
+    end
  114
+  end
  115
+end
1  spec/hijacker_spec.rb
@@ -167,4 +167,5 @@ def object.my_method_with_args(a,b)
167 167
     end
168 168
   end
169 169
 
  170
+
170 171
 end

0 notes on commit 714a483

Please sign in to comment.
Something went wrong with that request. Please try again.