functional-ruby 0.7.7 → 1.0.0

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +92 -152
  3. data/doc/memo.txt +192 -0
  4. data/doc/pattern_matching.txt +485 -0
  5. data/doc/protocol.txt +221 -0
  6. data/doc/record.txt +144 -0
  7. data/doc/thread_safety.txt +8 -0
  8. data/lib/functional.rb +48 -18
  9. data/lib/functional/abstract_struct.rb +161 -0
  10. data/lib/functional/delay.rb +117 -0
  11. data/lib/functional/either.rb +222 -0
  12. data/lib/functional/memo.rb +93 -0
  13. data/lib/functional/method_signature.rb +72 -0
  14. data/lib/functional/option.rb +209 -0
  15. data/lib/functional/pattern_matching.rb +117 -100
  16. data/lib/functional/protocol.rb +157 -0
  17. data/lib/functional/protocol_info.rb +193 -0
  18. data/lib/functional/record.rb +155 -0
  19. data/lib/functional/type_check.rb +112 -0
  20. data/lib/functional/union.rb +152 -0
  21. data/lib/functional/version.rb +3 -1
  22. data/spec/functional/abstract_struct_shared.rb +154 -0
  23. data/spec/functional/complex_pattern_matching_spec.rb +205 -0
  24. data/spec/functional/configuration_spec.rb +17 -0
  25. data/spec/functional/delay_spec.rb +147 -0
  26. data/spec/functional/either_spec.rb +237 -0
  27. data/spec/functional/memo_spec.rb +207 -0
  28. data/spec/functional/option_spec.rb +292 -0
  29. data/spec/functional/pattern_matching_spec.rb +279 -276
  30. data/spec/functional/protocol_info_spec.rb +444 -0
  31. data/spec/functional/protocol_spec.rb +274 -0
  32. data/spec/functional/record_spec.rb +175 -0
  33. data/spec/functional/type_check_spec.rb +103 -0
  34. data/spec/functional/union_spec.rb +110 -0
  35. data/spec/spec_helper.rb +6 -4
  36. metadata +55 -45
  37. data/lib/functional/behavior.rb +0 -138
  38. data/lib/functional/behaviour.rb +0 -2
  39. data/lib/functional/catalog.rb +0 -487
  40. data/lib/functional/collection.rb +0 -403
  41. data/lib/functional/inflect.rb +0 -127
  42. data/lib/functional/platform.rb +0 -120
  43. data/lib/functional/search.rb +0 -132
  44. data/lib/functional/sort.rb +0 -41
  45. data/lib/functional/utilities.rb +0 -189
  46. data/md/behavior.md +0 -188
  47. data/md/catalog.md +0 -32
  48. data/md/collection.md +0 -32
  49. data/md/inflect.md +0 -32
  50. data/md/pattern_matching.md +0 -512
  51. data/md/platform.md +0 -32
  52. data/md/search.md +0 -32
  53. data/md/sort.md +0 -32
  54. data/md/utilities.md +0 -55
  55. data/spec/functional/behavior_spec.rb +0 -528
  56. data/spec/functional/catalog_spec.rb +0 -1206
  57. data/spec/functional/collection_spec.rb +0 -752
  58. data/spec/functional/inflect_spec.rb +0 -85
  59. data/spec/functional/integration_spec.rb +0 -205
  60. data/spec/functional/platform_spec.rb +0 -501
  61. data/spec/functional/search_spec.rb +0 -187
  62. data/spec/functional/sort_spec.rb +0 -61
  63. data/spec/functional/utilities_spec.rb +0 -277
@@ -0,0 +1,444 @@
1
+ require 'spec_helper'
2
+
3
+ module Functional
4
+
5
+ describe ProtocolInfo do
6
+
7
+ let!(:kitchen_sink) do
8
+ ProtocolInfo.new(:Everything) do
9
+ instance_method :instance_method
10
+ class_method :class_method
11
+ attr_accessor :attr_accessor
12
+ attr_reader :attr_reader
13
+ attr_writer :attr_writer
14
+ class_attr_accessor :class_attr_accessor
15
+ class_attr_reader :class_attr_reader
16
+ class_attr_writer :class_attr_writer
17
+ constant :CONSTANT
18
+ end
19
+ end
20
+
21
+ context '#initialize' do
22
+
23
+ it 'raises an exception when no block is given' do
24
+ expect {
25
+ ProtocolInfo.new(:Foo)
26
+ }.to raise_error(ArgumentError)
27
+ end
28
+
29
+ it 'raises an exception when the name is nil' do
30
+ expect {
31
+ ProtocolInfo.new(nil){ nil }
32
+ }.to raise_error(ArgumentError)
33
+ end
34
+
35
+ it 'raises an exception when the name is blank' do
36
+ expect {
37
+ ProtocolInfo.new(''){ nil }
38
+ }.to raise_error(ArgumentError)
39
+ end
40
+
41
+ it 'specifies an instance method with no arity given' do
42
+ info = ProtocolInfo.new(:Foo) do
43
+ instance_method :foo
44
+ end
45
+
46
+ expect(info.instance_methods[:foo]).to be_nil
47
+ end
48
+
49
+ it 'specifies an instance method with a given arity' do
50
+ info = ProtocolInfo.new(:Foo) do
51
+ instance_method :foo, 2
52
+ end
53
+
54
+ expect(info.instance_methods[:foo]).to eq 2
55
+ end
56
+
57
+ it 'specifies a class method with any arity' do
58
+ info = ProtocolInfo.new(:Foo) do
59
+ class_method :foo
60
+ end
61
+
62
+ expect(info.class_methods[:foo]).to be_nil
63
+ end
64
+
65
+ it 'specifies a class method with a given arity' do
66
+ info = ProtocolInfo.new(:Foo) do
67
+ class_method :foo, 2
68
+ end
69
+
70
+ expect(info.class_methods[:foo]).to eq 2
71
+ end
72
+
73
+ it 'specifies an instance attribute reader' do
74
+ info = ProtocolInfo.new(:Foo) do
75
+ attr_reader :foo
76
+ end
77
+
78
+ expect(info.instance_methods[:foo]).to eq 0
79
+ end
80
+
81
+ it 'specifies an instance attribute writer' do
82
+ info = ProtocolInfo.new(:Foo) do
83
+ attr_writer :foo
84
+ end
85
+
86
+ expect(info.instance_methods[:foo=]).to eq 1
87
+ end
88
+
89
+ it 'specifies an instance attribute accessor' do
90
+ info = ProtocolInfo.new(:Foo) do
91
+ attr_accessor :foo
92
+ end
93
+
94
+ expect(info.instance_methods[:foo]).to eq 0
95
+ expect(info.instance_methods[:foo=]).to eq 1
96
+ end
97
+
98
+ it 'specifies a class attribute reader' do
99
+ info = ProtocolInfo.new(:Foo) do
100
+ class_attr_reader :foo
101
+ end
102
+
103
+ expect(info.class_methods[:foo]).to eq 0
104
+ end
105
+
106
+ it 'specifies a class attribute writer' do
107
+ info = ProtocolInfo.new(:Foo) do
108
+ class_attr_writer :foo
109
+ end
110
+
111
+ expect(info.class_methods[:foo=]).to eq 1
112
+ end
113
+
114
+ it 'specifies a class attribute accessor' do
115
+ info = ProtocolInfo.new(:Foo) do
116
+ class_attr_accessor :foo
117
+ end
118
+
119
+ expect(info.class_methods[:foo]).to eq 0
120
+ expect(info.class_methods[:foo=]).to eq 1
121
+ end
122
+
123
+ it 'specifies a constant' do
124
+ info = ProtocolInfo.new(:Foo) do
125
+ constant :FOO
126
+ end
127
+
128
+ expect(info.constants).to include :FOO
129
+ end
130
+ end
131
+
132
+ context '#satisfies?' do
133
+
134
+ it 'validates methods with no arity given' do
135
+ info = ProtocolInfo.new(:Foo) do
136
+ instance_method(:bar)
137
+ class_method(:baz)
138
+ end
139
+
140
+ clazz = Class.new do
141
+ def bar(a, b, c=1, d=2, *args); nil; end
142
+ def self.baz(); nil; end
143
+ end
144
+
145
+ expect(info.satisfies?(clazz.new)).to be true
146
+ end
147
+
148
+ it 'validates methods with no parameters' do
149
+ info = ProtocolInfo.new(:Foo) do
150
+ instance_method(:bar, 0)
151
+ class_method(:baz, 0)
152
+ end
153
+
154
+ clazz = Class.new do
155
+ def bar(); nil; end
156
+ def self.baz(); nil; end
157
+ end
158
+
159
+ expect(info.satisfies?(clazz.new)).to be true
160
+ end
161
+
162
+ it 'validates methods with a fixed number of parameters' do
163
+ info = ProtocolInfo.new(:Foo) do
164
+ instance_method(:bar, 3)
165
+ class_method(:baz, 3)
166
+ end
167
+
168
+ clazz = Class.new do
169
+ def bar(a,b,c); nil; end
170
+ def self.baz(a,b,c); nil; end
171
+ end
172
+
173
+ expect(info.satisfies?(clazz.new)).to be true
174
+ end
175
+
176
+ it 'validates methods with optional parameters' do
177
+ info = ProtocolInfo.new(:Foo) do
178
+ instance_method(:bar, -2)
179
+ class_method(:baz, -2)
180
+ end
181
+
182
+ clazz = Class.new do
183
+ def bar(a, b=1); nil; end
184
+ def self.baz(a, b=1, c=2); nil; end
185
+ end
186
+
187
+ expect(info.satisfies?(clazz.new)).to be true
188
+ end
189
+
190
+ ##NOTE: Syntax error on JRuby and Rbx
191
+ #it 'validates methods with keyword parameters' do
192
+ # info = ProtocolInfo.new(:Foo) do
193
+ # instance_method(:bar, -2)
194
+ # class_method(:baz, -3)
195
+ # end
196
+ #
197
+ # clazz = Class.new do
198
+ # def bar(a, foo: 'foo', baz: 'baz'); nil; end
199
+ # def self.baz(a, b, foo: 'foo', baz: 'baz'); nil; end
200
+ # end
201
+ #
202
+ # expect(info.satisfies?(clazz.new)).to be true
203
+ #end
204
+
205
+ it 'validates methods with variable length argument lists' do
206
+ info = ProtocolInfo.new(:Foo) do
207
+ instance_method(:bar, -2)
208
+ class_method(:baz, -3)
209
+ end
210
+
211
+ clazz = Class.new do
212
+ def bar(a, *args); nil; end
213
+ def self.baz(a, b, *args); nil; end
214
+ end
215
+
216
+ expect(info.satisfies?(clazz.new)).to be true
217
+ end
218
+
219
+ it 'validates methods with arity -1' do
220
+ info = ProtocolInfo.new(:Foo) do
221
+ instance_method(:bar, -1)
222
+ class_method(:baz, -1)
223
+ end
224
+
225
+ clazz = Class.new do
226
+ def bar(*args); nil; end
227
+ def self.baz(*args); nil; end
228
+ end
229
+
230
+ expect(info.satisfies?(clazz.new)).to be true
231
+ end
232
+
233
+ it 'validates instance attribute accessors' do
234
+ info = ProtocolInfo.new(:Foo) do
235
+ attr_accessor :foo
236
+ end
237
+
238
+ accessor_clazz = Class.new do
239
+ attr_accessor :foo
240
+ end
241
+
242
+ manual_clazz = Class.new do
243
+ def foo() true; end
244
+ def foo=(value) true; end
245
+ end
246
+
247
+ expect(info.satisfies?(accessor_clazz.new)).to be true
248
+ expect(info.satisfies?(manual_clazz.new)).to be true
249
+ end
250
+
251
+ it 'validates class attribute accessors' do
252
+ info = ProtocolInfo.new(:Foo) do
253
+ class_attr_accessor :foo
254
+ end
255
+
256
+ accessor_clazz = Class.new do
257
+ class << self
258
+ attr_accessor :foo
259
+ end
260
+ end
261
+
262
+ manual_clazz = Class.new do
263
+ def self.foo() true; end
264
+ def self.foo=(value) true; end
265
+ end
266
+
267
+ expect(info.satisfies?(accessor_clazz.new)).to be true
268
+ expect(info.satisfies?(manual_clazz.new)).to be true
269
+ end
270
+
271
+ it 'validates constants' do
272
+ info = ProtocolInfo.new(:Foo) do
273
+ constant :FOO
274
+ end
275
+
276
+ clazz = Class.new do
277
+ FOO = 42
278
+ end
279
+
280
+ expect(info.satisfies?(clazz.new)).to be false
281
+ end
282
+
283
+ it 'always accepts methods when arity not given' do
284
+ info = ProtocolInfo.new(:Foo) do
285
+ instance_method(:foo)
286
+ instance_method(:bar)
287
+ instance_method(:baz)
288
+ class_method(:foo)
289
+ class_method(:bar)
290
+ class_method(:baz)
291
+ end
292
+
293
+ clazz = Class.new do
294
+ def foo(); nil; end
295
+ def bar(a, b, c); nil; end
296
+ def baz(a, b, *args); nil; end
297
+ def self.foo(); nil; end
298
+ def self.bar(a, b, c); nil; end
299
+ def self.baz(a, b, *args); nil; end
300
+ end
301
+
302
+ expect(info.satisfies?(clazz.new)).to be true
303
+ end
304
+
305
+ it 'always accepts methods with arity -1' do
306
+ info = ProtocolInfo.new(:Foo) do
307
+ instance_method(:foo, 0)
308
+ instance_method(:bar, 2)
309
+ instance_method(:baz, -2)
310
+ class_method(:foo, 0)
311
+ class_method(:bar, -2)
312
+ class_method(:baz, 2)
313
+ end
314
+
315
+ clazz = Class.new do
316
+ def foo(*args); nil; end
317
+ def bar(*args); nil; end
318
+ def baz(*args); nil; end
319
+ def self.foo(*args); nil; end
320
+ def self.bar(*args); nil; end
321
+ def self.baz(*args); nil; end
322
+ end
323
+
324
+ expect(info.satisfies?(clazz.new)).to be true
325
+ end
326
+
327
+ it 'returns false if one or more instance methods do not match' do
328
+ info = ProtocolInfo.new(:Foo) do
329
+ instance_method(:bar, 0)
330
+ end
331
+
332
+ clazz = Class.new do
333
+ def bar(a, b, *args); nil; end
334
+ end
335
+
336
+ expect(info.satisfies?(clazz.new)).to be false
337
+ end
338
+
339
+ it 'returns false if one or more class methods do not match' do
340
+ info = ProtocolInfo.new(:Foo) do
341
+ class_method(:bar, 0)
342
+ end
343
+
344
+ clazz = Class.new do
345
+ def self.bar(a, b, *args); nil; end
346
+ end
347
+
348
+ expect(info.satisfies?(clazz.new)).to be false
349
+ end
350
+
351
+ it 'returns false if one or more instance attributes does not match' do
352
+ info = ProtocolInfo.new(:Foo) do
353
+ attr_accessor :foo
354
+ end
355
+
356
+ reader_clazz = Class.new do
357
+ def foo() true; end
358
+ def foo=() false; end
359
+ end
360
+
361
+ writer_clazz = Class.new do
362
+ def foo(value) false; end
363
+ def foo=(value) true; end
364
+ end
365
+
366
+ expect(info.satisfies?(reader_clazz.new)).to be false
367
+ expect(info.satisfies?(writer_clazz.new)).to be false
368
+ end
369
+
370
+ it 'returns false if one or more class attributes does not match' do
371
+ info = ProtocolInfo.new(:Foo) do
372
+ class_attr_accessor :foo
373
+ end
374
+
375
+ reader_clazz = Class.new do
376
+ def self.foo() true; end
377
+ def self.foo=() false; end
378
+ end
379
+
380
+ writer_clazz = Class.new do
381
+ def self.foo(value) false; end
382
+ def self.foo=(value) true; end
383
+ end
384
+
385
+ expect(info.satisfies?(reader_clazz.new)).to be false
386
+ expect(info.satisfies?(writer_clazz.new)).to be false
387
+ end
388
+
389
+ it 'returns false if one or more constants has not been defined' do
390
+ info = ProtocolInfo.new(:Foo) do
391
+ constant :FOO
392
+ end
393
+
394
+ clazz = Class.new do
395
+ BAR = 42
396
+ end
397
+
398
+ expect(info.satisfies?(clazz.new)).to be false
399
+ end
400
+
401
+ it 'supports all specifiable characteristics on classes' do
402
+ clazz = Class.new do
403
+ attr_accessor :attr_accessor
404
+ attr_reader :attr_reader
405
+ attr_writer :attr_writer
406
+ def instance_method() 42; end
407
+
408
+ class << self
409
+ attr_accessor :class_attr_accessor
410
+ attr_reader :class_attr_reader
411
+ attr_writer :class_attr_writer
412
+ def class_method() 42; end
413
+ end
414
+ end
415
+ clazz.const_set(:CONSTANT, 42)
416
+
417
+ expect(
418
+ kitchen_sink.satisfies?(clazz)
419
+ ).to be true
420
+ end
421
+
422
+ it 'supports all specifiable characteristics on modules' do
423
+ mod = Module.new do
424
+ attr_accessor :attr_accessor
425
+ attr_reader :attr_reader
426
+ attr_writer :attr_writer
427
+ def instance_method() 42; end
428
+
429
+ class << self
430
+ attr_accessor :class_attr_accessor
431
+ attr_reader :class_attr_reader
432
+ attr_writer :class_attr_writer
433
+ def class_method() 42; end
434
+ end
435
+ end
436
+ mod.const_set(:CONSTANT, 42)
437
+
438
+ expect(
439
+ kitchen_sink.satisfies?(mod)
440
+ ).to be true
441
+ end
442
+ end
443
+ end
444
+ end
@@ -0,0 +1,274 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'protocol specification' do
4
+
5
+ before(:each) do
6
+ @protocol_info = Functional::Protocol.class_variable_get(:@@info)
7
+ Functional::Protocol.class_variable_set(:@@info, {})
8
+ end
9
+
10
+ after(:each) do
11
+ Functional::Protocol.class_variable_set(:@@info, @protocol_info)
12
+ end
13
+
14
+ context 'SpecifyProtocol method' do
15
+
16
+ context 'without a block' do
17
+
18
+ it 'returns the specified protocol when defined' do
19
+ Functional::SpecifyProtocol(:Foo){ nil }
20
+ expect(Functional::SpecifyProtocol(:Foo)).to_not be_nil
21
+ end
22
+
23
+ it 'returns nil when not defined' do
24
+ expect(Functional::SpecifyProtocol(:Foo)).to be_nil
25
+ end
26
+ end
27
+
28
+ context 'with a block' do
29
+
30
+ it 'raises an exception if the protocol has already been specified' do
31
+ Functional::SpecifyProtocol(:Foo){ nil }
32
+
33
+ expect {
34
+ Functional::SpecifyProtocol(:Foo){ nil }
35
+ }.to raise_error(Functional::ProtocolError)
36
+ end
37
+
38
+ it 'returns the specified protocol once defined' do
39
+ expect(Functional::SpecifyProtocol(:Foo){ nil }).to be_a Functional::ProtocolInfo
40
+ end
41
+ end
42
+ end
43
+
44
+ describe Functional::Protocol do
45
+
46
+ context 'Satisfy?' do
47
+
48
+ it 'accepts and checks multiple protocols' do
49
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
50
+ Functional::SpecifyProtocol(:bar){ instance_method(:foo) }
51
+ Functional::SpecifyProtocol(:baz){ instance_method(:foo) }
52
+
53
+ clazz = Class.new do
54
+ def foo(); nil; end
55
+ end
56
+
57
+ expect(
58
+ Functional::Protocol.Satisfy?(clazz.new, :foo, :bar, :baz)
59
+ ).to be true
60
+ end
61
+
62
+ it 'returns false if one or more protocols have not been defined' do
63
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
64
+
65
+ expect(
66
+ Functional::Protocol.Satisfy?('object', :foo, :bar)
67
+ ).to be false
68
+ end
69
+
70
+ it 'raises an exception if no protocols are listed' do
71
+ expect {
72
+ Functional::Protocol::Satisfy?('object')
73
+ }.to raise_error(ArgumentError)
74
+ end
75
+
76
+ it 'returns true on success' do
77
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
78
+
79
+ clazz = Class.new do
80
+ def foo(); nil; end
81
+ end
82
+
83
+ expect(
84
+ Functional::Protocol.Satisfy?(clazz.new, :foo)
85
+ ).to be true
86
+ end
87
+
88
+ it 'returns false on failure' do
89
+ Functional::SpecifyProtocol(:foo) do
90
+ instance_method(:foo, 0)
91
+ class_method(:bar, 0)
92
+ end
93
+
94
+ clazz = Class.new do
95
+ def foo(); nil; end
96
+ end
97
+
98
+ expect(
99
+ Functional::Protocol.Satisfy?('object', :foo)
100
+ ).to be false
101
+ end
102
+
103
+ it 'validates classes' do
104
+ Functional::SpecifyProtocol(:foo) do
105
+ instance_method(:foo)
106
+ class_method(:bar)
107
+ end
108
+
109
+ clazz = Class.new do
110
+ def foo(); nil; end
111
+ def self.bar(); nil; end
112
+ end
113
+
114
+ expect(
115
+ Functional::Protocol.Satisfy?(clazz, :foo)
116
+ ).to be true
117
+ end
118
+
119
+ it 'validates modules' do
120
+ Functional::SpecifyProtocol(:foo) do
121
+ instance_method(:foo)
122
+ class_method(:bar)
123
+ end
124
+
125
+ mod = Module.new do
126
+ def foo(); nil; end
127
+ def self.bar(); nil; end
128
+ end
129
+
130
+ expect(
131
+ Functional::Protocol.Satisfy?(mod, :foo)
132
+ ).to be true
133
+ end
134
+ end
135
+
136
+ context 'Satisfy!' do
137
+
138
+ it 'accepts and checks multiple protocols' do
139
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
140
+ Functional::SpecifyProtocol(:bar){ instance_method(:foo) }
141
+ Functional::SpecifyProtocol(:baz){ instance_method(:foo) }
142
+
143
+ clazz = Class.new do
144
+ def foo(); nil; end
145
+ end
146
+
147
+ target = clazz.new
148
+ expect(
149
+ Functional::Protocol.Satisfy!(target, :foo, :bar, :baz)
150
+ ).to eq target
151
+ end
152
+
153
+ it 'raises an exception if one or more protocols have not been defined' do
154
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
155
+
156
+ expect{
157
+ Functional::Protocol.Satisfy!('object', :foo, :bar)
158
+ }.to raise_error(Functional::ProtocolError)
159
+ end
160
+
161
+ it 'raises an exception if no protocols are listed' do
162
+ expect {
163
+ Functional::Protocol::Satisfy!('object')
164
+ }.to raise_error(ArgumentError)
165
+ end
166
+
167
+ it 'returns the target on success' do
168
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
169
+
170
+ clazz = Class.new do
171
+ def foo(); nil; end
172
+ end
173
+
174
+ target = clazz.new
175
+ expect(
176
+ Functional::Protocol.Satisfy!(target, :foo)
177
+ ).to eq target
178
+ end
179
+
180
+ it 'raises an exception on failure' do
181
+ Functional::SpecifyProtocol(:foo){ instance_method(:foo) }
182
+
183
+ expect{
184
+ Functional::Protocol.Satisfy!('object', :foo)
185
+ }.to raise_error(Functional::ProtocolError)
186
+ end
187
+
188
+ it 'validates classes' do
189
+ Functional::SpecifyProtocol(:foo) do
190
+ instance_method(:foo)
191
+ class_method(:bar)
192
+ end
193
+
194
+ clazz = Class.new do
195
+ def foo(); nil; end
196
+ def self.bar(); nil; end
197
+ end
198
+
199
+ expect{
200
+ Functional::Protocol.Satisfy!(clazz, :foo)
201
+ }.to_not raise_exception
202
+ end
203
+
204
+ it 'validates modules' do
205
+ Functional::SpecifyProtocol(:foo) do
206
+ instance_method(:foo)
207
+ class_method(:bar)
208
+ end
209
+
210
+ mod = Module.new do
211
+ def foo(); nil; end
212
+ def self.bar(); nil; end
213
+ end
214
+
215
+ expect{
216
+ Functional::Protocol.Satisfy!(mod, :foo)
217
+ }.to_not raise_exception
218
+ end
219
+ end
220
+
221
+ context 'Specified?' do
222
+
223
+ it 'returns true when all protocols have been defined' do
224
+ Functional::SpecifyProtocol(:foo){ nil }
225
+ Functional::SpecifyProtocol(:bar){ nil }
226
+ Functional::SpecifyProtocol(:baz){ nil }
227
+
228
+ expect(Functional::Protocol.Specified?(:foo, :bar, :baz)).to be true
229
+ end
230
+
231
+ it 'returns false when one or more of the protocols have not been defined' do
232
+ Functional::SpecifyProtocol(:foo){ nil }
233
+ Functional::SpecifyProtocol(:bar){ nil }
234
+
235
+ expect(Functional::Protocol.Specified?(:foo, :bar, :baz)).to be false
236
+ end
237
+
238
+ it 'raises an exception when no protocols are given' do
239
+ expect {
240
+ Functional::Protocol.Specified?
241
+ }.to raise_error(ArgumentError)
242
+ end
243
+ end
244
+
245
+ context 'Specified!' do
246
+
247
+ it 'returns true when all protocols have been defined' do
248
+ Functional::SpecifyProtocol(:foo){ nil }
249
+ Functional::SpecifyProtocol(:bar){ nil }
250
+ Functional::SpecifyProtocol(:baz){ nil }
251
+
252
+ expect(Functional::Protocol.Specified!(:foo, :bar, :baz)).to be true
253
+ expect {
254
+ Functional::Protocol.Specified!(:foo, :bar, :baz)
255
+ }.to_not raise_error
256
+ end
257
+
258
+ it 'raises an exception when one or more of the protocols have not been defined' do
259
+ Functional::SpecifyProtocol(:foo){ nil }
260
+ Functional::SpecifyProtocol(:bar){ nil }
261
+
262
+ expect {
263
+ Functional::Protocol.Specified!(:foo, :bar, :baz)
264
+ }.to raise_error(Functional::ProtocolError)
265
+ end
266
+
267
+ it 'raises an exception when no protocols are given' do
268
+ expect {
269
+ Functional::Protocol.Specified!
270
+ }.to raise_error(ArgumentError)
271
+ end
272
+ end
273
+ end
274
+ end