police-dataflow 0.0.1
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.
- data/.document +5 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +9 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/lib/police-dataflow.rb +2 -0
- data/lib/police/dataflow.rb +16 -0
- data/lib/police/dataflow/core_extensions.rb +12 -0
- data/lib/police/dataflow/guarding.rb +16 -0
- data/lib/police/dataflow/label.rb +86 -0
- data/lib/police/dataflow/labeling.rb +71 -0
- data/lib/police/dataflow/proxies.rb +51 -0
- data/lib/police/dataflow/proxy_base.rb +132 -0
- data/lib/police/dataflow/proxying.rb +179 -0
- data/police-dataflow.gemspec +62 -0
- data/test/dataflow/core_extensions_test.rb +51 -0
- data/test/dataflow/labeling_test.rb +74 -0
- data/test/dataflow/proxies_test.rb +40 -0
- data/test/dataflow/proxy_base_test.rb +145 -0
- data/test/dataflow/proxying_test.rb +287 -0
- data/test/helper.rb +23 -0
- data/test/helpers/auto_flow_fixture.rb +6 -0
- data/test/helpers/no_flow_fixture.rb +14 -0
- data/test/helpers/proxying_fixture.rb +45 -0
- metadata +76 -0
@@ -0,0 +1,287 @@
|
|
1
|
+
require File.expand_path('../helper.rb', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Police::DataFlow::Proxying do
|
4
|
+
describe '#add_class_methods' do
|
5
|
+
before do
|
6
|
+
@proxy_class = Class.new BasicObject do
|
7
|
+
def self.__police_classes__
|
8
|
+
[NoFlowFixture]
|
9
|
+
end
|
10
|
+
alias object_id __id__
|
11
|
+
end
|
12
|
+
@proxied = ProxyingFixture.new
|
13
|
+
@proxy = @proxy_class.new
|
14
|
+
@proxy.instance_exec(@proxied) { |p| @__police_proxied__ = p }
|
15
|
+
|
16
|
+
Police::DataFlow::Proxying.add_class_methods @proxy_class, ProxyingFixture
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'adds public methods' do
|
20
|
+
@proxy_class.public_method_defined?(:length).must_equal true
|
21
|
+
@proxy_class.public_method_defined?(:==).must_equal true
|
22
|
+
@proxy_class.public_method_defined?(:<=>).must_equal true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'adds a protected method' do
|
26
|
+
@proxy_class.protected_method_defined?(:add).must_equal true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'adds a private method' do
|
30
|
+
@proxy_class.private_method_defined?(:log).must_equal true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#add_class_method' do
|
35
|
+
before do
|
36
|
+
@proxy_class = Class.new BasicObject do
|
37
|
+
def self.__police_classes__
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@proxied = ProxyingFixture.new
|
42
|
+
@proxy = @proxy_class.new
|
43
|
+
@proxy.instance_exec(@proxied) { |p| @__police_proxied__ = p }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'with protected method with arguments' do
|
47
|
+
before do
|
48
|
+
@method = ProxyingFixture.instance_method :add
|
49
|
+
Police::DataFlow::Proxying.add_class_method @proxy_class, @method,
|
50
|
+
:protected
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'defines the proxying method' do
|
54
|
+
@proxy_class.protected_method_defined?(:add).must_equal true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "has the proxying method's arity match the original" do
|
58
|
+
@proxy_class.instance_method(:add).arity.must_equal @method.arity
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'proxies the method' do
|
62
|
+
@proxy.__send__(:add, 'One', 'Two').must_equal 'One, Two'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'with public method with variable arguments and blocks' do
|
67
|
+
before do
|
68
|
+
@method = ProxyingFixture.instance_method :route
|
69
|
+
Police::DataFlow::Proxying.add_class_method @proxy_class, @method,
|
70
|
+
:public
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'defines the proxying method' do
|
74
|
+
@proxy_class.public_method_defined?(:route).must_equal true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "has the proxying method's arity match the original" do
|
78
|
+
@proxy_class.instance_method(:route).arity.must_equal @method.arity
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'proxies the method without a block' do
|
82
|
+
@proxy.route('One', 'Two').must_equal ['One', 'Two']
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'proxies the method with a block' do
|
86
|
+
result = []
|
87
|
+
@proxy.route('One', 'Two') { |*args| result << args }
|
88
|
+
result.must_equal [['One', 'Two']]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'proxies protected methods' do
|
93
|
+
Police::DataFlow::Proxying.add_class_method @proxy_class,
|
94
|
+
ProxyingFixture.instance_method(:add), :protected
|
95
|
+
@proxy_class.protected_method_defined?(:add).must_equal true
|
96
|
+
@proxy.__send__(:add, 'One', 'Two').must_equal 'One, Two'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#proxy_method_definition' do
|
101
|
+
it 'returns a non-empty string for a public method' do
|
102
|
+
Police::DataFlow::Proxying.proxy_method_definition([AutoFlowFixture],
|
103
|
+
ProxyingFixture.instance_method(:length), :public).length.wont_equal 0
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'returns a non-empty string for a private method' do
|
107
|
+
Police::DataFlow::Proxying.proxy_method_definition([AutoFlowFixture],
|
108
|
+
ProxyingFixture.instance_method(:length), :private).length.
|
109
|
+
wont_equal 0
|
110
|
+
end
|
111
|
+
|
112
|
+
# NOTE: testing the actual behavior would just duplicate the tests for
|
113
|
+
# add_class_method
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#proxy_method_call' do
|
117
|
+
it 'works for a public method without a block' do
|
118
|
+
Police::DataFlow::Proxying.proxy_method_call(
|
119
|
+
ProxyingFixture.instance_method(:length), :public, false).
|
120
|
+
must_equal '@__police_proxied__.length()'
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'works for a protected method without a block' do
|
124
|
+
Police::DataFlow::Proxying.proxy_method_call(
|
125
|
+
ProxyingFixture.instance_method(:add), :protected, false).
|
126
|
+
must_equal '@__police_proxied__.__send__(:add, arg1, arg2)'
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'works for a public method with a block' do
|
130
|
+
Police::DataFlow::Proxying.proxy_method_call(
|
131
|
+
ProxyingFixture.instance_method(:length), :public, true).
|
132
|
+
must_equal '@__police_proxied__.length(&block)'
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'works for a private method with a block' do
|
136
|
+
Police::DataFlow::Proxying.proxy_method_call(
|
137
|
+
ProxyingFixture.instance_method(:length), :private, true).
|
138
|
+
must_equal '@__police_proxied__.__send__(:length, &block)'
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'works for a private method with arguments and a block' do
|
142
|
+
Police::DataFlow::Proxying.proxy_method_call(
|
143
|
+
ProxyingFixture.instance_method(:log), :private, true).must_equal(
|
144
|
+
'@__police_proxied__.__send__(:log, arg1, arg2, *args, &block)')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#proxy_yield_args_decorating' do
|
149
|
+
let(:method) { ProxyingFixture.instance_method(:add) }
|
150
|
+
|
151
|
+
it 'is empty if no label class is filtering' do
|
152
|
+
Police::DataFlow::Proxying.proxy_yield_args_decorating([NoFlowFixture],
|
153
|
+
method).must_equal ''
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'works for one filtering label class' do
|
157
|
+
golden = 'labels = @__police_labels__; ' \
|
158
|
+
"labels[#{AutoFlowFixture.__id__}].each { |label, _| " \
|
159
|
+
"label.sample_yield_args_hook(self, yield_args, arg1, arg2) }"
|
160
|
+
Police::DataFlow::Proxying.proxy_yield_args_decorating(
|
161
|
+
[NoFlowFixture, AutoFlowFixture], method).must_equal golden
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'works for two filtering label classes' do
|
165
|
+
label2_class = Class.new BasicObject do
|
166
|
+
def self.yield_args_hook(method_name)
|
167
|
+
:"#{method_name}_ah"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
golden = 'labels = @__police_labels__; ' \
|
171
|
+
"labels[#{AutoFlowFixture.__id__}].each { |label, _| " \
|
172
|
+
"label.sample_yield_args_hook(self, yield_args, arg1, arg2) }; " \
|
173
|
+
"labels[#{label2_class.__id__}].each { |label, _| " \
|
174
|
+
"label.add_ah(self, yield_args, arg1, arg2) }"
|
175
|
+
Police::DataFlow::Proxying.proxy_yield_args_decorating([NoFlowFixture,
|
176
|
+
AutoFlowFixture, label2_class], method).must_equal golden
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe '#proxy_return_decorating' do
|
181
|
+
let(:method) { ProxyingFixture.instance_method(:add) }
|
182
|
+
|
183
|
+
it 'is empty if no label class is filtering' do
|
184
|
+
Police::DataFlow::Proxying.proxy_return_decorating([NoFlowFixture],
|
185
|
+
method).must_equal ''
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'works for one filtering label class' do
|
189
|
+
golden = 'labels = @__police_labels__; ' \
|
190
|
+
"labels[#{AutoFlowFixture.__id__}].each { |label, _| " \
|
191
|
+
"return_value = label.sample_return_hook(return_value, self, arg1, " \
|
192
|
+
"arg2) }"
|
193
|
+
Police::DataFlow::Proxying.proxy_return_decorating(
|
194
|
+
[NoFlowFixture, AutoFlowFixture], method).must_equal golden
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'works for two filtering label classes' do
|
198
|
+
label2_class = Class.new BasicObject do
|
199
|
+
def self.return_hook(method_name)
|
200
|
+
:"#{method_name}_rh"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
golden = 'labels = @__police_labels__; ' \
|
204
|
+
"labels[#{AutoFlowFixture.__id__}].each { |label, _| " \
|
205
|
+
"return_value = label.sample_return_hook(return_value, self, arg1, " \
|
206
|
+
"arg2) }; " \
|
207
|
+
"labels[#{label2_class.__id__}].each { |label, _| " \
|
208
|
+
"return_value = label.add_rh(return_value, self, arg1, arg2) }"
|
209
|
+
Police::DataFlow::Proxying.proxy_return_decorating([NoFlowFixture,
|
210
|
+
AutoFlowFixture, label2_class], method).must_equal golden
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe '#proxy_argument_list' do
|
215
|
+
describe 'without block-capturing' do
|
216
|
+
it 'works for an argument-less method' do
|
217
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
218
|
+
ProxyingFixture.instance_method(:length), false).must_equal ''
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'works for a one-argument method' do
|
222
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
223
|
+
ProxyingFixture.instance_method(:==), false).must_equal 'arg1'
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'works for a two-argument method' do
|
227
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
228
|
+
ProxyingFixture.instance_method(:add), false).
|
229
|
+
must_equal 'arg1, arg2'
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'works for a variable-argument method' do
|
233
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
234
|
+
ProxyingFixture.instance_method(:route), false).must_equal '*args'
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'works for one fixed + variable-argument method' do
|
238
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
239
|
+
ProxyingFixture.instance_method(:<=>), false).
|
240
|
+
must_equal 'arg1, *args'
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'works for two fixed + variable-argument method' do
|
244
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
245
|
+
ProxyingFixture.instance_method(:log), false).
|
246
|
+
must_equal 'arg1, arg2, *args'
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe 'with block-capturing' do
|
251
|
+
it 'works for an argument-less method' do
|
252
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
253
|
+
ProxyingFixture.instance_method(:length), true).must_equal '&block'
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'works for a one-argument method' do
|
257
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
258
|
+
ProxyingFixture.instance_method(:==), true).
|
259
|
+
must_equal 'arg1, &block'
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'works for a two-argument method' do
|
263
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
264
|
+
ProxyingFixture.instance_method(:add), true).
|
265
|
+
must_equal 'arg1, arg2, &block'
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'works for a variable-argument method' do
|
269
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
270
|
+
ProxyingFixture.instance_method(:route), true).
|
271
|
+
must_equal '*args, &block'
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'works for one fixed + variable-argument method' do
|
275
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
276
|
+
ProxyingFixture.instance_method(:<=>), true).
|
277
|
+
must_equal 'arg1, *args, &block'
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'works for two fixed + variable-argument method' do
|
281
|
+
Police::DataFlow::Proxying.proxy_argument_list(
|
282
|
+
ProxyingFixture.instance_method(:log), true).
|
283
|
+
must_equal 'arg1, arg2, *args, &block'
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'minitest/unit'
|
11
|
+
require 'minitest/spec'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
require 'police-dataflow'
|
16
|
+
|
17
|
+
class MiniTest::Unit::TestCase
|
18
|
+
end
|
19
|
+
|
20
|
+
Dir[File.expand_path('helpers/**/*.rb', File.dirname(__FILE__))].
|
21
|
+
each { |h| require h }
|
22
|
+
|
23
|
+
MiniTest::Unit.autorun
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Label that tests the no-autoflow behavior.
|
2
|
+
class NoFlowFixture < Police::DataFlow::Label
|
3
|
+
def self.autoflow?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.return_hook(method_name)
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.yield_args_hook(filter_name)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end # class NoFlowFixture
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class ProxyingFixture
|
2
|
+
# Zero arguments.
|
3
|
+
def length; end
|
4
|
+
|
5
|
+
# One argument.
|
6
|
+
def ==(other)
|
7
|
+
'== proxied'
|
8
|
+
end
|
9
|
+
|
10
|
+
# Reserved method proxying test.
|
11
|
+
def !=(other)
|
12
|
+
'!= proxied'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Two arguments.
|
16
|
+
def add(arg1, arg2)
|
17
|
+
"#{arg1}, #{arg2}"
|
18
|
+
end
|
19
|
+
protected :add
|
20
|
+
|
21
|
+
# Variable args.
|
22
|
+
def route(*rest)
|
23
|
+
if block_given?
|
24
|
+
yield(*rest)
|
25
|
+
else
|
26
|
+
rest
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# One fixed + variable args.
|
31
|
+
def <=>(arg1, *rest); end
|
32
|
+
|
33
|
+
# Two fixed + variable args.
|
34
|
+
def log(arg1, arg2, *rest); end
|
35
|
+
private :log
|
36
|
+
|
37
|
+
# Magic methods: magic_* methods return their name and args
|
38
|
+
def method_missing(name, *args)
|
39
|
+
if name[0, 6] == 'magic_'
|
40
|
+
[name[6..-1]] + args
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end # class ProxyingFixture
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: police-dataflow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Victor Costan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-28 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Pure Ruby implementtion of data flow label propagation.
|
15
|
+
email: victor@costan.us
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- LICENSE.txt
|
20
|
+
- README.markdown
|
21
|
+
files:
|
22
|
+
- .document
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- LICENSE.txt
|
26
|
+
- README.markdown
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- lib/police-dataflow.rb
|
30
|
+
- lib/police/dataflow.rb
|
31
|
+
- lib/police/dataflow/core_extensions.rb
|
32
|
+
- lib/police/dataflow/guarding.rb
|
33
|
+
- lib/police/dataflow/label.rb
|
34
|
+
- lib/police/dataflow/labeling.rb
|
35
|
+
- lib/police/dataflow/proxies.rb
|
36
|
+
- lib/police/dataflow/proxy_base.rb
|
37
|
+
- lib/police/dataflow/proxying.rb
|
38
|
+
- police-dataflow.gemspec
|
39
|
+
- test/dataflow/core_extensions_test.rb
|
40
|
+
- test/dataflow/labeling_test.rb
|
41
|
+
- test/dataflow/proxies_test.rb
|
42
|
+
- test/dataflow/proxy_base_test.rb
|
43
|
+
- test/dataflow/proxying_test.rb
|
44
|
+
- test/helper.rb
|
45
|
+
- test/helpers/auto_flow_fixture.rb
|
46
|
+
- test/helpers/no_flow_fixture.rb
|
47
|
+
- test/helpers/proxying_fixture.rb
|
48
|
+
homepage: http://github.com/csail/police
|
49
|
+
licenses:
|
50
|
+
- MIT
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
hash: -2247175555396933840
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.8.21
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Data flow label propagation
|
76
|
+
test_files: []
|