Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Raised exceptions reported

  • Loading branch information...
commit 36e8816d33b07be5cfd9a0a9082c1843e4391491 1 parent c77b4fb
@txus authored
View
57 lib/hijacker.rb
@@ -7,7 +7,7 @@
module Hijacker
# Methods that won't be hijacked in any case
- REJECTED_METHODS = (Object.instance_methods | Module.methods | %w{< <= > >= __original_[\w\d]+ [^\w\d]+})
+ REJECTED_METHODS = (Object.instance_methods | Module.methods | %w{__original_[\w\d]+})
FORBIDDEN_CLASSES = [Array, Hash, String, Fixnum, Float, Numeric, Symbol, Proc, Class, Object, Module]
class << self
@@ -35,30 +35,9 @@ def spy(object, options = {})
(class << object; self; end)
end
- inst_methods.each do |met|
- receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
- receiver.send(:undef_method, :"#{met}")
- receiver.class_eval <<EOS
- def #{met}(*args, &blk)
- __original_#{met}(*args,&blk).tap do |retval|
- Hijacker.register :#{met}, args, retval, self, #{uri.inspect}
- end
- end
-EOS
- end unless options[:only] == :singleton_methods
-
+ define_hijacked(inst_methods, receiver, uri) unless options[:only] == :singleton_methods
receiver = (class << object; self; end)
- sing_methods.each do |met|
- receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
- receiver.send(:undef_method, :"#{met}")
- receiver.class_eval <<EOS
- def #{met}(*args, &blk)
- __original_#{met}(*args,&blk).tap do |retval|
- Hijacker.register :#{met}, args, retval, self, #{uri.inspect}
- end
- end
-EOS
- end unless options[:only] == :instance_methods
+ define_hijacked(sing_methods, receiver, uri) unless options[:only] == :instance_methods
end
@@ -82,15 +61,19 @@ def restore(object)
end
end
- def register(method, args, retval, object, uri = nil)
+ def register(method, args, retval, raised, object, uri = nil)
args.map! do |arg|
{:inspect => arg.inspect, :class => arg.class.name}
end
- retval = {:inspect => retval.inspect, :class => retval.class.name}
+ if raised
+ raised = {:inspect => raised.message, :class => raised.class.name}
+ else
+ retval = {:inspect => retval.inspect, :class => retval.class.name}
+ end
object = {:inspect => object.inspect, :class => object.class.name}
server = DRbObject.new nil, (uri || self.drb_uri)
- server.handle method, args, retval, object
+ server.handle method, args, retval, raised, object
end
private
@@ -111,6 +94,26 @@ def guess_class_methods_from(object)
end
end
+ def define_hijacked(methods, receiver, uri)
+ methods.each do |met|
+ receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
+ receiver.send(:undef_method, :"#{met}")
+ writer = (met =~ /=$/)
+ receiver.class_eval <<EOS
+ def #{met}(#{writer ? 'arg' : '*args, &blk'})
+ begin
+ __original_#{met}(#{writer ? 'arg' : '*args, &blk'}).tap do |retval|
+ Hijacker.register :#{met}, #{writer ? '[arg]' : 'args' }, retval, nil, self, #{uri.inspect}
+ end
+ rescue=>error
+ Hijacker.register :#{met}, #{writer ? '[arg]' : 'args' }, nil, error, self, #{uri.inspect}
+ raise error
+ end
+ end
+EOS
+ end
+ end
+
end
end
View
7 lib/hijacker/handler.rb
@@ -21,7 +21,7 @@ def initialize(opts)
@opts = opts
end
- def handle(method, args, retval, object)
+ def handle(method, args, retval, raised, object)
# Parameters received
#
# method :foo
@@ -30,6 +30,11 @@ def handle(method, args, retval, object)
# {:inspect => '"string"', :class => 'String'}]
#
# retval {:inspect => ':bar', :class => 'Symbol'}
+ #
+ # - In case the method raised something, retval will be nil,
+ # and the exception info will be available in raised:
+ #
+ # raised {:inspect => 'wrong number of arguments (0 for 2)', :class => 'ArgumentError'}
#
# object {:inspect => '#<MyClass:0x003457>', :class => 'MyClass'}
#
View
17 lib/hijacker/handlers/logger.rb
@@ -18,7 +18,7 @@ def self.cli_options
:CYAN=>"\e[36m", :LCYAN=>"\e[1;36m",
:WHITE=>"\e[37m"}
- def handle(method, args, retval, object)
+ def handle(method, args, retval, raised, object)
out = []
out << ANSI[:BOLD] + ANSI[:UNDERLINE] + "#{Time.now}" unless opts[:without_timestamps]
out << ANSI[:CYAN] + object[:inspect]
@@ -32,10 +32,17 @@ def handle(method, args, retval, object)
ANSI[:RESET]
end.join(', ')
end
- out << "and returned"
- out << ANSI[:BLUE] + retval[:inspect]
- out << ANSI[:LBLUE] + "(#{retval[:class]})" unless opts[:without_classes]
- out << ANSI[:RESET] + "\n"
+ if raised
+ out << "and raised"
+ out << ANSI[:BLUE] + raised[:inspect]
+ out << ANSI[:LBLUE] + "(#{raised[:class]})" unless opts[:without_classes]
+ out << ANSI[:RESET] + "\n"
+ else
+ out << "and returned"
+ out << ANSI[:BLUE] + retval[:inspect]
+ out << ANSI[:LBLUE] + "(#{retval[:class]})" unless opts[:without_classes]
+ out << ANSI[:RESET] + "\n"
+ end
stdout.print out.join("#{ANSI[:RESET]} ")
end
View
1  spec/hijacker/handler_spec.rb
@@ -23,6 +23,7 @@ module Hijacker
{:inspect => "\"string\"", :class => "String"},
],
{:inspect => "\"retval\"", :class => "String"},
+ nil,
{:inspect => "MyClass", :class => "Class"}]
end
View
41 spec/hijacker/handlers/logger_spec.rb
@@ -27,6 +27,7 @@ module Hijacker
{:inspect => "\"string\"", :class => "String"},
],
{:inspect => "\"retval\"", :class => "String"},
+ nil,
{:inspect => "MyClass", :class => "Class"}]
end
@@ -84,6 +85,46 @@ module Hijacker
end
end
end
+ context "when given a raised exception" do
+
+ let(:args) do
+ [:bar,
+ [
+ {:inspect => "2", :class => "Fixnum"},
+ {:inspect => "\"string\"", :class => "String"},
+ ],
+ nil,
+ {:inspect => "wrong number of arguments (0 for 2)", :class => "ArgumentError"},
+ {:inspect => "MyClass", :class => "Class"}]
+ end
+
+ it "prints it instead of the return value" do
+ out = StringIO.new
+ subject.stub(:stdout).and_return out
+
+ Time.stub(:now).and_return Time.parse('2010-11-20')
+
+ subject.handle(*args)
+
+ ["00:00:00 +0100",
+ "MyClass",
+ "(Class)",
+ "received",
+ ":bar",
+ "with",
+ "2",
+ "(Fixnum)",
+ "\"string\"",
+ "(String)",
+ "and raised",
+ "wrong number of arguments (0 for 2)",
+ "(ArgumentError)"].each do |str|
+ out.string.should include(str)
+ end
+ end
+
+ end
+
end
end
View
38 spec/hijacker_spec.rb
@@ -14,6 +14,15 @@ def foo
def bar(a,b)
b
end
+
+ def foo=(value)
+ @value = value
+ end
+
+ def nasty
+ raise "Buuh"
+ end
+
end
describe Hijacker do
@@ -45,11 +54,11 @@ def bar(a,b)
Hijacker.spy(MyClass, :only => :instance_methods)
end
it "registers method calls without arguments" do
- Hijacker.should_receive(:register).with(:foo, [], 7, kind_of(MyClass), nil).ordered
+ Hijacker.should_receive(:register).with(:foo, [], 7, nil, kind_of(MyClass), nil).ordered
MyClass.new.foo.should == 7
end
it "registers method calls with arguments" do
- Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", kind_of(MyClass), nil).ordered
+ Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", nil, kind_of(MyClass), nil).ordered
MyClass.new.bar(2, "string").should == "string"
end
after(:each) do
@@ -61,11 +70,11 @@ def bar(a,b)
Hijacker.spy(MyClass)
end
it "registers method calls without arguments" do
- Hijacker.should_receive(:register).with(:foo, [], 7, kind_of(Class), nil).ordered
+ Hijacker.should_receive(:register).with(:foo, [], 7, nil, kind_of(Class), nil).ordered
MyClass.foo.should == 7
end
it "registers method calls with arguments" do
- Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", kind_of(Class), nil).ordered
+ Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", nil, kind_of(Class), nil).ordered
MyClass.bar(2, "string").should == "string"
end
after(:each) do
@@ -96,19 +105,27 @@ def object.my_method_with_args(a,b)
Hijacker.spy(object)
end
it "registers method calls without arguments" do
- Hijacker.should_receive(:register).with(:foo, [], 7, kind_of(MyClass), nil).ordered
- Hijacker.should_receive(:register).with(:my_method, [], 8, kind_of(MyClass), nil).ordered
+ Hijacker.should_receive(:register).with(:foo, [], 7, nil, kind_of(MyClass), nil).ordered
+ Hijacker.should_receive(:register).with(:my_method, [], 8, nil, kind_of(MyClass), nil).ordered
object.foo.should == 7
object.my_method.should == 8
end
it "registers method calls with arguments" do
- Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", kind_of(MyClass), nil).ordered
- Hijacker.should_receive(:register).with(:my_method_with_args, [2, "string"], "string", kind_of(MyClass), nil).ordered
+ Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", nil, kind_of(MyClass), nil).ordered
+ Hijacker.should_receive(:register).with(:my_method_with_args, [2, "string"], "string", nil, kind_of(MyClass), nil).ordered
object.bar(2, "string").should == "string"
object.my_method_with_args(2, "string").should == "string"
end
+ it "works well with writers" do
+ Hijacker.should_receive(:register).with(:foo=, [2], 2, nil, kind_of(MyClass), nil).ordered
+ object.foo = 2
+ end
+ it "records exceptions" do
+ Hijacker.should_receive(:register).with(:nasty, [], nil, kind_of(RuntimeError), kind_of(MyClass), nil).ordered
+ object.nasty rescue nil
+ end
it "does not affect other instances of the object's class" do
Hijacker.should_not_receive(:register)
MyClass.new.foo.should == 7
@@ -133,18 +150,19 @@ def object.my_method_with_args(a,b)
{:inspect => "\"string\"", :class => "String"},
],
{:inspect => "\"retval\"", :class => "String"},
+ nil,
{:inspect => "MyClass", :class => "Class"}
]
DRbObject.should_receive(:new).with(nil, "druby://localhost:9999").and_return server
server.should_receive(:handle).with *expected_args
- Hijacker.register(:bar, [2, "string"], "retval", MyClass)
+ Hijacker.register(:bar, [2, "string"], "retval", nil, MyClass)
end
context "when given a particular DRb uri" do
it "sends the call to that uri" do
DRbObject.should_receive(:new).with(nil, "druby://localhost:1212").and_return mock('DRb server', :handle => true)
- Hijacker.register(:bar, [2, "string"], "retval", MyClass, "druby://localhost:1212")
+ Hijacker.register(:bar, [2, "string"], "retval", nil, MyClass, "druby://localhost:1212")
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.