ice_nine 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
- bundler_args: --without guard metrics
2
+ before_install: gem install bundler
3
+ bundler_args: --without yard guard
3
4
  script: "bundle exec rake spec"
4
5
  rvm:
5
6
  - 1.8.7
data/Gemfile CHANGED
@@ -4,36 +4,55 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
- group :metrics do
8
- gem 'fattr', '~> 2.2.1'
9
- gem 'arrayfields', '~> 4.7.4'
10
- gem 'flay', '~> 1.4.3'
11
- gem 'flog', '~> 2.5.3'
12
- gem 'map', '~> 5.4.0'
13
- gem 'reek', '~> 1.2.8', :github => 'dkubb/reek'
14
- gem 'roodi', '~> 2.1.0'
15
- gem 'tailor', '~> 0.1.5'
16
- gem 'yardstick', '~> 0.4.0'
17
- gem 'yard-spellcheck', '~> 0.1.4'
18
-
19
- platforms :mri_19 do
20
- gem 'cane', '~> 1.1.0'
21
- gem 'simplecov', '~> 0.6.1'
7
+ group :yard do
8
+ gem 'redcarpet', '~> 2.2.2', :platforms => [ :mri, :rbx ]
9
+ end
10
+
11
+ group :guard do
12
+ gem 'guard', '~> 1.5.4'
13
+ gem 'guard-bundler', '~> 1.0.0'
14
+ gem 'guard-rspec', '~> 1.2.1'
15
+ end
16
+
17
+ group :benchmarks do
18
+ gem 'rbench', '~> 0.2.3'
19
+ end
20
+
21
+ platform :jruby do
22
+ group :jruby do
23
+ gem 'jruby-openssl', '~> 0.8.2'
22
24
  end
25
+ end
26
+
27
+ group :metrics do
28
+ gem 'flay', '~> 1.4.3'
29
+ gem 'flog', '~> 2.5.3'
30
+ gem 'reek', '~> 1.2.8', :github => 'dkubb/reek'
31
+ gem 'roodi', '~> 2.1.0'
32
+ gem 'yardstick', '~> 0.8.0'
23
33
 
24
- platforms :mri_18, :rbx do
25
- gem 'heckle', '~> 1.4.3'
26
- gem 'json', '~> 1.6.6'
27
- gem 'mspec', '~> 1.5.17'
28
- gem 'ruby2ruby', '= 1.2.2'
34
+ platforms :ruby_18, :ruby_19 do
35
+ # this indirectly depends on ffi which does not build on ruby-head
36
+ gem 'yard-spellcheck', '~> 0.1.5'
29
37
  end
30
38
 
31
39
  platforms :mri_18 do
32
- gem 'metric_fu', '~> 2.1.1'
33
- gem 'rcov', '~> 1.0.0'
40
+ gem 'arrayfields', '~> 4.7.4' # for metric_fu
41
+ gem 'fattr', '~> 2.2.0' # for metric_fu
42
+ gem 'heckle', '~> 1.4.3'
43
+ gem 'json', '~> 1.7.3' # for metric_fu rake task
44
+ gem 'map', '~> 6.2.0' # for metric_fu
45
+ gem 'metric_fu', '~> 2.1.1'
46
+ gem 'mspec', '~> 1.5.17'
47
+ gem 'rcov', '~> 1.0.0'
48
+ gem 'ruby2ruby', '= 1.2.2' # for heckle
49
+ end
50
+
51
+ platforms :ruby_19 do
52
+ gem 'simplecov', '~> 0.7.1'
34
53
  end
35
54
 
36
55
  platforms :rbx do
37
- gem 'pelusa', '~> 0.2.0'
56
+ gem 'pelusa', '~> 0.2.2'
38
57
  end
39
58
  end
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rubygems'
4
3
  require 'rake'
5
4
 
6
5
  FileList['tasks/**/*.rake'].each { |task| import task }
@@ -4,18 +4,19 @@ require File.expand_path('../lib/ice_nine/version', __FILE__)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = 'ice_nine'
7
- gem.version = IceNine::VERSION
8
- gem.authors = [ 'Dan Kubb' ]
9
- gem.email = [ 'dan.kubb@gmail.com' ]
7
+ gem.version = IceNine::VERSION.dup
8
+ gem.authors = ['Dan Kubb']
9
+ gem.email = %w[dan.kubb@gmail.com]
10
10
  gem.description = 'Deep Freeze Ruby Objects'
11
11
  gem.summary = gem.description
12
12
  gem.homepage = 'https://github.com/dkubb/ice_nine'
13
13
 
14
- gem.require_paths = %w[ lib ]
15
- gem.files = `git ls-files`.split("\n")
16
- gem.test_files = `git ls-files -- {spec}/*`.split("\n")
17
- gem.extra_rdoc_files = %w[ LICENSE README.md TODO ]
14
+ gem.require_paths = %w[lib]
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.test_files = `git ls-files -- {spec}/{unit,integration}`.split($/)
17
+ gem.extra_rdoc_files = %w[LICENSE README.md TODO]
18
18
 
19
- gem.add_development_dependency('rake', '~> 0.9.2.2')
19
+ gem.add_development_dependency('rake', '~> 10.0.3')
20
20
  gem.add_development_dependency('rspec', '~> 1.3.2')
21
+ gem.add_development_dependency('yard', '~> 0.8.3')
21
22
  end
@@ -16,7 +16,6 @@ require 'ice_nine/freezer/nil_class'
16
16
  require 'ice_nine/freezer/numeric'
17
17
  require 'ice_nine/freezer/range'
18
18
  require 'ice_nine/freezer/rubinius'
19
- require 'ice_nine/freezer/string'
20
19
  require 'ice_nine/freezer/struct'
21
20
  require 'ice_nine/freezer/symbol'
22
21
  require 'ice_nine/freezer/true_class'
@@ -37,5 +37,7 @@ module IceNine
37
37
  private_class_method :freeze_instance_variables
38
38
 
39
39
  end # class Object
40
+
41
+ BasicObject = Object
40
42
  end # class Freezer
41
43
  end # module IceNine
@@ -3,6 +3,6 @@
3
3
  module IceNine
4
4
 
5
5
  # Current gem version
6
- VERSION = '0.5.0'
6
+ VERSION = '0.6.0'
7
7
 
8
8
  end # module IceNine
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'ice_nine'
5
+ require 'delegate'
5
6
 
6
7
  describe IceNine, '.deep_freeze' do
7
8
  subject { object.deep_freeze(value) }
@@ -142,6 +143,44 @@ describe IceNine, '.deep_freeze' do
142
143
  end
143
144
  end
144
145
 
146
+ context 'with a String' do
147
+ let(:value) { '' }
148
+
149
+ before do
150
+ value.instance_eval { @a = '1' }
151
+ end
152
+
153
+ it 'returns the object' do
154
+ should be(value)
155
+ end
156
+
157
+ it 'freezes the object' do
158
+ expect { subject }.should change(value, :frozen?).from(false).to(true)
159
+ end
160
+
161
+ it 'freezes the instance variables in the String' do
162
+ subject.instance_variable_get(:@a).should be_frozen
163
+ end
164
+
165
+ context 'with a circular reference' do
166
+ before do
167
+ value.instance_eval { @self = self }
168
+ end
169
+
170
+ it 'returns the object' do
171
+ should be(value)
172
+ end
173
+
174
+ it 'freezes the object' do
175
+ expect { subject }.should change(value, :frozen?).from(false).to(true)
176
+ end
177
+
178
+ it 'freezes the instance variables in the String' do
179
+ subject.instance_variable_get(:@a).should be_frozen
180
+ end
181
+ end
182
+ end
183
+
145
184
  context 'with a Struct' do
146
185
  let(:value) { klass.new(%w[ 1 2 ]) }
147
186
  let(:klass) { Struct.new(:a) }
@@ -177,6 +216,44 @@ describe IceNine, '.deep_freeze' do
177
216
  end
178
217
  end
179
218
 
219
+ context 'with an SimpleDelegator' do
220
+ let(:value) { SimpleDelegator.new(nil) }
221
+
222
+ before do
223
+ value.instance_eval { @a = '1' }
224
+ end
225
+
226
+ it 'returns the object' do
227
+ should be(value)
228
+ end
229
+
230
+ it 'freezes the object' do
231
+ expect { subject }.should change(value, :frozen?).from(false).to(true)
232
+ end
233
+
234
+ it 'freezes the instance variables in the SimpleDelegator' do
235
+ subject.instance_variable_get(:@a).should be_frozen
236
+ end
237
+
238
+ context 'with a circular reference' do
239
+ before do
240
+ value.instance_eval { @self = self }
241
+ end
242
+
243
+ it 'returns the object' do
244
+ should be(value)
245
+ end
246
+
247
+ it 'freezes the object' do
248
+ expect { subject }.should change(value, :frozen?).from(false).to(true)
249
+ end
250
+
251
+ it 'freezes the instance variables in the SimpleDelegator' do
252
+ subject.instance_variable_get(:@a).should be_frozen
253
+ end
254
+ end
255
+ end
256
+
180
257
  [0.0, 0, 0x7fffffffffffffff, true, false, nil, :symbol].each do |value|
181
258
  context "with a #{value.class}" do
182
259
  let(:value) { value }
@@ -4,7 +4,7 @@ require 'spec'
4
4
  require 'spec/autorun'
5
5
 
6
6
  # require spec support files and shared behavior
7
- Dir[File.expand_path('../shared/**/*.rb', __FILE__)].each do |file|
7
+ Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each do |file|
8
8
  require file
9
9
  end
10
10
 
@@ -1,3 +1,3 @@
1
1
  require 'rbconfig'
2
2
 
3
- ::Config = RbConfig
3
+ ::Config = RbConfig unless defined?(::Config)
@@ -1,7 +1,9 @@
1
+ # encoding: utf-8
2
+
1
3
  desc 'Run metrics with Heckle'
2
- task :ci => %w[ ci:metrics heckle ]
4
+ task :ci => %w[ ci:metrics metrics:heckle ]
3
5
 
4
6
  namespace :ci do
5
- desc 'Run metrics'
6
- task :metrics => %w[ verify_measurements flog flay reek roodi metrics:all ]
7
+ desc 'Run metrics (except heckle) and spec'
8
+ task :metrics => %w[ spec metrics:verify_measurements metrics:flog metrics:flay metrics:reek metrics:roodi metrics:all ]
7
9
  end
@@ -7,37 +7,39 @@ begin
7
7
  config = YAML.load_file(File.expand_path('../../../config/flay.yml', __FILE__)).freeze
8
8
  threshold = config.fetch('threshold').to_i
9
9
  total_score = config.fetch('total_score').to_f
10
- files = Flay.expand_dirs_to_files(config.fetch('path', 'lib'))
10
+ files = Flay.expand_dirs_to_files(config.fetch('path', 'lib')).sort
11
11
 
12
- # original code by Marty Andrews:
13
- # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
14
- desc 'Analyze for code duplication'
15
- task :flay do
16
- # run flay once without a threshold to ensure the max mass matches the threshold
17
- flay = Flay.new(:fuzzy => false, :verbose => false, :mass => 0)
18
- flay.process(*files)
12
+ namespace :metrics do
13
+ # original code by Marty Andrews:
14
+ # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
15
+ desc 'Analyze for code duplication'
16
+ task :flay do
17
+ # run flay once without a threshold to ensure the max mass matches the threshold
18
+ flay = Flay.new(:fuzzy => false, :verbose => false, :mass => 0)
19
+ flay.process(*files)
19
20
 
20
- max = flay.masses.map { |hash, mass| mass.to_f / flay.hashes[hash].size }.max
21
- unless max.nil? || max >= threshold
22
- raise "Adjust flay threshold down to #{max}"
23
- end
21
+ max = (flay.masses.map { |hash, mass| mass.to_f / flay.hashes[hash].size }.max) || 0
22
+ unless max >= threshold
23
+ raise "Adjust flay threshold down to #{max}"
24
+ end
24
25
 
25
- total = flay.masses.reduce(0.0) { |total, (hash, mass)| total + (mass.to_f / flay.hashes[hash].size) }
26
- unless total == total_score
27
- raise "Flay total is now #{total}, but expected #{total_score}"
28
- end
26
+ total = flay.masses.reduce(0.0) { |total, (hash, mass)| total + (mass.to_f / flay.hashes[hash].size) }
27
+ unless total == total_score
28
+ raise "Flay total is now #{total}, but expected #{total_score}"
29
+ end
29
30
 
30
- # run flay a second time with the threshold set
31
- flay = Flay.new(:fuzzy => false, :verbose => false, :mass => threshold.succ)
32
- flay.process(*files)
31
+ # run flay a second time with the threshold set
32
+ flay = Flay.new(:fuzzy => false, :verbose => false, :mass => threshold.succ)
33
+ flay.process(*files)
33
34
 
34
- if flay.masses.any?
35
- flay.report
36
- raise "#{flay.masses.size} chunks of code have a duplicate mass > #{threshold}"
35
+ if flay.masses.any?
36
+ flay.report
37
+ raise "#{flay.masses.size} chunks of code have a duplicate mass > #{threshold}"
38
+ end
37
39
  end
38
40
  end
39
41
  rescue LoadError
40
42
  task :flay do
41
- abort 'Flay is not available. In order to run flay, you must: gem install flay'
43
+ $stderr.puts 'Flay is not available. In order to run flay, you must: gem install flay'
42
44
  end
43
45
  end
@@ -13,34 +13,37 @@ begin
13
13
  config = YAML.load_file(File.expand_path('../../../config/flog.yml', __FILE__)).freeze
14
14
  threshold = config.fetch('threshold').to_f.round_to(1)
15
15
 
16
- # original code by Marty Andrews:
17
- # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
18
- desc 'Analyze for code complexity'
19
- task :flog do
20
- flog = Flog.new
21
- flog.flog Array(config.fetch('path', 'lib'))
16
+ namespace :metrics do
17
+ # original code by Marty Andrews:
18
+ # http://blog.martyandrews.net/2009/05/enforcing-ruby-code-quality.html
19
+ desc 'Analyze for code complexity'
20
+ task :flog do
21
+ flog = Flog.new
22
+ flog.flog Array(config.fetch('path', 'lib'))
23
+
24
+ totals = flog.totals.select { |name, score| name[-5, 5] != '#none' }.
25
+ map { |name, score| [ name, score.round_to(1) ] }.
26
+ sort_by { |name, score| score }
27
+
28
+ if totals.any?
29
+ max = totals.last[1]
30
+ unless max >= threshold
31
+ raise "Adjust flog score down to #{max}"
32
+ end
33
+ end
22
34
 
23
- totals = flog.totals.select { |name, score| name[-5, 5] != '#none' }.
24
- map { |name, score| [ name, score.round_to(1) ] }.
25
- sort_by { |name, score| score }
35
+ bad_methods = totals.select { |name, score| score > threshold }
36
+ if bad_methods.any?
37
+ bad_methods.reverse_each do |name, score|
38
+ puts '%8.1f: %s' % [ score, name ]
39
+ end
26
40
 
27
- last = totals.last
28
- max = last[1] if last
29
- unless max.nil? || max >= threshold
30
- raise "Adjust flog score down to #{max}"
31
- end
32
-
33
- bad_methods = totals.select { |name, score| score > threshold }
34
- if bad_methods.any?
35
- bad_methods.reverse_each do |name, score|
36
- puts '%8.1f: %s' % [ score, name ]
41
+ raise "#{bad_methods.size} methods have a flog complexity > #{threshold}"
37
42
  end
38
-
39
- raise "#{bad_methods.size} methods have a flog complexity > #{threshold}"
40
43
  end
41
44
  end
42
45
  rescue LoadError
43
46
  task :flog do
44
- abort 'Flog is not available. In order to run flog, you must: gem install flog'
47
+ $stderr.puts 'Flog is not available. In order to run flog, you must: gem install flog'
45
48
  end
46
49
  end
@@ -7,7 +7,6 @@ $LOAD_PATH.unshift(File.expand_path('../../../lib', __FILE__))
7
7
 
8
8
  begin
9
9
  require 'pathname'
10
- require 'active_support/inflector'
11
10
  require 'heckle'
12
11
  require 'mspec'
13
12
  require 'mspec/utils/name_map'
@@ -26,185 +25,183 @@ begin
26
25
  end
27
26
  end
28
27
 
29
- desc 'Heckle each module and class'
30
- task :heckle => :coverage do
31
- unless Ruby2Ruby::VERSION == '1.2.2'
32
- raise "ruby2ruby version #{Ruby2Ruby::VERSION} may not work properly, 1.2.2 *only* is recommended for use with heckle"
33
- end
28
+ namespace :metrics do
29
+ desc 'Heckle each module and class'
30
+ task :heckle => :coverage do
31
+ unless Ruby2Ruby::VERSION == '1.2.2'
32
+ raise "ruby2ruby version #{Ruby2Ruby::VERSION} may not work properly, 1.2.2 *only* is recommended for use with heckle"
33
+ end
34
34
 
35
- require 'ice_nine'
35
+ require 'ice_nine'
36
36
 
37
- root_module_regexp = Regexp.union(
38
- 'IceNine'
39
- )
37
+ root_module_regexp = Regexp.union('IceNine')
40
38
 
41
- spec_dir = Pathname('spec/unit')
39
+ spec_dir = Pathname('spec/unit')
42
40
 
43
- NameMap::MAP.each do |op, method|
44
- next if method.kind_of?(Hash)
45
- NameMap::MAP[op] = { :default => method }
46
- end
41
+ NameMap::MAP.each do |op, method|
42
+ next if method.kind_of?(Hash)
43
+ NameMap::MAP[op] = { :default => method }
44
+ end
47
45
 
48
- aliases = Hash.new { |h,mod| h[mod] = Hash.new { |h,method| h[method] = method } }
49
- map = NameMap.new
46
+ aliases = Hash.new { |h,mod| h[mod] = Hash.new { |h,method| h[method] = method } }
47
+ map = NameMap.new
50
48
 
51
- heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
52
- unhandled_mutations = 0
49
+ heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
50
+ unhandled_mutations = 0
53
51
 
54
- ObjectSpace.each_object(Module) do |mod|
55
- next unless mod.name =~ /\A#{root_module_regexp}(?::|\z)/
52
+ ObjectSpace.each_object(Module) do |mod|
53
+ next unless mod.name =~ /\A#{root_module_regexp}(?::|\z)/
56
54
 
57
- spec_prefix = spec_dir.join(mod.name.underscore)
55
+ spec_prefix = spec_dir.join(mod.name.underscore)
58
56
 
59
- specs = []
57
+ specs = []
60
58
 
61
- # get the public class methods
62
- metaclass = class << mod; self end
63
- ancestors = metaclass.ancestors
59
+ # get the public class methods
60
+ metaclass = class << mod; self end
61
+ ancestors = metaclass.ancestors
64
62
 
65
- spec_class_methods = mod.singleton_methods(false)
63
+ spec_class_methods = mod.singleton_methods(false)
66
64
 
67
- spec_class_methods.reject! do |method|
68
- %w[ yaml_new yaml_tag_subclasses? included nesting constants ].include?(method.to_s)
69
- end
65
+ spec_class_methods.reject! do |method|
66
+ %w[ yaml_new yaml_tag_subclasses? included nesting constants ].include?(method.to_s)
67
+ end
70
68
 
71
- if mod.ancestors.include?(Singleton)
72
- spec_class_methods.reject! { |method| method.to_s == 'instance' }
73
- end
69
+ if mod.ancestors.include?(Singleton)
70
+ spec_class_methods.reject! { |method| method.to_s == 'instance' }
71
+ end
74
72
 
75
- # get the protected and private class methods
76
- other_class_methods = metaclass.protected_instance_methods(false) |
77
- metaclass.private_instance_methods(false)
73
+ # get the protected and private class methods
74
+ other_class_methods = metaclass.protected_instance_methods(false) |
75
+ metaclass.private_instance_methods(false)
78
76
 
79
- ancestors.each do |ancestor|
80
- other_class_methods -= ancestor.protected_instance_methods(false) |
81
- ancestor.private_instance_methods(false)
82
- end
77
+ ancestors.each do |ancestor|
78
+ other_class_methods -= ancestor.protected_instance_methods(false) |
79
+ ancestor.private_instance_methods(false)
80
+ end
83
81
 
84
- other_class_methods.reject! do |method|
85
- method.to_s == 'allocate' || SKIP_METHODS.include?(method.to_s)
86
- end
82
+ other_class_methods.reject! do |method|
83
+ method.to_s == 'allocate' || SKIP_METHODS.include?(method.to_s)
84
+ end
87
85
 
88
- other_class_methods.reject! do |method|
89
- next unless spec_class_methods.any? { |specced| specced.to_s == $1 }
86
+ other_class_methods.reject! do |method|
87
+ next unless spec_class_methods.any? { |specced| specced.to_s == $1 }
90
88
 
91
- spec_class_methods << method
92
- end
89
+ spec_class_methods << method
90
+ end
93
91
 
94
- spec_class_methods -= other_class_methods
92
+ spec_class_methods -= other_class_methods
95
93
 
96
- # get the instances methods
97
- spec_methods = mod.public_instance_methods(false)
94
+ # get the instances methods
95
+ spec_methods = mod.public_instance_methods(false)
98
96
 
99
- other_methods = mod.protected_instance_methods(false) |
100
- mod.private_instance_methods(false)
97
+ other_methods = mod.protected_instance_methods(false) |
98
+ mod.private_instance_methods(false)
101
99
 
102
- other_methods.reject! do |method|
103
- next unless spec_methods.any? { |specced| specced.to_s == $1 }
100
+ other_methods.reject! do |method|
101
+ next unless spec_methods.any? { |specced| specced.to_s == $1 }
104
102
 
105
- spec_methods << method
106
- end
103
+ spec_methods << method
104
+ end
107
105
 
108
- # map the class methods to spec files
109
- spec_class_methods.each do |method|
110
- method = aliases[mod.name][method]
111
- next if SKIP_METHODS.include?(method.to_s)
106
+ # map the class methods to spec files
107
+ spec_class_methods.each do |method|
108
+ method = aliases[mod.name][method]
109
+ next if SKIP_METHODS.include?(method.to_s)
112
110
 
113
- spec_file = spec_prefix.join('class_methods').join(map.file_name(method, mod.name))
111
+ spec_file = spec_prefix.join('class_methods').join(map.file_name(method, mod.name))
114
112
 
115
- unless spec_file.file?
116
- raise "No spec file #{spec_file} for #{mod}.#{method}"
117
- next
113
+ unless spec_file.file?
114
+ raise "No spec file #{spec_file} for #{mod}.#{method}"
115
+ end
116
+
117
+ specs << [ ".#{method}", [ spec_file ] ]
118
118
  end
119
119
 
120
- specs << [ ".#{method}", [ spec_file ] ]
121
- end
120
+ # map the instance methods to spec files
121
+ spec_methods.each do |method|
122
+ method = aliases[mod.name][method]
123
+ next if SKIP_METHODS.include?(method.to_s)
122
124
 
123
- # map the instance methods to spec files
124
- spec_methods.each do |method|
125
- method = aliases[mod.name][method]
126
- next if SKIP_METHODS.include?(method.to_s)
125
+ spec_file = spec_prefix.join(map.file_name(method, mod.name))
127
126
 
128
- spec_file = spec_prefix.join(map.file_name(method, mod.name))
127
+ unless spec_file.file?
128
+ raise "No spec file #{spec_file} for #{mod}##{method}"
129
+ end
129
130
 
130
- unless spec_file.file?
131
- raise "No spec file #{spec_file} for #{mod}##{method}"
132
- next
131
+ specs << [ "##{method}", [ spec_file ] ]
133
132
  end
134
133
 
135
- specs << [ "##{method}", [ spec_file ] ]
136
- end
137
-
138
- # non-public methods are considered covered if they can be mutated
139
- # and any spec fails for the current or descendant modules
140
- other_methods.each do |method|
141
- descedant_specs = []
134
+ # non-public methods are considered covered if they can be mutated
135
+ # and any spec fails for the current or descendant modules
136
+ other_methods.each do |method|
137
+ descedant_specs = []
142
138
 
143
- ObjectSpace.each_object(Module) do |descedant|
144
- next unless descedant.name =~ /\A#{root_module_regexp}(?::|\z)/ && mod >= descedant
145
- descedant_spec_prefix = spec_dir.join(descedant.name.underscore)
146
- descedant_specs << descedant_spec_prefix
139
+ ObjectSpace.each_object(Module) do |descedant|
140
+ next unless descedant.name =~ /\A#{root_module_regexp}(?::|\z)/ && mod >= descedant
141
+ descedant_spec_prefix = spec_dir.join(descedant.name.underscore)
142
+ descedant_specs << descedant_spec_prefix
147
143
 
148
- if method.to_s == 'initialize'
149
- descedant_specs.concat(Pathname.glob(descedant_spec_prefix.join('class_methods/new_spec.rb')))
144
+ if method.to_s == 'initialize'
145
+ descedant_specs.concat(Pathname.glob(descedant_spec_prefix.join('class_methods/new_spec.rb')))
146
+ end
150
147
  end
148
+
149
+ specs << [ "##{method}", descedant_specs ]
151
150
  end
152
151
 
153
- specs << [ "##{method}", descedant_specs ]
154
- end
152
+ other_class_methods.each do |method|
153
+ descedant_specs = []
155
154
 
156
- other_class_methods.each do |method|
157
- descedant_specs = []
155
+ ObjectSpace.each_object(Module) do |descedant|
156
+ next unless descedant.name =~ /\A#{root_module_regexp}(?::|\z)/ && mod >= descedant
157
+ descedant_specs << spec_dir.join(descedant.name.underscore).join('class_methods')
158
+ end
158
159
 
159
- ObjectSpace.each_object(Module) do |descedant|
160
- next unless descedant.name =~ /\A#{root_module_regexp}(?::|\z)/ && mod >= descedant
161
- descedant_specs << spec_dir.join(descedant.name.underscore).join('class_methods')
160
+ specs << [ ".#{method}", descedant_specs ]
162
161
  end
163
162
 
164
- specs << [ ".#{method}", descedant_specs ]
165
- end
166
-
167
- specs.sort.each do |(method, spec_files)|
168
- puts "Heckling #{mod}#{method}"
169
- IO.popen("spec #{spec_files.join(' ')} --heckle '#{mod}#{method}'") do |pipe|
170
- while line = pipe.gets
171
- case line = line.chomp
172
- when "The following mutations didn't cause test failures:"
173
- heckle_caught_modules[mod.name] << method
174
- when '+++ mutation'
175
- unhandled_mutations += 1
163
+ specs.sort.each do |(method, spec_files)|
164
+ puts "Heckling #{mod}#{method}"
165
+ IO.popen("spec #{spec_files.join(' ')} --heckle '#{mod}#{method}'") do |pipe|
166
+ while line = pipe.gets
167
+ case line = line.chomp
168
+ when "The following mutations didn't cause test failures:"
169
+ heckle_caught_modules[mod.name] << method
170
+ when '+++ mutation'
171
+ unhandled_mutations += 1
172
+ end
176
173
  end
177
174
  end
178
175
  end
179
176
  end
180
- end
181
177
 
182
- if unhandled_mutations > 0
183
- error_message_lines = [ "*************\n" ]
178
+ if unhandled_mutations > 0
179
+ error_message_lines = [ "*************\n" ]
184
180
 
185
- error_message_lines << "Heckle found #{unhandled_mutations} " \
186
- "mutation#{"s" unless unhandled_mutations == 1} " \
187
- "that didn't cause spec violations\n"
181
+ error_message_lines << "Heckle found #{unhandled_mutations} " \
182
+ "mutation#{"s" unless unhandled_mutations == 1} " \
183
+ "that didn't cause spec violations\n"
188
184
 
189
- heckle_caught_modules.each do |mod, methods|
190
- error_message_lines << "#{mod} contains the following " \
191
- 'poorly-specified methods:'
192
- methods.each do |method|
193
- error_message_lines << " - #{method}"
185
+ heckle_caught_modules.each do |mod, methods|
186
+ error_message_lines << "#{mod} contains the following " \
187
+ 'poorly-specified methods:'
188
+ methods.each do |method|
189
+ error_message_lines << " - #{method}"
190
+ end
191
+ error_message_lines << ''
194
192
  end
195
- error_message_lines << ''
196
- end
197
193
 
198
- error_message_lines << 'Get your act together and come back ' \
199
- 'when your specs are doing their job!'
194
+ error_message_lines << 'Get your act together and come back ' \
195
+ 'when your specs are doing their job!'
200
196
 
201
- raise error_message_lines.join("\n")
202
- else
203
- puts 'Well done! Your code withstood a heckling.'
197
+ raise error_message_lines.join("\n")
198
+ else
199
+ puts 'Well done! Your code withstood a heckling.'
200
+ end
204
201
  end
205
202
  end
206
203
  rescue LoadError
207
- task :heckle do
208
- abort 'Heckle or mspec is not available. In order to run heckle, you must: gem install heckle mspec'
204
+ task :heckle => :coverage do
205
+ $stderr.puts 'Heckle or mspec is not available. In order to run heckle, you must: gem install heckle mspec'
209
206
  end
210
207
  end
@@ -25,7 +25,7 @@ begin
25
25
  rescue LoadError
26
26
  namespace :metrics do
27
27
  task :all do
28
- abort 'metric_fu is not available. In order to run metrics:all, you must: gem install metric_fu'
28
+ $stderr.puts 'metric_fu is not available. In order to run metrics:all, you must: gem install metric_fu'
29
29
  end
30
30
  end
31
31
  end
@@ -3,9 +3,19 @@
3
3
  begin
4
4
  require 'reek/rake/task'
5
5
 
6
- Reek::Rake::Task.new
6
+ RBX_18_MODE = RUBY_VERSION < '1.9' && defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
7
+
8
+ namespace :metrics do
9
+ Reek::Rake::Task.new do |t|
10
+ # reek has some problems under rbx in 1.8 mode that cause the underlying
11
+ # script to raise an exception. Rather than halt the "rake ci" process due
12
+ # to one bug, we choose to ignore it in this specific case until reek can be
13
+ # fixed.
14
+ t.fail_on_error = ! RBX_18_MODE # always true, except under rbx 18 mode
15
+ end
16
+ end
7
17
  rescue LoadError
8
18
  task :reek do
9
- abort "Reek is not available. In order to run reek, you must: gem install reek"
19
+ $stderr.puts 'Reek is not available. In order to run reek, you must: gem install reek'
10
20
  end
11
21
  end
@@ -5,13 +5,15 @@ begin
5
5
  require 'rake/tasklib'
6
6
  require 'roodi_task'
7
7
 
8
- RoodiTask.new do |t|
9
- t.verbose = false
10
- t.config = File.expand_path('../../../config/roodi.yml', __FILE__)
11
- t.patterns = %w[ lib/**/*.rb ]
8
+ namespace :metrics do
9
+ RoodiTask.new do |t|
10
+ t.verbose = false
11
+ t.config = File.expand_path('../../../config/roodi.yml', __FILE__)
12
+ t.patterns = %w[ lib/**/*.rb ]
13
+ end
12
14
  end
13
15
  rescue LoadError
14
16
  task :roodi do
15
- abort 'Roodi is not available. In order to run roodi, you must: gem install roodi'
17
+ $stderr.puts 'Roodi is not available. In order to run roodi, you must: gem install roodi'
16
18
  end
17
19
  end
@@ -1,25 +1,25 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  begin
4
- require 'pathname'
5
- require 'yardstick'
6
4
  require 'yardstick/rake/measurement'
7
5
  require 'yardstick/rake/verify'
8
6
  require 'yaml'
9
7
 
10
8
  config = YAML.load_file(File.expand_path('../../../config/yardstick.yml', __FILE__))
11
9
 
12
- # yardstick_measure task
13
- Yardstick::Rake::Measurement.new
10
+ namespace :metrics do
11
+ # yardstick_measure task
12
+ Yardstick::Rake::Measurement.new
14
13
 
15
- # verify_measurements task
16
- Yardstick::Rake::Verify.new do |verify|
17
- verify.threshold = config.fetch('threshold')
14
+ # verify_measurements task
15
+ Yardstick::Rake::Verify.new do |verify|
16
+ verify.threshold = config.fetch('threshold')
17
+ end
18
18
  end
19
19
  rescue LoadError
20
20
  %w[ yardstick_measure verify_measurements ].each do |name|
21
21
  task name.to_s do
22
- abort "Yardstick is not available. In order to run #{name}, you must: gem install yardstick"
22
+ $stderr.puts "Yardstick is not available. In order to run #{name}, you must: gem install yardstick"
23
23
  end
24
24
  end
25
25
  end
@@ -1,5 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
+ spec_defaults = lambda do |spec|
4
+ spec.ruby_opts = %w[ -r./spec/support/config_alias ]
5
+ spec.spec_opts << '--options' << 'spec/spec.opts'
6
+ end
7
+
3
8
  begin
4
9
  require 'spec/rake/spectask'
5
10
 
@@ -7,42 +12,49 @@ begin
7
12
  task :spec => %w[ spec:unit spec:integration ]
8
13
 
9
14
  namespace :spec do
10
- Spec::Rake::SpecTask.new(:integration) do |t|
11
- t.ruby_opts = %w[ -r./spec/support/config_alias ]
12
- t.pattern = 'spec/integration/**/*_spec.rb'
15
+ desc 'Run unit specs'
16
+ Spec::Rake::SpecTask.new(:unit) do |unit|
17
+ spec_defaults.call(unit)
18
+ unit.pattern = 'spec/unit/**/*_spec.rb'
13
19
  end
14
20
 
15
- Spec::Rake::SpecTask.new(:unit) do |t|
16
- t.ruby_opts = %w[ -r./spec/support/config_alias ]
17
- t.pattern = 'spec/unit/**/*_spec.rb'
21
+ desc 'Run integration specs'
22
+ Spec::Rake::SpecTask.new(:integration) do |integration|
23
+ spec_defaults.call(integration)
24
+ integration.pattern = 'spec/integration/**/*_spec.rb'
18
25
  end
19
26
  end
20
27
  rescue LoadError
21
- task :spec do
22
- abort 'rspec is not available. In order to run spec, you must: gem install rspec'
28
+ %w[ spec spec:unit spec:integration ].each do |name|
29
+ task name do
30
+ $stderr.puts "rspec is not available. In order to run #{name}, you must: gem install rspec"
31
+ end
23
32
  end
24
33
  end
25
34
 
26
- begin
27
- if RUBY_VERSION < '1.9'
28
- desc 'Generate code coverage'
29
- Spec::Rake::SpecTask.new(:coverage) do |t|
30
- t.rcov = true
31
- t.pattern = 'spec/unit/**/*_spec.rb'
32
- t.rcov_opts = File.read('spec/rcov.opts').split(/\s+/)
35
+ namespace :metrics do
36
+ begin
37
+ if RUBY_VERSION < '1.9'
38
+ desc 'Generate code coverage'
39
+ Spec::Rake::SpecTask.new(:coverage) do |rcov|
40
+ spec_defaults.call(rcov)
41
+ rcov.rcov = true
42
+ rcov.pattern = 'spec/unit/**/*_spec.rb'
43
+ rcov.rcov_opts = File.read('spec/rcov.opts').split(/\s+/)
44
+ end
45
+ else
46
+ desc 'Generate code coverage'
47
+ task :coverage do
48
+ ENV['COVERAGE'] = 'true'
49
+ Rake::Task['spec:unit'].execute
50
+ end
33
51
  end
34
- else
35
- desc 'Generate code coverage'
52
+ rescue LoadError
36
53
  task :coverage do
37
- ENV['COVERAGE'] = 'true'
38
- Rake::Task['spec:unit'].execute
54
+ lib = RUBY_VERSION < '1.9' ? 'rcov' : 'simplecov'
55
+ $stderr.puts "coverage is not available. In order to run #{lib}, you must: gem install #{lib}"
39
56
  end
40
57
  end
41
- rescue LoadError
42
- task :coverage do
43
- lib = RUBY_VERSION < '1.9' ? 'rcov' : 'simplecov'
44
- abort "coverage is not available. In order to run #{lib}, you must: gem install #{lib}"
45
- end
46
58
  end
47
59
 
48
- task :test => 'spec'
60
+ task :test => :spec
@@ -6,6 +6,6 @@ begin
6
6
  YARD::Rake::YardocTask.new
7
7
  rescue LoadError
8
8
  task :yard do
9
- abort 'YARD is not available. In order to run yard, you must: gem install yard'
9
+ $stderr.puts 'YARD is not available. In order to run yard, you must: gem install yard'
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,58 +1,82 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ice_nine
3
- version: !ruby/object:Gem::Version
4
- version: 0.5.0
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Dan Kubb
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-10-25 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-12-20 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: rake
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: 0.9.2.2
22
- type: :development
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
- requirements:
25
+ requirements:
27
26
  - - ~>
28
- - !ruby/object:Gem::Version
29
- version: 0.9.2.2
30
- - !ruby/object:Gem::Dependency
27
+ - !ruby/object:Gem::Version
28
+ hash: 73
29
+ segments:
30
+ - 10
31
+ - 0
32
+ - 3
33
+ version: 10.0.3
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
31
37
  name: rspec
32
- requirement: !ruby/object:Gem::Requirement
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
33
40
  none: false
34
- requirements:
41
+ requirements:
35
42
  - - ~>
36
- - !ruby/object:Gem::Version
43
+ - !ruby/object:Gem::Version
44
+ hash: 31
45
+ segments:
46
+ - 1
47
+ - 3
48
+ - 2
37
49
  version: 1.3.2
38
50
  type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: yard
39
54
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
55
+ requirement: &id003 !ruby/object:Gem::Requirement
41
56
  none: false
42
- requirements:
57
+ requirements:
43
58
  - - ~>
44
- - !ruby/object:Gem::Version
45
- version: 1.3.2
59
+ - !ruby/object:Gem::Version
60
+ hash: 57
61
+ segments:
62
+ - 0
63
+ - 8
64
+ - 3
65
+ version: 0.8.3
66
+ type: :development
67
+ version_requirements: *id003
46
68
  description: Deep Freeze Ruby Objects
47
- email:
69
+ email:
48
70
  - dan.kubb@gmail.com
49
71
  executables: []
72
+
50
73
  extensions: []
51
- extra_rdoc_files:
74
+
75
+ extra_rdoc_files:
52
76
  - LICENSE
53
77
  - README.md
54
78
  - TODO
55
- files:
79
+ files:
56
80
  - .gitignore
57
81
  - .pelusa.yml
58
82
  - .rvmrc
@@ -82,7 +106,6 @@ files:
82
106
  - lib/ice_nine/freezer/object.rb
83
107
  - lib/ice_nine/freezer/range.rb
84
108
  - lib/ice_nine/freezer/rubinius.rb
85
- - lib/ice_nine/freezer/string.rb
86
109
  - lib/ice_nine/freezer/struct.rb
87
110
  - lib/ice_nine/freezer/symbol.rb
88
111
  - lib/ice_nine/freezer/true_class.rb
@@ -120,27 +143,37 @@ files:
120
143
  - tasks/yard.rake
121
144
  homepage: https://github.com/dkubb/ice_nine
122
145
  licenses: []
146
+
123
147
  post_install_message:
124
148
  rdoc_options: []
125
- require_paths:
149
+
150
+ require_paths:
126
151
  - lib
127
- required_ruby_version: !ruby/object:Gem::Requirement
152
+ required_ruby_version: !ruby/object:Gem::Requirement
128
153
  none: false
129
- requirements:
130
- - - ! '>='
131
- - !ruby/object:Gem::Version
132
- version: '0'
133
- required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ hash: 3
158
+ segments:
159
+ - 0
160
+ version: "0"
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
162
  none: false
135
- requirements:
136
- - - ! '>='
137
- - !ruby/object:Gem::Version
138
- version: '0'
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ hash: 3
167
+ segments:
168
+ - 0
169
+ version: "0"
139
170
  requirements: []
171
+
140
172
  rubyforge_project:
141
173
  rubygems_version: 1.8.24
142
174
  signing_key:
143
175
  specification_version: 3
144
176
  summary: Deep Freeze Ruby Objects
145
177
  test_files: []
178
+
146
179
  has_rdoc:
@@ -1,10 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module IceNine
4
- class Freezer
5
-
6
- # A freezer class for handling String objects
7
- class String < Object; end
8
-
9
- end # class Freezer
10
- end # module IceNine