rhook 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.6
1
+ 0.1.7
@@ -0,0 +1,43 @@
1
+ require "rubygems"
2
+ # $LOAD_PATH.unshift(File.dirname(__FILE__)+"/../lib")
3
+ require "rhook"
4
+
5
+ require "benchmark"
6
+
7
+ class Target
8
+ def target
9
+
10
+ end
11
+ end
12
+
13
+ n = 30000
14
+ Benchmark.bm(24) do |x|
15
+ t = Target.new
16
+
17
+ doit = lambda do
18
+ n.times do
19
+ t.target
20
+ end
21
+ end
22
+
23
+ # ========================================================================
24
+ x.report("direct:") do
25
+ doit.call
26
+ end
27
+
28
+ # ========================================================================
29
+ hook = Target._rhook.hack(:target) do |inv|
30
+ inv.call
31
+ end
32
+
33
+ x.report("rhook enabled:") do
34
+ doit.call
35
+ end
36
+
37
+ # ========================================================================
38
+ hook.disable
39
+
40
+ x.report("rhook disabled:") do
41
+ doit.call
42
+ end
43
+ end
@@ -0,0 +1,38 @@
1
+ require "rubygems"
2
+ # $LOAD_PATH.unshift(File.dirname(__FILE__)+"/../lib")
3
+ require "rhook"
4
+
5
+ require "benchmark"
6
+ require "logger"
7
+
8
+ n = 30000
9
+ Benchmark.bm(24) do |x|
10
+ logger = Logger.new(open("/dev/null", "w"))
11
+
12
+ doit = lambda do
13
+ n.times do
14
+ logger.info("msg")
15
+ end
16
+ end
17
+
18
+ # ========================================================================
19
+ x.report("direct:") do
20
+ doit.call
21
+ end
22
+
23
+ # ========================================================================
24
+ hook = Logger._rhook.hack(:add) do |inv|
25
+ inv.call
26
+ end
27
+
28
+ x.report("rhook enabled:") do
29
+ doit.call
30
+ end
31
+
32
+ # ========================================================================
33
+ hook.disable
34
+
35
+ x.report("rhook disabled:") do
36
+ doit.call
37
+ end
38
+ end
@@ -21,6 +21,8 @@ module RHook
21
21
  class RHookService
22
22
  # @private
23
23
  attr_reader :hooks_map
24
+ # @private
25
+ attr_accessor :last_name_call_method_done
24
26
 
25
27
  # @private
26
28
  def initialize(obj)
@@ -42,7 +44,8 @@ module RHook
42
44
  # Add hook to the {#bound_object}. If it is a kind of Class, the hook is affected to all instance & subclasses of the class.
43
45
  #
44
46
  # @param [Symbol] name hook-point's name (commonly equals to method name)
45
- # @option opt [true] :disable Create hook but make disabled. (by default, automatically enabled.)
47
+ # @option opt [true] :disable Creates hook but make disabled. (by default, automatically enabled.)
48
+ # @option opt [RHook::HookGroup] :group Adds itself into the specified hook-group.
46
49
  # @yield [inv] The hook block.
47
50
  # @yieldparam [Invocation] inv
48
51
  # @yieldreturn The result value. (Returned value of called method.)
@@ -53,7 +56,11 @@ module RHook
53
56
  (@hooks_map[name.to_sym] ||= []).unshift( hook )
54
57
  RHook.registry.class_cached_flag_map.delete(name)
55
58
  opt[:disable] or hook.enable()
56
- HookGroup.add_to_current_groups(hook)
59
+ if opt[:group]
60
+ opt[:group].add(hook)
61
+ else
62
+ HookGroup.add_to_current_groups(hook)
63
+ end
57
64
  hook
58
65
  end
59
66
 
@@ -124,6 +131,11 @@ module RHook
124
131
 
125
132
  # @private
126
133
  def call_method(name, method_name, args, block, opt = {})
134
+ if @last_name_call_method_done == name
135
+ return @obj.__send__(method_name, *args, &block)
136
+ end
137
+ @last_name_call_method_done = name
138
+
127
139
  hooks = concat_hooks([], name)
128
140
  hooks.empty? and return @obj.__send__(method_name, *args, &block)
129
141
 
@@ -133,9 +145,13 @@ module RHook
133
145
  inv.args = args
134
146
  inv.block = block
135
147
  inv.hooks = hooks
136
- inv.target_proc = @obj.method(method_name)
148
+ inv.target_proc = lambda do |*args, &block|
149
+ @obj.__send__(method_name, *args, &block)
150
+ end
137
151
  inv.hint = opt[:hint] || {}
138
152
  inv.proceed()
153
+ ensure
154
+ @last_name_call_method_done = nil
139
155
  end
140
156
 
141
157
  # Wraps the code block to be hookable.
@@ -398,6 +414,12 @@ module RHook
398
414
  self
399
415
  end
400
416
 
417
+ # Tests the given hook is registered in this group.
418
+ # @return [Boolean]
419
+ def include?(hook)
420
+ @hooks.include?(hook)
421
+ end
422
+
401
423
  # @private
402
424
  def self.add_to_current_groups(hook)
403
425
  (Thread.current["rhook_group"] || []).each do |group|
@@ -415,8 +437,14 @@ module RHook
415
437
  # }
416
438
  # XXX_feature_for_library.disable
417
439
  #
440
+ # @example
441
+ # grp = RHook.group
442
+ # Target._rhook.bind(..., :group => grp) { ... }
443
+ #
418
444
  # @return [HookGroup]
419
445
  def self.group(&block)
420
- HookGroup.new.wrap(&block)
446
+ group = HookGroup.new
447
+ block and group.wrap(&block)
448
+ group
421
449
  end
422
450
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rhook}
8
- s.version = "0.1.6"
8
+ s.version = "0.1.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kaoru Kobo"]
12
- s.date = %q{2010-12-01}
12
+ s.date = %q{2011-01-14}
13
13
  s.description = %q{You can provide hook point in your code, and can customize its behavior from outside. Also you can 'hack' (== injecting hook point from outside) any methods in existing code.}
14
14
  s.email = %q{}
15
15
  s.extra_rdoc_files = [
@@ -23,6 +23,8 @@ Gem::Specification.new do |s|
23
23
  "README.rdoc",
24
24
  "Rakefile",
25
25
  "VERSION",
26
+ "examples/benchmark_empty_method.rb",
27
+ "examples/benchmark_logger.rb",
26
28
  "examples/log_socket_data.rb",
27
29
  "lib/rhook.rb",
28
30
  "rhook.gemspec",
@@ -38,6 +40,8 @@ Gem::Specification.new do |s|
38
40
  s.rubygems_version = %q{1.3.7}
39
41
  s.summary = %q{Easily drive AOP & hacking existing library with Ruby}
40
42
  s.test_files = [
43
+ "examples/benchmark_empty_method.rb",
44
+ "examples/benchmark_logger.rb",
41
45
  "examples/log_socket_data.rb",
42
46
  "spec/examples/log_buffer_example_spec.rb",
43
47
  "spec/rhook_minor_spec.rb",
@@ -31,7 +31,7 @@ describe "rhook (minor specifications / behavior, and bugs)" do
31
31
  # [bug] It calls the target method/procedure twice when no hooks are registered.
32
32
  t.order_call
33
33
  t.order_ary.should == ["orig"]
34
-
34
+
35
35
  t._rhook.bind(:order_target) do |inv|
36
36
  t.order_ary << "before_call"
37
37
  inv.call
@@ -119,6 +119,71 @@ describe "rhook (minor specifications / behavior, and bugs)" do
119
119
  result = Target._rhook.on_method(:on_method_test_non_existent, :ifdef => true)
120
120
  result.should == true
121
121
  end
122
+
123
+ end
124
+
125
+ # ========================================================================
126
+ describe "is applied to the method (== 'hack'ed), and also it is called via _rhook.to(), " do
127
+ class Target
128
+ def both_on_method_and_to
129
+ _rhook.to.both_on_method_and_to_target
130
+ end
131
+
132
+ def both_on_method_and_to_target
133
+
134
+ end
135
+ end
136
+
137
+ example "even though, the hook should be just called once." do
138
+ m = mock
139
+ m.should_receive(:called).once
140
+
141
+ Target._rhook.hack(:both_on_method_and_to_target) { |inv|
142
+ m.called
143
+ inv.call
144
+ }
145
+ Target.new.both_on_method_and_to()
146
+ end
122
147
  end
123
148
  end
149
+
150
+ # ========================================================================
151
+ describe "#call_method(#to): " do
152
+ before :each do
153
+ end
154
+
155
+ example "[bugfix] super: no superclass method" do
156
+ class CallMethodSuperTest_Super
157
+ def the_method
158
+
159
+ end
160
+ end
161
+
162
+ module CallMethodSuperTest_Module
163
+ def the_method
164
+ super
165
+ end
166
+ end
167
+
168
+ class CallMethodSuperTest_Inherited < CallMethodSuperTest_Super
169
+ include CallMethodSuperTest_Module
170
+ end
171
+
172
+ # This bug does not appear without hooks.
173
+ CallMethodSuperTest_Inherited._rhook.bind(:the_method) do |inv|
174
+ inv.call
175
+ end
176
+
177
+ # OK.
178
+ CallMethodSuperTest_Inherited.new.the_method
179
+
180
+ # We fixed the bug this cause error:
181
+ lambda {
182
+ CallMethodSuperTest_Inherited.new._rhook.to.the_method
183
+ }.should_not raise_error
184
+ # - super: no superclass method `the_method'
185
+ end
186
+ end
187
+ # ========================================================================
188
+
124
189
  end
@@ -213,6 +213,16 @@ describe "rhook (advanced usage)" do
213
213
  t.group_1.should == "hack1"
214
214
  t.group_2.should == "hack2"
215
215
  end
216
+
217
+ example "Adding a hook to group with bind()'s :group option." do
218
+ # Instantiate a group with RHook.group() without block.
219
+ group = RHook.group
220
+ t = Target.new
221
+ hook = t._rhook.hack(:group_1, :group => group) do |inv|
222
+ inv.call
223
+ end
224
+ group.include?(hook).should be_true
225
+ end
216
226
  end
217
227
  # ================================================================
218
228
 
@@ -234,29 +244,31 @@ describe "rhook (advanced usage)" do
234
244
 
235
245
  end
236
246
 
237
- lambda { |called|
238
- t = Target.new
239
- t._rhook.bind(:invocation_object_target) { |inv|
240
- # first hook
241
- called.yes
242
- inv.call()
243
- inv.returned.should == :returned_value
247
+ m = mock
248
+ m.should_receive(:second).once.ordered
249
+ m.should_receive(:first).once.ordered
250
+
251
+ t = Target.new
252
+ t._rhook.bind(:invocation_object_target) { |inv|
253
+ # first hook
254
+ m.first
255
+ inv.call()
256
+ inv.returned.should == :returned_value
244
257
  :returned_value_hooked
245
- }
246
- t._rhook.bind(:invocation_object_target) { |inv|
247
- # second hook
248
- called.yes
249
- inv.args.should == args
250
- inv.block.should == block
251
- inv.hint[:hintkey].should == :hintval
252
- inv.receiver.should == t
253
- inv.target.should == t
254
- inv.returned.should be_nil
255
- inv.call()
256
- inv.returned.should == :returned_value_hooked
257
- }
258
- t.invocation_object(*args, &block)
259
- }.should calls_hook(:times => 2)
258
+ }
259
+ t._rhook.bind(:invocation_object_target) { |inv|
260
+ # second hook
261
+ m.second
262
+ inv.args.should == args
263
+ inv.block.should == block
264
+ inv.hint[:hintkey].should == :hintval
265
+ inv.receiver.should == t
266
+ inv.target.should == t
267
+ inv.returned.should be_nil
268
+ inv.call()
269
+ inv.returned.should == :returned_value_hooked
270
+ }
271
+ t.invocation_object(*args, &block)
260
272
  end
261
273
  end
262
274
  # ========================================================================
@@ -11,44 +11,3 @@ Spec::Runner.configure do |config|
11
11
 
12
12
  end
13
13
 
14
- # ========================================================================
15
- # Defines custom matcher to test the hook was called.
16
-
17
- module ::Spec::Matchers
18
- class HookCalledMatcher
19
- def initialize(opt)
20
- @times = opt[:times]
21
- @count = 0
22
- end
23
-
24
- def yes
25
- @count += 1
26
- end
27
-
28
- def matches?(block)
29
- block.call(self)
30
- if @times
31
- begin
32
- @count.should == @times
33
- rescue
34
- @times_msg = " (Exactly called count: #{$!})"
35
- false
36
- end
37
- else
38
- @count > 0
39
- end
40
- end
41
-
42
- def failure_message
43
- "Expected the hook to be called.#{@times_msg}"
44
- end
45
-
46
- def negative_failure_message
47
- "Expected the hook not to be called.#{@times_msg}"
48
- end
49
- end
50
-
51
- def calls_hook(opt = {})
52
- HookCalledMatcher.new(opt)
53
- end
54
- end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhook
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 6
10
- version: 0.1.6
9
+ - 7
10
+ version: 0.1.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kaoru Kobo
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-01 00:00:00 +09:00
18
+ date: 2011-01-14 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -66,6 +66,8 @@ files:
66
66
  - README.rdoc
67
67
  - Rakefile
68
68
  - VERSION
69
+ - examples/benchmark_empty_method.rb
70
+ - examples/benchmark_logger.rb
69
71
  - examples/log_socket_data.rb
70
72
  - lib/rhook.rb
71
73
  - rhook.gemspec
@@ -109,6 +111,8 @@ signing_key:
109
111
  specification_version: 3
110
112
  summary: Easily drive AOP & hacking existing library with Ruby
111
113
  test_files:
114
+ - examples/benchmark_empty_method.rb
115
+ - examples/benchmark_logger.rb
112
116
  - examples/log_socket_data.rb
113
117
  - spec/examples/log_buffer_example_spec.rb
114
118
  - spec/rhook_minor_spec.rb