police-dataflow 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,6 @@
1
+ # Label that tests the autoflow behavior.
2
+ class AutoFlowFixture < Police::DataFlow::Label
3
+ def self.autoflow?
4
+ true
5
+ end
6
+ end # class AutoFlowFixture
@@ -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: []