dao 7.0.0 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,195 @@
1
+ require 'test/unit'
2
+
3
+ testdir = File.expand_path(File.dirname(__FILE__))
4
+ rootdir = File.dirname(testdir)
5
+ libdir = File.join(rootdir, 'lib')
6
+
7
+ STDOUT.sync = true
8
+
9
+ $:.unshift(testdir) unless $:.include?(testdir)
10
+ $:.unshift(libdir) unless $:.include?(libdir)
11
+ $:.unshift(rootdir) unless $:.include?(rootdir)
12
+
13
+ class Testing
14
+ class Slug < ::String
15
+ def Slug.for(*args)
16
+ string = args.flatten.compact.join('-')
17
+ words = string.to_s.scan(%r/\w+/)
18
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
19
+ words.delete_if{|word| word.nil? or word.strip.empty?}
20
+ new(words.join('-').downcase)
21
+ end
22
+ end
23
+
24
+ class Context
25
+ attr_accessor :name
26
+
27
+ def initialize(name, *args)
28
+ @name = name
29
+ end
30
+
31
+ def to_s
32
+ Slug.for(name)
33
+ end
34
+ end
35
+ end
36
+
37
+ def Testing(*args, &block)
38
+ Class.new(::Test::Unit::TestCase) do
39
+
40
+ ## class methods
41
+ #
42
+ class << self
43
+ def contexts
44
+ @contexts ||= []
45
+ end
46
+
47
+ def context(*args, &block)
48
+ return contexts.last if(args.empty? and block.nil?)
49
+
50
+ context = Testing::Context.new(*args)
51
+ contexts.push(context)
52
+
53
+ begin
54
+ block.call(context)
55
+ ensure
56
+ contexts.pop
57
+ end
58
+ end
59
+
60
+ def slug_for(*args)
61
+ string = [context, args].flatten.compact.join('-')
62
+ words = string.to_s.scan(%r/\w+/)
63
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
64
+ words.delete_if{|word| word.nil? or word.strip.empty?}
65
+ words.join('-').downcase.sub(/_$/, '')
66
+ end
67
+
68
+ def name() const_get(:Name) end
69
+
70
+ def testno()
71
+ '%05d' % (@testno ||= 0)
72
+ ensure
73
+ @testno += 1
74
+ end
75
+
76
+ def testing(*args, &block)
77
+ method = ["test", testno, slug_for(*args)].delete_if{|part| part.empty?}.join('_')
78
+ define_method(method, &block)
79
+ end
80
+
81
+ def test(*args, &block)
82
+ testing(*args, &block)
83
+ end
84
+
85
+ def setup(&block)
86
+ define_method(:setup, &block) if block
87
+ end
88
+
89
+ def teardown(&block)
90
+ define_method(:teardown, &block) if block
91
+ end
92
+
93
+ def prepare(&block)
94
+ @prepare ||= []
95
+ @prepare.push(block) if block
96
+ @prepare
97
+ end
98
+
99
+ def cleanup(&block)
100
+ @cleanup ||= []
101
+ @cleanup.push(block) if block
102
+ @cleanup
103
+ end
104
+ end
105
+
106
+ ## configure the subclass!
107
+ #
108
+ const_set(:Testno, '0')
109
+ slug = slug_for(*args).gsub(%r/-/,'_')
110
+ name = ['TESTING', '%03d' % const_get(:Testno), slug].delete_if{|part| part.empty?}.join('_')
111
+ name = name.upcase!
112
+ const_set(:Name, name)
113
+ const_set(:Missing, Object.new.freeze)
114
+
115
+ ## instance methods
116
+ #
117
+ alias_method('__assert__', 'assert')
118
+
119
+ def assert(*args, &block)
120
+ if args.size == 1 and args.first.is_a?(Hash)
121
+ options = args.first
122
+ expected = getopt(:expected, options){ missing }
123
+ actual = getopt(:actual, options){ missing }
124
+ if expected == missing and actual == missing
125
+ actual, expected, *ignored = options.to_a.flatten
126
+ end
127
+ expected = expected.call() if expected.respond_to?(:call)
128
+ actual = actual.call() if actual.respond_to?(:call)
129
+ assert_equal(expected, actual)
130
+ end
131
+
132
+ if block
133
+ label = "assert(#{ args.join(' ') })"
134
+ result = nil
135
+ assert_nothing_raised{ result = block.call }
136
+ __assert__(result, label)
137
+ result
138
+ else
139
+ result = args.shift
140
+ label = "assert(#{ args.join(' ') })"
141
+ __assert__(result, label)
142
+ result
143
+ end
144
+ end
145
+
146
+ def missing
147
+ self.class.const_get(:Missing)
148
+ end
149
+
150
+ def getopt(opt, hash, options = nil, &block)
151
+ [opt.to_s, opt.to_s.to_sym].each do |key|
152
+ return hash[key] if hash.has_key?(key)
153
+ end
154
+ default =
155
+ if block
156
+ block.call
157
+ else
158
+ options.is_a?(Hash) ? options[:default] : nil
159
+ end
160
+ return default
161
+ end
162
+
163
+ def subclass_of exception
164
+ class << exception
165
+ def ==(other) super or self > other end
166
+ end
167
+ exception
168
+ end
169
+
170
+ ##
171
+ #
172
+ module_eval(&block)
173
+
174
+ self.setup()
175
+ self.prepare.each{|b| b.call()}
176
+
177
+ at_exit{
178
+ self.teardown()
179
+ self.cleanup.each{|b| b.call()}
180
+ }
181
+
182
+ self
183
+ end
184
+ end
185
+
186
+
187
+ if $0 == __FILE__
188
+
189
+ Testing 'Testing' do
190
+ testing('foo'){ assert true }
191
+ test{ assert true }
192
+ p instance_methods.grep(/test/)
193
+ end
194
+
195
+ end
@@ -0,0 +1,397 @@
1
+
2
+ Testing Wrap do
3
+
4
+ ##
5
+ #
6
+ testing 'that wrap can be included in a class' do
7
+ assert do
8
+ Class.new do
9
+ include Wrap
10
+ end
11
+ end
12
+ end
13
+
14
+ ##
15
+ #
16
+ testing 'that a method can be wrapped ***after*** it is defined' do
17
+ assert do
18
+ wrapped_class do
19
+ def foo() 42 end
20
+
21
+ assert{ new.foo() == 42 }
22
+
23
+ wrap :foo
24
+
25
+ assert{ new.foo() == 42 }
26
+ end
27
+ end
28
+ end
29
+
30
+ ##
31
+ #
32
+ testing 'that a method can be wrapped ***before*** it is defined' do
33
+ assert do
34
+ wrapped_class do
35
+ assert_raises(NoMethodError){ new.foo() }
36
+
37
+ wrap :foo
38
+
39
+ assert_raises(NoMethodError){ new.foo() }
40
+
41
+ define_method(:foo){ accum.push(42) }
42
+
43
+ assert_nothing_raised{ new.foo() }
44
+ end
45
+ end
46
+ end
47
+
48
+ ##
49
+ #
50
+ testing 'that wrapping gives :before and :after goodness' do
51
+ assert do
52
+ wrapped_class do
53
+ wrap :foo
54
+
55
+ define_method(:foo){ accum.push(42) }
56
+ before(:foo){ accum.push(:before) }
57
+ after(:foo){ accum.push(:after) }
58
+
59
+ assert {
60
+ c = new
61
+ c.foo()
62
+ c.accum == [:before, 42, :after]
63
+ }
64
+ end
65
+ end
66
+ end
67
+
68
+ ##
69
+ #
70
+ testing 'that :before and :after will auto-wrap methods iff needed' do
71
+ assert do
72
+ wrapped_class do
73
+ before(:foo){ accum.push(:before) }
74
+ after(:foo){ accum.push(:after) }
75
+
76
+ define_method(:foo){ accum.push(42) }
77
+
78
+ assert {
79
+ c = new
80
+ c.foo()
81
+ c.accum == [:before, 42, :after]
82
+ }
83
+ end
84
+ end
85
+ end
86
+
87
+ ##
88
+ #
89
+ testing 'that callbacks are halted with "false" iff they return "false"' do
90
+ assert do
91
+ wrapped_class do
92
+ wrap :foo
93
+
94
+ define_method(:foo){ accum.push(42) }
95
+
96
+ before(:foo){ accum.push(:foo) }
97
+ before(:foo){ accum.push(:bar); return false}
98
+ before(:foo){ accum.push(:foobar) }
99
+
100
+ assert {
101
+ c = new
102
+ c.foo()
103
+ c.accum == [:foo, :bar]
104
+ }
105
+ end
106
+ end
107
+ end
108
+
109
+ ##
110
+ #
111
+ testing 'that callbacks can be halted with "halt!"' do
112
+ assert do
113
+ wrapped_class do
114
+ wrap :foo
115
+
116
+ define_method(:foo){ accum.push(42) }
117
+
118
+ before(:foo){ accum.push(:foo) }
119
+ before(:foo){ accum.push(:bar); halt!}
120
+ before(:foo){ accum.push(:foobar) }
121
+
122
+ assert {
123
+ c = new
124
+ c.foo()
125
+ c.accum == [:foo, :bar]
126
+ }
127
+ end
128
+ end
129
+
130
+ assert do
131
+ wrapped_class do
132
+ wrap :foo
133
+
134
+ define_method(:foo){ accum.push(42) }
135
+
136
+ after(:foo){ accum.push(:foo) }
137
+ after(:foo){ accum.push(:bar); halt!}
138
+ after(:foo){ accum.push(:foobar) }
139
+
140
+ assert {
141
+ c = new
142
+ c.foo()
143
+ c.accum == [42, :foo, :bar]
144
+ }
145
+ end
146
+ end
147
+ end
148
+
149
+ ##
150
+ #
151
+ testing 'that :before callbacks are passed the number of args they can eat, and no more' do
152
+ c =
153
+ assert do
154
+ wrapped_class do
155
+ wrap :foo
156
+
157
+ define_method(:foo){|*a|}
158
+
159
+ before(:foo){|x| accum.push([x]) }
160
+ before(:foo){|x,y| accum.push([x,y]) }
161
+ before(:foo){|x,y,z| accum.push([x,y,z]) }
162
+ end
163
+ end
164
+
165
+ assert do
166
+ o = c.new
167
+ o.foo(1,2,3)
168
+ assert o.accum === [[1], [1,2], [1,2,3]]
169
+ true
170
+ end
171
+ end
172
+
173
+ ##
174
+ #
175
+ testing 'that :after callbacks are passed result of the method they follow, iff possible' do
176
+ c =
177
+ assert do
178
+ wrapped_class do
179
+ wrap :foo
180
+
181
+ define_method(:foo){ result = [1,2,3] }
182
+
183
+ after(:foo){ accum.push(:nada) }
184
+ after(:foo){|result| accum.push(result) }
185
+ end
186
+ end
187
+
188
+ assert do
189
+ o = c.new
190
+ o.foo()
191
+ assert o.accum === [:nada, [1,2,3]]
192
+ true
193
+ end
194
+ end
195
+
196
+ ##
197
+ #
198
+ testing 'that callbacks are inherited cleverly' do
199
+ c =
200
+ assert do
201
+ wrapped_class do
202
+ wrap :foo
203
+
204
+ define_method(:foo){}
205
+
206
+ before(:foo){ accum.push(:before_superclass) }
207
+ after(:foo){ accum.push(:after_superclass) }
208
+ end
209
+ end
210
+
211
+ assert do
212
+ o = c.new
213
+ o.foo()
214
+ assert o.accum === [:before_superclass, :after_superclass]
215
+ end
216
+
217
+ b =
218
+ assert do
219
+ Class.new(c) do
220
+ before(:foo){ accum.push(:before_subclass) }
221
+ after(:foo){ accum.push(:after_subclass) }
222
+ end
223
+ end
224
+
225
+ assert do
226
+ o = b.new
227
+ o.foo()
228
+ assert o.accum === [:before_superclass, :before_subclass, :after_subclass, :after_superclass]
229
+ end
230
+ end
231
+
232
+ ##
233
+ #
234
+ testing 'that methods added via module inclusion preserve wrapping too' do
235
+ c =
236
+ assert do
237
+ wrapped_class do
238
+ define_method(:foo){ accum.push(:original) }
239
+
240
+ wrap :foo
241
+
242
+ before(:foo){ accum.push(:before) }
243
+ after(:foo){ accum.push(:after) }
244
+ end
245
+ end
246
+
247
+ assert do
248
+ o = c.new
249
+ o.foo()
250
+ #assert o.accum === [:before, :original, :after]
251
+ end
252
+
253
+ m =
254
+ Module.new do
255
+ define_method(:foo){ accum.push(:mixin); accum }
256
+ end
257
+
258
+ c.send(:include, m)
259
+
260
+ assert do
261
+ o = c.new
262
+ o.foo()
263
+ assert o.accum === [:before, :mixin, :after]
264
+ end
265
+ end
266
+
267
+ ##
268
+ #
269
+ testing 'that initialize can be wrapped' do
270
+ c =
271
+ assert do
272
+ wrapped_class do
273
+ define_method(:initialize){ accum.push(42) }
274
+
275
+ wrap :initialize
276
+
277
+ before(:initialize){ accum.push(:before) }
278
+ after(:initialize){ accum.push(:after) }
279
+ end
280
+ end
281
+
282
+ assert do
283
+ o = c.new
284
+ assert o.accum === [:before, 42, :after]
285
+ end
286
+ end
287
+
288
+
289
+ ##
290
+ #
291
+ testing 'that wrap aliases can be defined as syntax sugar' do
292
+ c =
293
+ assert do
294
+ wrapped_class do
295
+ define_method(:run_validations){ accum.push(:during); accum }
296
+
297
+ wrap :run_validations
298
+ end
299
+ end
300
+
301
+ assert do
302
+ o = c.new
303
+ o.run_validations()
304
+ o.accum
305
+ assert o.accum === [:during]
306
+ end
307
+
308
+ c.class_eval do
309
+ wrap_alias :validation, :run_validations
310
+
311
+ before(:validation){ accum.push(:before) }
312
+ after(:validation){ accum.push(:after) }
313
+ end
314
+
315
+ assert do
316
+ o = c.new
317
+ o.run_validations()
318
+ o.accum
319
+ assert o.accum === [:before, :during, :after]
320
+ end
321
+
322
+ assert do
323
+ o = Class.new(c).new
324
+ o.run_validations()
325
+ o.accum
326
+ assert o.accum === [:before, :during, :after]
327
+ end
328
+ end
329
+
330
+ ##
331
+ #
332
+ testing 'that wrapping preserves method arity like a boss' do
333
+ assert do
334
+ wrapped_class do
335
+ def foo(x, y) [x, y] end
336
+
337
+ assert{ instance_method(:foo).arity == 2 }
338
+ assert{ new.foo(4, 2) == [4, 2] }
339
+
340
+ wrap :foo
341
+
342
+ assert{ instance_method(:foo).arity == 2 }
343
+ assert{ new.foo(4, 2) == [4, 2] }
344
+
345
+ def foo() end
346
+ assert{ instance_method(:foo).arity == 0 }
347
+
348
+ def foo(x) end
349
+ assert{ instance_method(:foo).arity == 1 }
350
+
351
+ def foo(*x) end
352
+ assert{ instance_method(:foo).arity == -1 }
353
+
354
+ def foo(x, *y) end
355
+ assert{ instance_method(:foo).arity == -2 }
356
+ end
357
+ end
358
+ end
359
+
360
+ private
361
+ def wrapped_class(&block)
362
+ tc = self
363
+
364
+ c =
365
+ Class.new do
366
+ include Wrap
367
+
368
+ const_set(:TC, tc)
369
+
370
+ def self.method_missing(method, *args, &block)
371
+ case method.to_s
372
+ when /^\Aassert/
373
+ const_get(:TC).send(method, *args, &block)
374
+ else
375
+ super
376
+ end
377
+ end
378
+
379
+ def accum
380
+ @accum ||= []
381
+ end
382
+
383
+ module_eval(&block)
384
+ end
385
+
386
+ c
387
+ end
388
+ end
389
+
390
+
391
+ BEGIN {
392
+ testdir = File.dirname(File.expand_path(__FILE__))
393
+ rootdir = File.dirname(testdir)
394
+ libdir = File.join(rootdir, 'lib')
395
+ require File.join(libdir, 'wrap')
396
+ require File.join(testdir, 'testing')
397
+ }