protocol 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ require 'protocol'
2
+
3
+ # Protocol version of the Comparable module, that actually checks, if #<=>
4
+ # was implemented by the including (conforming) class.
5
+ Comparing = Protocol do
6
+ # Compares _self_ with _other_ and returns -1, 0, or +1 depending on whether
7
+ # _self_ is less than, equal to, or greater than _other_.
8
+ def <=>(other) end
9
+
10
+ include Comparable
11
+ end
12
+
13
+ # Protocol version of the Enumerable module, that actually checks, if #each
14
+ # was implemented by the including (conforming) class.
15
+ Enumerating = Protocol do
16
+ # Iterate over each element of this Enumerating class and pass it to the
17
+ # _block_. Because protocol cannot determine if a block is expected from a
18
+ # C-function, I left it out of the specification for now.
19
+ understand :each
20
+
21
+ include Enumerable
22
+ end
data/make_doc.rb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set et sw=2 ts=2:
3
+
4
+ require 'rbconfig'
5
+
6
+ bindir = Config::CONFIG['bindir']
7
+ $outdir = 'doc/'
8
+ puts "Creating documentation in '#$outdir'."
9
+ system "#{bindir}/ruby #{bindir}/rdoc -S -d --main=Protocol -o #$outdir lib/protocol.rb"
@@ -0,0 +1,620 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'protocol'
5
+
6
+ class TestProtocol < Test::Unit::TestCase
7
+ TestProtocol_foo = Protocol do
8
+ check_failure :none
9
+
10
+ understand :foo
11
+ end
12
+
13
+ TestProtocol_foo_fail = Protocol do
14
+ understand :foo
15
+ end
16
+
17
+ TestProtocol_bar = Protocol do
18
+ understand :bar
19
+ end
20
+
21
+ TestProtocol_foo_bar_1 = Protocol do
22
+ include TestProtocol_foo
23
+ understand :bar
24
+ end
25
+
26
+ TestProtocol_foo_bar_1_fail = Protocol do
27
+ include TestProtocol_foo
28
+ understand :bar
29
+ end
30
+
31
+ TestProtocol_foo_bar_2 = Protocol do
32
+ include TestProtocol_foo
33
+ include TestProtocol_bar
34
+ end
35
+
36
+ TestProtocol_foo_bar_2_fail = Protocol do
37
+ check_failure :error
38
+
39
+ include TestProtocol_foo
40
+ include TestProtocol_bar
41
+ end
42
+
43
+ TestProtocolArgs = Protocol do
44
+ understand :bar, 2
45
+ understand :baz, 3
46
+ understand :foo, -1
47
+ end
48
+
49
+ TestProtocolArgsOverwritten = Protocol do
50
+ include TestProtocolArgs
51
+
52
+ def bar(a, b, c)
53
+ end
54
+
55
+ def foo(a)
56
+ end
57
+ end
58
+
59
+ TestProtocolBlock = Protocol do
60
+ def foo(x, &block)
61
+ end
62
+ end
63
+
64
+ TestProtocolPartial = Protocol do
65
+ check_failure :none
66
+
67
+ implementation
68
+
69
+ def map(&block)
70
+ result = []
71
+ each { |x| result << block.call(x) }
72
+ result
73
+ end
74
+
75
+ specification
76
+
77
+ def each(&block) end
78
+ end
79
+
80
+ TestProtocolPartial_fail = Protocol do
81
+ check_failure :error
82
+
83
+ def each(&block) end
84
+
85
+ implementation
86
+
87
+ def map(&block)
88
+ result = []
89
+ each { |x| result << block.call(x) }
90
+ result
91
+ end
92
+ end
93
+
94
+ TestProtocolWrapMethodPassedFoo = Protocol do
95
+ def foo(foo, *rest) end
96
+ end
97
+
98
+ TestProtocolWrapMethodPassedBar = Protocol do
99
+ def bar() end
100
+ end
101
+
102
+ TestProtocolWrapMethod = Protocol do
103
+ def foo_bar(foo, bar)
104
+ TestProtocolWrapMethodPassedFoo =~ foo
105
+ TestProtocolWrapMethodPassedBar =~ bar
106
+ end
107
+ end
108
+
109
+ TestProtocolPostcondition = Protocol do
110
+ def foo_bar(foo, bar)
111
+ postcondition { foo + bar == result }
112
+ end
113
+
114
+ def foo_bars(foo, *bars)
115
+ postcondition { bars.unshift(foo) == result }
116
+ end
117
+ end
118
+
119
+ TestProtocolPrecondition = Protocol do
120
+ def foo_bar(foo, bar)
121
+ precondition { foo == 5 }
122
+ precondition { bar == 7 }
123
+ end
124
+ end
125
+
126
+ class MyClass
127
+ def one_with_block(foo, &block) end
128
+ end
129
+
130
+ TestProtocolInheritance = Protocol do
131
+ inherit MyClass, :one_with_block
132
+ end
133
+
134
+ TestProtocolInheritanceC = Protocol do
135
+ inherit ::Array, :each, true
136
+ end
137
+
138
+ def test_define_protocol
139
+ foo_protocol = Protocol do
140
+ understand :foo
141
+ understand :bar
142
+ end
143
+ assert_kind_of Protocol::ProtocolModule, foo_protocol
144
+ assert_raises(Protocol::SpecificationError) do
145
+ foo2_protocol = Protocol do
146
+ understand :foo
147
+ understand :foo
148
+ end
149
+ end
150
+ foo3_protocol = Protocol do
151
+ understand :foo, 1
152
+ understand :bar
153
+ end
154
+ assert_kind_of Protocol::ProtocolModule, foo3_protocol
155
+ assert_equal foo_protocol[:bar], foo3_protocol[:bar]
156
+ assert_not_same foo_protocol[:bar], foo3_protocol[:bar]
157
+ assert_not_equal foo_protocol[:foo], foo3_protocol[:foo]
158
+ assert_not_same foo_protocol[:foo], foo3_protocol[:foo]
159
+ assert foo_protocol.understand?(:foo)
160
+ assert foo_protocol.understand?(:bar)
161
+ assert !foo_protocol.understand?(:baz)
162
+ assert foo3_protocol.understand?(:foo)
163
+ assert foo3_protocol.understand?(:foo, 1)
164
+ assert foo3_protocol.understand?(:bar)
165
+ assert !foo3_protocol.understand?(:baz)
166
+ assert_equal [ foo3_protocol[:bar] ], foo3_protocol.grep(/^b/)
167
+ end
168
+
169
+ def test_simple_without_fail
170
+ c1 = Class.new do
171
+ def foo; end
172
+
173
+ conform_to TestProtocol_foo
174
+ end
175
+ assert c1.conform_to?(TestProtocol_foo)
176
+ assert c1.new.conform_to?(TestProtocol_foo)
177
+ assert !c1.conform_to?(TestProtocol_foo_bar_1)
178
+ assert !c1.new.conform_to?(TestProtocol_foo_bar_1)
179
+ assert !c1.conform_to?(TestProtocol_bar)
180
+ assert !c1.new.conform_to?(TestProtocol_bar)
181
+ assert_equal 2, TestProtocol_foo_bar_1.check_failures(Object).size
182
+ assert_equal 2, TestProtocol_foo_bar_1.check_failures(Object.new).size
183
+ assert_equal 1, TestProtocol_foo_bar_1.check_failures(c1).size
184
+ assert_equal 1, TestProtocol_foo_bar_1.check_failures(c1.new).size
185
+
186
+ c2 = Class.new do
187
+ conform_to TestProtocol_foo
188
+ end
189
+ assert !c2.conform_to?(TestProtocol_foo)
190
+ assert !c2.new.conform_to?(TestProtocol_foo)
191
+ assert !c2.conform_to?(TestProtocol_foo_bar_1)
192
+ assert !c2.new.conform_to?(TestProtocol_foo_bar_1)
193
+ assert !c2.conform_to?(TestProtocol_bar)
194
+ assert !c2.new.conform_to?(TestProtocol_bar)
195
+ end
196
+
197
+ def test_simple_with_fail
198
+ c1 = Class.new do
199
+ def foo; end
200
+
201
+ conform_to TestProtocol_foo_fail
202
+ end
203
+ assert c1.conform_to?(TestProtocol_foo_fail)
204
+ assert c1.new.conform_to?(TestProtocol_foo_fail)
205
+ assert !c1.conform_to?(TestProtocol_foo_bar_1)
206
+ assert !c1.new.conform_to?(TestProtocol_foo_bar_1)
207
+ assert !c1.conform_to?(TestProtocol_bar)
208
+ assert !c1.new.conform_to?(TestProtocol_bar)
209
+
210
+ begin
211
+ c2 = Class.new do
212
+ conform_to TestProtocol_foo_fail
213
+ end
214
+ assert(false)
215
+ rescue Protocol::CheckFailed
216
+ assert(true)
217
+ rescue
218
+ assert(false)
219
+ end
220
+ end
221
+
222
+ def test_inclusion1_with_fail
223
+ begin
224
+ c = Class.new do
225
+ def bar; end
226
+ conform_to TestProtocol_foo_bar_1_fail
227
+ end
228
+ assert(false)
229
+ rescue Protocol::CheckFailed
230
+ assert(true)
231
+ rescue
232
+ assert(false)
233
+ end
234
+ end
235
+
236
+ def test_inclusion2
237
+ c = Class.new do
238
+ def foo; end
239
+ def bar; end
240
+ conform_to TestProtocol_foo_bar_1
241
+ end
242
+ assert(true)
243
+ assert c.conform_to?(TestProtocol_foo_bar_1)
244
+ end
245
+
246
+ def test_inclusion3
247
+ c = Class.new do
248
+ def bar; end
249
+ conform_to TestProtocol_foo_bar_2
250
+ end
251
+ assert !c.conform_to?(TestProtocol_foo_bar_2)
252
+ assert(false)
253
+ rescue Protocol::CheckFailed
254
+ assert(true)
255
+ rescue
256
+ assert(false)
257
+ end
258
+
259
+ # Check argument arity
260
+
261
+ def test_arity1
262
+ c = Class.new do
263
+ def bar(x, y) x + y end
264
+ def foo(*x) x end
265
+ def baz(x, y, z) Math.sqrt(x * x + y * y + z * z) end
266
+
267
+ conform_to TestProtocolArgs
268
+ end
269
+ assert c.conform_to?(TestProtocolArgs)
270
+ assert c.new.conform_to?(TestProtocolArgs)
271
+ rescue
272
+ assert(false)
273
+ end
274
+
275
+ def test_arity2
276
+ c = Class.new do
277
+ def bar(x, y) x + y end
278
+ def baz(x, y, z) Math.sqrt(x * x + y * y + z * z) end
279
+ def foo(x) x end
280
+
281
+ conform_to TestProtocolArgs
282
+ end
283
+ assert(false)
284
+ rescue Protocol::CheckFailed
285
+ assert(true)
286
+ rescue
287
+ assert(false)
288
+ end
289
+
290
+ def test_arity3
291
+ c = Class.new do
292
+ def bar(x, y) x + y end
293
+ def baz(x, y, z) Math.sqrt(x * x + y * y + z * z) end
294
+ def foo(x) x end
295
+
296
+ conform_to TestProtocolArgs
297
+ end
298
+ rescue Protocol::CheckFailed
299
+ assert(true)
300
+ rescue
301
+ assert(false)
302
+ end
303
+
304
+ def test_block
305
+ begin
306
+ c1 = Class.new do
307
+ def foo(x) end
308
+
309
+ conform_to TestProtocolBlock
310
+ end
311
+ rescue Protocol::CheckFailed
312
+ assert(true)
313
+ rescue
314
+ assert(false)
315
+ end
316
+ c1b = Class.new do
317
+ def foo(x) end
318
+ end
319
+ assert !c1b.new.conform_to?(TestProtocolBlock)
320
+ begin
321
+ c2 = Class.new do
322
+ def foo(x, &block) block[x] end
323
+
324
+ conform_to TestProtocolBlock
325
+ end
326
+ assert(true)
327
+ rescue Protocol::CheckFailed
328
+ assert(false)
329
+ rescue
330
+ assert(false)
331
+ end
332
+ begin
333
+ c3 = Class.new do
334
+ def foo(x) yield x end
335
+
336
+ conform_to TestProtocolBlock
337
+ end
338
+ assert(true)
339
+ rescue Protocol::CheckFailed
340
+ assert(false)
341
+ rescue
342
+ assert(false)
343
+ end
344
+ obj = Object.new
345
+ assert !obj.conform_to?(TestProtocolBlock)
346
+ def obj.foo(x, &b) end
347
+ assert obj.conform_to?(TestProtocolBlock)
348
+ end
349
+
350
+ def test_partial_without_fail
351
+ c1 = Class.new do
352
+ def each(&block)
353
+ (1..3).each(&block)
354
+ self
355
+ end
356
+
357
+ conform_to TestProtocolPartial
358
+ end
359
+ obj = c1.new
360
+ assert c1.conform_to?(TestProtocolPartial)
361
+ assert obj.conform_to?(TestProtocolPartial)
362
+ assert_equal [ 1, 4, 9], obj.map { |x| x * x }
363
+ assert_equal obj, obj.each { |x| x * x }
364
+
365
+ c2 = Class.new do
366
+ conform_to TestProtocolPartial
367
+ end
368
+ assert !c2.conform_to?(TestProtocolPartial)
369
+ assert !c2.new.conform_to?(TestProtocolPartial)
370
+ assert_raises(NoMethodError) { c2.new.map { |x| x * x } }
371
+ assert_equal obj, obj.each { |x| x * x }
372
+ end
373
+
374
+ def test_partial_with_fail
375
+ c1 = Class.new do
376
+ def each(&block)
377
+ (1..3).each(&block)
378
+ self
379
+ end
380
+
381
+ conform_to TestProtocolPartial_fail
382
+ end
383
+ obj = c1.new
384
+ assert c1.conform_to?(TestProtocolPartial)
385
+ assert obj.conform_to?(TestProtocolPartial)
386
+ assert_equal [ 1, 4, 9], obj.map { |x| x * x }
387
+ assert_equal obj, obj.each { |x| x * x }
388
+
389
+ begin
390
+ c2 = Class.new do
391
+ conform_to TestProtocolPartial_fail
392
+ end
393
+ assert(false)
394
+ rescue Protocol::CheckFailed
395
+ assert(true)
396
+ rescue
397
+ assert(false)
398
+ end
399
+ end
400
+
401
+ def test_overwrite
402
+ c = Class.new do
403
+ def bar(x, y, z) x + y + z end
404
+ def baz(x, y, z) Math.sqrt(x * x + y * y + z * z) end
405
+ def foo(x) x end
406
+
407
+ conform_to TestProtocolArgsOverwritten
408
+ end
409
+ assert c.conform_to?(TestProtocolArgsOverwritten)
410
+ rescue Protocol::CheckFailed
411
+ assert(false)
412
+ rescue
413
+ assert(false)
414
+ end
415
+
416
+ def test_messages
417
+ assert_equal %w[bar baz foo], TestProtocolArgs.messages.map { |x| x.name }
418
+ assert_equal [2, 3, -1], TestProtocolArgs.messages.map { |x| x.arity }
419
+ assert_equal "TestProtocol::TestProtocolArgs#bar(2), TestProtocol::TestProtocolArgs#baz(3), TestProtocol::TestProtocolArgs#foo(-1)", TestProtocolArgs.to_s
420
+ assert_equal %w[bar baz foo], TestProtocolArgsOverwritten.messages.map { |x| x.name }
421
+ assert_equal [3, 3, 1], TestProtocolArgsOverwritten.messages.map { |x| x.arity }
422
+ assert_equal "TestProtocol::TestProtocolArgsOverwritten#bar(3), TestProtocol::TestProtocolArgs#baz(3), TestProtocol::TestProtocolArgsOverwritten#foo(1)", TestProtocolArgsOverwritten.to_s
423
+ end
424
+
425
+ def test_wrapped_method
426
+ begin
427
+ c1 = Class.new do
428
+ def foo(foo, *rest) foo end
429
+
430
+ conform_to TestProtocolWrapMethodPassedFoo
431
+ end
432
+ assert(true)
433
+ rescue Protocol::CheckFailed
434
+ assert(false)
435
+ rescue
436
+ assert(false)
437
+ end
438
+ begin
439
+ c2 = Class.new do
440
+ def bar() :bar end
441
+
442
+ conform_to TestProtocolWrapMethodPassedBar
443
+ end
444
+ assert(true)
445
+ rescue Protocol::CheckFailed
446
+ assert(false)
447
+ rescue
448
+ assert(false)
449
+ end
450
+ begin
451
+ c3 = Class.new do
452
+ def foo_bar(foo, bar)
453
+ [ foo.foo(:foo, :baz), bar.bar ]
454
+ end
455
+
456
+ conform_to TestProtocolWrapMethod
457
+ end
458
+ assert(true)
459
+ rescue Protocol::CheckFailed
460
+ assert(false)
461
+ rescue
462
+ assert(false)
463
+ end
464
+ begin
465
+ assert_equal [:foo, :bar], c3.new.foo_bar(c1.new, c2.new)
466
+ rescue Protocol::CheckFailed
467
+ assert(false)
468
+ rescue
469
+ assert(false)
470
+ end
471
+ begin
472
+ c3.new.foo_bar c1.new, c1.new
473
+ assert(false)
474
+ rescue Protocol::CheckFailed
475
+ assert(true)
476
+ rescue
477
+ assert(false)
478
+ end
479
+ end
480
+
481
+ def test_precondition
482
+ begin
483
+ c1 = Class.new do
484
+ def foo_bar(foo, bar)
485
+ foo + bar
486
+ end
487
+
488
+ conform_to TestProtocolPrecondition
489
+ end
490
+ assert(true)
491
+ rescue Protocol::CheckFailed
492
+ assert(false)
493
+ rescue
494
+ assert(false)
495
+ end
496
+ assert_equal 5 + 7, c1.new.foo_bar(5, 7)
497
+ assert_raises(Protocol::PreconditionCheckError) { c1.new.foo_bar(5, 8) }
498
+ end
499
+
500
+ def test_postcondition
501
+ begin
502
+ c1 = Class.new do
503
+ def foo_bar(foo, bar)
504
+ foo + bar
505
+ end
506
+
507
+ def foo_bars(foo, *bars)
508
+ bars.unshift foo
509
+ end
510
+
511
+ conform_to TestProtocolPostcondition
512
+ end
513
+ c2 = Class.new do
514
+ def foo_bar(foo, bar)
515
+ foo + bar + 1
516
+ end
517
+
518
+ def foo_bars(foo, *bars)
519
+ bars.unshift foo
520
+ end
521
+
522
+ conform_to TestProtocolPostcondition
523
+ end
524
+ assert(true)
525
+ rescue Protocol::CheckFailed
526
+ assert(false)
527
+ rescue
528
+ assert(false)
529
+ end
530
+ assert_equal [5, 7], c1.new.foo_bars(5, 7)
531
+ assert_equal 5 + 7, c1.new.foo_bar(5, 7)
532
+ assert_equal [5, 7], c2.new.foo_bars(5, 7)
533
+ assert_raises(Protocol::PostconditionCheckError) { c2.new.foo_bar(5, 7) }
534
+ o1 = Object.new
535
+ def o1.foo_bar(foo, bar)
536
+ foo + bar
537
+ end
538
+ def o1.foo_bars(foo, *bars)
539
+ bars.unshift foo
540
+ end
541
+ assert TestProtocolPostcondition =~ o1
542
+ assert_equal [5, 7], o1.foo_bars(5, 7)
543
+ assert_equal 5 + 7, o1.foo_bar(5, 7)
544
+ o2 = Object.new
545
+ def o2.foo_bar(foo, bar)
546
+ foo + bar + 1
547
+ end
548
+ def o2.foo_bars(foo, *bars)
549
+ bars.unshift foo
550
+ end
551
+ assert TestProtocolPostcondition =~ o2
552
+ assert_equal [5, 7], o2.foo_bars(5, 7)
553
+ assert_raises(Protocol::PostconditionCheckError) { o2.foo_bar(5, 7) }
554
+ end
555
+
556
+ def test_inheritance
557
+ begin
558
+ c1 = Class.new do
559
+ conform_to TestProtocolInheritance
560
+ end
561
+ rescue Protocol::CheckFailed
562
+ assert(true)
563
+ rescue
564
+ assert(false)
565
+ end
566
+ begin
567
+ c2 = Class.new do
568
+ def one_with_block() end
569
+ conform_to TestProtocolInheritance
570
+ end
571
+ rescue Protocol::CheckFailed
572
+ assert(true)
573
+ rescue
574
+ assert(false)
575
+ end
576
+ begin
577
+ c3 = Class.new do
578
+ def one_with_block(foo) end
579
+ conform_to TestProtocolInheritance
580
+ end
581
+ rescue Protocol::CheckFailed
582
+ assert(true)
583
+ rescue
584
+ assert(false)
585
+ end
586
+ begin
587
+ c4 = Class.new do
588
+ def one_with_block(foo, &block) end
589
+ conform_to TestProtocolInheritance
590
+ end
591
+ assert(true)
592
+ rescue Protocol::CheckFailed
593
+ assert(false)
594
+ rescue
595
+ assert(false)
596
+ end
597
+ begin
598
+ c5 = Class.new do
599
+ def each() end
600
+ conform_to TestProtocolInheritanceC
601
+ end
602
+ rescue Protocol::CheckFailed
603
+ assert(true)
604
+ rescue
605
+ assert(false)
606
+ end
607
+ begin
608
+ c6 = Class.new do
609
+ def each(&block) end
610
+ conform_to TestProtocolInheritanceC
611
+ end
612
+ assert(true)
613
+ rescue Protocol::CheckFailed
614
+ assert(false)
615
+ rescue
616
+ assert(false)
617
+ end
618
+ end
619
+ end
620
+ # vim: set et sw=2 ts=2: