deprecatable 1.0.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.
- data/.autotest +9 -0
- data/.gemtest +1 -0
- data/HISTORY.rdoc +4 -0
- data/Manifest.txt +26 -0
- data/README.rdoc +175 -0
- data/Rakefile +33 -0
- data/examples/alert_frequency.rb +101 -0
- data/examples/at_exit.rb +68 -0
- data/examples/caller_context_padding.rb +97 -0
- data/lib/deprecatable.rb +106 -0
- data/lib/deprecatable/alerter.rb +162 -0
- data/lib/deprecatable/call_site.rb +91 -0
- data/lib/deprecatable/call_site_context.rb +112 -0
- data/lib/deprecatable/deprecated_method.rb +210 -0
- data/lib/deprecatable/options.rb +138 -0
- data/lib/deprecatable/registry.rb +55 -0
- data/lib/deprecatable/util.rb +26 -0
- data/test/helpers.rb +18 -0
- data/test/test_deprecatable.rb +149 -0
- data/test/test_deprecatable_alerter.rb +41 -0
- data/test/test_deprecatable_call_site.rb +28 -0
- data/test/test_deprecatable_call_site_context.rb +57 -0
- data/test/test_deprecatable_deprecated_method.rb +61 -0
- data/test/test_deprecatable_options.rb +83 -0
- data/test/test_deprecatable_registry.rb +32 -0
- data/test/test_deprecatable_util.rb +13 -0
- metadata +146 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
require "helpers"
|
2
|
+
|
3
|
+
class TestDeprecatable < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Deprecatable.registry.clear
|
7
|
+
Deprecatable.options.reset
|
8
|
+
|
9
|
+
@deprecated_class = Class.new do
|
10
|
+
extend Deprecatable
|
11
|
+
def self.name
|
12
|
+
"TestDeprecatable::DeprecateMe"
|
13
|
+
end
|
14
|
+
def deprecate_me; end
|
15
|
+
deprecate :deprecate_me
|
16
|
+
end
|
17
|
+
|
18
|
+
@deprecatable_class = Class.new do
|
19
|
+
extend Deprecatable
|
20
|
+
def self.name
|
21
|
+
"TestDeprecatable::DeprecatableClass"
|
22
|
+
end
|
23
|
+
def deprecate_me; end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_deprecated_method_is_regsitered
|
28
|
+
assert_equal( 1, Deprecatable.registry.size )
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_call_site_is_recorded
|
32
|
+
i = @deprecated_class.new
|
33
|
+
capture_io do
|
34
|
+
i.deprecate_me
|
35
|
+
end
|
36
|
+
assert_equal( 1, Deprecatable.registry.items.first.invocation_count )
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_different_call_sites_are_recorded_independently
|
40
|
+
i = @deprecated_class.new
|
41
|
+
capture_io do
|
42
|
+
42.times { i.deprecate_me }
|
43
|
+
24.times { i.deprecate_me }
|
44
|
+
end
|
45
|
+
dm = Deprecatable.registry.items.first
|
46
|
+
assert_equal( 66, dm.invocation_count )
|
47
|
+
assert_equal( 2, dm.call_site_count )
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_alerts_are_issued_only_once_for_a_callsite
|
51
|
+
i = @deprecated_class.new
|
52
|
+
callable = lambda { |c| c.deprecate_me }
|
53
|
+
stdout, stderr = capture_io do
|
54
|
+
callable.call( i )
|
55
|
+
end
|
56
|
+
line = __LINE__ - 4
|
57
|
+
|
58
|
+
assert_match( /#{File.expand_path( __FILE__ )}:#{line}/m, stderr )
|
59
|
+
assert_match( /---> #{line}:\s+callable = lambda \{ |c| c\.deprecate_me \}/, stderr )
|
60
|
+
|
61
|
+
assert_silent do
|
62
|
+
callable.call( i )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_alerts_are_issued_never_for_a_callsite
|
67
|
+
::Deprecatable.options.alert_frequency = :never
|
68
|
+
i = @deprecated_class.new
|
69
|
+
assert_silent do
|
70
|
+
i.deprecate_me
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_alerts_are_issued_for_every_call_to_a_callsite
|
75
|
+
::Deprecatable.options.alert_frequency = :always
|
76
|
+
i = @deprecated_class.new
|
77
|
+
stdout, stderr = capture_io do
|
78
|
+
42.times { i.deprecate_me }
|
79
|
+
end
|
80
|
+
line = __LINE__ - 2
|
81
|
+
lines = stderr.split(/\n/)
|
82
|
+
assert_equal( 42, lines.grep( /#{File.expand_path( __FILE__)}:#{line}/ ).size )
|
83
|
+
assert_equal( 42, lines.grep( /--->/ ).size )
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_raise_an_exception_if_deprecating_a_method_that_does_not_exist
|
87
|
+
assert_raises( NameError ) do
|
88
|
+
@deprecatable_class.deprecate :wibble
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def assert_alert_match( regex, klass, &block )
|
93
|
+
stdout, stderr = capture_io do
|
94
|
+
i = klass.new
|
95
|
+
i.deprecate_me
|
96
|
+
end
|
97
|
+
assert_match( regex, stderr )
|
98
|
+
return stderr
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_adds_an_additional_message_when_given
|
102
|
+
@deprecatable_class.deprecate :deprecate_me, :message => "You should switch to using Something#bar"
|
103
|
+
assert_alert_match( /\* You should switch to using Something#bar/m, @deprecatable_class )
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_adds_a_removal_date_when_given
|
107
|
+
@deprecatable_class.deprecate :deprecate_me, :removal_date => "2011-09-02"
|
108
|
+
assert_alert_match( /Will be removed after 2011-09-02/m, @deprecatable_class )
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_adds_a_removal_version_when_given
|
112
|
+
@deprecatable_class.deprecate :deprecate_me, :removal_version => "4.2"
|
113
|
+
assert_alert_match( /Will be removed in version 4.2/m, @deprecatable_class )
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_deprecating_an_included_method
|
117
|
+
mod = Module.new do
|
118
|
+
extend Deprecatable
|
119
|
+
def deprecate_me; end
|
120
|
+
deprecate :deprecate_me, :message => "KABOOM!"
|
121
|
+
end
|
122
|
+
klass = Class.new do
|
123
|
+
include mod
|
124
|
+
end
|
125
|
+
|
126
|
+
assert_alert_match( /KABOOM!/, klass )
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_deprecating_a_class_method
|
130
|
+
klass = Class.new do
|
131
|
+
class << self
|
132
|
+
extend Deprecatable
|
133
|
+
def deprecate_me; end
|
134
|
+
deprecate :deprecate_me, :message => "Class Method KABOOM!"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
stdout, stderr = capture_io do
|
139
|
+
klass.deprecate_me
|
140
|
+
end
|
141
|
+
assert_match( /Class Method KABOOM/, stderr )
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_has_an_at_exit_handler
|
145
|
+
io = IO.popen( "ruby -Ilib examples/at_exit.rb 2>&1" )
|
146
|
+
lines = io.readlines.join('')
|
147
|
+
assert_match( /Deprecatable 'at_exit' Report/m, lines )
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
class TestDeprecatableAlerter < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Deprecatable.registry.clear
|
6
|
+
Deprecatable.options.reset
|
7
|
+
|
8
|
+
@old_alerter = Deprecatable.alerter
|
9
|
+
@alerter = ::Deprecatable::StringIOAlerter.new
|
10
|
+
Deprecatable.alerter = @alerter
|
11
|
+
|
12
|
+
@deprecated_class = Class.new do
|
13
|
+
extend Deprecatable
|
14
|
+
def self.name
|
15
|
+
"TestDeprecatable::DeprecateMe"
|
16
|
+
end
|
17
|
+
def deprecate_me; end
|
18
|
+
deprecate :deprecate_me
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
Deprecatable.alerter = @old_alerter
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_alert
|
27
|
+
i = @deprecated_class.new
|
28
|
+
i.deprecate_me
|
29
|
+
|
30
|
+
assert_match( /---> #{__LINE__ - 2}:/, Deprecatable.alerter.to_s )
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_final_report
|
34
|
+
i = @deprecated_class.new
|
35
|
+
12.times { i.deprecate_me }
|
36
|
+
10.times { i.deprecate_me }
|
37
|
+
Deprecatable.alerter.final_report
|
38
|
+
assert_match( /Called 12 time/, Deprecatable.alerter.to_s )
|
39
|
+
assert_match( /Called 10 time/, Deprecatable.alerter.to_s )
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
# This file requires exact position of lines. If you should happent to chagen
|
3
|
+
# tne numer of lines in this file that appear before the first test, some of the
|
4
|
+
# tests will fail
|
5
|
+
class TestDeprecatableCallSite < MiniTest::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@file = __FILE__
|
8
|
+
@before = 'This is the line before'
|
9
|
+
@line = __LINE__
|
10
|
+
@after = 'This is the line after'
|
11
|
+
@call_site = ::Deprecatable::CallSite.new( @file, @line, 1 )
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_initializes_with_a_filename_and_line_number
|
15
|
+
assert_equal( File.expand_path( @file ), @call_site.file )
|
16
|
+
assert_equal( @line, @call_site.line_number )
|
17
|
+
assert_equal( 1, @call_site.context_padding )
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_captures_the_call_site_context
|
21
|
+
context = [
|
22
|
+
" 8: @before = 'This is the line before'\n",
|
23
|
+
"---> 9: @line = __LINE__\n",
|
24
|
+
" 10: @after = 'This is the line after'\n",
|
25
|
+
]
|
26
|
+
assert_array_equal( context, @call_site.formatted_context_lines )
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Context line 1
|
2
|
+
# Context line 2
|
3
|
+
# Context line 3
|
4
|
+
# Context line 4
|
5
|
+
|
6
|
+
|
7
|
+
require 'helpers'
|
8
|
+
|
9
|
+
# Context line 9
|
10
|
+
# Context line 10
|
11
|
+
# Context line 11
|
12
|
+
# Context line 12
|
13
|
+
# Context line 13
|
14
|
+
|
15
|
+
class TestDeprecatableCallSiteContext < MiniTest::Unit::TestCase
|
16
|
+
def setup
|
17
|
+
@ctx = Deprecatable::CallSiteContext.new( File.expand_path(__FILE__), 11, 2 )
|
18
|
+
end
|
19
|
+
|
20
|
+
def context_lines_for( range, arrow_line )
|
21
|
+
width = ("%d" % range.to_a.last).length
|
22
|
+
range.map do |x|
|
23
|
+
prefix = ( x == arrow_line ) ? "--->" : " "
|
24
|
+
"#{prefix} #{("%d" % x).rjust( width )}: # Context line #{x}\n"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_gets_the_context_from_the_middle_of_a_file
|
29
|
+
context_lines = (9..13).map { |x| "# Context line #{x}\n" }
|
30
|
+
assert_array_equal( context_lines, @ctx.context_lines )
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_properly_formats_the_context_from_the_middle_of_the_file
|
34
|
+
formatted_lines = [ ]
|
35
|
+
formatted_lines += context_lines_for( (9..13), 11 )
|
36
|
+
assert_array_equal( formatted_lines, @ctx.formatted_context_lines )
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_properly_formats_the_context_at_the_beginning_of_the_file
|
40
|
+
ctx = Deprecatable::CallSiteContext.new( File.expand_path(__FILE__), 2, 2 )
|
41
|
+
formatted_lines = [ ]
|
42
|
+
formatted_lines += context_lines_for( (1..4), 2 )
|
43
|
+
assert_array_equal( formatted_lines, ctx.formatted_context_lines )
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_properly_formats_the_context_at_the_end_of_the_file
|
47
|
+
ctx = Deprecatable::CallSiteContext.new( File.expand_path(__FILE__), 56, 2 )
|
48
|
+
formatted_lines = [ ]
|
49
|
+
formatted_lines += context_lines_for( (54..57), 56)
|
50
|
+
assert_array_equal( formatted_lines, ctx.formatted_context_lines )
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Context line 54
|
55
|
+
# Context line 55
|
56
|
+
# Context line 56
|
57
|
+
# Context line 57
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
class TestDeprecatableDeprecatedMethod < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@klass = Class.new do
|
6
|
+
def self.name
|
7
|
+
"TestDeprecatableDeprecatedMethod::DeprecatableClass"
|
8
|
+
end
|
9
|
+
def m1
|
10
|
+
"m1"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
@module = Module.new do
|
15
|
+
def self.name
|
16
|
+
"TestDeprecatableDeprecatedMethod::DeprecatableModule"
|
17
|
+
end
|
18
|
+
def m2; "m2"; end
|
19
|
+
end
|
20
|
+
|
21
|
+
@dep_class = Deprecatable::DeprecatedMethod.new( @klass, "m1", __FILE__, 7 )
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_records_meta_information_about_the_deprecation
|
25
|
+
assert_equal( @klass , @dep_class.klass )
|
26
|
+
assert_equal( "m1" , @dep_class.method )
|
27
|
+
assert_equal( File.expand_path( __FILE__ ) , @dep_class.file )
|
28
|
+
assert_equal( 7 , @dep_class.line_number )
|
29
|
+
assert_equal( "_deprecated_m1" , @dep_class.deprecated_method_name )
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_records_an_invocation_of_an_instance_method
|
33
|
+
dc = @klass.new
|
34
|
+
m = nil
|
35
|
+
capture_io do
|
36
|
+
m = dc.m1
|
37
|
+
end
|
38
|
+
assert_equal( "m1", m )
|
39
|
+
assert_equal( 1, @dep_class.invocation_count )
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_records_uniq_call_sites
|
43
|
+
dc = @klass.new
|
44
|
+
capture_io do
|
45
|
+
3.times { dc.m1 }
|
46
|
+
3.times { dc.m1 }
|
47
|
+
end
|
48
|
+
assert_equal( 6, @dep_class.invocation_count )
|
49
|
+
assert_equal( 2, @dep_class.call_site_count )
|
50
|
+
assert_equal( 2, @dep_class.call_sites.size )
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_has_a_string_representation_of_a_deprecated_instance_method
|
54
|
+
assert_equal( "TestDeprecatableDeprecatedMethod::DeprecatableClass#m1 defined at #{File.expand_path(__FILE__)}:7", @dep_class.to_s )
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_has_a_string_representation_of_a_deprecated_module_method
|
58
|
+
dm = Deprecatable::DeprecatedMethod.new( @module, "m2", __FILE__, 11 )
|
59
|
+
assert_equal( "TestDeprecatableDeprecatedMethod::DeprecatableModule.m2 defined at #{File.expand_path(__FILE__)}:11", dm.to_s )
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require "helpers"
|
2
|
+
|
3
|
+
class TestDeprecatableOptions < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@options = Deprecatable::Options.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
ENV.keys.each do |k|
|
11
|
+
next unless k =~/^DEPRECATABLE/
|
12
|
+
ENV.delete( k )
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_defaults_exist
|
17
|
+
assert_equal( 2 , @options.caller_context_padding )
|
18
|
+
assert_equal( true , @options.has_at_exit_report? )
|
19
|
+
assert_equal( 1 , @options.alert_frequency )
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_caller_context_padding_raises_error_if_set_to_negative_number
|
23
|
+
assert_raises( ArgumentError, "caller_context_mapping must be > 0" ) do
|
24
|
+
@options.caller_context_padding = -1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_caller_context_padding_raises_error_if_environemtn_set_to_negative_number
|
29
|
+
ENV['DEPRECATABLE_CALLER_CONTEXT_PADDING'] = "-1"
|
30
|
+
assert_raises( ArgumentError, "caller_context_mapping must be > 0" ) do
|
31
|
+
@options.caller_context_padding
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_caller_context_padding_may_be_set
|
36
|
+
@options.caller_context_padding = 4
|
37
|
+
assert_equal( 4, @options.caller_context_padding )
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_caller_context_padding_may_be_overridden_by_environment_variable
|
41
|
+
assert_equal( 2, @options.caller_context_padding )
|
42
|
+
@options.caller_context_padding = 4
|
43
|
+
assert_equal( 4, @options.caller_context_padding )
|
44
|
+
ENV['DEPRECATABLE_CALLER_CONTEXT_PADDING'] = "10"
|
45
|
+
assert_equal( 10, @options.caller_context_padding )
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_has_at_exit_report_may_be_turned_off
|
49
|
+
@options.has_at_exit_report = false
|
50
|
+
refute @options.has_at_exit_report?, "has_at_exit_report? must be false"
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_has_at_exit_report_may_be_overridden_by_environment_variable
|
54
|
+
@options.has_at_exit_report = false
|
55
|
+
refute @options.has_at_exit_report?
|
56
|
+
ENV['DEPRECATABLE_HAS_AT_EXIT_REPORT'] = "true"
|
57
|
+
assert @options.has_at_exit_report?, "has_at_exit_report? must be true"
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_alert_frequency_may_be_set
|
61
|
+
@options.alert_frequency = :once
|
62
|
+
assert_equal( 1, @options.alert_frequency )
|
63
|
+
|
64
|
+
@options.alert_frequency = :never
|
65
|
+
assert_equal( 0, @options.alert_frequency )
|
66
|
+
|
67
|
+
@options.alert_frequency = :always
|
68
|
+
assert_equal( "Infinity", @options.alert_frequency.to_s )
|
69
|
+
assert @options.alert_frequency.infinite?
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_alert_frequency_may_be_overridden_by_environment_variable
|
73
|
+
ENV['DEPRECATABLE_ALERT_FREQUENCY'] = "42"
|
74
|
+
assert_equal( 42, @options.alert_frequency)
|
75
|
+
ENV['DEPRECATABLE_ALERT_FREQUENCY'] = "once"
|
76
|
+
assert_equal( 1, @options.alert_frequency)
|
77
|
+
ENV['DEPRECATABLE_ALERT_FREQUENCY'] = "never"
|
78
|
+
assert_equal( 0, @options.alert_frequency)
|
79
|
+
ENV['DEPRECATABLE_ALERT_FREQUENCY'] = "always"
|
80
|
+
assert @options.alert_frequency.infinite?
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'helpers'
|
2
|
+
|
3
|
+
class TestDeprecatableRegistry < MiniTest::Unit::TestCase
|
4
|
+
class DeprecatedExample
|
5
|
+
def boom; end
|
6
|
+
end
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@registry = Deprecatable::Registry.new
|
10
|
+
@dm = Deprecatable::DeprecatedMethod.new( TestDeprecatableRegistry::DeprecatedExample, "boom", __FILE__, 6 )
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_registers_a_deprecated_method
|
14
|
+
assert_equal( 0, @registry.size )
|
15
|
+
@registry.register( @dm )
|
16
|
+
assert_equal( 1, @registry.size )
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_that_a_given_method_may_only_be_registered_once
|
20
|
+
assert_equal( 0, @registry.size )
|
21
|
+
@registry.register( @dm )
|
22
|
+
assert_equal( 1, @registry.size )
|
23
|
+
@registry.register( @dm )
|
24
|
+
assert_equal( 1, @registry.size )
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_returns_all_the_items_in_the_registry
|
28
|
+
@registry.register( @dm )
|
29
|
+
assert_equal( 1, @registry.items.size )
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|