functional-ruby 0.7.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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