furnish 0.0.4 → 0.1.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.
- data/CHANGELOG.md +36 -0
- data/Gemfile +0 -2
- data/Guardfile +2 -2
- data/furnish.gemspec +3 -2
- data/lib/furnish.rb +2 -4
- data/lib/furnish/protocol.rb +226 -0
- data/lib/furnish/provisioner.rb +1 -38
- data/lib/furnish/provisioner_group.rb +254 -38
- data/lib/furnish/provisioners/api.rb +430 -0
- data/lib/furnish/provisioners/dummy.rb +19 -12
- data/lib/furnish/scheduler.rb +148 -25
- data/lib/furnish/version.rb +1 -1
- data/lib/furnish/vm.rb +3 -0
- data/test/dummy_classes.rb +275 -0
- data/test/mt_cases.rb +103 -45
- data/test/test_api.rb +68 -0
- data/test/test_dummy.rb +6 -6
- data/test/test_protocol.rb +211 -0
- data/test/test_provisioner_group.rb +163 -11
- data/test/test_scheduler_basic.rb +57 -4
- data/test/test_scheduler_threaded.rb +5 -17
- metadata +18 -13
data/test/mt_cases.rb
CHANGED
@@ -1,37 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'dummy_classes'
|
2
2
|
require 'furnish/test'
|
3
3
|
|
4
|
-
Dummy = Furnish::Provisioner::Dummy unless defined? Dummy
|
5
|
-
|
6
|
-
class StartFailDummy < Dummy
|
7
|
-
def startup(*args)
|
8
|
-
super
|
9
|
-
false
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class StopFailDummy < Dummy
|
14
|
-
def shutdown
|
15
|
-
super
|
16
|
-
false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class StartExceptionDummy < Dummy
|
21
|
-
def startup(*args)
|
22
|
-
super
|
23
|
-
raise "ermagherd startup"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class StopExceptionDummy < Dummy
|
28
|
-
def shutdown(*args)
|
29
|
-
super
|
30
|
-
raise "ermagherd shutdown"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
4
|
module Furnish
|
5
|
+
# These tests are run for both threaded and serial cases.
|
35
6
|
class RestartingSchedulerTestCase < SchedulerTestCase
|
36
7
|
def teardown
|
37
8
|
sched.stop
|
@@ -49,6 +20,91 @@ module Furnish
|
|
49
20
|
assert(provisioner.store[ [name, "shutdown"].join("-") ], "dummy provisioner for #{name} recorded the shutdown run")
|
50
21
|
end
|
51
22
|
|
23
|
+
def test_recovery_mode
|
24
|
+
[RecoverableDummy, RaisingRecoverableDummy].each do |prov|
|
25
|
+
test1 = "#{prov}-test1"
|
26
|
+
test2 = "#{prov}-test2"
|
27
|
+
test3 = "#{prov}-test3"
|
28
|
+
|
29
|
+
sched.s(test1, Dummy.new)
|
30
|
+
sched.s(test2, prov.new)
|
31
|
+
sched.run rescue nil # FIXME oof. maybe move this to indepedent tests for serial mode?
|
32
|
+
assert(sched.serial || sched.running?)
|
33
|
+
unless sched.serial
|
34
|
+
sleep 0.1 while !sched.needs_recovery.has_key?(test2)
|
35
|
+
end
|
36
|
+
assert(sched.needs_recovery?)
|
37
|
+
assert_includes(sched.needs_recovery.keys, test2)
|
38
|
+
refute_solved(test2)
|
39
|
+
sched.s(test3, Dummy.new, [test2])
|
40
|
+
refute_solved(test3)
|
41
|
+
assert(sched.serial || sched.running?)
|
42
|
+
assert_empty(sched.recover)
|
43
|
+
assert(sched.serial || sched.running?)
|
44
|
+
if sched.serial
|
45
|
+
sched.run rescue nil
|
46
|
+
end
|
47
|
+
sched.wait_for(test1, test2, test3)
|
48
|
+
assert_started(test2)
|
49
|
+
assert_started(test3)
|
50
|
+
assert_started(test1)
|
51
|
+
sched.teardown
|
52
|
+
sched.stop
|
53
|
+
|
54
|
+
test4 = "#{prov}-test4"
|
55
|
+
test5 = "#{prov}-test5"
|
56
|
+
|
57
|
+
[test1, test2, test3, test4, test5].each { |x| x.replace(x + "-permfail") }
|
58
|
+
|
59
|
+
sched.s(test1, Dummy.new)
|
60
|
+
sched.s(test2, prov.new)
|
61
|
+
sched.s(test3, Dummy.new, [test2])
|
62
|
+
sched.s(test4, FailedRecoverDummy.new)
|
63
|
+
sched.s(test5, Dummy.new, [test4])
|
64
|
+
sched.run rescue nil
|
65
|
+
if sched.serial
|
66
|
+
assert(sched.needs_recovery?)
|
67
|
+
end
|
68
|
+
sched.run rescue nil
|
69
|
+
assert(sched.serial || sched.running?)
|
70
|
+
unless sched.serial
|
71
|
+
sleep 0.1 while !sched.needs_recovery.has_key?(test2)
|
72
|
+
sleep 0.1 while !sched.needs_recovery.has_key?(test4)
|
73
|
+
end
|
74
|
+
assert(sched.needs_recovery?)
|
75
|
+
refute_solved(test2)
|
76
|
+
refute_solved(test3)
|
77
|
+
refute_solved(test4)
|
78
|
+
assert(sched.serial || sched.running?)
|
79
|
+
assert_equal({ test4 => false }, sched.recover)
|
80
|
+
assert(sched.serial || sched.running?)
|
81
|
+
if sched.serial
|
82
|
+
sched.run rescue nil
|
83
|
+
end
|
84
|
+
sched.wait_for(test1, test2, test3)
|
85
|
+
assert_started(test2)
|
86
|
+
assert_started(test3)
|
87
|
+
assert_started(test1)
|
88
|
+
refute_solved(test4)
|
89
|
+
refute_solved(test5)
|
90
|
+
sched.force_deprovision = true
|
91
|
+
sched.deprovision_group(test4)
|
92
|
+
sched.force_deprovision = false
|
93
|
+
refute_includes(sched.needs_recovery.keys, test4)
|
94
|
+
refute(sched.needs_recovery?)
|
95
|
+
sched.s(test4, Dummy.new)
|
96
|
+
if sched.serial
|
97
|
+
sched.run
|
98
|
+
end
|
99
|
+
assert(sched.serial || sched.running?)
|
100
|
+
sched.wait_for(test4, test5)
|
101
|
+
assert_solved(test4) # we tore it down, so assert_started will break here.
|
102
|
+
assert_started(test5)
|
103
|
+
sched.teardown
|
104
|
+
sched.stop
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
52
108
|
def test_run_tracking
|
53
109
|
#--
|
54
110
|
# This is a tad convoluted. Dummy's startup method sets an ivar which
|
@@ -66,14 +122,12 @@ module Furnish
|
|
66
122
|
assert_equal("floop", sched.vm.groups['test1'].first.report.last, 'state was stored after provision success')
|
67
123
|
|
68
124
|
assert(sched.schedule_provision('test2', [Dummy.new, StartFailDummy.new], []))
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
assert_raises(RuntimeError) do
|
73
|
-
sched.run
|
74
|
-
sleep 0.1 while sched.running?
|
125
|
+
sched.run rescue nil # FIXME oof. maybe move this to indepedent tests for serial mode?
|
126
|
+
unless sched.serial
|
127
|
+
sleep 0.1 while !sched.needs_recovery.has_key?('test2')
|
75
128
|
end
|
76
|
-
|
129
|
+
assert(sched.serial || sched.running?)
|
130
|
+
assert_includes(sched.needs_recovery.keys, 'test2')
|
77
131
|
assert_equal("floop", sched.vm.groups['test2'].first.report.last, "provision failed but state is still stored for the provisions that succeeded")
|
78
132
|
end
|
79
133
|
|
@@ -198,23 +252,25 @@ module Furnish
|
|
198
252
|
tempfiles.push(tf)
|
199
253
|
Furnish.logger = Furnish::Logger.new(tf)
|
200
254
|
|
201
|
-
sched.
|
255
|
+
sched.signal_handler = false
|
256
|
+
sched.run
|
202
257
|
Process.kill(signal, Process.pid)
|
203
258
|
|
204
259
|
sched.stop
|
205
260
|
sleep 0.1 # wait for any writes to complete
|
206
261
|
|
207
|
-
%w[solved working waiting].each do |section|
|
262
|
+
%w[solved working waiting provisioning].each do |section|
|
208
263
|
refute_match(/#{section}/, File.read(tf.path), "#{signal} yielded no output with the #{section} set")
|
209
264
|
end
|
210
265
|
|
211
|
-
sched.
|
266
|
+
sched.signal_handler = true
|
267
|
+
sched.run
|
212
268
|
Process.kill(signal, Process.pid)
|
213
269
|
|
214
270
|
sched.stop
|
215
271
|
sleep 0.1 # wait for any writes to complete
|
216
272
|
|
217
|
-
%w[solved working waiting].each do |section|
|
273
|
+
%w[solved working waiting provisioning].each do |section|
|
218
274
|
assert_match(/#{section}/, File.read(tf.path), "#{signal} yielded output with the #{section} set")
|
219
275
|
end
|
220
276
|
end
|
@@ -226,10 +282,12 @@ module Furnish
|
|
226
282
|
def test_provision_failures
|
227
283
|
dummy = StartFailDummy.new
|
228
284
|
assert(sched.schedule_provision('blarg', dummy))
|
229
|
-
|
230
|
-
|
231
|
-
sched.
|
285
|
+
sched.run rescue nil # FIXME oof. maybe move this to indepedent tests for serial mode?
|
286
|
+
if !sched.serial
|
287
|
+
sleep 0.1 while !sched.needs_recovery.has_key?('blarg')
|
232
288
|
end
|
289
|
+
assert(sched.serial || sched.running?, 'still running after failure')
|
290
|
+
assert_includes(sched.needs_recovery, 'blarg')
|
233
291
|
sched.stop
|
234
292
|
sched.deprovision_group('blarg')
|
235
293
|
|
data/test/test_api.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestAPI < Furnish::TestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
# NOTE this class is defined in test/dummy_classes.rb
|
7
|
+
@klass = APIDummy
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_constructor
|
11
|
+
assert_raises(ArgumentError, "Arguments must be a kind of hash") { @klass.new(nil) }
|
12
|
+
obj = @klass.new(:foo => 1)
|
13
|
+
assert_equal(1, obj.foo, "attrs are set based on contents of constructor")
|
14
|
+
assert_raises(ArgumentError) { @klass.new(:quux => 2) }
|
15
|
+
assert_raises(ArgumentError) { @klass.new(:bar => 2) }
|
16
|
+
assert_raises(ArgumentError) { @klass.new(:foo => "string") }
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_interface
|
20
|
+
assert_respond_to(@klass, :furnish_properties)
|
21
|
+
assert_respond_to(@klass, :furnish_property)
|
22
|
+
|
23
|
+
assert_kind_of(Hash, @klass.furnish_properties)
|
24
|
+
assert_includes(@klass.furnish_properties, :foo)
|
25
|
+
assert_includes(@klass.furnish_properties, :a_string)
|
26
|
+
refute_includes(@klass.furnish_properties, :bar)
|
27
|
+
assert_kind_of(Hash, @klass.furnish_properties[:foo])
|
28
|
+
assert_equal("does things with foo", @klass.furnish_properties[:foo][:description])
|
29
|
+
assert_equal(Integer, @klass.furnish_properties[:foo][:type])
|
30
|
+
|
31
|
+
obj = @klass.new(:foo => 1)
|
32
|
+
|
33
|
+
assert_respond_to(obj, :furnish_group_name)
|
34
|
+
assert_respond_to(obj, :furnish_group_name=)
|
35
|
+
|
36
|
+
%w[startup shutdown].each do |meth|
|
37
|
+
assert_raises(NotImplementedError, "#{meth} method not implemented for #{@klass.name}") { obj.send(meth) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_report
|
42
|
+
obj = @klass.new(:foo => 1)
|
43
|
+
assert_equal(["unknown"], obj.report, "default report uses 'unknown' as the group name")
|
44
|
+
obj.furnish_group_name = "frobnik"
|
45
|
+
assert_equal(["frobnik"], obj.report, "when furnish_group_name is set, uses that in the report")
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_to_s
|
49
|
+
obj = @klass.new(:foo => 1)
|
50
|
+
assert_equal("unknown[#{@klass.name}]", obj.to_s, "formatted properly without a furnish group name")
|
51
|
+
obj.furnish_group_name = "frobnik"
|
52
|
+
assert_equal("frobnik[#{@klass.name}]", obj.to_s, "formatted properly without a furnish group name")
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_equality
|
56
|
+
assert_equal(Dummy.new, Dummy.new)
|
57
|
+
assert_equal(APIDummy.new(:foo => 1), APIDummy.new(:foo => 1))
|
58
|
+
refute_equal(APIDummy.new(:foo => 2), APIDummy.new(:foo => 1))
|
59
|
+
refute_equal(Dummy.new, StopFailDummy.new)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_recovery
|
63
|
+
prov = APIDummy.new
|
64
|
+
refute(prov.recover(:startup, nil))
|
65
|
+
prov = BrokenRecoverAPIDummy.new
|
66
|
+
assert_raises(NotImplementedError) { prov.recover(:startup, nil) }
|
67
|
+
end
|
68
|
+
end
|
data/test/test_dummy.rb
CHANGED
@@ -14,7 +14,7 @@ require 'helper'
|
|
14
14
|
class TestDummy < Furnish::TestCase
|
15
15
|
def test_defaults
|
16
16
|
dummy = Dummy.new
|
17
|
-
dummy.
|
17
|
+
dummy.furnish_group_name = 'dummy_test'
|
18
18
|
assert(dummy.startup, 'startup returns true by default')
|
19
19
|
assert(dummy.shutdown, 'shutdown returns true by default')
|
20
20
|
assert_equal(['dummy_test', 'floop'], dummy.report, 'report returns boxed name and ivar by default')
|
@@ -29,7 +29,7 @@ class TestDummy < Furnish::TestCase
|
|
29
29
|
machine_names = %w[one two three]
|
30
30
|
machine_names.each do |name|
|
31
31
|
dummy = Dummy.new
|
32
|
-
dummy.
|
32
|
+
dummy.furnish_group_name = name
|
33
33
|
assert(dummy.startup)
|
34
34
|
end
|
35
35
|
|
@@ -42,7 +42,7 @@ class TestDummy < Furnish::TestCase
|
|
42
42
|
|
43
43
|
machine_names.each do |name|
|
44
44
|
dummy = Dummy.new
|
45
|
-
dummy.
|
45
|
+
dummy.furnish_group_name = name
|
46
46
|
assert(dummy.shutdown)
|
47
47
|
end
|
48
48
|
|
@@ -54,7 +54,7 @@ class TestDummy < Furnish::TestCase
|
|
54
54
|
def test_call_order
|
55
55
|
dummies = Dummy.new, Dummy.new
|
56
56
|
dummies.each_with_index do |x, i|
|
57
|
-
x.
|
57
|
+
x.furnish_group_name = "foo"
|
58
58
|
x.id = "foo#{i}"
|
59
59
|
assert(x.startup)
|
60
60
|
end
|
@@ -72,10 +72,10 @@ class TestDummy < Furnish::TestCase
|
|
72
72
|
|
73
73
|
def test_marshal
|
74
74
|
dummy = Dummy.new
|
75
|
-
dummy.
|
75
|
+
dummy.furnish_group_name = "dummy_marshal_test"
|
76
76
|
assert(dummy.startup)
|
77
77
|
assert(dummy.shutdown)
|
78
|
-
assert_equal([dummy.
|
78
|
+
assert_equal([dummy.furnish_group_name, 'floop'], dummy.report)
|
79
79
|
|
80
80
|
obj = Palsy::Object.new('dummy')
|
81
81
|
%w[startup shutdown report].each do |meth|
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestProtocol < Furnish::TestCase
|
4
|
+
#--
|
5
|
+
# see the Furnish::Protocol docs for truth tables and whatnot
|
6
|
+
#++
|
7
|
+
|
8
|
+
def test_setters
|
9
|
+
proto = Furnish::Protocol.new
|
10
|
+
assert_equal([:requires, :accepts, :yields], Furnish::Protocol::VALIDATOR_NAMES)
|
11
|
+
|
12
|
+
Furnish::Protocol::VALIDATOR_NAMES.each do |vname|
|
13
|
+
proto.send(vname, :foo, "a description", Integer)
|
14
|
+
assert_includes(proto[vname], :foo)
|
15
|
+
assert_equal({ :description => "a description", :type => Integer }, proto[vname][:foo])
|
16
|
+
proto.send(vname, "bar")
|
17
|
+
assert_includes(proto[vname], :bar)
|
18
|
+
assert_equal({ :description => "", :type => Object }, proto[vname][:bar])
|
19
|
+
end
|
20
|
+
|
21
|
+
refute(proto[:accepts_from_any])
|
22
|
+
proto.accepts_from_any(true)
|
23
|
+
assert(proto[:accepts_from_any])
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_configure
|
27
|
+
proto = Furnish::Protocol.new
|
28
|
+
proto.configure do
|
29
|
+
requires :foo, "a description", Integer
|
30
|
+
accepts "bar"
|
31
|
+
yields :quux, "another description", Hash
|
32
|
+
end
|
33
|
+
|
34
|
+
assert_includes(proto[:requires], :foo)
|
35
|
+
assert_includes(proto[:accepts], :bar)
|
36
|
+
assert_includes(proto[:yields], :quux)
|
37
|
+
|
38
|
+
assert_equal(
|
39
|
+
{ :description => "a description", :type => Integer },
|
40
|
+
proto[:requires][:foo]
|
41
|
+
)
|
42
|
+
|
43
|
+
assert_equal(
|
44
|
+
{ :description => "", :type => Object },
|
45
|
+
proto[:accepts][:bar]
|
46
|
+
)
|
47
|
+
|
48
|
+
assert_equal(
|
49
|
+
{ :description => "another description", :type => Hash },
|
50
|
+
proto[:yields][:quux]
|
51
|
+
)
|
52
|
+
|
53
|
+
proto = Furnish::Protocol.new
|
54
|
+
|
55
|
+
assert_raises(RuntimeError) do
|
56
|
+
proto.configure do
|
57
|
+
accepts_from(Furnish::Protocol.new)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
proto = Furnish::Protocol.new
|
62
|
+
|
63
|
+
assert_raises(RuntimeError) do
|
64
|
+
proto.configure do
|
65
|
+
requires_from(Furnish::Protocol.new)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_requires_from
|
71
|
+
proto1 = Furnish::Protocol.new
|
72
|
+
proto2 = Furnish::Protocol.new
|
73
|
+
|
74
|
+
assert(proto2.requires_from(nil))
|
75
|
+
|
76
|
+
proto1.yields(:bar)
|
77
|
+
proto2.requires(:bar)
|
78
|
+
|
79
|
+
assert(proto2.requires_from(proto1))
|
80
|
+
|
81
|
+
proto1 = Furnish::Protocol.new
|
82
|
+
refute(proto2.requires_from(proto1))
|
83
|
+
|
84
|
+
proto1.yields(:bar)
|
85
|
+
proto2 = Furnish::Protocol.new
|
86
|
+
|
87
|
+
assert(proto2.requires_from(proto1))
|
88
|
+
|
89
|
+
proto2.requires(:bar)
|
90
|
+
proto2.requires(:quux)
|
91
|
+
|
92
|
+
refute(proto2.requires_from(proto1))
|
93
|
+
|
94
|
+
proto1 = Furnish::Protocol.new
|
95
|
+
proto2 = Furnish::Protocol.new
|
96
|
+
|
97
|
+
proto1.yields(:bar, "bar", Integer)
|
98
|
+
proto2.requires(:bar, "bar", Integer)
|
99
|
+
|
100
|
+
assert(proto2.requires_from(proto1), 'types match')
|
101
|
+
|
102
|
+
proto1 = Furnish::Protocol.new
|
103
|
+
proto2 = Furnish::Protocol.new
|
104
|
+
|
105
|
+
proto1.yields(:bar, "bar", Integer)
|
106
|
+
proto2.requires(:bar, "bar", Fixnum)
|
107
|
+
|
108
|
+
assert(proto2.requires_from(proto1), 'Integer is an ancestor of Fixnum')
|
109
|
+
|
110
|
+
proto1 = Furnish::Protocol.new
|
111
|
+
proto2 = Furnish::Protocol.new
|
112
|
+
|
113
|
+
proto1.yields(:bar, "bar", Fixnum)
|
114
|
+
proto2.requires(:bar, "bar", Integer)
|
115
|
+
|
116
|
+
refute(proto2.requires_from(proto1), 'Fixnum is not an ancestor of Integer')
|
117
|
+
|
118
|
+
proto1 = Furnish::Protocol.new
|
119
|
+
proto2 = Furnish::Protocol.new
|
120
|
+
|
121
|
+
proto1.yields(:bar, "bar", String)
|
122
|
+
proto2.requires(:bar, "bar", Integer)
|
123
|
+
|
124
|
+
refute(proto2.requires_from(proto1), 'completely different types (String/Integer)')
|
125
|
+
|
126
|
+
proto1 = Furnish::Protocol.new
|
127
|
+
proto2 = Furnish::Protocol.new
|
128
|
+
|
129
|
+
proto1.yields(:bar, "bar")
|
130
|
+
proto2.requires(:bar, "bar", Integer)
|
131
|
+
|
132
|
+
assert(proto2.requires_from(proto1), 'default type is Object, succeeds with other types')
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_accepts_from
|
136
|
+
proto1 = Furnish::Protocol.new
|
137
|
+
proto2 = Furnish::Protocol.new
|
138
|
+
|
139
|
+
assert(proto2.accepts_from(nil))
|
140
|
+
|
141
|
+
proto1.yields(:bar)
|
142
|
+
proto2.accepts(:bar)
|
143
|
+
|
144
|
+
assert(proto2.accepts_from(proto1))
|
145
|
+
|
146
|
+
proto1 = Furnish::Protocol.new
|
147
|
+
refute(proto2.accepts_from(proto1))
|
148
|
+
|
149
|
+
proto1.yields(:foo)
|
150
|
+
refute(proto2.accepts_from(proto1))
|
151
|
+
|
152
|
+
proto2.accepts_from_any(true)
|
153
|
+
assert(proto2.accepts_from(proto1))
|
154
|
+
|
155
|
+
proto1 = Furnish::Protocol.new
|
156
|
+
proto2 = Furnish::Protocol.new
|
157
|
+
proto2.accepts(:quux)
|
158
|
+
proto2.accepts(:bar)
|
159
|
+
proto1.yields(:quux)
|
160
|
+
|
161
|
+
assert(proto2.accepts_from(proto1))
|
162
|
+
|
163
|
+
proto1 = Furnish::Protocol.new
|
164
|
+
proto2 = Furnish::Protocol.new
|
165
|
+
|
166
|
+
proto1.yields(:bar, "bar", Integer)
|
167
|
+
proto2.accepts(:bar, "bar", Integer)
|
168
|
+
|
169
|
+
assert(proto2.accepts_from(proto1), 'types match')
|
170
|
+
|
171
|
+
proto1 = Furnish::Protocol.new
|
172
|
+
proto2 = Furnish::Protocol.new
|
173
|
+
|
174
|
+
proto1.yields(:bar, "bar", Integer)
|
175
|
+
proto2.accepts(:bar, "bar", Fixnum)
|
176
|
+
|
177
|
+
assert(proto2.accepts_from(proto1), 'Integer is an ancestor of Fixnum')
|
178
|
+
|
179
|
+
proto1 = Furnish::Protocol.new
|
180
|
+
proto2 = Furnish::Protocol.new
|
181
|
+
|
182
|
+
proto1.yields(:bar, "bar", Fixnum)
|
183
|
+
proto2.accepts(:bar, "bar", Integer)
|
184
|
+
|
185
|
+
refute(proto2.accepts_from(proto1), 'Fixnum is not an ancestor of Integer')
|
186
|
+
|
187
|
+
proto1 = Furnish::Protocol.new
|
188
|
+
proto2 = Furnish::Protocol.new
|
189
|
+
|
190
|
+
proto1.yields(:bar, "bar", String)
|
191
|
+
proto2.accepts(:bar, "bar", Integer)
|
192
|
+
|
193
|
+
refute(proto2.accepts_from(proto1), 'completely different types (String/Integer)')
|
194
|
+
|
195
|
+
proto1 = Furnish::Protocol.new
|
196
|
+
proto2 = Furnish::Protocol.new
|
197
|
+
|
198
|
+
proto1.yields(:bar, "bar")
|
199
|
+
proto2.accepts(:bar, "bar", Integer)
|
200
|
+
|
201
|
+
assert(proto2.accepts_from(proto1), 'default type is Object, succeeds with other types')
|
202
|
+
|
203
|
+
proto1 = Furnish::Protocol.new
|
204
|
+
proto2 = Furnish::Protocol.new
|
205
|
+
|
206
|
+
proto1.yields(:foo, "foo")
|
207
|
+
proto2.accepts(:bar, "bar", Integer)
|
208
|
+
|
209
|
+
refute(proto2.accepts_from(proto1), "nothing accepted is yielded")
|
210
|
+
end
|
211
|
+
end
|