aquarium 0.1.8 → 0.2.0

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.
Files changed (51) hide show
  1. data/CHANGES +59 -2
  2. data/README +33 -16
  3. data/RELEASE-PLAN +28 -5
  4. data/UPGRADE +11 -0
  5. data/examples/aspect_design_example.rb +2 -2
  6. data/examples/aspect_design_example_spec.rb +2 -2
  7. data/examples/design_by_contract_example.rb +4 -4
  8. data/examples/design_by_contract_example_spec.rb +4 -4
  9. data/examples/method_missing_example.rb +4 -1
  10. data/examples/method_missing_example_spec.rb +4 -1
  11. data/examples/method_tracing_example.rb +2 -2
  12. data/examples/method_tracing_example_spec.rb +16 -16
  13. data/lib/aquarium/aspects/advice.rb +47 -25
  14. data/lib/aquarium/aspects/aspect.rb +81 -39
  15. data/lib/aquarium/aspects/dsl/aspect_dsl.rb +1 -1
  16. data/lib/aquarium/aspects/exclusion_handler.rb +2 -2
  17. data/lib/aquarium/aspects/join_point.rb +28 -28
  18. data/lib/aquarium/aspects/pointcut.rb +61 -15
  19. data/lib/aquarium/extras/design_by_contract.rb +7 -7
  20. data/lib/aquarium/finders.rb +0 -1
  21. data/lib/aquarium/finders/method_finder.rb +10 -20
  22. data/lib/aquarium/finders/type_finder.rb +141 -75
  23. data/lib/aquarium/utils.rb +1 -0
  24. data/lib/aquarium/utils/logic_error.rb +9 -0
  25. data/lib/aquarium/utils/method_utils.rb +4 -3
  26. data/lib/aquarium/utils/nil_object.rb +1 -0
  27. data/lib/aquarium/utils/type_utils.rb +19 -0
  28. data/lib/aquarium/version.rb +2 -2
  29. data/spec/aquarium/aspects/advice_chain_node_spec.rb +2 -2
  30. data/spec/aquarium/aspects/advice_spec.rb +28 -5
  31. data/spec/aquarium/aspects/aspect_invocation_spec.rb +522 -289
  32. data/spec/aquarium/aspects/aspect_spec.rb +59 -41
  33. data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +7 -7
  34. data/spec/aquarium/aspects/aspect_with_subtypes_spec.rb +2 -2
  35. data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -2
  36. data/spec/aquarium/aspects/concurrent_aspects_with_objects_and_types_spec.rb +1 -1
  37. data/spec/aquarium/aspects/dsl/aspect_dsl_spec.rb +34 -34
  38. data/spec/aquarium/aspects/join_point_spec.rb +79 -0
  39. data/spec/aquarium/aspects/pointcut_or_composition_spec.rb +13 -3
  40. data/spec/aquarium/aspects/pointcut_spec.rb +310 -63
  41. data/spec/aquarium/extras/design_by_contract_spec.rb +4 -4
  42. data/spec/aquarium/finders/method_finder_spec.rb +208 -54
  43. data/spec/aquarium/finders/type_finder_spec.rb +24 -88
  44. data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +206 -0
  45. data/spec/aquarium/spec_example_classes.rb +75 -12
  46. data/spec/aquarium/utils/logic_error_spec.rb +10 -0
  47. data/spec/aquarium/utils/type_utils_sample_classes.rb +203 -0
  48. data/spec/aquarium/utils/type_utils_spec.rb +47 -1
  49. metadata +48 -39
  50. data/lib/aquarium/finders/object_finder.rb +0 -75
  51. data/spec/aquarium/finders/object_finder_spec.rb +0 -231
@@ -7,7 +7,7 @@ describe Aquarium::Extras::DesignByContract, "precondition" do
7
7
  def action *args
8
8
  end
9
9
 
10
- precondition :method => :action, :message => "Must pass more than one argument." do |jp, *args|
10
+ precondition :method => :action, :message => "Must pass more than one argument." do |jp, obj, *args|
11
11
  args.size > 0
12
12
  end
13
13
  end
@@ -27,7 +27,7 @@ describe Aquarium::Extras::DesignByContract, "postcondition" do
27
27
  def action *args
28
28
  end
29
29
 
30
- postcondition :method => :action, :message => "Must pass more than one argument and first argument must be non-empty." do |jp, *args|
30
+ postcondition :method => :action, :message => "Must pass more than one argument and first argument must be non-empty." do |jp, obj, *args|
31
31
  args.size > 0 && ! args[0].empty?
32
32
  end
33
33
  end
@@ -58,8 +58,8 @@ describe Aquarium::Extras::DesignByContract, "invariant" do
58
58
  "bad"
59
59
  end
60
60
 
61
- invariant :methods => /action$/, :message => "Must not change the @invar value." do |jp, *args|
62
- jp.context.advised_object.invar == 0
61
+ invariant :methods => /action$/, :message => "Must not change the @invar value." do |jp, obj, *args|
62
+ obj.invar == 0
63
63
  end
64
64
  end
65
65
 
@@ -15,6 +15,18 @@ module M
15
15
  end
16
16
  def mmodule2
17
17
  end
18
+ def self.cmmodule1
19
+ end
20
+ end
21
+
22
+ module M2
23
+ include M
24
+ def mmodule3
25
+ end
26
+ def mmodule4
27
+ end
28
+ def self.cmmodule3
29
+ end
18
30
  end
19
31
 
20
32
  class Derived < Base
@@ -25,8 +37,24 @@ class Derived < Base
25
37
  end
26
38
  def mmodule1
27
39
  end
40
+ def mmodule2b
41
+ end
42
+ end
43
+
44
+ class Derived2 < Base
45
+ include M2
46
+ def mbase1
47
+ end
48
+ def mderived1
49
+ end
50
+ def mmodule1
51
+ end
52
+ def mmodule2b
53
+ end
28
54
  def mmodule3
29
55
  end
56
+ def mmodule4b
57
+ end
30
58
  end
31
59
 
32
60
  # :startdoc:
@@ -203,30 +231,75 @@ describe Aquarium::Finders::MethodFinder, "#find (behavior for derived classes)"
203
231
  before_method_finder_spec
204
232
  end
205
233
 
206
- it "should find Base and Derived methods in the specified class, by default." do
234
+ it "should find base and derived methods in the specified class, by default." do
207
235
  actual = Aquarium::Finders::MethodFinder.new.find :types => Derived, :methods => [/^mbase/, /^mmodule/]
208
236
  actual.matched.size.should == 1
209
- actual.matched[Derived].should == Set.new([:mbase1, :mbase2, :mmodule1, :mmodule2, :mmodule3])
237
+ actual.matched[Derived].should == Set.new([:mbase1, :mbase2, :mmodule1, :mmodule2, :mmodule2b])
210
238
  end
211
239
 
212
- it "should find Base and Derived methods in the specified object, by default." do
240
+ it "should find base and derived methods in the specified object, by default." do
213
241
  child = Derived.new
214
242
  actual = Aquarium::Finders::MethodFinder.new.find :object => child, :methods => [/^mbase/, /^mderived/, /^mmodule/]
215
243
  actual.matched.size.should == 1
216
- actual.matched[child].should == Set.new([:mbase1, :mbase2, :mderived1, :mmodule1, :mmodule2, :mmodule3])
244
+ actual.matched[child].should == Set.new([:mbase1, :mbase2, :mderived1, :mmodule1, :mmodule2, :mmodule2b])
217
245
  end
218
246
 
219
- it "should find Derived methods only for a type when ancestor methods are suppressed, which also suppresses method overrides." do
247
+ it "should only find Derived methods for a type when ancestor methods are excluded, which also excludes method overrides." do
220
248
  actual = Aquarium::Finders::MethodFinder.new.find :types => Derived, :methods => [/^mder/, /^mmod/], :options => [:exclude_ancestor_methods]
221
249
  actual.matched.size.should == 1
222
- actual.matched[Derived].should == Set.new([:mderived1, :mmodule3])
250
+ actual.matched[Derived].should == Set.new([:mderived1, :mmodule2b])
223
251
  end
224
252
 
225
- it "should find Derived methods only for an object when ancestor methods are suppressed, which also suppresses method overrides." do
253
+ it "should only find Derived methods for an object when ancestor methods are excluded, which also excludes method overrides." do
226
254
  child = Derived.new
227
255
  actual = Aquarium::Finders::MethodFinder.new.find :object => child, :methods => [/^mder/, /^mmodule/], :options => [:exclude_ancestor_methods]
228
256
  actual.matched.size.should == 1
229
- actual.matched[child].should == Set.new([:mderived1, :mmodule3])
257
+ actual.matched[child].should == Set.new([:mderived1, :mmodule2b])
258
+ end
259
+ end
260
+
261
+ describe Aquarium::Finders::MethodFinder, "#find (behavior for included modules)" do
262
+ before(:each) do
263
+ before_method_finder_spec
264
+ end
265
+
266
+ it "should find included and defined methods in the specified modules, by default." do
267
+ actual = Aquarium::Finders::MethodFinder.new.find :type => [M, M2], :methods => /^mmodule/
268
+ actual.matched.size.should == 2
269
+ actual.matched[M].should == Set.new([:mmodule1, :mmodule2])
270
+ actual.matched[M2].should == Set.new([:mmodule1, :mmodule2, :mmodule3, :mmodule4])
271
+ end
272
+
273
+ it "should find included and overridden methods in classes that include the specified modules, by default." do
274
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [Derived, Derived2], :methods => /^mmodule/
275
+ actual.matched.size.should == 2
276
+ actual.matched[Derived].should == Set.new([:mmodule1, :mmodule2, :mmodule2b])
277
+ actual.matched[Derived2].should == Set.new([:mmodule1, :mmodule2, :mmodule2b, :mmodule3, :mmodule4, :mmodule4b])
278
+ end
279
+
280
+ it "should find included and overridden methods in instances of classes that include the specified modules, by default." do
281
+ child = Derived.new
282
+ child2 = Derived2.new
283
+ actual = Aquarium::Finders::MethodFinder.new.find :objects => [child, child2], :methods => /^mmodule/
284
+ actual.matched.size.should == 2
285
+ actual.matched[child].should == Set.new([:mmodule1, :mmodule2, :mmodule2b])
286
+ actual.matched[child2].should == Set.new([:mmodule1, :mmodule2, :mmodule2b, :mmodule3, :mmodule4, :mmodule4b])
287
+ end
288
+
289
+ it "should only find defined methods for a module when ancestor methods are excluded, which also excludes method overrides." do
290
+ actual = Aquarium::Finders::MethodFinder.new.find :type => [M, M2], :methods => /^mmod/, :options => [:exclude_ancestor_methods]
291
+ actual.matched.size.should == 2
292
+ actual.matched[M].should == Set.new([:mmodule1, :mmodule2])
293
+ actual.matched[M2].should == Set.new([:mmodule3, :mmodule4])
294
+ end
295
+
296
+ it "should not find any methods from included modules in classes when ancestor methods are excluded, which also excludes method overrides." do
297
+ child = Derived.new
298
+ child2 = Derived2.new
299
+ actual = Aquarium::Finders::MethodFinder.new.find :objects => [child, child2], :methods => /^mmodule/, :options => [:exclude_ancestor_methods]
300
+ actual.matched.size.should == 2
301
+ actual.matched[child].should == Set.new([:mmodule2b])
302
+ actual.matched[child2].should == Set.new([:mmodule2b, :mmodule4b])
230
303
  end
231
304
  end
232
305
 
@@ -235,7 +308,7 @@ describe Aquarium::Finders::MethodFinder, "#find (searching for class methods)"
235
308
  before_method_finder_spec
236
309
  end
237
310
 
238
- it "should find all class methods matching a regular expression for types when :class is used." do
311
+ it "should find all class methods specified by regular expression for types when :class is used." do
239
312
  # Have to add some rspec methods to the expected lists!
240
313
  expected = {}
241
314
  expected[Kernel] = [:chomp!, :chop!, :respond_to?]
@@ -266,12 +339,60 @@ describe Aquarium::Finders::MethodFinder, "#find (searching for class methods)"
266
339
  end
267
340
  end
268
341
 
342
+ describe Aquarium::Finders::MethodFinder, "#find (searching for class methods defined in modules)" do
343
+ before(:each) do
344
+ before_method_finder_spec
345
+ end
346
+
347
+ def do_class_methods_for_modules method_spec, options_spec
348
+ actual = Aquarium::Finders::MethodFinder.new.find :type => [M, M2], :methods => method_spec, :options => options_spec
349
+ actual.matched.size.should == 2
350
+ actual.matched[M].should == Set.new([:cmmodule1])
351
+ actual.matched[M2].should == Set.new([:cmmodule3])
352
+ end
353
+
354
+ it "should find all class methods specified by regular expression for modules when :class is used." do
355
+ do_class_methods_for_modules /^cmmodule/, [:class]
356
+ end
357
+
358
+ it "should find all class methods specified by name for modules when :class is used." do
359
+ do_class_methods_for_modules [:cmmodule1, :cmmodule3], [:class]
360
+ end
361
+
362
+ it "should not find class methods defined in included modules, because they do not become class methods in the including module." do
363
+ do_class_methods_for_modules /^cmmodule/, [:class]
364
+ end
365
+
366
+ it "should not find class methods defined in included modules, if ancestor methods are excluded explicitly." do
367
+ do_class_methods_for_modules /^cmmodule/, [:class, :exclude_ancestor_methods]
368
+ end
369
+
370
+ it "should find all public class methods in types when searching with the :all method specification and the :class option." do
371
+ actual = Aquarium::Finders::MethodFinder.new.find :type => [M, M2], :methods => :all, :options => [:class]
372
+ actual.matched.size.should == 2
373
+ actual.matched[M].should == Set.new(M.public_methods.sort.map{|m| m.intern})
374
+ actual.matched[M2].should == Set.new(M2.public_methods.sort.map{|m| m.intern})
375
+ end
376
+
377
+ it "should not find any module-defined class methods in classes that include the modules." do
378
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [Derived, Derived2], :methods => /^cmmodule/, :options => [:class]
379
+ actual.matched.size.should == 0
380
+ end
381
+
382
+ it "should not find any module-defined class methods in instances of classes that include the modules." do
383
+ child = Derived.new
384
+ child2 = Derived2.new
385
+ actual = Aquarium::Finders::MethodFinder.new.find :objects => [child, child2], :methods => /^cmmodule/, :options => [:class]
386
+ actual.matched.size.should == 0
387
+ end
388
+ end
389
+
269
390
  describe Aquarium::Finders::MethodFinder, "#find (searching for instance methods)" do
270
391
  before(:each) do
271
392
  before_method_finder_spec
272
393
  end
273
394
 
274
- it "should find all public instance methods in types when searching with the :all method specification." do
395
+ it "should find all public instance methods in classes when searching with the :all method specification." do
275
396
  actual = Aquarium::Finders::MethodFinder.new.find :types => [ClassWithPublicInstanceMethod, ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod], :methods => :all
276
397
  actual.matched.size.should == 3
277
398
  [ClassWithPublicInstanceMethod, ClassWithProtectedInstanceMethod, ClassWithPrivateInstanceMethod].each do |c|
@@ -279,6 +400,13 @@ describe Aquarium::Finders::MethodFinder, "#find (searching for instance methods
279
400
  end
280
401
  end
281
402
 
403
+ it "should find all public instance methods in modules when searching with the :all method specification." do
404
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [M, M2], :methods => :all
405
+ actual.matched.size.should == 2
406
+ actual.matched[M].should == Set.new([:mmodule1, :mmodule2])
407
+ actual.matched[M2].should == Set.new([:mmodule1, :mmodule2, :mmodule3, :mmodule4])
408
+ end
409
+
282
410
  it "should find all public instance methods in objects when searching with the :all method specification." do
283
411
  pub = ClassWithPublicInstanceMethod.new
284
412
  pro = ClassWithProtectedInstanceMethod.new
@@ -290,6 +418,22 @@ describe Aquarium::Finders::MethodFinder, "#find (searching for instance methods
290
418
  end
291
419
  end
292
420
 
421
+ it "should find the module-defined public instance methods in when searching a class with the :all method specification." do
422
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [Derived, Derived2], :methods => :all
423
+ actual.matched.size.should == 2
424
+ [:mmodule1, :mmodule2].each {|m| actual.matched[Derived].should include(m)}
425
+ [:mmodule1, :mmodule2, :mmodule3, :mmodule4].each {|m| actual.matched[Derived2].should include(m)}
426
+ end
427
+
428
+ it "should find the module-defined public instance methods in when searching an instance of a class with the :all method specification." do
429
+ child = Derived.new
430
+ child2 = Derived2.new
431
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [child, child2], :methods => :all
432
+ actual.matched.size.should == 2
433
+ [:mmodule1, :mmodule2].each {|m| actual.matched[child].should include(m)}
434
+ [:mmodule1, :mmodule2, :mmodule3, :mmodule4].each {|m| actual.matched[child2].should include(m)}
435
+ end
436
+
293
437
  it "should find only one instance method for a type when searching with a regexp matching one method." do
294
438
  actual = Aquarium::Finders::MethodFinder.new.find :types => ClassWithPublicInstanceMethod, :methods => /instance_test_method/
295
439
  actual.matched.size.should == 1
@@ -443,19 +587,41 @@ class ExcludeMethodTester
443
587
  end
444
588
 
445
589
  describe Aquarium::Finders::MethodFinder, "#find for types (using :exclude_methods)" do
446
- it "should return an empty result if :exclude_methods => :all specified." do
590
+ it "should return an empty result for classes if :exclude_methods => :all specified." do
447
591
  actual = Aquarium::Finders::MethodFinder.new.find :types => ExcludeMethodTester, :methods => :all, :exclude_methods => :all, :options => :exclude_ancestor_methods
448
592
  actual.matched.size.should == 0
449
593
  actual.not_matched.size.should == 0
450
594
  end
595
+ it "should return an empty result for modules if :exclude_methods => :all specified." do
596
+ actual = Aquarium::Finders::MethodFinder.new.find :types => M2, :methods => :all, :exclude_methods => :all, :options => :exclude_ancestor_methods
597
+ actual.matched.size.should == 0
598
+ actual.not_matched.size.should == 0
599
+ end
600
+ it "should return an empty result for classes including modules if :exclude_methods => :all specified." do
601
+ actual = Aquarium::Finders::MethodFinder.new.find :types => Derived2, :methods => :all, :exclude_methods => :all, :options => :exclude_ancestor_methods
602
+ actual.matched.size.should == 0
603
+ actual.not_matched.size.should == 0
604
+ end
451
605
 
452
- it "should remove excluded methods from the result where a single excluded methods is specified by name." do
606
+ it "should remove excluded methods from the result for classes where a single excluded methods is specified by name." do
453
607
  actual = Aquarium::Finders::MethodFinder.new.find :types => ExcludeMethodTester, :methods => :all, :exclude_method => :method1, :options => :exclude_ancestor_methods
454
608
  actual.matched.size.should == 1
455
609
  actual.matched[ExcludeMethodTester].size.should == 2
456
610
  actual.matched[ExcludeMethodTester].should == Set.new([:method2, :method3])
457
611
  actual.not_matched.size.should == 0
458
612
  end
613
+ it "should remove excluded methods from the result for modules where a single excluded methods is specified by name." do
614
+ actual = Aquarium::Finders::MethodFinder.new.find :types => M, :methods => :all, :exclude_method => :mmodule1
615
+ actual.matched.size.should == 1
616
+ actual.matched[M].size.should == 1
617
+ actual.matched[M].should == Set.new([:mmodule2])
618
+ actual.not_matched.size.should == 0
619
+ end
620
+ it "should remove excluded methods from the result for classes that include modules where a single excluded methods is specified by name." do
621
+ actual = Aquarium::Finders::MethodFinder.new.find :types => Derived, :methods => :all, :exclude_method => :mmodule1
622
+ actual.matched.size.should == 1
623
+ actual.matched[Derived].should_not include(:mmodule1)
624
+ end
459
625
 
460
626
  it "should remove excluded methods from the result where the excluded methods are specified by an array of names." do
461
627
  actual = Aquarium::Finders::MethodFinder.new.find :types => ExcludeMethodTester, :methods => :all, :exclude_methods => [:method1, :method2], :options => :exclude_ancestor_methods
@@ -488,11 +654,16 @@ describe Aquarium::Finders::MethodFinder, "#find for types (using :exclude_metho
488
654
  end
489
655
 
490
656
  describe Aquarium::Finders::MethodFinder, "#find for objects (using :exclude_methods)" do
491
- it "should return an empty result if :exclude_methods => :all specified." do
657
+ it "should return an empty result for instances of classes if :exclude_methods => :all specified." do
492
658
  actual = Aquarium::Finders::MethodFinder.new.find :object => ExcludeMethodTester.new, :methods => :all, :exclude_methods => :all, :options => :exclude_ancestor_methods
493
659
  actual.matched.size.should == 0
494
660
  actual.not_matched.size.should == 0
495
661
  end
662
+ it "should return an empty result for for instances of classes that include modules if :exclude_methods => :all specified." do
663
+ actual = Aquarium::Finders::MethodFinder.new.find :object => Derived2.new, :methods => :all, :exclude_methods => :all, :options => :exclude_ancestor_methods
664
+ actual.matched.size.should == 0
665
+ actual.not_matched.size.should == 0
666
+ end
496
667
 
497
668
  it "should remove excluded methods from the result where a single excluded methods is specified by name." do
498
669
  emt = ExcludeMethodTester.new
@@ -542,7 +713,7 @@ describe Aquarium::Finders::MethodFinder, "#find (using :options => :exclude_anc
542
713
  before_method_finder_spec
543
714
  end
544
715
 
545
- it "should suppress ancestor methods for types when :exclude_ancestor_methods is specified." do
716
+ it "should suppress ancestor methods for classes when :exclude_ancestor_methods is specified." do
546
717
  actual = Aquarium::Finders::MethodFinder.new.find :types => @test_classes, :methods => /test_method/, :options => [:public, :instance, :exclude_ancestor_methods]
547
718
  actual.matched.size.should == 1
548
719
  actual.matched[ClassWithPublicInstanceMethod].should == Set.new([:public_instance_test_method])
@@ -552,7 +723,6 @@ describe Aquarium::Finders::MethodFinder, "#find (using :options => :exclude_anc
552
723
  actual.not_matched[ClassWithPublicClassMethod].should == Set.new([/test_method/])
553
724
  actual.not_matched[ClassWithPrivateClassMethod].should == Set.new([/test_method/])
554
725
  end
555
-
556
726
  it "should suppress ancestor methods for objects when :exclude_ancestor_methods is specified." do
557
727
  actual = Aquarium::Finders::MethodFinder.new.find :objects => @test_objects, :methods => /test_method/, :options => [:public, :instance, :exclude_ancestor_methods]
558
728
  actual.matched.size.should == 1
@@ -563,6 +733,29 @@ describe Aquarium::Finders::MethodFinder, "#find (using :options => :exclude_anc
563
733
  actual.not_matched[@cpub].should == Set.new([/test_method/])
564
734
  actual.not_matched[@cpri].should == Set.new([/test_method/])
565
735
  end
736
+
737
+ it "should suppress ancestor methods for modules when :exclude_ancestor_methods is specified." do
738
+ actual = Aquarium::Finders::MethodFinder.new.find :type => M2, :methods => /^mmodule/, :options => [:instance, :exclude_ancestor_methods]
739
+ actual.matched.size.should == 1
740
+ actual.matched[M2].should == Set.new([:mmodule3, :mmodule4])
741
+ actual.not_matched.size.should == 0
742
+ end
743
+ it "should suppress ancestor methods for classes including modules when :exclude_ancestor_methods is specified." do
744
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [Derived, Derived2], :methods => /^mmodule/, :options => [:instance, :exclude_ancestor_methods]
745
+ actual.matched.size.should == 2
746
+ actual.matched[Derived].should == Set.new([:mmodule2b])
747
+ actual.matched[Derived2].should == Set.new([:mmodule2b, :mmodule4b])
748
+ actual.not_matched.size.should == 0
749
+ end
750
+ it "should suppress ancestor methods for instances of classes including modules when :exclude_ancestor_methods is specified." do
751
+ child = Derived.new
752
+ child2 = Derived2.new
753
+ actual = Aquarium::Finders::MethodFinder.new.find :types => [child, child2], :methods => /^mmodule/, :options => [:instance, :exclude_ancestor_methods]
754
+ actual.matched.size.should == 2
755
+ actual.matched[child].should == Set.new([:mmodule2b])
756
+ actual.matched[child2].should == Set.new([:mmodule2b, :mmodule4b])
757
+ actual.not_matched.size.should == 0
758
+ end
566
759
  end
567
760
 
568
761
  describe Aquarium::Finders::MethodFinder, "#find (using :options => [:public, :instance])" do
@@ -925,45 +1118,6 @@ describe "Aquarium::Finders::MethodFinder#find (looking for methods that end in
925
1118
  end
926
1119
  end
927
1120
 
928
- describe "Aquarium::Finders::MethodFinder#find_all_by" do
929
- it "should accept :all for the methods argument." do
930
- actual = Aquarium::Finders::MethodFinder.new.find_all_by ClassWithPublicInstanceMethod, :all, :exclude_ancestor_methods
931
- actual.matched.size.should == 1
932
- actual.matched[ClassWithPublicInstanceMethod].should == Set.new([:public_instance_test_method])
933
- actual.not_matched.size.should == 0
934
- pub = ClassWithPublicInstanceMethod.new
935
- actual = Aquarium::Finders::MethodFinder.new.find_all_by pub, :all, :exclude_ancestor_methods
936
- actual.matched.size.should == 1
937
- actual.matched[pub].should == Set.new([:public_instance_test_method])
938
- actual.not_matched.size.should == 0
939
- end
940
-
941
- it "should behave like Aquarium::Finders::MethodFinder#find with an explicit parameter list rather than a hash." do
942
- expected = Aquarium::Finders::MethodFinder.new.find :types => ClassWithPrivateInstanceMethod,
943
- :methods => /test_method/, :options => [:private, :instance, :exclude_ancestor_methods]
944
- actual = Aquarium::Finders::MethodFinder.new.find_all_by ClassWithPrivateInstanceMethod,
945
- /test_method/, :private, :instance, :exclude_ancestor_methods
946
- actual.should == expected
947
-
948
- expected = Aquarium::Finders::MethodFinder.new.find :objects => @pub,
949
- :methods => /test_method/, :options => [:private, :instance, :exclude_ancestor_methods]
950
- actual = Aquarium::Finders::MethodFinder.new.find_all_by @pub,
951
- /test_method/, :private, :instance, :exclude_ancestor_methods
952
- actual.should == expected
953
-
954
- expected = Aquarium::Finders::MethodFinder.new.find :types => [ClassWithPublicInstanceMethod, ClassWithPrivateInstanceMethod],
955
- :methods => ["foo", /test_method/], :options => [:instance, :exclude_ancestor_methods]
956
- actual = Aquarium::Finders::MethodFinder.new.find_all_by [ClassWithPublicInstanceMethod, ClassWithPrivateInstanceMethod],
957
- ["foo", /test_method/], :instance, :exclude_ancestor_methods
958
- actual.should == expected
959
-
960
- expected = Aquarium::Finders::MethodFinder.new.find :objects => [@pub, @pri],
961
- :methods => ["foo", /test_method/], :options => [:instance, :exclude_ancestor_methods]
962
- actual = Aquarium::Finders::MethodFinder.new.find_all_by [@pub, @pri],
963
- ["foo", /test_method/], :instance, :exclude_ancestor_methods
964
- actual.should == expected
965
- end
966
- end
967
1121
 
968
1122
  describe "Aquarium::Finders::MethodFinder.is_recognized_method_option" do
969
1123
 
@@ -1,7 +1,14 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
  require 'aquarium/finders/type_finder'
3
3
 
4
- describe Aquarium::Finders::TypeFinder, "#find" do
4
+ class Outside
5
+ class Inside1; end
6
+ class Inside2
7
+ class ReallyInside; end
8
+ end
9
+ end
10
+
11
+ describe Aquarium::Finders::TypeFinder, "#find invocation parameters" do
5
12
 
6
13
  it "should raise if an uknown option is specified." do
7
14
  lambda { Aquarium::Finders::TypeFinder.new.find :foo => 'bar', :baz => ''}.should raise_error(Aquarium::Utils::InvalidOptions)
@@ -11,6 +18,10 @@ describe Aquarium::Finders::TypeFinder, "#find" do
11
18
  lambda { Aquarium::Finders::TypeFinder.new.find "foo" }.should raise_error(Aquarium::Utils::InvalidOptions)
12
19
  end
13
20
 
21
+ it "should raise if the input type value is nil." do
22
+ lambda { Aquarium::Finders::TypeFinder.new.find :type => nil }.should raise_error(Aquarium::Utils::InvalidOptions)
23
+ end
24
+
14
25
  it "should return no matched types and no unmatched type expressions by default (i.e., the input is empty)." do
15
26
  actual = Aquarium::Finders::TypeFinder.new.find
16
27
  actual.matched.should == {}
@@ -40,6 +51,15 @@ describe Aquarium::Finders::TypeFinder, "#find" do
40
51
  actual.matched.should == {}
41
52
  actual.not_matched.should == {}
42
53
  end
54
+
55
+ it "should accept a hash and treat it as equivalent to an explicit list parameters." do
56
+ expected_found_types = [Outside::Inside1, Outside::Inside2]
57
+ expected_unfound_exps = %w[Foo::Bar::Baz]
58
+ hash = {:names => (expected_found_types.map {|t| t.to_s} + expected_unfound_exps)}
59
+ actual = Aquarium::Finders::TypeFinder.new.find hash
60
+ actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
61
+ actual.not_matched_keys.sort.should == expected_unfound_exps.sort
62
+ end
43
63
  end
44
64
 
45
65
  describe Aquarium::Finders::TypeFinder, "#is_recognized_option" do
@@ -59,12 +79,6 @@ describe Aquarium::Finders::TypeFinder, "#is_recognized_option" do
59
79
  end
60
80
  end
61
81
 
62
- class Outside
63
- class Inside1; end
64
- class Inside2
65
- class ReallyInside; end
66
- end
67
- end
68
82
 
69
83
  describe Aquarium::Finders::TypeFinder, "#find with :type or :name used to specify a single type" do
70
84
  it "should find a type matching a simple name (without :: namespace delimiters) using its name and the :type option." do
@@ -123,7 +137,8 @@ describe Aquarium::Finders::TypeFinder, "#find with :types, :names, :type, and :
123
137
  expected_found_types = [FalseClass, Module, TrueClass]
124
138
  expected_unfound_exps = []
125
139
  actual = Aquarium::Finders::TypeFinder.new.find :types => [/eClass$/, /^Modu/]
126
- actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
140
+ expected_found_types.each {|t| actual.matched_keys.should include(t)}
141
+ # actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
127
142
  actual.not_matched_keys.sort.should == expected_unfound_exps.sort
128
143
  end
129
144
 
@@ -209,87 +224,8 @@ describe Aquarium::Finders::TypeFinder, "#find" do
209
224
  end
210
225
  end
211
226
 
212
- describe Aquarium::Finders::TypeFinder, "#find_all_by" do
213
- it "should find types with :: namespace delimiters using lists of regular expressions." do
214
- expected_found_types = [Outside::Inside1, Outside::Inside2]
215
- expected_unfound_exps = [/^.*Fo+::.*Bar+::Baz.$/]
216
- actual = Aquarium::Finders::TypeFinder.new.find_all_by [/^.*Fo+::.*Bar+::Baz.$/, /Outside::.*1$/, /Out.*::In.*2/]
217
- actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
218
- actual.not_matched_keys.should == expected_unfound_exps
219
- end
220
-
221
- it "should find types with :: namespace delimiters using their names." do
222
- expected_found_types = [Outside::Inside1, Outside::Inside2]
223
- expected_unfound_exps = %w[Foo::Bar::Baz]
224
- actual = Aquarium::Finders::TypeFinder.new.find_all_by(expected_found_types.map {|t| t.to_s} + expected_unfound_exps)
225
- actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
226
- actual.not_matched_keys.should == expected_unfound_exps
227
- end
228
-
229
- it "should find types when types given." do
230
- expected_found_types = [Outside::Inside1, Outside::Inside2]
231
- actual = Aquarium::Finders::TypeFinder.new.find_all_by expected_found_types
232
- actual.matched_keys.sort_by {|x| x.to_s}.should == expected_found_types.sort_by {|x| x.to_s}
233
- actual.not_matched_keys.should == []
234
- end
235
- end
236
-
237
- describe Aquarium::Finders::TypeFinder, "#find_by_name" do
238
- it "should find a single type when given a single type name." do
239
- tf = Aquarium::Finders::TypeFinder.new
240
- actual = tf.find_by_name("String")
241
- actual.matched_keys.should == [String]
242
- actual.not_matched_keys.should == []
243
- actual = tf.find_by_name("Kernel")
244
- actual.matched_keys.should == [Kernel]
245
- actual.not_matched_keys.should == []
246
- actual = tf.find_by_name("Module")
247
- actual.matched_keys.should == [Module]
248
- actual.not_matched_keys.should == []
249
- end
250
-
251
- it "should find a single type when given a valid type name with :: separators." do
252
- tf = Aquarium::Finders::TypeFinder.new
253
- actual = tf.find_by_name "Outside::Inside1"
254
- actual.matched_keys.should == [Outside::Inside1]
255
- actual.not_matched_keys.should == []
256
- end
257
-
258
- it "should find a single type when given that type." do
259
- tf = Aquarium::Finders::TypeFinder.new
260
- actual = tf.find_by_name Outside::Inside1
261
- actual.matched_keys.should == [Outside::Inside1]
262
- actual.not_matched_keys.should == []
263
- end
264
-
265
- it "should return no matches if the type can't be found." do
266
- tf = Aquarium::Finders::TypeFinder.new
267
- actual = tf.find_by_name "UnknownClass1::UnknownClass2"
268
- actual.matched_keys.should == []
269
- actual.not_matched_keys.should == ["UnknownClass1::UnknownClass2"]
270
- end
271
-
272
- it "should return no matches if the type name is invalid." do
273
- tf = Aquarium::Finders::TypeFinder.new
274
- actual = tf.find_by_name "$foo:bar"
275
- actual.matched_keys.should == []
276
- actual.not_matched_keys.should == ["$foo:bar"]
277
- end
278
- end
279
-
280
- describe Aquarium::Finders::TypeFinder, "#find_by_type" do
281
- it "is synonymous with find_by_name." do
282
- tf = Aquarium::Finders::TypeFinder.new
283
- actual = tf.find_by_name "Outside::Inside1"
284
- actual.matched_keys.should == [Outside::Inside1]
285
- actual.not_matched_keys.should == []
286
- actual = tf.find_by_name Outside::Inside1
287
- actual.matched_keys.should == [Outside::Inside1]
288
- actual.not_matched_keys.should == []
289
- end
290
- end
291
227
 
292
- # This is a spec for a protected method.
228
+ # This is a spec for a protected method. It's primarily to keep the code coverage 100%, because there is rarely-invoked error handling code...
293
229
  describe Aquarium::Finders::TypeFinder, "#get_type_from_parent should" do
294
230
  it "should raise if a type doesn't exist that matches the constant" do
295
231
  lambda {Aquarium::Finders::TypeFinder.new.send(:get_type_from_parent, Aquarium::Finders, "Nonexistent", /Non/)}.should raise_error(NameError)