police-dataflow 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|