ice_nine 0.10.0 → 0.11.0

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