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.
@@ -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: []