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.
- checksums.yaml +7 -15
- data/.travis.yml +8 -7
- data/Gemfile +10 -0
- data/Gemfile.devtools +5 -4
- data/README.md +4 -24
- data/benchmarks/speed.rb +4 -2
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/reek.yml +9 -2
- data/config/rubocop.yml +0 -1
- data/ice_nine.gemspec +1 -0
- data/lib/ice_nine.rb +24 -9
- data/lib/ice_nine/core_ext/object.rb +17 -3
- data/lib/ice_nine/freezer.rb +43 -3
- data/lib/ice_nine/freezer/array.rb +6 -8
- data/lib/ice_nine/freezer/false_class.rb +2 -2
- data/lib/ice_nine/freezer/hash.rb +22 -9
- data/lib/ice_nine/freezer/hash/state.rb +3 -3
- data/lib/ice_nine/freezer/module.rb +2 -2
- data/lib/ice_nine/freezer/nil_class.rb +2 -2
- data/lib/ice_nine/freezer/no_freeze.rb +5 -6
- data/lib/ice_nine/freezer/numeric.rb +2 -2
- data/lib/ice_nine/freezer/object.rb +7 -8
- data/lib/ice_nine/freezer/range.rb +7 -8
- data/lib/ice_nine/freezer/rubinius.rb +2 -2
- data/lib/ice_nine/freezer/struct.rb +2 -2
- data/lib/ice_nine/freezer/symbol.rb +2 -2
- data/lib/ice_nine/freezer/true_class.rb +2 -2
- data/lib/ice_nine/support/recursion_guard.rb +48 -28
- data/lib/ice_nine/version.rb +3 -3
- data/spec/integration/ice_nine/class_methods/deep_freeze_bang_spec.rb +21 -0
- data/spec/integration/ice_nine/class_methods/deep_freeze_spec.rb +5 -254
- data/spec/shared/array_deep_freeze_shared_spec.rb +9 -0
- data/spec/shared/hash_deep_freeze_shared_spec.rb +23 -0
- data/spec/shared/ice_nine_deep_freeze_shared_spec.rb +263 -0
- data/spec/shared/no_freeze_deep_freeze_shared_spec.rb +19 -0
- data/spec/shared/object_deep_freeze_shared_spec.rb +19 -0
- data/spec/shared/range_deep_freeze_shared_spec.rb +13 -0
- data/spec/unit/ice_nine/class_methods/deep_freeze_bang_spec.rb +24 -0
- data/spec/unit/ice_nine/class_methods/deep_freeze_spec.rb +6 -19
- data/spec/unit/ice_nine/core_ext/object/deep_freeze_bang_spec.rb +24 -0
- data/spec/unit/ice_nine/core_ext/object/deep_freeze_spec.rb +3 -9
- data/spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb +0 -14
- data/spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb +1 -7
- data/spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb +1 -29
- data/spec/unit/ice_nine/freezer/module/class_methods/deep_freeze_spec.rb +1 -7
- data/spec/unit/ice_nine/freezer/nil_class/class_methods/deep_freeze_spec.rb +1 -7
- data/spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb +3 -23
- data/spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb +3 -12
- data/spec/unit/ice_nine/freezer/object/class_methods/deep_freeze_spec.rb +0 -18
- data/spec/unit/ice_nine/freezer/range/class_methods/deep_freeze_spec.rb +0 -18
- data/spec/unit/ice_nine/freezer/struct/class_methods/deep_freeze_spec.rb +1 -11
- data/spec/unit/ice_nine/freezer/symbol/class_methods/deep_freeze_spec.rb +1 -7
- data/spec/unit/ice_nine/freezer/true_class/class_methods/deep_freeze_spec.rb +1 -7
- data/spec/unit/ice_nine/recursion_guard/frozen/guard_spec.rb +28 -0
- data/spec/unit/ice_nine/recursion_guard/object_set/guard_spec.rb +31 -0
- data/spec/unit/object/deep_freeze_spec.rb +3 -9
- metadata +54 -41
- data/spec/unit/ice_nine/recursion_guard/class_methods/guard_spec.rb +0 -33
@@ -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
|
-
|
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 '
|
40
|
-
expect { subject }.
|
26
|
+
it 'leaves the object frozen' do
|
27
|
+
expect { subject }.not_to change(value, :frozen?).from(true)
|
41
28
|
end
|
42
29
|
|
43
|
-
it '
|
44
|
-
expect(subject.instance_variable_get(:@a)).
|
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
|