ice_nine 0.10.0 → 0.11.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.
Files changed (59) hide show
  1. checksums.yaml +7 -15
  2. data/.travis.yml +8 -7
  3. data/Gemfile +10 -0
  4. data/Gemfile.devtools +5 -4
  5. data/README.md +4 -24
  6. data/benchmarks/speed.rb +4 -2
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/reek.yml +9 -2
  10. data/config/rubocop.yml +0 -1
  11. data/ice_nine.gemspec +1 -0
  12. data/lib/ice_nine.rb +24 -9
  13. data/lib/ice_nine/core_ext/object.rb +17 -3
  14. data/lib/ice_nine/freezer.rb +43 -3
  15. data/lib/ice_nine/freezer/array.rb +6 -8
  16. data/lib/ice_nine/freezer/false_class.rb +2 -2
  17. data/lib/ice_nine/freezer/hash.rb +22 -9
  18. data/lib/ice_nine/freezer/hash/state.rb +3 -3
  19. data/lib/ice_nine/freezer/module.rb +2 -2
  20. data/lib/ice_nine/freezer/nil_class.rb +2 -2
  21. data/lib/ice_nine/freezer/no_freeze.rb +5 -6
  22. data/lib/ice_nine/freezer/numeric.rb +2 -2
  23. data/lib/ice_nine/freezer/object.rb +7 -8
  24. data/lib/ice_nine/freezer/range.rb +7 -8
  25. data/lib/ice_nine/freezer/rubinius.rb +2 -2
  26. data/lib/ice_nine/freezer/struct.rb +2 -2
  27. data/lib/ice_nine/freezer/symbol.rb +2 -2
  28. data/lib/ice_nine/freezer/true_class.rb +2 -2
  29. data/lib/ice_nine/support/recursion_guard.rb +48 -28
  30. data/lib/ice_nine/version.rb +3 -3
  31. data/spec/integration/ice_nine/class_methods/deep_freeze_bang_spec.rb +21 -0
  32. data/spec/integration/ice_nine/class_methods/deep_freeze_spec.rb +5 -254
  33. data/spec/shared/array_deep_freeze_shared_spec.rb +9 -0
  34. data/spec/shared/hash_deep_freeze_shared_spec.rb +23 -0
  35. data/spec/shared/ice_nine_deep_freeze_shared_spec.rb +263 -0
  36. data/spec/shared/no_freeze_deep_freeze_shared_spec.rb +19 -0
  37. data/spec/shared/object_deep_freeze_shared_spec.rb +19 -0
  38. data/spec/shared/range_deep_freeze_shared_spec.rb +13 -0
  39. data/spec/unit/ice_nine/class_methods/deep_freeze_bang_spec.rb +24 -0
  40. data/spec/unit/ice_nine/class_methods/deep_freeze_spec.rb +6 -19
  41. data/spec/unit/ice_nine/core_ext/object/deep_freeze_bang_spec.rb +24 -0
  42. data/spec/unit/ice_nine/core_ext/object/deep_freeze_spec.rb +3 -9
  43. data/spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb +0 -14
  44. data/spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb +1 -7
  45. data/spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb +1 -29
  46. data/spec/unit/ice_nine/freezer/module/class_methods/deep_freeze_spec.rb +1 -7
  47. data/spec/unit/ice_nine/freezer/nil_class/class_methods/deep_freeze_spec.rb +1 -7
  48. data/spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb +3 -23
  49. data/spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb +3 -12
  50. data/spec/unit/ice_nine/freezer/object/class_methods/deep_freeze_spec.rb +0 -18
  51. data/spec/unit/ice_nine/freezer/range/class_methods/deep_freeze_spec.rb +0 -18
  52. data/spec/unit/ice_nine/freezer/struct/class_methods/deep_freeze_spec.rb +1 -11
  53. data/spec/unit/ice_nine/freezer/symbol/class_methods/deep_freeze_spec.rb +1 -7
  54. data/spec/unit/ice_nine/freezer/true_class/class_methods/deep_freeze_spec.rb +1 -7
  55. data/spec/unit/ice_nine/recursion_guard/frozen/guard_spec.rb +28 -0
  56. data/spec/unit/ice_nine/recursion_guard/object_set/guard_spec.rb +31 -0
  57. data/spec/unit/object/deep_freeze_spec.rb +3 -9
  58. metadata +54 -41
  59. data/spec/unit/ice_nine/recursion_guard/class_methods/guard_spec.rb +0 -33
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'IceNine::Freezer::Array.deep_freeze' do
4
+ it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
5
+
6
+ it 'freezes each entry' do
7
+ expect(subject.select(&:frozen?)).to eql(subject.to_a)
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'IceNine::Freezer::Hash.deep_freeze' do
4
+ it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
5
+
6
+ it 'freezes each key' do
7
+ expect(subject.keys.select(&:frozen?)).to eql(subject.keys)
8
+ end
9
+
10
+ it 'freezes each value' do
11
+ expect(subject.values.select(&:frozen?)).to eql(subject.values)
12
+ end
13
+
14
+ if RUBY_VERSION >= '1.9' && RUBY_ENGINE == 'rbx'
15
+ it 'does not freeze the state' do
16
+ expect(subject.instance_variable_get(:@state)).to_not be_frozen
17
+ end
18
+
19
+ it 'does not freeze the entries' do
20
+ expect(subject.instance_variable_get(:@entries)).to_not be_frozen
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,263 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'IceNine.deep_freeze' do
4
+
5
+ context 'with an Object' do
6
+ let(:value) { Object.new }
7
+
8
+ before do
9
+ value.instance_eval { @a = '1' }
10
+ end
11
+
12
+ it 'returns the object' do
13
+ should be(value)
14
+ end
15
+
16
+ it 'freezes the object' do
17
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
18
+ end
19
+
20
+ it 'freezes the instance variables in the Object' do
21
+ expect(subject.instance_variable_get(:@a)).to be_frozen
22
+ end
23
+
24
+ context 'with a circular reference' do
25
+ before do
26
+ value.instance_eval { @self = self }
27
+ end
28
+
29
+ it 'returns the object' do
30
+ should be(value)
31
+ end
32
+
33
+ it 'freezes the object' do
34
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
35
+ end
36
+
37
+ it 'freezes the instance variables in the Object' do
38
+ expect(subject.instance_variable_get(:@a)).to be_frozen
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'with an Array' do
44
+ let(:value) { %w[a] }
45
+
46
+ it 'returns the object' do
47
+ should be(value)
48
+ end
49
+
50
+ it 'freezes the object' do
51
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
52
+ end
53
+
54
+ it 'freezes each element in the Array' do
55
+ expect(subject.select(&:frozen?)).to eql(subject)
56
+ end
57
+
58
+ context 'with a circular reference' do
59
+ before do
60
+ value << value
61
+ end
62
+
63
+ it 'returns the object' do
64
+ should be(value)
65
+ end
66
+
67
+ it 'freezes the object' do
68
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
69
+ end
70
+
71
+ it 'freezes each element in the Array' do
72
+ expect(subject.select(&:frozen?)).to eql(subject)
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'with a Hash' do
78
+ let(:value) { { Object.new => Object.new } }
79
+
80
+ it 'returns the object' do
81
+ should be(value)
82
+ end
83
+
84
+ it 'freezes the object' do
85
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
86
+ end
87
+
88
+ it 'freezes each key in the Hash' do
89
+ expect(subject.keys.select(&:frozen?)).to eql(subject.keys)
90
+ end
91
+
92
+ it 'freezes each value in the Hash' do
93
+ expect(subject.values.select(&:frozen?)).to eql(subject.values)
94
+ end
95
+
96
+ context 'with a circular reference' do
97
+ before do
98
+ value[value] = value
99
+ end
100
+
101
+ it 'returns the object' do
102
+ should be(value)
103
+ end
104
+
105
+ it 'freezes the object' do
106
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
107
+ end
108
+
109
+ it 'freezes each key in the Hash' do
110
+ expect(subject.keys.select(&:frozen?)).to eql(subject.keys)
111
+ end
112
+
113
+ it 'freezes each value in the Hash' do
114
+ expect(subject.values.select(&:frozen?)).to eql(subject.values)
115
+ end
116
+ end
117
+ end
118
+
119
+ context 'with a Range' do
120
+ let(:value) { 'a'..'z' }
121
+
122
+ it 'returns the object' do
123
+ should be(value)
124
+ end
125
+
126
+ it 'freezes the object' do
127
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
128
+ end
129
+
130
+ it 'freeze the first object in the Range' do
131
+ expect(subject.begin).to be_frozen
132
+ end
133
+
134
+ it 'freeze the last object in the Range' do
135
+ expect(subject.end).to be_frozen
136
+ end
137
+ end
138
+
139
+ context 'with a String' do
140
+ let(:value) { '' }
141
+
142
+ before do
143
+ value.instance_eval { @a = '1' }
144
+ end
145
+
146
+ it 'returns the object' do
147
+ should be(value)
148
+ end
149
+
150
+ it 'freezes the object' do
151
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
152
+ end
153
+
154
+ it 'freezes the instance variables in the String' do
155
+ expect(subject.instance_variable_get(:@a)).to be_frozen
156
+ end
157
+
158
+ context 'with a circular reference' do
159
+ before do
160
+ value.instance_eval { @self = self }
161
+ end
162
+
163
+ it 'returns the object' do
164
+ should be(value)
165
+ end
166
+
167
+ it 'freezes the object' do
168
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
169
+ end
170
+
171
+ it 'freezes the instance variables in the String' do
172
+ expect(subject.instance_variable_get(:@a)).to be_frozen
173
+ end
174
+ end
175
+ end
176
+
177
+ context 'with a Struct' do
178
+ let(:value) { klass.new(%w[ 1 2 ]) }
179
+ let(:klass) { Struct.new(:a) }
180
+
181
+ it 'returns the object' do
182
+ should be(value)
183
+ end
184
+
185
+ it 'freezes the object' do
186
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
187
+ end
188
+
189
+ it 'freezes each value in the Struct' do
190
+ expect(subject.values.select(&:frozen?)).to eql(subject.values)
191
+ end
192
+
193
+ context 'with a circular reference' do
194
+ before do
195
+ value.a = value
196
+ end
197
+
198
+ it 'returns the object' do
199
+ should be(value)
200
+ end
201
+
202
+ it 'freezes the object' do
203
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
204
+ end
205
+
206
+ it 'freezes each value in the Struct' do
207
+ expect(subject.values.select(&:frozen?)).to eql(subject.values)
208
+ end
209
+ end
210
+ end
211
+
212
+ context 'with an SimpleDelegator' do
213
+ let(:value) { SimpleDelegator.new(nil) }
214
+
215
+ before do
216
+ value.instance_eval { @a = '1' }
217
+ end
218
+
219
+ it 'returns the object' do
220
+ should be(value)
221
+ end
222
+
223
+ it 'freezes the object' do
224
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
225
+ end
226
+
227
+ it 'freezes the instance variables in the SimpleDelegator' do
228
+ expect(subject.instance_variable_get(:@a)).to be_frozen
229
+ end
230
+
231
+ context 'with a circular reference' do
232
+ before do
233
+ value.instance_eval { @self = self }
234
+ end
235
+
236
+ it 'returns the object' do
237
+ should be(value)
238
+ end
239
+
240
+ it 'freezes the object' do
241
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
242
+ end
243
+
244
+ it 'freezes the instance variables in the SimpleDelegator' do
245
+ expect(subject.instance_variable_get(:@a)).to be_frozen
246
+ end
247
+ end
248
+ end
249
+
250
+ [0.0, 0, 0x7fffffffffffffff, true, false, nil, :symbol].each do |value|
251
+ context "with a #{value.class}" do
252
+ let(:value) { value }
253
+
254
+ it 'returns the object' do
255
+ should be(value)
256
+ end
257
+
258
+ it 'does not freeze the object' do
259
+ expect { subject }.to_not change(value, :frozen?).from(false)
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'IceNine::Freezer::NoFreeze.deep_freeze' do
4
+ before do
5
+ value.instance_eval { @a = '1' } unless value.frozen?
6
+ end
7
+
8
+ it 'returns the object' do
9
+ should be(value)
10
+ end
11
+
12
+ it 'does not freeze the object' do
13
+ expect { subject }.to_not change(value, :frozen?).from(false)
14
+ end
15
+
16
+ it 'does not freeze instance variables' do
17
+ expect(subject.instance_variable_get(:@a)).to_not be_frozen
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'IceNine::Freezer::Object.deep_freeze' do
4
+ before do
5
+ value.instance_eval { @a = '1' }
6
+ end
7
+
8
+ it 'returns the object' do
9
+ should be(value)
10
+ end
11
+
12
+ it 'freezes the object' do
13
+ expect { subject }.to change(value, :frozen?).from(false).to(true)
14
+ end
15
+
16
+ it 'freezes instance variables' do
17
+ expect(subject.instance_variable_get(:@a)).to be_frozen
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'IceNine::Freezer::Range.deep_freeze' do
4
+ it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
5
+
6
+ it 'freeze the first element' do
7
+ expect(subject.begin).to be_frozen
8
+ end
9
+
10
+ it 'freeze the last element' do
11
+ expect(subject.end).to be_frozen
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'ice_nine'
5
+
6
+ describe IceNine, '.deep_freeze!' do
7
+ subject { object.deep_freeze!(value) }
8
+
9
+ let(:object) { IceNine }
10
+ let(:value) { Object.new }
11
+
12
+ context 'when the object is not frozen' do
13
+ it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
14
+ end
15
+
16
+ context 'when the object is frozen' do
17
+ before do
18
+ value.instance_eval { @a = '1' }
19
+ value.freeze
20
+ end
21
+
22
+ it_behaves_like 'IceNine::Freezer::NoFreeze.deep_freeze'
23
+ end
24
+ end
@@ -9,26 +9,13 @@ describe IceNine, '.deep_freeze' do
9
9
  let(:object) { IceNine }
10
10
  let(:value) { Object.new }
11
11
 
12
- before do
13
- value.instance_eval { @a = '1' }
14
- end
15
-
16
12
  context 'when the object is not frozen' do
17
- it 'returns the object' do
18
- should be(value)
19
- end
20
-
21
- it 'freezes the object' do
22
- expect { subject }.to change(value, :frozen?).from(false).to(true)
23
- end
24
-
25
- it 'freezes the instance variables in the Object' do
26
- expect(subject.instance_variable_get(:@a)).to be_frozen
27
- end
13
+ it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
28
14
  end
29
15
 
30
16
  context 'when the object is frozen' do
31
17
  before do
18
+ value.instance_eval { @a = '1' }
32
19
  value.freeze
33
20
  end
34
21
 
@@ -36,12 +23,12 @@ describe IceNine, '.deep_freeze' do
36
23
  should be(value)
37
24
  end
38
25
 
39
- it 'does not freeze the object' do
40
- expect { subject }.to_not change(value, :frozen?).from(true)
26
+ it 'leaves the object frozen' do
27
+ expect { subject }.not_to change(value, :frozen?).from(true)
41
28
  end
42
29
 
43
- it 'does not freeze the instance variables in the Object' do
44
- expect(subject.instance_variable_get(:@a)).to_not be_frozen
30
+ it 'freezes instance variables' do
31
+ expect(subject.instance_variable_get(:@a)).to be_frozen
45
32
  end
46
33
  end
47
34
  end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'ice_nine'
5
+ require 'ice_nine/core_ext/object'
6
+
7
+ describe IceNine::CoreExt::Object, '#deep_freeze!' do
8
+ subject { value.deep_freeze! }
9
+
10
+ let(:value) { Object.new.extend(IceNine::CoreExt::Object) }
11
+
12
+ context 'when the object is not frozen' do
13
+ it_behaves_like 'IceNine::Freezer::Object.deep_freeze'
14
+ end
15
+
16
+ context 'when the object is frozen' do
17
+ before do
18
+ value.instance_eval { @a = '1' }
19
+ value.freeze
20
+ end
21
+
22
+ it_behaves_like 'IceNine::Freezer::NoFreeze.deep_freeze'
23
+ end
24
+ end