deprecatable 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|