police-dataflow 0.0.1 → 0.0.2
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 +15 -0
- data/Gemfile +8 -7
- data/Gemfile.lock +57 -18
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/police/dataflow.rb +2 -1
- data/lib/police/dataflow/core_extensions.rb +18 -4
- data/lib/police/dataflow/gate_profiles/ruby1.9.3 +167 -0
- data/lib/police/dataflow/gating.rb +70 -0
- data/lib/police/dataflow/label.rb +19 -14
- data/lib/police/dataflow/labeling.rb +103 -22
- data/lib/police/dataflow/proxies.rb +33 -5
- data/lib/police/dataflow/proxy_base.rb +80 -40
- data/lib/police/dataflow/proxy_numeric.rb +22 -0
- data/lib/police/dataflow/proxying.rb +215 -40
- data/police-dataflow.gemspec +11 -15
- data/tasks/info.rake +43 -0
- data/test/dataflow/core_extensions_test.rb +8 -8
- data/test/dataflow/labeling_test.rb +324 -15
- data/test/dataflow/proxies_test.rb +7 -11
- data/test/dataflow/proxy_base_test.rb +199 -72
- data/test/dataflow/proxy_numeric_test.rb +45 -0
- data/test/dataflow/proxying_test.rb +333 -80
- data/test/helper.rb +2 -2
- data/test/helpers/hooks_flow_fixture.rb +22 -0
- data/test/helpers/no_flow_fixture.rb +4 -4
- data/test/helpers/proxying_fixture.rb +11 -7
- data/test/helpers/sticky_fixture.rb +14 -0
- metadata +12 -12
- data/lib/police/dataflow/guarding.rb +0 -16
- data/test/helpers/auto_flow_fixture.rb +0 -6
@@ -4,44 +4,44 @@ describe Police::DataFlow do
|
|
4
4
|
before do
|
5
5
|
@object = 'Hello'
|
6
6
|
@class = @object.class
|
7
|
-
@label =
|
7
|
+
@label = StickyFixture.new
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
describe '#label' do
|
11
11
|
describe 'with a single label' do
|
12
12
|
before do
|
13
13
|
@object = Police::DataFlow.label @object, @label
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
it 'labels the object correctly' do
|
17
17
|
Police::DataFlow.labels(@object).must_equal [@label]
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it 'is idempotent' do
|
21
21
|
same_object = Police::DataFlow.label @object, @label
|
22
22
|
same_object.must_equal @object
|
23
23
|
Police::DataFlow.labels(@object).must_equal [@label]
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
it 'returns a working proxy' do
|
27
27
|
@object.length.must_equal 5
|
28
28
|
@object.class.must_equal @class
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
it 'returns a label-preserving proxy' do
|
32
32
|
@object << ' world'
|
33
33
|
@object.length.must_equal 11
|
34
34
|
Police::DataFlow.labels(@object).must_equal [@label]
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
describe 'with two labels' do
|
39
39
|
before do
|
40
40
|
@label2 = NoFlowFixture.new
|
41
41
|
@object = Police::DataFlow.label @object, @label
|
42
42
|
@object = Police::DataFlow.label @object, @label2
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
it 'labels the object correctly' do
|
46
46
|
Set.new(Police::DataFlow.labels(@object)).
|
47
47
|
must_equal Set.new([@label, @label2])
|
@@ -4,64 +4,89 @@ describe Police::DataFlow do
|
|
4
4
|
before do
|
5
5
|
@object = 'Hello'
|
6
6
|
@class = @object.class
|
7
|
-
@p_label =
|
7
|
+
@p_label = StickyFixture.new
|
8
8
|
end
|
9
|
-
|
10
|
-
describe '
|
9
|
+
|
10
|
+
describe '.label' do
|
11
11
|
describe 'with a single label' do
|
12
12
|
before do
|
13
13
|
@object = Police::DataFlow.label @object, @p_label
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
it 'labels the object correctly' do
|
17
17
|
Police::DataFlow.labels(@object).must_equal [@p_label]
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it 'is idempotent' do
|
21
21
|
same_object = Police::DataFlow.label @object, @p_label
|
22
22
|
same_object.must_equal @object
|
23
|
+
same_object.__id__.must_equal @object.__id__
|
23
24
|
Police::DataFlow.labels(@object).must_equal [@p_label]
|
24
25
|
end
|
25
|
-
|
26
|
+
|
26
27
|
it 'is idempotent vs label type' do
|
27
|
-
|
28
|
+
p_label2 = StickyFixture.new
|
29
|
+
same_object = Police::DataFlow.label @object, p_label2
|
30
|
+
same_object.must_equal @object
|
31
|
+
same_object.__id__.must_equal @object.__id__
|
32
|
+
Police::DataFlow.labels(@object).sort_by(&:__id__).must_equal(
|
33
|
+
[@p_label, p_label2].sort_by(&:__id__))
|
28
34
|
end
|
29
|
-
|
35
|
+
|
30
36
|
it 'returns a working proxy' do
|
31
37
|
@object.length.must_equal 5
|
32
38
|
@object.class.must_equal @class
|
33
39
|
end
|
34
|
-
|
40
|
+
|
35
41
|
it 'returns a label-preserving proxy' do
|
36
42
|
@object << ' world'
|
37
43
|
@object.length.must_equal 11
|
38
44
|
Police::DataFlow.labels(@object).must_equal [@p_label]
|
39
45
|
end
|
40
|
-
|
46
|
+
|
41
47
|
it 'returns a label-propagating proxy' do
|
42
48
|
Police::DataFlow.labels(@object[2..5]).must_equal [@p_label]
|
43
49
|
end
|
44
50
|
end
|
45
|
-
|
51
|
+
|
46
52
|
describe 'with two labels' do
|
47
53
|
before do
|
48
54
|
@n_label = NoFlowFixture.new
|
49
55
|
@object = Police::DataFlow.label @object, @p_label
|
50
56
|
@object = Police::DataFlow.label @object, @n_label
|
51
57
|
end
|
52
|
-
|
58
|
+
|
53
59
|
it 'labels the object correctly' do
|
54
60
|
Set.new(Police::DataFlow.labels(@object)).
|
55
61
|
must_equal Set.new([@p_label, @n_label])
|
56
62
|
end
|
57
|
-
|
63
|
+
|
58
64
|
it 'propagates the labels correctly' do
|
59
65
|
Police::DataFlow.labels(@object[2..5]).must_equal [@p_label]
|
60
66
|
end
|
61
67
|
end
|
68
|
+
|
69
|
+
describe 'on built-in Fixnums' do
|
70
|
+
before do
|
71
|
+
@number = Police::DataFlow.label 21, @p_label
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns a working proxy' do
|
75
|
+
(@number * 2).must_equal 42
|
76
|
+
(2 * @number).must_equal 42
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns a label-propagating proxy' do
|
80
|
+
Police::DataFlow.labels(@number * 2).must_equal [@p_label]
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns a proxy that coerces numbers correctly' do
|
84
|
+
Police::DataFlow.labels(2 * @number).must_equal [@p_label]
|
85
|
+
end
|
86
|
+
end
|
62
87
|
end
|
63
|
-
|
64
|
-
describe '
|
88
|
+
|
89
|
+
describe '.labels' do
|
65
90
|
it 'returns an empty array for un-labeled objects' do
|
66
91
|
Police::DataFlow.labels(@object).must_equal []
|
67
92
|
end
|
@@ -71,4 +96,288 @@ describe Police::DataFlow do
|
|
71
96
|
Police::DataFlow.labels(labeled).must_equal [@p_label]
|
72
97
|
end
|
73
98
|
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
describe Police::DataFlow::Labeling do
|
103
|
+
before do
|
104
|
+
@n1_label = NoFlowFixture.new
|
105
|
+
@n2_label = NoFlowFixture.new
|
106
|
+
@s1_label = StickyFixture.new
|
107
|
+
@s2_label = StickyFixture.new
|
108
|
+
@h1_label = HooksFlowFixture.new
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '.add_label_to_set' do
|
112
|
+
before do
|
113
|
+
@set = {
|
114
|
+
NoFlowFixture.__id__ => {
|
115
|
+
@n1_label => true,
|
116
|
+
@n2_label => true
|
117
|
+
},
|
118
|
+
StickyFixture.__id__ => {
|
119
|
+
@s1_label => true
|
120
|
+
}
|
121
|
+
}
|
122
|
+
@set_n = @set[NoFlowFixture.__id__]
|
123
|
+
@set_s = @set[StickyFixture.__id__]
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'no-ops when the label is in the set' do
|
127
|
+
Police::DataFlow::Labeling.add_label_to_set(@n1_label, @set).must_equal(
|
128
|
+
false)
|
129
|
+
@set[NoFlowFixture.__id__].__id__.must_equal @set_n.__id__
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'adds labels to existing groups' do
|
133
|
+
Police::DataFlow::Labeling.add_label_to_set(@s2_label, @set).must_equal(
|
134
|
+
false)
|
135
|
+
@set[StickyFixture.__id__].__id__.must_equal @set_s.__id__
|
136
|
+
@set[StickyFixture.__id__].must_equal @s1_label => true,
|
137
|
+
@s2_label => true
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'creates new groups when necessary' do
|
141
|
+
Police::DataFlow::Labeling.add_label_to_set(@h1_label, @set).must_equal(
|
142
|
+
true)
|
143
|
+
@set[HooksFlowFixture.__id__].must_equal @h1_label => true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '.merge_sets!' do
|
148
|
+
before do
|
149
|
+
@target = {
|
150
|
+
NoFlowFixture.__id__ => {
|
151
|
+
@n1_label => true,
|
152
|
+
@n2_label => true
|
153
|
+
},
|
154
|
+
StickyFixture.__id__ => {
|
155
|
+
@s1_label => true
|
156
|
+
}
|
157
|
+
}
|
158
|
+
@target_n = @target[NoFlowFixture.__id__]
|
159
|
+
@target_s = @target[StickyFixture.__id__]
|
160
|
+
@source = {
|
161
|
+
NoFlowFixture.__id__ => {
|
162
|
+
@n2_label => true
|
163
|
+
},
|
164
|
+
StickyFixture.__id__ => {
|
165
|
+
@s2_label => true
|
166
|
+
},
|
167
|
+
HooksFlowFixture.__id__ => {
|
168
|
+
@h1_label => true
|
169
|
+
}
|
170
|
+
}
|
171
|
+
Police::DataFlow::Labeling.merge_sets! @target, @source
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'behaves when target is a superset of source' do
|
175
|
+
@target[NoFlowFixture.__id__].must_equal(
|
176
|
+
@n1_label => true, @n2_label => true)
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'merges label sets' do
|
180
|
+
@target[StickyFixture.__id__].must_equal(
|
181
|
+
@s1_label => true, @s2_label => true)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'adds missing sets' do
|
185
|
+
@target[HooksFlowFixture.__id__].must_equal @h1_label => true
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'does not create unnecessary objects' do
|
189
|
+
@target[NoFlowFixture.__id__].__id__.must_equal @target_n.__id__
|
190
|
+
@target[StickyFixture.__id__].__id__.must_equal @target_s.__id__
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'does not reuse source objects' do
|
194
|
+
@target[HooksFlowFixture.__id__].__id__.wont_equal(
|
195
|
+
@source[HooksFlowFixture.__id__].__id__)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '.bulky_sticky_label' do
|
200
|
+
before do
|
201
|
+
@set = {
|
202
|
+
NoFlowFixture.__id__ => {
|
203
|
+
@n1_label => true,
|
204
|
+
@n2_label => true
|
205
|
+
},
|
206
|
+
StickyFixture.__id__ => {
|
207
|
+
@s1_label => true
|
208
|
+
}
|
209
|
+
}
|
210
|
+
@set_n = @set[NoFlowFixture.__id__]
|
211
|
+
@set_s = @set[StickyFixture.__id__]
|
212
|
+
end
|
213
|
+
|
214
|
+
describe 'with an unlabeled object' do
|
215
|
+
before do
|
216
|
+
@object = 'Hello'
|
217
|
+
@labeled = Police::DataFlow::Labeling.bulk_sticky_label @object, @set
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'labels the object correctly' do
|
221
|
+
Police::DataFlow.labels(@labeled).sort_by(&:__id__).must_equal(
|
222
|
+
[@n1_label, @n2_label, @s1_label].sort_by(&:__id__))
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'proxies the object correctly' do
|
226
|
+
@labeled.length.must_equal 5
|
227
|
+
@labeled[1].must_equal 'e'
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'does not reuse the label set' do
|
231
|
+
@labeled.__police_labels__.__id__.wont_equal @set.__id__
|
232
|
+
@labeled.__police_stickies__.__id__.wont_equal @set.__id__
|
233
|
+
@labeled.__police_labels__[NoFlowFixture.__id__].__id__.wont_equal(
|
234
|
+
@set_n.__id__)
|
235
|
+
@labeled.__police_labels__[StickyFixture.__id__].__id__.wont_equal(
|
236
|
+
@set_s.__id__)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe 'with a labeled object with enough groups' do
|
241
|
+
before do
|
242
|
+
@original = 'Hello'
|
243
|
+
@object = Police::DataFlow.label @original, @n1_label
|
244
|
+
@object = Police::DataFlow.label @object, @s2_label
|
245
|
+
@object = Police::DataFlow.label @object, @h1_label
|
246
|
+
|
247
|
+
@set2_n = @object.__police_labels__[NoFlowFixture.__id__]
|
248
|
+
@set2_s = @object.__police_labels__[StickyFixture.__id__]
|
249
|
+
|
250
|
+
@labeled = Police::DataFlow::Labeling.bulk_sticky_label @object, @set
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'labels the object correctly' do
|
254
|
+
Police::DataFlow.labels(@labeled).sort_by(&:__id__).must_equal(
|
255
|
+
[@n1_label, @n2_label, @s1_label, @s2_label, @h1_label].
|
256
|
+
sort_by(&:__id__))
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'proxies the object correctly' do
|
260
|
+
@labeled.length.must_equal 5
|
261
|
+
@labeled[1].must_equal 'e'
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'reuses the proxy' do
|
265
|
+
@object.__id__.must_equal @labeled.__id__
|
266
|
+
Police::DataFlow::Labeling.proxy_class(@object).must_equal(
|
267
|
+
Police::DataFlow::Labeling.proxy_class(@labeled))
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'reuses the label set groups' do
|
271
|
+
@object.__police_labels__[NoFlowFixture.__id__].__id__.must_equal(
|
272
|
+
@set2_n.__id__)
|
273
|
+
@object.__police_labels__[StickyFixture.__id__].__id__.must_equal(
|
274
|
+
@set2_s.__id__)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe 'with a labeled object that needs a new group' do
|
279
|
+
before do
|
280
|
+
@original = 'Hello'
|
281
|
+
@object = Police::DataFlow.label @original, @n1_label
|
282
|
+
@object = Police::DataFlow.label @object, @h1_label
|
283
|
+
|
284
|
+
@set2_n = @object.__police_labels__[NoFlowFixture.__id__]
|
285
|
+
|
286
|
+
@labeled = Police::DataFlow::Labeling.bulk_sticky_label @object, @set
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'labels the object correctly' do
|
290
|
+
Police::DataFlow.labels(@labeled).sort_by(&:__id__).must_equal(
|
291
|
+
[@n1_label, @n2_label, @s1_label, @h1_label].
|
292
|
+
sort_by(&:__id__))
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'proxies the object correctly' do
|
296
|
+
@labeled.length.must_equal 5
|
297
|
+
@labeled[1].must_equal 'e'
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'creates a new proxy' do
|
301
|
+
@object.__id__.wont_equal @labeled.__id__
|
302
|
+
Police::DataFlow::Labeling.proxy_class(@object).wont_equal(
|
303
|
+
Police::DataFlow::Labeling.proxy_class(@labeled))
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'reuses label set groups when possible' do
|
307
|
+
@object.__police_labels__[NoFlowFixture.__id__].__id__.must_equal(
|
308
|
+
@set2_n.__id__)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe '.dup' do
|
314
|
+
before do
|
315
|
+
@set = {
|
316
|
+
NoFlowFixture.__id__ => {
|
317
|
+
@n1_label => true,
|
318
|
+
@n2_label => true
|
319
|
+
},
|
320
|
+
StickyFixture.__id__ => {
|
321
|
+
@s1_label => true
|
322
|
+
}
|
323
|
+
}
|
324
|
+
@set_n = @set[NoFlowFixture.__id__]
|
325
|
+
@set_s = @set[StickyFixture.__id__]
|
326
|
+
@copy = Police::DataFlow::Labeling.dup_set @set
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'does not change the source set' do
|
330
|
+
@set[NoFlowFixture.__id__].__id__.must_equal @set_n.__id__
|
331
|
+
@set[StickyFixture.__id__].__id__.must_equal @set_s.__id__
|
332
|
+
@set_n.must_equal @n1_label => true, @n2_label => true
|
333
|
+
@set_s.must_equal @s1_label => true
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'copies the groups in the source set' do
|
337
|
+
@copy[NoFlowFixture.__id__].must_equal @n1_label => true,
|
338
|
+
@n2_label => true
|
339
|
+
@copy[StickyFixture.__id__].must_equal @s1_label => true
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'does not reuse the groups in the source set' do
|
343
|
+
@copy[NoFlowFixture.__id__].__id__.wont_equal @set_n.__id__
|
344
|
+
@copy[StickyFixture.__id__].__id__.wont_equal @set_s.__id__
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'does not create new groups' do
|
348
|
+
@copy.keys.must_equal [NoFlowFixture.__id__, StickyFixture.__id__]
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
describe '.proxy_class' do
|
353
|
+
before do
|
354
|
+
@object = 'Hello'
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'returns nil for un-labeled objects' do
|
358
|
+
Police::DataFlow::Labeling.proxy_class(@object).must_equal nil
|
359
|
+
end
|
360
|
+
|
361
|
+
describe 'for proxied objects' do
|
362
|
+
before do
|
363
|
+
@labeled = Police::DataFlow.label @object, @s1_label
|
364
|
+
end
|
365
|
+
|
366
|
+
it 'returns a ProxyBase subclass' do
|
367
|
+
Police::DataFlow::Labeling.proxy_class(@labeled).superclass.must_equal(
|
368
|
+
Police::DataFlow::ProxyBase)
|
369
|
+
end
|
370
|
+
|
371
|
+
it "returns the proxy's real class" do
|
372
|
+
klass = Police::DataFlow::Labeling.proxy_class @labeled
|
373
|
+
klass.class_eval do
|
374
|
+
def boom
|
375
|
+
'headshot'
|
376
|
+
end
|
377
|
+
end
|
378
|
+
lambda { @object.boom }.must_raise NoMethodError
|
379
|
+
@labeled.boom.must_equal 'headshot'
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
74
383
|
end
|
@@ -4,35 +4,31 @@ describe Police::DataFlow::Proxies do
|
|
4
4
|
describe '#for' do
|
5
5
|
before do
|
6
6
|
@label_set = {}
|
7
|
-
|
8
|
-
Police::DataFlow::Labeling.add_label_to_set NoFlowFixture.new,
|
9
|
-
@label_set, @autoflow_set
|
7
|
+
Police::DataFlow::Labeling.add_label_to_set NoFlowFixture.new, @label_set
|
10
8
|
end
|
11
|
-
|
9
|
+
|
12
10
|
let(:result) do
|
13
11
|
Police::DataFlow::Proxies.for ProxyingFixture, @label_set
|
14
12
|
end
|
15
13
|
after { Police::DataFlow::Proxies.clear_cache }
|
16
|
-
|
14
|
+
|
17
15
|
it 'creates a Police::DataFlow::ProxyBase subclass' do
|
18
16
|
result.superclass.must_equal Police::DataFlow::ProxyBase
|
19
17
|
end
|
20
|
-
|
18
|
+
|
21
19
|
it 'caches classes' do
|
22
20
|
Police::DataFlow::Proxies.for(ProxyingFixture, @label_set).
|
23
21
|
must_equal result
|
24
22
|
end
|
25
|
-
|
23
|
+
|
26
24
|
it 'creates different proxies for different classes' do
|
27
25
|
Police::DataFlow::Proxies.for(Class.new(ProxyingFixture), @label_set).
|
28
26
|
wont_equal result
|
29
27
|
end
|
30
|
-
|
28
|
+
|
31
29
|
it 'creates different proxies for sets of different label classes' do
|
32
30
|
label_set = @label_set.clone
|
33
|
-
|
34
|
-
Police::DataFlow::Labeling.add_label_to_set AutoFlowFixture.new,
|
35
|
-
label_set, autoflow_set
|
31
|
+
Police::DataFlow::Labeling.add_label_to_set StickyFixture.new, label_set
|
36
32
|
Police::DataFlow::Proxies.for(ProxyingFixture, label_set).
|
37
33
|
wont_equal result
|
38
34
|
end
|