cordon 0.2.2 → 0.3.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.
@@ -11,7 +11,7 @@ From Wikipedia:
11
11
 
12
12
  I've never been a big fan of the way RSpec adds <code>#should</code> and <code>#should_not</code> to Kernel, but until recently I'd never been able to articulate why. Then I worked on a project that became <a href="https://github.com/geeksam/kookaburra/">Kookaburra</a>, and I found a specific reason to be annoyed.
13
13
 
14
- Basically, putting <code>#should</code> on all objects gives you the freedom to <s>shoot yourself in the foot</s> put RSpec expectations *anywhere*, not just inside an <code>#it</code> block. So, I went looking for a way to make <code>#should</code> explode if it was called outside a specific context.
14
+ Basically, putting <code>#should</code> on all objects gives you the freedom to <strike>shoot yourself in the foot</strike>^H^H^H put RSpec expectations *anywhere*, not just inside an <code>#it</code> block. So, I went looking for a way to make <code>#should</code> explode if it was called outside a specific context.
15
15
 
16
16
  After several false starts and horrible ideas, I've got something that actually isn't too bad.
17
17
 
@@ -44,13 +44,23 @@ In both examples, note that Cordon's <code>.embargo</code> method must be called
44
44
 
45
45
  ## TODO
46
46
 
47
- - Write integration macros (and tests, obviously) for various spec frameworks:
48
- - <s>RSpec</s>
49
- - <s>MiniTest::Spec</s>
50
- - <s>Yoda</s> <em>(Actually, Yoda appears to abuse Ruby syntax badly enough that it may not work with Cordon.)</em>
51
- - ?
52
- - <s>Add a declarative API to customize the name of the function that wraps assertions</s>
53
- - probably some other stuff I can't think of at the moment
47
+ <!-- Apparently Markdown and HTML don't mix, because "* <strike>foo</strike>" doesn't work the way I thought it should -->
48
+ <ul>
49
+ <li>
50
+ Write integration macros (and tests, obviously) for various spec frameworks:
51
+ <ul>
52
+ <li><strike>RSpec</strike></li>
53
+ <li><strike>MiniTest::Spec</strike></li>
54
+ <li><strike>Yoda</strike> <em>(Actually, Yoda appears to abuse Ruby syntax badly enough that it may not work with Cordon.)</em></li>
55
+ <li>?</li>
56
+ </ul>
57
+ </li>
58
+ <li><strike>Add a declarative API to customize the name of the function that wraps assertions</strike></li>
59
+ <li>RDoc</li>
60
+ <li>Add a "detection mode" which rescues Cordon::Violation, records the backtrace, and reports all violations in a Kernel#at_exit callback. (UPDATE: added Cordon.monitor for frameworks, and Cordon.watchlist for methods, but didn't get #at_exit working yet.)</li>
61
+ <li>MAYBE: Figure out how to raise Cordon::Violation only when in (or not in?) a certain calling context (this could be hairy), which might make #assert_that optional</li>
62
+ <li>probably some other stuff I can't think of at the moment</li>
63
+ </ul>
54
64
 
55
65
 
56
66
 
@@ -68,5 +78,4 @@ In both examples, note that Cordon's <code>.embargo</code> method must be called
68
78
 
69
79
  ## Copyright
70
80
 
71
- Copyright (c) 2012 Sam Livingston-Gray. See LICENSE.txt for
72
- further details.
81
+ Copyright (c) 2012 Sam Livingston-Gray. See LICENSE.txt for further details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cordon}
8
- s.version = "0.2.2"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = [%q{Sam Livingston-Gray}]
12
- s.date = %q{2012-03-09}
12
+ s.date = %q{2012-03-15}
13
13
  s.description = %q{A bit of an experiment, really}
14
14
  s.email = %q{geeksam@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -24,18 +24,21 @@ Gem::Specification.new do |s|
24
24
  "cordon.gemspec",
25
25
  "lib/cordon.rb",
26
26
  "lib/cordon/blacklist.rb",
27
+ "lib/cordon/method_list.rb",
27
28
  "lib/cordon/sanitaire.rb",
28
29
  "lib/cordon/violation.rb",
30
+ "lib/cordon/watchlist.rb",
29
31
  "lib/cordon/whitelist.rb",
30
32
  "test/framework_integration/minitest_spec_spec.rb",
31
33
  "test/framework_integration/rspec_spec.rb",
32
34
  "test/helper.rb",
33
35
  "test/integration/backtrace_cleaning_test.rb",
34
- "test/integration/cordon_basic_examples_test.rb",
35
- "test/integration/cordon_customization_test.rb",
36
- "test/integration/cordon_default_behavior_test.rb",
37
- "test/integration/cordon_edge_cases_test.rb",
38
- "test/integration/integration_test_helper.rb"
36
+ "test/integration/basic_examples_test.rb",
37
+ "test/integration/customization_test.rb",
38
+ "test/integration/default_behavior_test.rb",
39
+ "test/integration/edge_cases_test.rb",
40
+ "test/integration/integration_test_helper.rb",
41
+ "test/integration/watchlist_test.rb"
39
42
  ]
40
43
  s.homepage = %q{http://github.com/geeksam/cordon}
41
44
  s.licenses = [%q{WTFPL}]
@@ -26,27 +26,78 @@ end
26
26
 
27
27
 
28
28
  module Cordon
29
- # Declare specific methods as off-limits
29
+ # Shorthand for blacklisting the undesirable methods in specific frameworks
30
+ def self.embargo(framework)
31
+ wrap_framework(framework, :blacklist)
32
+ end
33
+
34
+ # Shorthand for watchlisting the undesirable methods in specific frameworks
35
+ # NOTE: while this will record incursions, you'll have to call Cordon.incursion_report
36
+ # yourself until I figure out how to make it print out at exit.
37
+ def self.monitor(framework)
38
+ wrap_framework(framework, :watchlist)
39
+ end
40
+
41
+ # Declare specific methods as off-limits so that invocations raise an exception
30
42
  def self.blacklist(subject, methods)
31
- methods.each do |method|
32
- Blacklist.blacklist_method(subject, method.to_sym)
33
- end
43
+ Blacklist.wrap_methods(subject, methods)
34
44
  end
35
45
 
36
- # Shorthand for blacklisting the undesirable methods in specific frameworks
37
- def self.embargo(framework)
46
+ # Declare specific methods as off-limits so that invocations are logged
47
+ def self.watchlist(subject, methods)
48
+ Watchlist.wrap_methods(subject, methods)
49
+ end
50
+
51
+ # Allow user-defined aliases of #assert_that
52
+ def self.wrap_assertions_with(custom_method_name)
53
+ Sanitaire.wrap_assertions_with(custom_method_name)
54
+ end
55
+
56
+ # Convenience accessor for reporting on watchlist incursions
57
+ def self.incursions
58
+ Watchlist.incursions
59
+ end
60
+
61
+ # Plain-text report of watchlist incursions
62
+ def self.incursion_report
63
+ Watchlist.incursion_report
64
+ end
65
+
66
+ # Allow custom filtering of backtraces on Cordon::Violation errors.
67
+ # Pass this a block that takes a backtrace and returns a backtrace.
68
+ # Multiple filters can be defined; all will be applied.
69
+ def self.filter_violation_backtrace(&proc)
70
+ Violation.add_custom_backtrace_filter(&proc)
71
+ end
72
+
73
+ # Reset custom filtering of backtraces.
74
+ # (This is mostly here for ease of testing.)
75
+ def self.dont_filter_violation_backtrace!
76
+ Violation.clear_custom_backtrace_filters
77
+ end
78
+
79
+ protected
80
+
81
+ def self.wrap_framework(framework, technique)
82
+ raise "Don't know how to wrap framework with #{technique.inspect}!" unless [:blacklist, :watchlist].include?(technique)
83
+
84
+ # Figure out which methods to wrap
85
+ list = []
38
86
  case framework
39
87
  when :rspec
40
- blacklist Kernel, [:should, :should_not]
88
+ list << [Kernel, [:should, :should_not]]
41
89
  when :minitest_spec
42
90
  must_and_wont = MiniTest::Expectations.instance_methods.map(&:to_s).select {|e| e =~ /^(must|wont)_/}
43
- blacklist MiniTest::Expectations, must_and_wont
91
+ list << [MiniTest::Expectations, must_and_wont]
44
92
  else
45
93
  raise "I don't know how to embargo #{framework}!"
46
94
  end
47
- end
48
95
 
49
- def self.wrap_assertions_with(custom_method_name)
50
- Sanitaire.wrap_assertions_with(custom_method_name)
96
+ # Wrap them using the appropriate technique
97
+ # (which should be either :blacklist or :watchlist)
98
+ list.each do |subject, methods|
99
+ send technique, subject, methods
100
+ end
51
101
  end
102
+
52
103
  end
@@ -1,30 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), 'method_list')
2
+
1
3
  module Cordon
2
4
  module Blacklist
3
- TheList = {}
4
-
5
- def self.blacklist_method(subject, method)
6
- return if unbound_method(subject, method) # be idempotent
7
-
8
- # Unbind the original method, and replace it with a wrapper that
9
- # checks for permission before binding and calling the original
10
- Blacklist.unbind_method(subject, method)
11
- subject.__cordon__wrap_method__(method)
12
- end
13
-
14
- def self.invoke_method(instance, subject, method, *args, &b)
15
- um = unbound_method(subject, method)
16
- um.bind(instance).call(*args, &b)
17
- end
18
-
19
- protected
20
-
21
- def self.unbind_method(subject, method)
22
- um = subject.instance_method(method) # will raise NameError if the method doesn't exist
23
- TheList[[subject, method]] = um
24
- end
25
-
26
- def self.unbound_method(subject, method)
27
- TheList[[subject, method]]
28
- end
5
+ extend MethodList
29
6
  end
30
7
  end
@@ -0,0 +1,38 @@
1
+ module Cordon
2
+ module MethodList
3
+ def includes?(subject, method)
4
+ method_list.has_key?([subject, method])
5
+ end
6
+
7
+ def wrap_methods(subject, methods)
8
+ methods.each do |method|
9
+ wrap_method(subject, method.to_sym)
10
+ end
11
+ end
12
+
13
+ def wrap_method(subject, method)
14
+ return if includes?(subject, method) # be idempotent
15
+
16
+ # Unbind the original method, and replace it with a wrapper that
17
+ # decides whether to bind and call the original
18
+ unbind_method(subject, method)
19
+ subject.__cordon__wrap_method__(method)
20
+ end
21
+
22
+ def invoke_method(instance, subject, method, *args, &b)
23
+ unbound_method = method_list[[subject, method]]
24
+ unbound_method.bind(instance).call(*args, &b)
25
+ end
26
+
27
+ protected
28
+
29
+ def unbind_method(subject, method)
30
+ unbound_method = subject.instance_method(method) # will raise NameError if the method doesn't exist
31
+ method_list[[subject, method]] = unbound_method
32
+ end
33
+
34
+ def method_list
35
+ @method_list ||= {}
36
+ end
37
+ end
38
+ end
@@ -14,8 +14,14 @@ module Cordon
14
14
  protected
15
15
 
16
16
  def __cordon__call_method__(subject, method, *args, &b)
17
- ::Cordon::Whitelist.check_permissions(self, subject, method, *args)
18
- ::Cordon::Blacklist.invoke_method(self, subject, method, *args, &b)
17
+ case
18
+ when Watchlist.includes?(subject, method)
19
+ ::Cordon::Watchlist.invoke_method(self, subject, method, *args, &b)
20
+ when Whitelist.admits?(self)
21
+ ::Cordon::Blacklist.invoke_method(self, subject, method, *args, &b)
22
+ else
23
+ raise ::Cordon::Violation.from_invocation(subject, method, args)
24
+ end
19
25
  end
20
26
  end
21
27
  end
@@ -1,9 +1,37 @@
1
1
  module Cordon
2
2
  class Violation < Exception
3
+ SelfRegex = /\/lib\/cordon.*\.rb\:\d+\:in/
4
+ CustomFilterProcs = []
5
+
6
+ def self.add_custom_backtrace_filter(&proc)
7
+ CustomFilterProcs << proc
8
+ end
9
+
10
+ def self.clear_custom_backtrace_filters
11
+ CustomFilterProcs.clear
12
+ end
13
+
14
+ def self.from_invocation(subject, method, args)
15
+ method_descriptor = '%s#%s' % [subject, method]
16
+ message = '%s(%s)' % [method_descriptor, args.map(&:inspect).join(', ')]
17
+ new(message).tap { |e| e.method_descriptor = method_descriptor }
18
+ end
19
+
20
+ attr_accessor :method_descriptor
21
+
3
22
  def backtrace
4
23
  bt = super
5
- bt.shift while bt && bt.first =~ /cordon\.rb\:\d+\:in/
6
- bt
24
+ return if bt.nil?
25
+
26
+ # Take anything in 'lib/cordon*.rb' off of the *top* of the backtrace so users don't get distracted by it
27
+ bt.shift while bt.first =~ SelfRegex
28
+
29
+ # Apply any other custom filters to the backtrace before returning it
30
+ CustomFilterProcs.each do |filter|
31
+ bt = filter.call(bt)
32
+ end
33
+
34
+ return bt
7
35
  end
8
36
  end
9
37
  end
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), 'method_list')
2
+
3
+ module Cordon
4
+ module Watchlist
5
+ extend MethodList
6
+
7
+ class << self
8
+ def invoke_method(instance, subject, method, *args, &b)
9
+ record_incursion(subject, method, args)
10
+ super
11
+ end
12
+
13
+ def incursions
14
+ @incursions ||= []
15
+ end
16
+
17
+ def incursion_report
18
+ report = <<-EOF.strip
19
+ =======================
20
+ Cordon Incursion Report
21
+ =======================
22
+ EOF
23
+ n = incursions.length
24
+ max_width = n.to_s.length
25
+
26
+ incursions_by_method = Hash.new { |hash, key| hash[key] = [] }
27
+ incursions.each do |incursion|
28
+ incursions_by_method[incursion.method_descriptor] << incursion
29
+ end
30
+
31
+ incursions_by_method.to_a.sort.each do |method_descriptor, incursions|
32
+ report << "\n\n#{method_descriptor}\n#{'-' * method_descriptor.length}"
33
+ incursions.each do |incursion|
34
+ report << "\n" + incursion.backtrace.first.to_s
35
+ end
36
+ end
37
+ report << "\n"
38
+ report
39
+ end
40
+
41
+ protected
42
+
43
+ def record_incursion(subject, method, args)
44
+ raise Cordon::Violation.from_invocation(subject, method, args)
45
+ rescue Cordon::Violation => e
46
+ incursions << e
47
+ end
48
+ end
49
+ end
50
+ end
@@ -6,11 +6,8 @@ module Cordon
6
6
  TheList << object
7
7
  end
8
8
 
9
- def self.check_permissions(instance, subject, method, *args)
10
- allowed = !! TheList.delete(instance)
11
- return if allowed
12
- message = '%s#%s(%s)' % [subject, method, args.map(&:inspect).join(', ')]
13
- raise ::Cordon::Violation, message
9
+ def self.admits?(instance)
10
+ !! TheList.delete(instance)
14
11
  end
15
12
  end
16
13
  end
@@ -17,4 +17,20 @@ class BacktraceCleaningUnitTest < CordonUnitTest
17
17
  failure_message << (e.backtrace[0..3] + ['(rest of backtrace omitted)']).map { |e| ' ' + e }.join("\n")
18
18
  refute e.backtrace.first.include?('cordon.rb:'), failure_message
19
19
  end
20
+
21
+ def test_custom_cleaning
22
+ Cordon.filter_violation_backtrace { |backtrace|
23
+ project_root = File.expand_path(File.join(File.dirname(__FILE__), *%w[.. ..]))
24
+ in_project = Regexp.new(project_root)
25
+ backtrace.select { |line| line =~ in_project }
26
+ }
27
+
28
+ foo.verboten_method_for_backtrace
29
+
30
+ rescue Cordon::Violation => e
31
+ refute e.backtrace.any? { |line| line =~ /\/unit\.rb:/ }, "Custom backtrace filter did not work"
32
+
33
+ ensure
34
+ Cordon.dont_filter_violation_backtrace!
35
+ end
20
36
  end
@@ -0,0 +1,103 @@
1
+ require File.join(File.dirname(__FILE__), 'integration_test_helper')
2
+
3
+ $shady_method_call_count = 0
4
+ module Kernel
5
+ def shady_method
6
+ # we are a hedge. move along.
7
+ $shady_method_call_count += 1
8
+ end
9
+
10
+ def dubious_method
11
+ # nothing to see here either
12
+ end
13
+ end
14
+
15
+ # In addition to blacklisting methods, Cordon can also place them on a watchlist.
16
+ # This will track invocations for later reporting.
17
+ # (It's not nearly as glamorous as the Bond movies would have you believe.)
18
+ Cordon.watchlist Kernel, [:shady_method, :dubious_method]
19
+
20
+ class WatchlistTest < CordonUnitTest
21
+ def method_one
22
+ shady_method; @method_one_line = __LINE__
23
+ end
24
+ def method_two
25
+ shady_method; @method_two_line = __LINE__
26
+ end
27
+ def method_three
28
+ dubious_method; @method_three_line = __LINE__
29
+ end
30
+
31
+ def setup
32
+ $shady_method_call_count = 0
33
+ Cordon.filter_violation_backtrace do |backtrace|
34
+ current_file = File.expand_path(__FILE__)
35
+ in_file = Regexp.new(current_file)
36
+ backtrace.select { |line| line =~ in_file }
37
+ end
38
+ end
39
+
40
+ def teardown
41
+ Cordon.dont_filter_violation_backtrace!
42
+ Cordon.incursions.clear
43
+ end
44
+
45
+ def test_shady_calls_are_allowed
46
+ method_one; assert_equal 1, $shady_method_call_count
47
+ method_one; assert_equal 2, $shady_method_call_count
48
+ method_two; assert_equal 3, $shady_method_call_count
49
+ end
50
+
51
+ def test_shady_calls_are_counted
52
+ assert Cordon.incursions.empty?
53
+
54
+ method_one; assert_equal 1, Cordon.incursions.length
55
+ method_one; assert_equal 2, Cordon.incursions.length
56
+ method_two; assert_equal 3, Cordon.incursions.length
57
+ end
58
+
59
+ def test_shady_calls_are_logged
60
+ assert Cordon.incursions.empty?
61
+
62
+ method_one; invocation_1_line = __LINE__
63
+ method_one; invocation_2_line = __LINE__
64
+ method_two; invocation_3_line = __LINE__
65
+
66
+ i1, i2, i3 = *Cordon.incursions
67
+
68
+ # Quick sanity check: make sure we're only looking at backtraces in the current file (see #setup)
69
+ assert i1.backtrace.length == 2
70
+ assert i2.backtrace.length == 2
71
+ assert i3.backtrace.length == 2
72
+
73
+ # NOTE: using assert_match prints a weird MiniTest error
74
+
75
+ # First line should be the actual invocation of #shady_method
76
+ assert i1.backtrace[0] =~ /watchlist_test.rb:#{@method_one_line}:in `method_one'$/, i1.backtrace[0]
77
+ assert i2.backtrace[0] =~ /watchlist_test.rb:#{@method_one_line}:in `method_one'$/, i2.backtrace[0]
78
+ assert i3.backtrace[0] =~ /watchlist_test.rb:#{@method_two_line}:in `method_two'$/, i3.backtrace[0]
79
+
80
+ # Second line should be the place where method_(one|two) was called
81
+ assert i1.backtrace[1] =~ /watchlist_test.rb:#{invocation_1_line}:in `test_shady_calls_are_logged'$/, i1.backtrace[1]
82
+ assert i2.backtrace[1] =~ /watchlist_test.rb:#{invocation_2_line}:in `test_shady_calls_are_logged'$/, i2.backtrace[1]
83
+ assert i3.backtrace[1] =~ /watchlist_test.rb:#{invocation_3_line}:in `test_shady_calls_are_logged'$/, i3.backtrace[1]
84
+ end
85
+
86
+ def test_incursion_report
87
+ method_one
88
+ method_two
89
+ method_one
90
+ method_two
91
+ method_three
92
+
93
+ report = Cordon.incursion_report
94
+
95
+ assert report =~ /Kernel#shady_method/
96
+ assert report =~ /Kernel#dubious_method/
97
+
98
+ assert report =~ /watchlist_test.rb:#{@method_one_line}:in `method_one'$/
99
+ assert report =~ /watchlist_test.rb:#{@method_one_line}:in `method_one'$/
100
+ assert report =~ /watchlist_test.rb:#{@method_two_line}:in `method_two'$/
101
+ assert report =~ /watchlist_test.rb:#{@method_three_line}:in `method_three'$/
102
+ end
103
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cordon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-09 00:00:00.000000000Z
12
+ date: 2012-03-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rdoc
16
- requirement: &2156968780 !ruby/object:Gem::Requirement
16
+ requirement: &2155010720 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.12'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2156968780
24
+ version_requirements: *2155010720
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &2156967060 !ruby/object:Gem::Requirement
27
+ requirement: &2155010220 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2156967060
35
+ version_requirements: *2155010220
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &2156964940 !ruby/object:Gem::Requirement
38
+ requirement: &2155009740 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.8.3
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2156964940
46
+ version_requirements: *2155009740
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: mocha
49
- requirement: &2156962400 !ruby/object:Gem::Requirement
49
+ requirement: &2155009240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.10.3
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2156962400
57
+ version_requirements: *2155009240
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: ruby-debug19
60
- requirement: &2156960720 !ruby/object:Gem::Requirement
60
+ requirement: &2155008740 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2156960720
68
+ version_requirements: *2155008740
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &2156958500 !ruby/object:Gem::Requirement
71
+ requirement: &2155008260 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2156958500
79
+ version_requirements: *2155008260
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: minitest
82
- requirement: &2156956460 !ruby/object:Gem::Requirement
82
+ requirement: &2155007680 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2156956460
90
+ version_requirements: *2155007680
91
91
  description: A bit of an experiment, really
92
92
  email: geeksam@gmail.com
93
93
  executables: []
@@ -103,18 +103,21 @@ files:
103
103
  - cordon.gemspec
104
104
  - lib/cordon.rb
105
105
  - lib/cordon/blacklist.rb
106
+ - lib/cordon/method_list.rb
106
107
  - lib/cordon/sanitaire.rb
107
108
  - lib/cordon/violation.rb
109
+ - lib/cordon/watchlist.rb
108
110
  - lib/cordon/whitelist.rb
109
111
  - test/framework_integration/minitest_spec_spec.rb
110
112
  - test/framework_integration/rspec_spec.rb
111
113
  - test/helper.rb
112
114
  - test/integration/backtrace_cleaning_test.rb
113
- - test/integration/cordon_basic_examples_test.rb
114
- - test/integration/cordon_customization_test.rb
115
- - test/integration/cordon_default_behavior_test.rb
116
- - test/integration/cordon_edge_cases_test.rb
115
+ - test/integration/basic_examples_test.rb
116
+ - test/integration/customization_test.rb
117
+ - test/integration/default_behavior_test.rb
118
+ - test/integration/edge_cases_test.rb
117
119
  - test/integration/integration_test_helper.rb
120
+ - test/integration/watchlist_test.rb
118
121
  homepage: http://github.com/geeksam/cordon
119
122
  licenses:
120
123
  - WTFPL
@@ -130,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
133
  version: '0'
131
134
  segments:
132
135
  - 0
133
- hash: 2252535489042103113
136
+ hash: 3052646131815485488
134
137
  required_rubygems_version: !ruby/object:Gem::Requirement
135
138
  none: false
136
139
  requirements: