private_please 0.0.2 → 0.0.3

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 (39) hide show
  1. data/.ruby-version +1 -0
  2. data/CHANGELOG +6 -0
  3. data/README.md +51 -7
  4. data/TODO +11 -13
  5. data/lib/private_please/candidate.rb +41 -0
  6. data/lib/private_please/report/reporter.rb +52 -0
  7. data/lib/private_please/report/templates/simple.txt.erb +61 -0
  8. data/lib/private_please/ruby_backports.rb +22 -0
  9. data/lib/private_please/storage/calls_store.rb +41 -0
  10. data/lib/private_please/storage/candidates_store.rb +48 -0
  11. data/lib/private_please/storage/methods_names.rb +9 -0
  12. data/lib/private_please/storage/methods_names_bucket.rb +69 -0
  13. data/lib/private_please/tracking/extension.rb +19 -0
  14. data/lib/private_please/tracking/instrumentor.rb +71 -0
  15. data/lib/private_please/tracking/instruments_all_below.rb +41 -0
  16. data/lib/private_please/tracking/line_change_tracker.rb +36 -0
  17. data/lib/private_please/version.rb +1 -1
  18. data/lib/private_please.rb +33 -50
  19. data/private_please.gemspec +1 -0
  20. data/sample.rb +68 -0
  21. data/spec/01_marking_candidate_methods_to_observe_spec.rb +153 -0
  22. data/spec/02_logging_calls_on_candidate_methods_spec.rb +39 -0
  23. data/spec/04_instrumented_program_activity_observation_result_spec.rb +89 -0
  24. data/spec/fixtures/sample_class_for_report.rb +54 -0
  25. data/spec/fixtures/sample_class_with_all_calls_combinations.rb +69 -0
  26. data/spec/spec_helper.rb +52 -1
  27. data/spec/units/calls_store_spec.rb +15 -0
  28. data/spec/units/candidates_store_spec.rb +55 -0
  29. metadata +58 -28
  30. data/lib/private_please/candidates.rb +0 -37
  31. data/lib/private_please/configuration.rb +0 -21
  32. data/lib/private_please/line_change_tracker.rb +0 -19
  33. data/lib/private_please/recorder.rb +0 -34
  34. data/lib/private_please/report/template.txt.erb +0 -15
  35. data/lib/private_please/report.rb +0 -47
  36. data/spec/01_marking_methods_spec.rb +0 -30
  37. data/spec/02_calling_methods_spec.rb +0 -58
  38. data/spec/03_configuration_spec.rb +0 -52
  39. data/spec/04_at_exit_report_printing_spec.rb +0 -47
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe PrivatePlease::Storage::CandidatesStore do
5
+
6
+ let(:candidates_store) { PrivatePlease::Storage::CandidatesStore.new }
7
+
8
+ # instance methods
9
+ let(:object_to_s) {PrivatePlease::Candidate.for_instance_method(Object, 'to_s' )}
10
+ let(:object_hash) {PrivatePlease::Candidate.for_instance_method(Object, 'hash' )}
11
+ # class methods
12
+ let(:object_new ) {PrivatePlease::Candidate.for_class_method(Object, 'new' )}
13
+
14
+ context 'when fresh' do
15
+ it 'is empty (has no candidates)' do
16
+ candidates_store .should be_empty
17
+ candidates_store.instance_methods.should be_empty
18
+ candidates_store.class_methods .should be_empty
19
+ end
20
+ end
21
+
22
+ example 'storing the 1st instance method candidate stores it so that it can be retrieved' do
23
+ candidates_store.store(object_to_s)
24
+
25
+ candidates_store.stored?(object_to_s).should be_true
26
+ candidates_store.instance_methods.should == {'Object' => mnames_for('to_s')}
27
+ candidates_store.class_methods .should be_empty
28
+ end
29
+
30
+ example 'storing the 1st class method candidate stores it so that it can be retrieved' do
31
+ candidates_store.store(object_new)
32
+
33
+ candidates_store.stored?(object_new).should be_true
34
+ candidates_store.instance_methods.should be_empty
35
+ candidates_store.class_methods .should == {'Object' => mnames_for('new')}
36
+ end
37
+
38
+ example 'storing the 2nd instance method candidate stores it so that it can be retrieved' do
39
+ candidates_store.store(object_to_s)
40
+ candidates_store.store(object_hash)
41
+
42
+ candidates_store.stored?(object_hash).should be_true
43
+ candidates_store.instance_methods.should == {'Object' => mnames_for(%w(hash to_s))}
44
+ candidates_store.class_methods .should be_empty
45
+ end
46
+
47
+ example 'storing avoids duplication' do
48
+ candidates_store.store(object_to_s)
49
+ candidates_store.store(object_to_s) # duplication : ignore it
50
+
51
+ candidates_store.instance_methods.should == {'Object' => mnames_for(%w(to_s))}
52
+ candidates_store.class_methods .should be_empty
53
+ end
54
+
55
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: private_please
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alain Ravet
@@ -15,10 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-07-23 00:00:00 Z
18
+ date: 2013-04-28 00:00:00 +02:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ requirement: &id001 !ruby/object:Gem::Requirement
22
23
  none: false
23
24
  requirements:
24
25
  - - ">="
@@ -27,12 +28,12 @@ dependencies:
27
28
  segments:
28
29
  - 0
29
30
  version: "0"
30
- prerelease: false
31
31
  type: :development
32
32
  name: rake
33
- requirement: *id001
33
+ version_requirements: *id001
34
+ prerelease: false
34
35
  - !ruby/object:Gem::Dependency
35
- version_requirements: &id002 !ruby/object:Gem::Requirement
36
+ requirement: &id002 !ruby/object:Gem::Requirement
36
37
  none: false
37
38
  requirements:
38
39
  - - ">="
@@ -41,12 +42,12 @@ dependencies:
41
42
  segments:
42
43
  - 0
43
44
  version: "0"
44
- prerelease: false
45
45
  type: :development
46
46
  name: rspec
47
- requirement: *id002
47
+ version_requirements: *id002
48
+ prerelease: false
48
49
  - !ruby/object:Gem::Dependency
49
- version_requirements: &id003 !ruby/object:Gem::Requirement
50
+ requirement: &id003 !ruby/object:Gem::Requirement
50
51
  none: false
51
52
  requirements:
52
53
  - - ">="
@@ -55,10 +56,24 @@ dependencies:
55
56
  segments:
56
57
  - 0
57
58
  version: "0"
58
- prerelease: false
59
59
  type: :development
60
60
  name: guard-rspec
61
- requirement: *id003
61
+ version_requirements: *id003
62
+ prerelease: false
63
+ - !ruby/object:Gem::Dependency
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ name: rb-fsevent
75
+ version_requirements: *id004
76
+ prerelease: false
62
77
  description: Test if methods can be made private
63
78
  email:
64
79
  - alainravet@gmail.com
@@ -71,6 +86,7 @@ extra_rdoc_files: []
71
86
  files:
72
87
  - .gitignore
73
88
  - .rspec
89
+ - .ruby-version
74
90
  - CHANGELOG
75
91
  - Gemfile
76
92
  - Guardfile
@@ -79,19 +95,30 @@ files:
79
95
  - Rakefile
80
96
  - TODO
81
97
  - lib/private_please.rb
82
- - lib/private_please/candidates.rb
83
- - lib/private_please/configuration.rb
84
- - lib/private_please/line_change_tracker.rb
85
- - lib/private_please/recorder.rb
86
- - lib/private_please/report.rb
87
- - lib/private_please/report/template.txt.erb
98
+ - lib/private_please/candidate.rb
99
+ - lib/private_please/report/reporter.rb
100
+ - lib/private_please/report/templates/simple.txt.erb
101
+ - lib/private_please/ruby_backports.rb
102
+ - lib/private_please/storage/calls_store.rb
103
+ - lib/private_please/storage/candidates_store.rb
104
+ - lib/private_please/storage/methods_names.rb
105
+ - lib/private_please/storage/methods_names_bucket.rb
106
+ - lib/private_please/tracking/extension.rb
107
+ - lib/private_please/tracking/instrumentor.rb
108
+ - lib/private_please/tracking/instruments_all_below.rb
109
+ - lib/private_please/tracking/line_change_tracker.rb
88
110
  - lib/private_please/version.rb
89
111
  - private_please.gemspec
90
- - spec/01_marking_methods_spec.rb
91
- - spec/02_calling_methods_spec.rb
92
- - spec/03_configuration_spec.rb
93
- - spec/04_at_exit_report_printing_spec.rb
112
+ - sample.rb
113
+ - spec/01_marking_candidate_methods_to_observe_spec.rb
114
+ - spec/02_logging_calls_on_candidate_methods_spec.rb
115
+ - spec/04_instrumented_program_activity_observation_result_spec.rb
116
+ - spec/fixtures/sample_class_for_report.rb
117
+ - spec/fixtures/sample_class_with_all_calls_combinations.rb
94
118
  - spec/spec_helper.rb
119
+ - spec/units/calls_store_spec.rb
120
+ - spec/units/candidates_store_spec.rb
121
+ has_rdoc: true
95
122
  homepage: https://github.com/alainravet/private_please
96
123
  licenses: []
97
124
 
@@ -121,13 +148,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
148
  requirements: []
122
149
 
123
150
  rubyforge_project:
124
- rubygems_version: 1.8.24
151
+ rubygems_version: 1.6.2
125
152
  signing_key:
126
153
  specification_version: 3
127
154
  summary: Test if methods can be made private
128
155
  test_files:
129
- - spec/01_marking_methods_spec.rb
130
- - spec/02_calling_methods_spec.rb
131
- - spec/03_configuration_spec.rb
132
- - spec/04_at_exit_report_printing_spec.rb
156
+ - spec/01_marking_candidate_methods_to_observe_spec.rb
157
+ - spec/02_logging_calls_on_candidate_methods_spec.rb
158
+ - spec/04_instrumented_program_activity_observation_result_spec.rb
159
+ - spec/fixtures/sample_class_for_report.rb
160
+ - spec/fixtures/sample_class_with_all_calls_combinations.rb
133
161
  - spec/spec_helper.rb
162
+ - spec/units/calls_store_spec.rb
163
+ - spec/units/candidates_store_spec.rb
@@ -1,37 +0,0 @@
1
- module PrivatePlease
2
- class Candidates
3
- def self.instance
4
- @@__instance ||= new
5
- end
6
-
7
- def self.reset_before_new_test
8
- @@__instance = nil
9
- end
10
-
11
- attr_reader :candidates, :inside_called_candidates, :outside_called_candidates
12
- def initialize
13
- @candidates = Hash.new{ [] }
14
- @inside_called_candidates = Hash.new{ [] }
15
- @outside_called_candidates = Hash.new{ [] }
16
- end
17
-
18
- def record_candidate(self_class, name)
19
- candidates[self_class.to_s] += Array(name)
20
- end
21
-
22
- def record_outside_call(self_class, name)
23
- #TODO use a Set instead of an Array
24
- unless outside_called_candidates[self_class.to_s].include?(name)
25
- outside_called_candidates[self_class.to_s] += Array(name)
26
- end
27
- end
28
-
29
- def record_inside_call(self_class, name)
30
- #TODO use a Set instead of an Array
31
- unless inside_called_candidates[self_class.to_s].include?(name)
32
- inside_called_candidates[self_class.to_s] += Array(name)
33
- end
34
- end
35
-
36
- end
37
- end
@@ -1,21 +0,0 @@
1
- module PrivatePlease
2
- class Configuration
3
- def self.instance
4
- @@__instance ||= new
5
- end
6
-
7
- # only used by tests #TODO : refactor to remove .instance and .reset
8
- def self.reset_before_new_test
9
- @@__instance = nil
10
- end
11
-
12
- attr_reader :active
13
- def initialize
14
- @active
15
- end
16
-
17
- def activate(flag)
18
- @active = flag
19
- end
20
- end
21
- end
@@ -1,19 +0,0 @@
1
- module PrivatePlease
2
- class LineChangeTracker
3
- class << self
4
- attr_accessor :prev_prev_self, :prev_self, :curr_self
5
- @@prev_self = @@curr_self = nil
6
- end
7
-
8
- MY_TRACE_FUN = proc do |event, file, line, id, binding, klass|
9
- return unless 'line'==event
10
- LineChangeTracker.prev_prev_self = LineChangeTracker.prev_self
11
- LineChangeTracker.prev_self = LineChangeTracker.curr_self
12
- LineChangeTracker.curr_self = (eval 'self', binding)
13
- #puts "my : #{event} in #{file}/#{line} id:#{id} klass:#{klass} - self = #{(eval'self', binding).inspect}"
14
- end
15
-
16
- end
17
- end
18
-
19
- set_trace_func(PrivatePlease::LineChangeTracker::MY_TRACE_FUN)
@@ -1,34 +0,0 @@
1
- module PrivatePlease
2
- class Recorder
3
-
4
- def self.instance
5
- @@__instance ||= new(Candidates.instance)
6
- end
7
-
8
- # only used by tests #TODO : refactor to remove .instance and .reset
9
- def self.reset_before_new_test
10
- @@__instance = nil
11
- end
12
-
13
- def initialize(storage)
14
- @storage = storage
15
- end
16
-
17
-
18
- def record_candidate(self_class, name)
19
- @storage.record_candidate(self_class, name)
20
- # do more. ex: logging, ..
21
- end
22
-
23
- def record_outside_call(self_class, name)
24
- @storage.record_outside_call(self_class, name)
25
- # do more. ex: logging, ..
26
- end
27
-
28
- def record_inside_call(self_class, name)
29
- @storage.record_inside_call(self_class, name)
30
- # do more. ex: logging, ..
31
- end
32
-
33
- end
34
- end
@@ -1,15 +0,0 @@
1
- PrivatePlease report :
2
- ====================================================================================
3
- Good candidates :
4
- ====================================================================================
5
- <% good_candidates.keys.each do |klass|%>
6
- in <%= klass %> :
7
- <%= good_candidates[klass].join(', ')%>
8
- <% end %>
9
-
10
- ====================================================================================
11
- Bad candidates :
12
- <% bad_candidates.keys.each do |klass| %>
13
- in <%= klass %> :
14
- <%= bad_candidates[klass].join(', ')%>
15
- <% end %>
@@ -1,47 +0,0 @@
1
- module PrivatePlease
2
- class Report
3
-
4
- # @param [PrivatePlease::Recorder] recorder
5
- def self.build(storage)
6
- new(storage)
7
- end
8
-
9
- # @param [PrivatePlease::Recorder] recorder
10
- def initialize(storage)
11
- @storage = storage
12
- end
13
-
14
- TEMPLATE_PATH = File.dirname(__FILE__) + '/report/template.txt.erb'
15
-
16
- def to_s
17
- erb = ERB.new(File.read(TEMPLATE_PATH))
18
-
19
- good_candidates = good_candidates() # for ERB/binding
20
- bad_candidates = bad_candidates() # for ERB/binding
21
- erb.result(binding)
22
- end
23
-
24
- # @return [Hash]
25
- def never_called_candidates
26
- @storage.candidates.tap do |all|
27
- all.keys.each do |klass|
28
- all[klass] = all[klass] - @storage.outside_called_candidates[klass] - @storage.inside_called_candidates[klass]
29
- end
30
- end
31
- end
32
-
33
- # @return [Hash]
34
- def good_candidates
35
- @storage.inside_called_candidates.tap do |all|
36
- all.keys.each do |klass|
37
- all[klass] = all[klass] - @storage.outside_called_candidates[klass]
38
- end
39
- end
40
- end
41
-
42
- # @return [Hash]
43
- def bad_candidates
44
- @storage.outside_called_candidates
45
- end
46
- end
47
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe PrivatePlease, 'marking methods' do
4
-
5
- let(:storage) { PrivatePlease.storage }
6
-
7
- it('records the candidates and associate them to the owning class') do
8
- module Marking
9
- class Simple1
10
- def foo ; 'foo' end
11
- def bar ; 'bar' end
12
- def buz ; 'bar' end
13
- private_please :bar, :buz
14
- end
15
- end
16
- storage.candidates['Marking::Simple1'].should == [:bar, :buz]
17
- end
18
-
19
- it('does not record invalid candidates (method not found in the class)') do
20
- module Marking
21
- class Simple2
22
- def foo ; 'foo' end
23
- private_please :foo
24
- private_please :invalid_method
25
- end
26
- end
27
- storage.candidates['Marking::Simple2'].should == [:foo]
28
- end
29
-
30
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe PrivatePlease, 'calling marked methods' do
4
- before() do
5
- PrivatePlease.activate(true)
6
- end
7
- let(:storage) { PrivatePlease.storage }
8
-
9
- module Calling
10
- class Simple
11
- def public_m ; private_m() end
12
- def private_m; 'SUCCESS' end
13
- private_please :private_m
14
- end
15
- end
16
-
17
- #--------------
18
- context 'from INSIDE the class' do
19
- #--------------
20
-
21
- before { Calling::Simple.new.public_m }
22
-
23
- it('records the call to the p+p method in PrivatePlease.inside_called_candidates') do
24
- storage.inside_called_candidates[ 'Calling::Simple'].to_a.should == [:private_m]
25
- storage.outside_called_candidates['Calling::Simple'].to_a.should == []
26
- end
27
-
28
- it('records multiple calls only once') do
29
- 2.times{ Calling::Simple.new.public_m }
30
- storage.inside_called_candidates[ 'Calling::Simple'].to_a.should == [:private_m]
31
- storage.outside_called_candidates['Calling::Simple'].to_a.should == []
32
- end
33
- end
34
-
35
-
36
- #--------------
37
- context 'from OUTSIDE the class' do
38
- #--------------
39
-
40
- before { @result = Calling::Simple.new.private_m }
41
-
42
- it 'goes thru (as the method is still public)' do
43
- @result.should == 'SUCCESS'
44
- end
45
-
46
- it('records the call to the p+p method in PrivatePlease.inside_called_candidates') do
47
- storage.inside_called_candidates[ 'Calling::Simple'].to_a.should == []
48
- storage.outside_called_candidates['Calling::Simple'].to_a.should == [:private_m]
49
- end
50
-
51
- it('records multiple calls only once') do
52
- 2.times{ Calling::Simple.new.private_m }
53
- storage.inside_called_candidates[ 'Calling::Simple'].to_a.should == []
54
- storage.outside_called_candidates['Calling::Simple'].to_a.should == [:private_m]
55
- end
56
- end
57
-
58
- end
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe PrivatePlease, 'configuring PrivatePlease' do
4
- module Config
5
- class Simple
6
- def public_m ; private_m() end
7
- def private_m; 'SUCCESS' end
8
- private_please :private_m
9
- end
10
- end
11
-
12
- def do_the_calls
13
- Config::Simple.new.tap do |o|
14
- o.public_m # -> inside call
15
- o.private_m # -> outside call
16
- end
17
- end
18
-
19
- #--------------
20
-
21
- it 'is disabled by default' do
22
- PrivatePlease::Configuration.reset_before_new_test
23
- PrivatePlease.should_not be_active
24
- end
25
- let(:storage) { PrivatePlease.storage }
26
-
27
- context 'when disabled' do
28
-
29
- before { PrivatePlease.activate(false) }
30
- before { do_the_calls }
31
-
32
- it('is not active') { PrivatePlease.should_not be_active }
33
-
34
- it 'does NOT record the calls to candidates' do
35
- storage.inside_called_candidates[ 'Config::Simple'].to_a.should == []
36
- storage.outside_called_candidates['Config::Simple'].to_a.should == []
37
- end
38
- end
39
-
40
- context 'when enabled' do
41
-
42
- before { PrivatePlease.activate(true) }
43
- before { do_the_calls }
44
-
45
- it('is active') { PrivatePlease.should be_active }
46
-
47
- it 'DOES record the calls to candidates' do
48
- storage.inside_called_candidates[ 'Config::Simple'].to_a.should == [:private_m]
49
- storage.outside_called_candidates['Config::Simple'].to_a.should == [:private_m]
50
- end
51
- end
52
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe PrivatePlease, 'reporting the calls on candidates' do
4
-
5
- module Reporting
6
- class Simple
7
- def public_m ; private_m1a() end
8
- def private_m1a ; private_m1b end
9
- def private_m1b ; private_m1c end
10
-
11
- def private_m ; private_m1c end
12
- def private_m1c ; 'SUCCESS' end
13
-
14
- def ignored ; 'never called' end
15
- private_please :private_m1a, :private_m1b, :private_m1c, :private_m, :ignored
16
- end
17
- end
18
-
19
- before() { PrivatePlease.activate(true) }
20
- before do
21
- Reporting::Simple.new.public_m
22
- Reporting::Simple.new.private_m
23
- Reporting::Simple.new.private_m1c
24
- end
25
-
26
- describe 'the activity report' do
27
- let(:the_report) { PrivatePlease.report }
28
-
29
- specify '#good_candidates is the list of methods that CAN be made private' do
30
- the_report.good_candidates['Reporting::Simple'].
31
- should =~ [:private_m1a, :private_m1b]
32
- end
33
-
34
- specify '#bad_candidates is the list of methods that CANNOT be made private' do
35
- the_report.bad_candidates['Reporting::Simple'].
36
- should =~ [:private_m1c, :private_m]
37
- end
38
-
39
- xspecify '#never_called_candidates is the list of methods that were never called' do
40
- the_report.never_called_candidates['Reporting::Simple'].
41
- should == [:ignored]
42
- end
43
- end
44
-
45
- specify 'at_exit prints the report in the STDOUT'
46
-
47
- end