hijacker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ *.rbc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.2@hijacker
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in hijacker.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ hijacker (0.0.1)
5
+ trollop
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ configuration (1.2.0)
11
+ diff-lcs (1.1.2)
12
+ guard (0.2.2)
13
+ open_gem (~> 1.4.2)
14
+ thor (~> 0.14.3)
15
+ guard-rspec (0.1.8)
16
+ guard (>= 0.2.0)
17
+ launchy (0.3.7)
18
+ configuration (>= 0.0.5)
19
+ rake (>= 0.8.1)
20
+ open_gem (1.4.2)
21
+ launchy (~> 0.3.5)
22
+ rake (0.8.7)
23
+ rspec (2.1.0)
24
+ rspec-core (~> 2.1.0)
25
+ rspec-expectations (~> 2.1.0)
26
+ rspec-mocks (~> 2.1.0)
27
+ rspec-core (2.1.0)
28
+ rspec-expectations (2.1.0)
29
+ diff-lcs (~> 1.1.2)
30
+ rspec-mocks (2.1.0)
31
+ simplecov (0.3.7)
32
+ simplecov-html (>= 0.3.7)
33
+ simplecov-html (0.3.9)
34
+ thor (0.14.4)
35
+ trollop (1.16.2)
36
+
37
+ PLATFORMS
38
+ java
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ bundler (~> 1.0.7)
43
+ guard
44
+ guard-rspec
45
+ hijacker!
46
+ rspec (~> 2.1.0)
47
+ simplecov
48
+ trollop
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at http://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch('^spec/(.*)_spec.rb')
6
+ watch('^lib/(.*)\.rb') { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('^spec/spec_helper.rb') { "spec" }
8
+ end
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :default => :spec
data/Readme.md ADDED
@@ -0,0 +1,114 @@
1
+ #hijacker
2
+
3
+ A little gem that hijacks any ruby object and broadcasts all its activity
4
+ to a particular hijacker server. Useful for logging and those awfully hardcore
5
+ debugging afternoons! There might be other uses to it, for sure. Just be
6
+ creative :)
7
+
8
+ Hijacker is tested with Ruby 1.8.7, 1.9.2, JRuby 1.5.3 and Rubinius 1.1.
9
+
10
+ ##Install and configure
11
+
12
+ In your Gemfile:
13
+
14
+ gem 'hijacker'
15
+
16
+ If you are using Rails, you might want to put this configuration snippet in an
17
+ initializer or something (you can always put it in any other part of the code
18
+ otherwise, as long as it's before hijacking any object):
19
+
20
+ Hijacker.configure do
21
+ uri '<YOUR HIJACKER SERVER URI>'
22
+ end
23
+
24
+ And that's it! Oooor not. You have to spawn your server. In the command line:
25
+
26
+ hijacker
27
+
28
+ And it will output the URI for this server. *Note this* and pass it to your
29
+ configuration block!
30
+
31
+ Some options you can pass to the server command:
32
+
33
+ hijacker --without-timestamps (don't show the timestamps)
34
+ hijacker --without-classes (don't show the object classes)
35
+ hijacker --port 1234 (spawn the server in port 1234 rather than 8787)
36
+
37
+ ##Ok, and now for some hijacking action!
38
+
39
+ require 'hijacker' # You don't have to when using Bundler :)
40
+
41
+ class MyClass
42
+ def foo(bar, baz)
43
+ bar + baz
44
+ end
45
+ end
46
+
47
+ some_object = Object.new
48
+
49
+ # These are the important lines:
50
+
51
+ Hijacker.spy(some_object)
52
+ Hijacker.spy(MyClass)
53
+
54
+ instance = MyClass.new
55
+ instance.foo(3, 4)
56
+
57
+ Run this code and, if you look at the server output, you'll see nothing less
58
+ than...
59
+
60
+ <a nice timestamp> MyClass (Class) received :new and returned #<MyClass:0x000000874> (MyClass)
61
+ <a nice timestamp> #<MyClass:0x000000874> (MyClass) received :foo with 3
62
+ (Fixnum), 4 (Fixnum) and returned 7
63
+
64
+ If you want to un-hijack any object, just call #restore:
65
+
66
+ Hijacker.restore(MyClass)
67
+ Hijacker.restore(some_object)
68
+
69
+ If you don't want to have to remember every hijacked object you have to call
70
+ restore on it, you can just spy a particular object within the duration of a block:
71
+
72
+ Hijacker.spying(MyClass) do
73
+ # inside this block, MyClass will be spied
74
+ end
75
+ # here not anymore
76
+
77
+ Awesome! You can fine-tune your spying, for example by only spying on instance
78
+ methods or singleton methods only:
79
+
80
+ Hijacker.spy(MyClass, :only => :instance_methods) # or :singleton_methods
81
+
82
+ And, last but not least... you can specify a *particular hijacker server* for
83
+ a *particular object* you are spying on!
84
+
85
+ # All activity on MyClass and its instances will
86
+ # be sent to druby://localhost:9999
87
+ Hijacker.spy(MyClass, :uri => 'druby://localhost:9999')
88
+
89
+ # But for example, the activity of some_object will
90
+ # be sent to the default uri specified in the configuration
91
+ # back earlier (remember?)
92
+ Hijacker.spy(some_object)
93
+
94
+ Of course, you can specify a particular server uri for a block, with #spying:
95
+
96
+ Hijacker.spying(foo_object, :uri => 'druby://localhost:1234') do
97
+ # all the activity of foo_object inside this block
98
+ # will be sent to the hijacker server on druby://localhost:1234
99
+ end
100
+
101
+ ##Note on Patches/Pull Requests
102
+
103
+ * Fork the project.
104
+ * Make your feature addition or bug fix.
105
+ * Add specs for it. This is important so I don't break it in a
106
+ future version unintentionally.
107
+ * Commit, do not mess with rakefile, version, or history.
108
+ If you want to have your own version, that is fine but bump version
109
+ in a commit by itself I can ignore when I pull.
110
+ * Send me a pull request. Bonus points for topic branches.
111
+
112
+ ## Copyright
113
+
114
+ Copyright (c) 2010 Josep M. Bach. See LICENSE for details.
data/bin/hijacker ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby -w
2
+ # hijacker server
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
4
+
5
+ require 'hijacker'
6
+
7
+ opts = Trollop::options do
8
+ version "hijacker 0.0.1 (c) 2010 Josep M. Bach"
9
+ banner <<-EOS
10
+ Hijacker server listens for reports by hijackers spying on ruby objects.
11
+
12
+ Usage:
13
+ hijacker [options]
14
+ where [options] are:
15
+ EOS
16
+ opt :without_classes, "Don't show classes of objects"
17
+ opt :without_timestamps, "Don't show timestamps"
18
+ opt :port, "DRb port to use (default is 8787)", :default => 8787
19
+ end
20
+
21
+ begin
22
+ raise unless opts[:port].to_i > 0 && opts[:port].to_i < 9999
23
+ rescue
24
+ Trollop::die :port, "must be a valid number between 0 and 9999"
25
+ end
26
+
27
+ DRB_URI="druby://localhost:#{opts[:port]}"
28
+
29
+ # Start up the DRb service
30
+ DRb.start_service DRB_URI, Hijacker::Logger.new(opts)
31
+
32
+ ANSI = Hijacker::Logger::ANSI
33
+ # We need the uri of the service to connect a client
34
+ welcome = []
35
+ welcome << ANSI[:BOLD] + "hijacker server"
36
+ welcome << "listening on"
37
+ welcome << ANSI[:BOLD] + DRb.uri + ANSI[:RESET]
38
+ puts welcome.join("#{ANSI[:RESET]} ") + "\n"
39
+
40
+ # We need the uri of the service to connect a client
41
+ instructions = "Put this code in the configuration of your ruby program #{ANSI[:BOLD]}before any call to Hijacker#{ANSI[:RESET]}:\n\n"
42
+ instructions += "\t" + "Hijacker.config do\n"
43
+ instructions += "\t" + " uri '#{DRb.uri}'\n"
44
+ instructions += "\t" + "end\n\n"
45
+ puts instructions
46
+ instructions = "Or optionally attach a particular hijacked object to this server adding :uri => '#{DRb.uri}' when calling Hijacker's :spy or :spying method.\n\n"
47
+ puts instructions
48
+
49
+ # wait for the DRb service to finish before exiting
50
+ DRb.thread.join
data/hijacker.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "hijacker/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "hijacker"
7
+ s.version = Hijacker::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Josep M. Bach"]
10
+ s.email = ["josep.m.bach@gmail.com"]
11
+ s.homepage = "http://github.com/txus/hijacker"
12
+ s.summary = %q{Spy on your ruby objects and send their activity to a hijacker server anywhere through DRb}
13
+ s.description = %q{Spy on your ruby objects and send their activity to a hijacker server anywhere through DRb}
14
+
15
+ s.rubyforge_project = "hijacker"
16
+
17
+ s.add_runtime_dependency 'trollop'
18
+ s.default_executable = "hijacker"
19
+
20
+ s.add_development_dependency 'bundler', '~> 1.0.7'
21
+ s.add_development_dependency 'rspec', '~> 2.1.0'
22
+ s.add_development_dependency 'guard'
23
+ s.add_development_dependency 'guard-rspec'
24
+ s.add_development_dependency "simplecov"
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
29
+ s.require_paths = ["lib"]
30
+ end
@@ -0,0 +1,19 @@
1
+ module Hijacker
2
+ class << self
3
+ def configure(&block)
4
+ self.instance_eval(&block)
5
+ end
6
+
7
+ def uri(drb)
8
+ @@drb_uri = drb
9
+ end
10
+
11
+ def drb_uri
12
+ begin
13
+ @@drb_uri
14
+ rescue
15
+ raise "Neither a global nor a local Hijacker server URI is configured. Please refer to the README to find out how to do this."
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ module Hijacker
2
+ class Logger
3
+
4
+ ANSI = {:RESET=>"\e[0m", :BOLD=>"\e[1m", :UNDERLINE=>"\e[4m",
5
+ :LGRAY=>"\e[0;37m", :GRAY=>"\e[1;30m",
6
+ :RED=>"\e[31m",
7
+ :GREEN=>"\e[32m", :LGREEN=>"\e[1;32m",
8
+ :YELLOW=>"\e[33m",
9
+ :BLUE=>"\e[34m", :LBLUE=>"\e[1;34m",
10
+ :PURPLE=>"\e[35m", :LPURPLE=>"\e[1;35m",
11
+ :CYAN=>"\e[36m", :LCYAN=>"\e[1;36m",
12
+ :WHITE=>"\e[37m"}
13
+
14
+ # Make dRuby send Logger instances as dRuby references,
15
+ # not copies.
16
+ include DRb::DRbUndumped
17
+
18
+ attr_reader :opts
19
+
20
+ def initialize(opts)
21
+ @opts = opts
22
+ end
23
+
24
+ def log(method, args, retval, object)
25
+ out = []
26
+ out << ANSI[:BOLD] + ANSI[:UNDERLINE] + "#{Time.now}" unless opts[:without_timestamps]
27
+ out << ANSI[:CYAN] + object[:inspect]
28
+ out << ANSI[:LCYAN] + "(#{object[:class]})" unless opts[:without_classes]
29
+ out << "received"
30
+ out << ANSI[:RED] + ":#{method}"
31
+ unless args.empty?
32
+ out << "with"
33
+ out << args.map do |arg|
34
+ ANSI[:GREEN] + arg[:inspect] + ANSI[:LGREEN] + (opts[:without_classes] ? "" : " (#{arg[:class]})") +
35
+ ANSI[:RESET]
36
+ end.join(', ')
37
+ end
38
+ out << "and returned"
39
+ out << ANSI[:BLUE] + retval[:inspect]
40
+ out << ANSI[:LBLUE] + "(#{retval[:class]})" unless opts[:without_classes]
41
+ out << ANSI[:RESET] + "\n"
42
+ stdout.print out.join("#{ANSI[:RESET]} ")
43
+ end
44
+
45
+ private
46
+
47
+ def stdout
48
+ $stdout
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,3 @@
1
+ module Hijacker
2
+ VERSION = "0.0.1"
3
+ end
data/lib/hijacker.rb ADDED
@@ -0,0 +1,116 @@
1
+ require 'drb'
2
+ require 'trollop'
3
+ require 'hijacker/config'
4
+ require 'hijacker/logger'
5
+
6
+ module Hijacker
7
+
8
+ # Methods that won't be hijacked in any case
9
+ REJECTED_METHODS = (Object.instance_methods | Module.methods | %w{< <= > >= __original_[\w\d]+ [^\w\d]+})
10
+ FORBIDDEN_CLASSES = [Array, Hash, String, Fixnum, Float, Numeric, Symbol, Proc, Class, Object, BasicObject, Module]
11
+
12
+ class << self
13
+
14
+ def spying(*args, &block)
15
+ raise "No block given" unless block
16
+ Hijacker.spy(*args)
17
+ block.call
18
+ Hijacker.restore(args.first)
19
+ end
20
+
21
+ def spy(object, options = {})
22
+ raise "Cannot spy on the following forbidden classes: #{FORBIDDEN_CLASSES.map(&:to_s).join(', ')}" if FORBIDDEN_CLASSES.include?(object)
23
+ rejection = /^(#{REJECTED_METHODS.join('|')})/
24
+ only = options[:only]
25
+ uri = options[:uri]
26
+ custom_rejection = options[:reject] if options[:reject].is_a?(Regexp)
27
+
28
+ inst_methods = guess_instance_methods_from(object).reject{|m| (m =~ rejection)}.reject{|m| m =~ custom_rejection}
29
+ sing_methods = guess_class_methods_from(object).reject{|m| m =~ rejection}.reject{|m| m =~ custom_rejection}
30
+
31
+ receiver = if object.is_a?(Class)
32
+ object
33
+ else
34
+ (class << object; self; end)
35
+ end
36
+
37
+ inst_methods.each do |met|
38
+ receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
39
+ receiver.send(:undef_method, :"#{met}")
40
+ receiver.class_eval <<EOS
41
+ def #{met}(*args, &blk)
42
+ __original_#{met}(*args,&blk).tap do |retval|
43
+ Hijacker.register :#{met}, args, retval, self.dup, #{uri.inspect}
44
+ end
45
+ end
46
+ EOS
47
+ end unless options[:only] == :singleton_methods
48
+
49
+ receiver = (class << object; self; end)
50
+ sing_methods.each do |met|
51
+ puts "Defining #{met}"
52
+ receiver.send(:alias_method, :"__original_#{met}", :"#{met}")
53
+ receiver.send(:undef_method, :"#{met}")
54
+ receiver.class_eval <<EOS
55
+ def #{met}(*args, &blk)
56
+ __original_#{met}(*args,&blk).tap do |retval|
57
+ Hijacker.register :#{met}, args, retval, self.dup, #{uri.inspect}
58
+ end
59
+ end
60
+ EOS
61
+ end unless options[:only] == :instance_methods
62
+
63
+ end
64
+
65
+ def restore(object)
66
+ receiver = if object.is_a?(Class)
67
+ object
68
+ else
69
+ (class << object; self; end)
70
+ end
71
+ guess_instance_methods_from(object).select{|m| m =~ /__original_/}.each do |met|
72
+ met = met.to_s.gsub!("__original_", "")
73
+ receiver.send(:undef_method, :"#{met}")
74
+ receiver.send(:alias_method, :"#{met}", :"__original_#{met}")
75
+ end
76
+
77
+ receiver = (class << object; self; end)
78
+ guess_class_methods_from(object).select{|m| m =~ /__original_/}.each do |met|
79
+ met = met.to_s.gsub!("__original_", "")
80
+ receiver.send(:undef_method, :"#{met}")
81
+ receiver.send(:alias_method, :"#{met}", :"__original_#{met}")
82
+ end
83
+ end
84
+
85
+ def register(method, args, retval, object, uri = nil)
86
+ args.map! do |arg|
87
+ {:inspect => arg.inspect, :class => arg.class.name}
88
+ end
89
+ retval = {:inspect => retval.inspect, :class => retval.class.name}
90
+ object = {:inspect => object.inspect, :class => object.class.name}
91
+
92
+ server = DRbObject.new nil, (uri || self.drb_uri)
93
+ server.log method, args, retval, object
94
+ end
95
+
96
+ private
97
+
98
+ def guess_instance_methods_from(object)
99
+ if object.is_a?(Class)
100
+ object.instance_methods
101
+ else
102
+ object.methods
103
+ end
104
+ end
105
+
106
+ def guess_class_methods_from(object)
107
+ if object.is_a?(Class)
108
+ object.methods
109
+ else
110
+ []
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hijacker, "configuration" do
4
+
5
+ describe "#configure" do
6
+ it 'accepts a block with the \'uri\' configuration option' do
7
+ Hijacker.configure do
8
+ uri 'druby://localhost:8787'
9
+ end
10
+ Hijacker.drb_uri.should == 'druby://localhost:8787'
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Hijacker
4
+ describe Logger do
5
+
6
+ subject { Logger.new({:my => :option}) }
7
+
8
+ it "initializes with options" do
9
+ subject.opts.should == {:my => :option}
10
+ end
11
+
12
+ describe "#log" do
13
+
14
+ let(:args) do
15
+ [:bar,
16
+ [
17
+ {:inspect => "2", :class => "Fixnum"},
18
+ {:inspect => "\"string\"", :class => "String"},
19
+ ],
20
+ {:inspect => "\"retval\"", :class => "String"},
21
+ {:inspect => "MyClass", :class => "Class"}]
22
+ end
23
+
24
+ it 'prints the received args' do
25
+ out = StringIO.new
26
+ subject.stub(:stdout).and_return out
27
+
28
+ Time.stub(:now).and_return Time.parse('2010-11-20')
29
+
30
+ subject.log(*args)
31
+
32
+ ["00:00:00 +0100",
33
+ "MyClass",
34
+ "(Class)",
35
+ "received",
36
+ ":bar",
37
+ "with",
38
+ "2",
39
+ "(Fixnum)",
40
+ "\"string\"",
41
+ "(String)",
42
+ "and returned",
43
+ "\"retval\"",
44
+ "(String)"].each do |str|
45
+ out.string.should include(str)
46
+ end
47
+ end
48
+ context "when given :without_timestamps" do
49
+ it 'discards the timestamps' do
50
+ logger = Logger.new({:without_timestamps => true})
51
+
52
+ out = StringIO.new
53
+ logger.stub(:stdout).and_return out
54
+
55
+ Time.stub(:now).and_return Time.parse('2010-11-20')
56
+
57
+ logger.log(*args)
58
+
59
+ out.string.should_not include("2010-11-20")
60
+ end
61
+ end
62
+ context "when given :without_classes" do
63
+ it 'discards the classes' do
64
+ logger = Logger.new({:without_classes => true})
65
+
66
+ out = StringIO.new
67
+ logger.stub(:stdout).and_return out
68
+
69
+ Time.stub(:now).and_return Time.parse('2010-11-20')
70
+
71
+ logger.log(*args)
72
+
73
+ ["(Class)", "(Fixnum)", "(String)"].each do |str|
74
+ out.string.should_not include(str)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,152 @@
1
+ require 'spec_helper'
2
+
3
+ class MyClass
4
+ def self.foo
5
+ 3 + 4
6
+ end
7
+ def self.bar(a,b)
8
+ b
9
+ end
10
+
11
+ def foo
12
+ 3 + 4
13
+ end
14
+ def bar(a,b)
15
+ b
16
+ end
17
+ end
18
+
19
+ describe Hijacker do
20
+
21
+ describe "#spying" do
22
+ it 'runs a block spying on a particular object' do
23
+ blk = lambda {
24
+ MyClass.foo
25
+ }
26
+ Hijacker.should_receive(:spy).with(MyClass).once.ordered
27
+ MyClass.should_receive(:foo).once.ordered
28
+ Hijacker.should_receive(:restore).with(MyClass).once.ordered
29
+
30
+ Hijacker.spying(MyClass, &blk)
31
+ end
32
+
33
+ it 'raises if no block given' do
34
+ expect {
35
+ Hijacker.spying(MyClass)
36
+ }.to raise_error("No block given")
37
+ end
38
+ end
39
+
40
+ describe "#spy - #restore" do
41
+
42
+ describe "hijacking a Class" do
43
+ describe "instance methods" do
44
+ before(:each) do
45
+ Hijacker.spy(MyClass, :only => :instance_methods)
46
+ end
47
+ it "registers method calls without arguments" do
48
+ Hijacker.should_receive(:register).with(:foo, [], 7, kind_of(MyClass), nil).ordered
49
+ MyClass.new.foo.should == 7
50
+ end
51
+ it "registers method calls with arguments" do
52
+ Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", kind_of(MyClass), nil).ordered
53
+ MyClass.new.bar(2, "string").should == "string"
54
+ end
55
+ after(:each) do
56
+ Hijacker.restore(MyClass)
57
+ end
58
+ end
59
+ describe "class methods" do
60
+ before(:each) do
61
+ Hijacker.spy(MyClass)
62
+ end
63
+ it "registers method calls without arguments" do
64
+ Hijacker.should_receive(:register).with(:foo, [], 7, kind_of(Class), nil).ordered
65
+ MyClass.foo.should == 7
66
+ end
67
+ it "registers method calls with arguments" do
68
+ Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", kind_of(Class), nil).ordered
69
+ MyClass.bar(2, "string").should == "string"
70
+ end
71
+ after(:each) do
72
+ Hijacker.restore(MyClass)
73
+ end
74
+ end
75
+ describe "forbidden classes (are not hijacked)" do
76
+ [Array, Hash, String, Fixnum, Float, Numeric, Symbol].each do |forbidden|
77
+ it "protects #{forbidden}" do
78
+ expect {
79
+ Hijacker.spy(forbidden)
80
+ }.to raise_error
81
+ end
82
+ end
83
+ end
84
+ end
85
+ describe "hijacking an object" do
86
+ describe "instance methods" do
87
+ let(:object) { MyClass.new }
88
+
89
+ before(:each) do
90
+ def object.my_method
91
+ 8
92
+ end
93
+ def object.my_method_with_args(a,b)
94
+ b
95
+ end
96
+ Hijacker.spy(object)
97
+ end
98
+ it "registers method calls without arguments" do
99
+ Hijacker.should_receive(:register).with(:foo, [], 7, kind_of(MyClass), nil).ordered
100
+ Hijacker.should_receive(:register).with(:my_method, [], 8, kind_of(MyClass), nil).ordered
101
+
102
+ object.foo.should == 7
103
+ object.my_method.should == 8
104
+ end
105
+ it "registers method calls with arguments" do
106
+ Hijacker.should_receive(:register).with(:bar, [2, "string"], "string", kind_of(MyClass), nil).ordered
107
+ Hijacker.should_receive(:register).with(:my_method_with_args, [2, "string"], "string", kind_of(MyClass), nil).ordered
108
+
109
+ object.bar(2, "string").should == "string"
110
+ object.my_method_with_args(2, "string").should == "string"
111
+ end
112
+ it "does not affect other instances of the object's class" do
113
+ Hijacker.should_not_receive(:register)
114
+ MyClass.new.foo.should == 7
115
+ end
116
+ after(:each) do
117
+ Hijacker.restore(object)
118
+ end
119
+ end
120
+ end
121
+
122
+ end
123
+
124
+ describe "#register" do
125
+ it 'sends the registered method call to the DRb server' do
126
+ server = mock('DRb server')
127
+
128
+ Hijacker.stub(:drb_uri).and_return "druby://localhost:9999"
129
+
130
+ expected_args = [:bar,
131
+ [
132
+ {:inspect => "2", :class => "Fixnum"},
133
+ {:inspect => "\"string\"", :class => "String"},
134
+ ],
135
+ {:inspect => "\"retval\"", :class => "String"},
136
+ {:inspect => "MyClass", :class => "Class"}
137
+ ]
138
+
139
+ DRbObject.should_receive(:new).with(nil, "druby://localhost:9999").and_return server
140
+ server.should_receive(:log).with *expected_args
141
+
142
+ Hijacker.register(:bar, [2, "string"], "retval", MyClass)
143
+ end
144
+ context "when given a particular DRb uri" do
145
+ it "sends the call to that uri" do
146
+ DRbObject.should_receive(:new).with(nil, "druby://localhost:1212").and_return mock('DRb server', :log => true)
147
+ Hijacker.register(:bar, [2, "string"], "retval", MyClass, "druby://localhost:1212")
148
+ end
149
+ end
150
+ end
151
+
152
+ end
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+
12
+ require 'hijacker'
13
+ require 'rspec'
14
+
15
+ # Requires supporting files with custom matchers and macros, etc,
16
+ # in ./support/ and its subdirectories.
17
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hijacker
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Josep M. Bach
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-20 00:00:00 +01:00
18
+ default_executable: hijacker
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: trollop
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 0
44
+ - 7
45
+ version: 1.0.7
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 2
58
+ - 1
59
+ - 0
60
+ version: 2.1.0
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: guard
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: guard-rspec
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ type: :development
88
+ version_requirements: *id005
89
+ - !ruby/object:Gem::Dependency
90
+ name: simplecov
91
+ prerelease: false
92
+ requirement: &id006 !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ type: :development
101
+ version_requirements: *id006
102
+ description: Spy on your ruby objects and send their activity to a hijacker server anywhere through DRb
103
+ email:
104
+ - josep.m.bach@gmail.com
105
+ executables:
106
+ - hijacker
107
+ extensions: []
108
+
109
+ extra_rdoc_files: []
110
+
111
+ files:
112
+ - .gitignore
113
+ - .rspec
114
+ - .rvmrc
115
+ - Gemfile
116
+ - Gemfile.lock
117
+ - Guardfile
118
+ - Rakefile
119
+ - Readme.md
120
+ - bin/hijacker
121
+ - hijacker.gemspec
122
+ - lib/hijacker.rb
123
+ - lib/hijacker/config.rb
124
+ - lib/hijacker/logger.rb
125
+ - lib/hijacker/version.rb
126
+ - spec/hijacker/config_spec.rb
127
+ - spec/hijacker/logger_spec.rb
128
+ - spec/hijacker_spec.rb
129
+ - spec/spec_helper.rb
130
+ has_rdoc: true
131
+ homepage: http://github.com/txus/hijacker
132
+ licenses: []
133
+
134
+ post_install_message:
135
+ rdoc_options: []
136
+
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ requirements: []
156
+
157
+ rubyforge_project: hijacker
158
+ rubygems_version: 1.3.7
159
+ signing_key:
160
+ specification_version: 3
161
+ summary: Spy on your ruby objects and send their activity to a hijacker server anywhere through DRb
162
+ test_files:
163
+ - spec/hijacker/config_spec.rb
164
+ - spec/hijacker/logger_spec.rb
165
+ - spec/hijacker_spec.rb
166
+ - spec/spec_helper.rb