C0 code coverage information
Generated on Sun Oct 26 11:18:06 -0500 2008 with rcov 0.8.1.2
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 require File.dirname(__FILE__) + '/../spec_helper'
2 require 'aquarium/spec_example_types'
3 require 'aquarium/extensions/hash'
4 require 'aquarium/utils/nil_object'
5 require 'aquarium/aspects/join_point'
6 require 'aquarium/aspects/advice'
7
8 class Dummy
9 def eql?; false; end
10 def count; 0; end
11 end
12
13 class ProtectionExample
14 def public_instance_m; end
15 protected
16 def protected_instance_m; end
17 private
18 def private_instance_m; end
19 def self.public_class_m; end
20 def self.private_class_m; end
21 private_class_method :private_class_m
22 end
23
24 include Aquarium::Aspects
25
26 describe JoinPoint, "#initialize with invalid parameters" do
27
28 it "should require either a :type or an :object parameter, but not both." do
29 lambda { JoinPoint.new :method_name => :count }.should raise_error(Aquarium::Utils::InvalidOptions)
30 lambda { JoinPoint.new :type => String, :object => "", :method_name => :count }.should raise_error(Aquarium::Utils::InvalidOptions)
31 end
32
33 it "should require a :method_name." do
34 lambda { JoinPoint.new :type => String }.should raise_error(Aquarium::Utils::InvalidOptions)
35 end
36
37 it "should except :method as a synonym for :method_name." do
38 lambda { JoinPoint.new :type => String, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
39 end
40
41 it "should require a valid type name if a name is specified." do
42 lambda { JoinPoint.new :type => "String", :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
43 lambda { JoinPoint.new :type => "Stringgy", :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
44 end
45
46 it "should require a valid type name symbol if a name is specified." do
47 lambda { JoinPoint.new :type => :String, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
48 lambda { JoinPoint.new :type => :Stringgy, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
49 end
50
51 it "should require a valid type name regular expression if one is specified." do
52 lambda { JoinPoint.new :type => /^String$/, :method => :split }.should_not raise_error(Aquarium::Utils::InvalidOptions)
53 lambda { JoinPoint.new :type => /^Stringgy$/, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
54 end
55
56 it "should reject a regular expression that matches no types." do
57 lambda { JoinPoint.new :type => /^Stringgy$/, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
58 end
59
60 it "should reject a regular expression that matches more than one type." do
61 lambda { JoinPoint.new :type => /^M/, :method => :split }.should raise_error(Aquarium::Utils::InvalidOptions)
62 end
63 end
64
65 describe JoinPoint, "#initialize with parameters that specify class vs. instance methods" do
66 it "should assume the :method_name refers to an instance method, by default." do
67 jp = JoinPoint.new :type => String, :method => :split
68 jp.instance_method?.should be_true
69 jp.class_method?.should be_false
70 end
71
72 it "should treat the :method_name as refering to an instance method if :instance_method is specified as true." do
73 jp = JoinPoint.new :type => String, :method => :split, :instance_method => true
74 jp.instance_method?.should be_true
75 jp.class_method?.should be_false
76 end
77
78 it "should treat the :method_name as refering to a class method if :instance_method is specified as false." do
79 jp = JoinPoint.new :type => String, :method => :split, :instance_method => false
80 jp.instance_method?.should be_false
81 jp.class_method?.should be_true
82 end
83
84 it "should treat the :method_name as refering to an instance method if :class_method is specified as false." do
85 jp = JoinPoint.new :type => String, :method => :split, :class_method => false
86 jp.instance_method?.should be_true
87 jp.class_method?.should be_false
88 end
89
90 it "should treat the :method_name as refering to a class method if :class_method is specified as true." do
91 jp = JoinPoint.new :type => String, :method => :split, :class_method => true
92 jp.instance_method?.should be_false
93 jp.class_method?.should be_true
94 end
95
96 it "should treat give precedence to :instance_method if appears with :class_method." do
97 jp = JoinPoint.new :type => String, :method => :split, :instance_method => false, :class_method => true
98 jp.instance_method?.should be_false
99 jp.class_method?.should be_true
100 jp = JoinPoint.new :type => String, :method => :split, :instance_method => true, :class_method => false
101 jp.instance_method?.should be_true
102 jp.class_method?.should be_false
103 end
104 end
105
106 describe JoinPoint, "#visibility" do
107 it "should return :public for public instance methods." do
108 jp = JoinPoint.new :type => ProtectionExample, :method => :public_instance_m
109 jp.visibility.should == :public
110 end
111
112 it "should return :public for public instance methods, when only instance methods are specified." do
113 jp = JoinPoint.new :type => ProtectionExample, :method => :public_instance_m, :instance_method => true
114 jp.visibility.should == :public
115 end
116
117 it "should return :public for public class methods, when only class methods are specified using :instance_method => false." do
118 jp = JoinPoint.new :type => ProtectionExample, :method => :public_class_m, :instance_method => false
119 jp.visibility.should == :public
120 end
121
122 it "should return :public for public instance methods, when only instance methods are specified using :class_method => false." do
123 jp = JoinPoint.new :type => ProtectionExample, :method => :public_instance_m, :class_method => false
124 jp.visibility.should == :public
125 end
126
127 it "should return :public for public class methods, when only class methods are specified." do
128 jp = JoinPoint.new :type => ProtectionExample, :method => :public_class_m, :class_method => true
129 jp.visibility.should == :public
130 end
131
132 it "should return :protected for protected instance methods." do
133 jp = JoinPoint.new :type => ProtectionExample, :method => :protected_instance_m
134 jp.visibility.should == :protected
135 end
136
137 it "should return :protected for protected instance methods, when only instance methods are specified." do
138 jp = JoinPoint.new :type => ProtectionExample, :method => :protected_instance_m, :instance_method => true
139 jp.visibility.should == :protected
140 end
141
142 it "should return nil for protected class methods, when only class methods are specified using :instance_method => false." do
143 jp = JoinPoint.new :type => ProtectionExample, :method => :protected_class_method, :instance_method => false
144 jp.visibility.should == nil
145 end
146
147 it "should return :protected for protected instance methods, when only instance methods are specified using :class_method => false." do
148 jp = JoinPoint.new :type => ProtectionExample, :method => :protected_instance_m, :class_method => false
149 jp.visibility.should == :protected
150 end
151
152 it "should return nil for protected class methods, when only class methods are specified." do
153 jp = JoinPoint.new :type => ProtectionExample, :method => :protected_class_method, :class_method => true
154 jp.visibility.should == nil
155 end
156
157 it "should return :private for private instance methods." do
158 jp = JoinPoint.new :type => ProtectionExample, :method => :private_instance_m
159 jp.visibility.should == :private
160 end
161
162 it "should return :private for private instance methods, when only instance methods are specified." do
163 jp = JoinPoint.new :type => ProtectionExample, :method => :private_instance_m, :instance_method => true
164 jp.visibility.should == :private
165 end
166
167 it "should return :private for private class methods, when only class methods are specified using :instance_method => false." do
168 jp = JoinPoint.new :type => ProtectionExample, :method => :private_class_m, :instance_method => false
169 jp.visibility.should == :private
170 end
171
172 it "should return :private for private instance methods, when only instance methods are specified using :class_method => false." do
173 jp = JoinPoint.new :type => ProtectionExample, :method => :private_instance_m, :class_method => false
174 jp.visibility.should == :private
175 end
176
177 it "should return :private for private class methods, when only class methods are specified." do
178 jp = JoinPoint.new :type => ProtectionExample, :method => :private_class_m, :class_method => true
179 jp.visibility.should == :private
180 end
181
182 it "should return nil for non-existent methods." do
183 jp = JoinPoint.new :type => ProtectionExample, :method => :foo
184 jp.visibility.should == nil
185 jp = JoinPoint.new :type => ProtectionExample, :method => :foo, :instance_method => true
186 jp.visibility.should == nil
187 jp = JoinPoint.new :type => ProtectionExample, :method => :foo, :instance_method => false
188 jp.visibility.should == nil
189 jp = JoinPoint.new :type => ProtectionExample, :method => :foo, :class_method => true
190 jp.visibility.should == nil
191 jp = JoinPoint.new :type => ProtectionExample, :method => :foo, :class_method => false
192 jp.visibility.should == nil
193 end
194 end
195
196 describe JoinPoint, "#target_type" do
197 it "should return the type at the JoinPoint" do
198 jp = JoinPoint.new :type => ProtectionExample, :method => :foo
199 jp.target_type.should be_eql(ProtectionExample)
200 end
201 end
202
203 describe JoinPoint, "#target_object" do
204 it "should return the object at the JoinPoint" do
205 example = ProtectionExample.new
206 jp = JoinPoint.new :object => example, :method => :foo
207 jp.target_object.should be_eql(example)
208 end
209 end
210
211 class InvokeOriginalClass
212 def invoke; @called = true; end
213 def called; @called; end
214 end
215
216 describe JoinPoint, "#proceed" do
217 it "should raise when the the context object doesn't have a 'proceed proc'" do
218 jp = JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
219 ioc = InvokeOriginalClass.new
220 jp.context.advice_kind = :around
221 jp.context.advised_object = ioc
222 jp.context.parameters = []
223 jp.context.proceed_proc = nil
224 lambda { jp.proceed }.should raise_error(JoinPoint::ProceedMethodNotAvailable)
225 end
226
227 it "should not raise when the advice is :around advice" do
228 jp = JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
229 ioc = InvokeOriginalClass.new
230 jp.context.advice_kind = :around
231 jp.context.advised_object = ioc
232 jp.context.parameters = []
233 jp.context.proceed_proc = Aquarium::Aspects::NoAdviceChainNode.new(:alias_method_name => :invoke)
234 lambda { jp.proceed }.should_not raise_error(JoinPoint::ProceedMethodNotAvailable)
235 end
236
237 it "should invoke the actual join point" do
238 jp = JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
239 ioc = InvokeOriginalClass.new
240 jp.context.advice_kind = :around
241 jp.context.advised_object = ioc
242 jp.context.parameters = []
243 jp.context.proceed_proc = Aquarium::Aspects::NoAdviceChainNode.new(:alias_method_name => :invoke)
244 jp.proceed
245 ioc.called.should be_true
246 end
247 end
248
249 class InvokeOriginalClass
250 def invoke; @called = true; end
251 def called; @called; end
252 end
253
254 describe JoinPoint, "#invoke_original_join_point" do
255 it "should raise when the join point has an empty context" do
256 jp = JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
257 lambda { jp.invoke_original_join_point }.should raise_error(JoinPoint::ContextNotCorrectlyDefined)
258 end
259
260 it "should invoke the original join point" do
261 jp = JoinPoint.new :type => InvokeOriginalClass, :method => :invoke
262 ioc = InvokeOriginalClass.new
263 jp.context.advice_kind = :around
264 jp.context.advised_object = ioc
265 jp.context.parameters = []
266 jp.context.current_advice_node = Aquarium::Aspects::NoAdviceChainNode.new(:alias_method_name => :invoke)
267 jp.invoke_original_join_point
268 ioc.called.should be_true
269 end
270 end
271
272
273 describe JoinPoint, "#dup" do
274 it "should duplicate the fields in the join point." do
275 jp = JoinPoint.new :type => String, :method_name => :count
276 jp2 = jp.dup
277 jp2.should eql(jp)
278 end
279 end
280
281 describe JoinPoint, "#eql?" do
282 setup do
283 @jp1 = JoinPoint.new :type => Dummy, :method_name => :count
284 @jp2 = JoinPoint.new :type => Dummy, :method_name => :count
285 @jp3 = JoinPoint.new :type => Array, :method_name => :size
286 @jp4 = JoinPoint.new :object => [], :method_name => :size
287 @jp5 = JoinPoint.new :object => [], :method_name => :size
288 end
289
290 it "should return true for the same join point." do
291 @jp1.should eql(@jp1)
292 end
293
294 it "should return true for an identical join point." do
295 @jp1.should eql(@jp2)
296 end
297
298 it "should return false for a non-identical join point." do
299 @jp1.should_not eql(@jp3)
300 end
301
302 it "should return false when one join point matches a method for a class and the other matches the same method in an instance of the class." do
303 @jp3.should_not eql(@jp4)
304 end
305
306 it "should return false for a non-join point object." do
307 @jp1.should_not eql("foo")
308 end
309
310 it "should return false for two join points that are equal except for the ids of the object they reference." do
311 @jp4.should_not eql(@jp5)
312 end
313 end
314
315 describe JoinPoint, "#==" do
316 setup do
317 @jp1 = JoinPoint.new :type => Dummy, :method_name => :count
318 @jp2 = JoinPoint.new :type => Dummy, :method_name => :count
319 @jp3 = JoinPoint.new :type => Array, :method_name => :size
320 @jp4 = JoinPoint.new :object => [], :method_name => :size
321 @jp5 = JoinPoint.new :object => [], :method_name => :size
322 end
323
324 it "should return true for the same join point." do
325 @jp1.should == @jp1
326 end
327
328 it "should return true for an identical join point." do
329 @jp1.should == @jp2
330 end
331
332 it "should return false for a non-identical join point." do
333 @jp1.should_not == @jp3
334 end
335
336 it "should return false when one join point matches a method for a class and the other matches the same method in an instance of the class." do
337 @jp3.should_not == @jp4
338 end
339
340 it "should return false for a non-join point object." do
341 @jp1.should_not == "foo"
342 end
343
344 it "should return false for two join points that are equal except for the ids of the object they reference." do
345 @jp4.should_not == @jp5
346 end
347 end
348
349 describe JoinPoint, "#<=>" do
350 setup do
351 @jp1 = JoinPoint.new :type => Dummy, :method_name => :count
352 @jp1nc = JoinPoint.new :type => Dummy, :method_name => :count
353 @jp2 = JoinPoint.new :type => Dummy, :method_name => :count
354 @jp2nc = JoinPoint.new :type => Dummy, :method_name => :count
355 @jp3 = JoinPoint.new :type => Array, :method_name => :size
356 @jp4 = JoinPoint.new :object => [], :method_name => :size
357 @jp5 = JoinPoint.new :object => [], :method_name => :size
358 dummy = Dummy.new
359 @jp6 = JoinPoint.new :object => dummy, :method_name => :size
360 @jp6nc = JoinPoint.new :object => dummy, :method_name => :size
361 @jp7 = JoinPoint.new :object => dummy, :method_name => :size
362 @jp7nc = JoinPoint.new :object => dummy, :method_name => :size
363 [@jp1, @jp2, @jp6, @jp7].each do |jp|
364 jp.context.advice_kind = :before
365 jp.context.advised_object = dummy
366 jp.context.parameters = []
367 jp.context.block_for_method = nil
368 jp.context.returned_value = nil
369 jp.context.raised_exception = nil
370 jp.context.proceed_proc = nil
371 end
372 end
373
374 it "should return 1 of the second object is nil" do
375 (@jp1 <=> nil).should == 1
376 end
377
378 it "should return 0 for the same join point with no context" do
379 (@jp1nc <=> @jp1nc).should == 0
380 (@jp6nc <=> @jp6nc).should == 0
381 end
382
383 it "should return 0 for the same join point with equivalent contexts" do
384 (@jp1 <=> @jp1).should == 0
385 (@jp6 <=> @jp6).should == 0
386 end
387
388 it "should return 0 for equivalent join points with no context" do
389 (@jp1nc <=>@jp2nc).should == 0
390 (@jp6nc <=>@jp7nc).should == 0
391 end
392
393 it "should return 0 for equivalent join points with equivalent contexts" do
394 (@jp1 <=> @jp2).should == 0
395 (@jp6 <=> @jp7).should == 0
396 end
397
398 it "should return +1 for join points that are equivalent except for the context, where the first join point has a context and the second has an 'empty' context" do
399 (@jp1 <=> @jp2nc).should == 1
400 (@jp6 <=> @jp7nc).should == 1
401 end
402
403 it "should return -1 for join points that are equivalent except for the context, where the second join point has a context and the first has an 'empty' context" do
404 (@jp1nc <=> @jp2).should == -1
405 (@jp6nc <=> @jp6).should == -1
406 end
407
408 it "should sort by type name first" do
409 end
410 end
411
412 describe JoinPoint, "#type_or_object" do
413 it "should return the type if the object is nil" do
414 jp = JoinPoint.new :type => String, :method_name => :split
415 jp.type_or_object.should eql(String)
416 end
417
418 it "should return the object if the type is nil" do
419 jp = JoinPoint.new :object => String.new, :method_name => :split
420 jp.type_or_object.should eql("")
421 end
422 end
423
424 describe JoinPoint, "#exists?" do
425 it "should return false if the join point represents a non-existent join point for an instance method in the runtime environment" do
426 jp = JoinPoint.new :type => ProtectionExample, :method_name => :foo
427 jp.exists?.should be_false
428 end
429
430 it "should return false if the join point represents a non-existent join point for a class method in the runtime environment" do
431 jp = JoinPoint.new :type => ProtectionExample, :method_name => :foo, :class_method => true
432 jp.exists?.should be_false
433 end
434
435 it "should return true if the join point represents a real join point for a public instance method in the runtime environment" do
436 jp = JoinPoint.new :type => ProtectionExample, :method_name => :public_instance_m
437 jp.exists?.should be_true
438 end
439
440 it "should return true if the join point represents a real join point for a protected instance method in the runtime environment" do
441 jp = JoinPoint.new :type => ProtectionExample, :method_name => :protected_instance_m
442 jp.exists?.should be_true
443 end
444
445 it "should return true if the join point represents a real join point for a private instance method in the runtime environment" do
446 jp = JoinPoint.new :type => ProtectionExample, :method_name => :private_instance_m
447 jp.exists?.should be_true
448 end
449
450 it "should return true if the join point represents a real join point for a public class method in the runtime environment" do
451 jp = JoinPoint.new :type => ProtectionExample, :method_name => :public_class_m, :class_method => true
452 jp.exists?.should be_true
453 end
454
455 it "should return true if the join point represents a real join point for a private class method in the runtime environment" do
456 jp = JoinPoint.new :type => ProtectionExample, :method_name => :private_class_m, :class_method => true
457 jp.exists?.should be_true
458 end
459
460 class ProtectionExample2
461 def public_instance_m; end
462 protected
463 def protected_instance_m; end
464 private
465 def private_instance_m; end
466 def self.public_class_m; end
467 def self.private_class_m; end
468 private_class_method :private_class_m
469 end
470
471 end
472
473 describe JoinPoint::Context, "#initialize" do
474 it "should initialize :advice_kind to Advice::UNKNOWN_ADVICE_KIND if not specified." do
475 context = JoinPoint::Context.new
476 context.advice_kind.should equal(Advice::UNKNOWN_ADVICE_KIND)
477 end
478
479 it "should initialize :advised_object to equal a NilObject if not specified." do
480 context = JoinPoint::Context.new
481 context.advised_object.should eql(Aquarium::Utils::NilObject.new)
482 end
483
484 it "should initialize :parameters to [] if not specified." do
485 context = JoinPoint::Context.new
486 context.parameters.should eql([])
487 end
488
489 it "should accept a :returned_value argument." do
490 lambda { JoinPoint::Context.new :advice_kind => :before, :advised_object => "object", :parameters => [","], :returned_value => ["12", "34"]}.should_not raise_error(Aquarium::Utils::InvalidOptions)
491 end
492
493 it "should accept a :raised_exception argument." do
494 lambda { JoinPoint::Context.new :advice_kind => :before, :advised_object => "object", :parameters => [","], :raised_exception => NameError.new}.should_not raise_error(Aquarium::Utils::InvalidOptions)
495 end
496
497 end
498
499 describe JoinPoint::Context, "#target_object" do
500 it "should be a synonym for #advised_object." do
501 object = "12,34"
502 jp = JoinPoint.new :type => String, :method_name => :split
503 jp.context.advised_object = @object
504 jp.context.target_object.should == jp.context.advised_object
505 end
506 end
507
508 def do_common_eql_setup
509 @object = "12,34"
510 @object2 = "12,34,56"
511 @jp_with_context1 = JoinPoint.new :type => String, :method_name => :split
512 @jp_with_context2 = JoinPoint.new :type => String, :method_name => :split
513 @jp_with_context2b = JoinPoint.new :type => String, :method_name => :split
514 @jp_with_context2c = JoinPoint.new :type => String, :method_name => :split
515 @jp_with_context2d = JoinPoint.new :type => String, :method_name => :split
516 @jp_with_context1.context.advice_kind = :before
517 @jp_with_context1.context.advised_object = @object
518 @jp_with_context1.context.parameters = [","]
519 @jp_with_context1.context.returned_value = ["12", "34"]
520 @jp_with_context2.context.advice_kind = :before
521 @jp_with_context2.context.advised_object = @object
522 @jp_with_context2.context.parameters = [","]
523 @jp_with_context2.context.returned_value = ["12", "34"]
524 @jp_with_context2b.context.advice_kind = :after
525 @jp_with_context2b.context.advised_object = @object
526 @jp_with_context2b.context.parameters = [","]
527 @jp_with_context2b.context.returned_value = ["12", "34"]
528 @jp_with_context2c.context.advice_kind = :before
529 @jp_with_context2c.context.advised_object = @object2
530 @jp_with_context2c.context.parameters = [","]
531 @jp_with_context2c.context.returned_value = ["12", "34"]
532 @jp_with_context2d.context.advice_kind = :before
533 @jp_with_context2d.context.advised_object = @object
534 @jp_with_context2d.context.parameters = ["2"]
535 @jp_with_context2d.context.returned_value = ["1", ",34"]
536 end
537
538 describe JoinPoint::Context, "#eql?" do
539 setup do
540 do_common_eql_setup
541 end
542
543 it "should return true for identical contexts." do
544 @jp_with_context1.context.should eql(@jp_with_context2.context)
545 end
546
547 it "should return false for different contexts." do
548 @jp_with_context1.context.should_not eql(@jp_with_context2b.context)
549 @jp_with_context1.context.should_not eql(@jp_with_context2c.context)
550 @jp_with_context1.context.should_not eql(@jp_with_context2d.context)
551 end
552
553 it "should return false if two equal but different objects are specified." do
554 jp_with_diff_object = JoinPoint.new :type => String, :method_name => :split
555 jp_with_diff_object.context.advised_object = "12,34"
556 @jp_with_context1.context.should_not eql(jp_with_diff_object.context)
557 end
558 end
559
560 describe JoinPoint::Context, "#==" do
561 setup do
562 do_common_eql_setup
563 end
564
565 it "should return true for identical contexts." do
566 @jp_with_context1.context.should == @jp_with_context2.context
567 end
568
569 it "should return false for different contexts." do
570 @jp_with_context1.context.should_not == @jp_with_context2b.context
571 @jp_with_context1.context.should_not == @jp_with_context2c.context
572 @jp_with_context1.context.should_not == @jp_with_context2d.context
573 end
574
575 it "should return false if two equal but different objects are specified." do
576 jp_with_diff_object = JoinPoint.new :type => String, :method_name => :split
577 jp_with_diff_object.context.advised_object = "12,34"
578 @jp_with_context1.context.should_not == jp_with_diff_object.context
579 end
580 end
Generated using the rcov code coverage analysis tool for Ruby version 0.8.1.2.