dosire-god 0.7.9

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 (108) hide show
  1. data/History.txt +261 -0
  2. data/Manifest.txt +107 -0
  3. data/README.txt +59 -0
  4. data/Rakefile +35 -0
  5. data/bin/god +127 -0
  6. data/examples/events.god +84 -0
  7. data/examples/gravatar.god +54 -0
  8. data/examples/single.god +66 -0
  9. data/ext/god/extconf.rb +55 -0
  10. data/ext/god/kqueue_handler.c +123 -0
  11. data/ext/god/netlink_handler.c +167 -0
  12. data/init/god +42 -0
  13. data/lib/god/behavior.rb +52 -0
  14. data/lib/god/behaviors/clean_pid_file.rb +21 -0
  15. data/lib/god/behaviors/clean_unix_socket.rb +21 -0
  16. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  17. data/lib/god/cli/command.rb +206 -0
  18. data/lib/god/cli/run.rb +177 -0
  19. data/lib/god/cli/version.rb +23 -0
  20. data/lib/god/condition.rb +96 -0
  21. data/lib/god/conditions/always.rb +23 -0
  22. data/lib/god/conditions/complex.rb +86 -0
  23. data/lib/god/conditions/cpu_usage.rb +80 -0
  24. data/lib/god/conditions/degrading_lambda.rb +52 -0
  25. data/lib/god/conditions/disk_usage.rb +27 -0
  26. data/lib/god/conditions/flapping.rb +128 -0
  27. data/lib/god/conditions/http_response_code.rb +168 -0
  28. data/lib/god/conditions/lambda.rb +25 -0
  29. data/lib/god/conditions/memory_usage.rb +82 -0
  30. data/lib/god/conditions/process_exits.rb +72 -0
  31. data/lib/god/conditions/process_running.rb +74 -0
  32. data/lib/god/conditions/tries.rb +44 -0
  33. data/lib/god/configurable.rb +57 -0
  34. data/lib/god/contact.rb +106 -0
  35. data/lib/god/contacts/email.rb +95 -0
  36. data/lib/god/dependency_graph.rb +41 -0
  37. data/lib/god/diagnostics.rb +37 -0
  38. data/lib/god/driver.rb +206 -0
  39. data/lib/god/errors.rb +24 -0
  40. data/lib/god/event_handler.rb +111 -0
  41. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  42. data/lib/god/event_handlers/kqueue_handler.rb +17 -0
  43. data/lib/god/event_handlers/netlink_handler.rb +13 -0
  44. data/lib/god/logger.rb +120 -0
  45. data/lib/god/metric.rb +59 -0
  46. data/lib/god/process.rb +327 -0
  47. data/lib/god/registry.rb +32 -0
  48. data/lib/god/simple_logger.rb +53 -0
  49. data/lib/god/socket.rb +96 -0
  50. data/lib/god/sugar.rb +47 -0
  51. data/lib/god/system/portable_poller.rb +42 -0
  52. data/lib/god/system/process.rb +42 -0
  53. data/lib/god/system/slash_proc_poller.rb +82 -0
  54. data/lib/god/task.rb +487 -0
  55. data/lib/god/timeline.rb +25 -0
  56. data/lib/god/trigger.rb +43 -0
  57. data/lib/god/watch.rb +183 -0
  58. data/lib/god.rb +644 -0
  59. data/test/configs/child_events/child_events.god +44 -0
  60. data/test/configs/child_events/simple_server.rb +3 -0
  61. data/test/configs/child_polls/child_polls.god +37 -0
  62. data/test/configs/child_polls/simple_server.rb +12 -0
  63. data/test/configs/complex/complex.god +59 -0
  64. data/test/configs/complex/simple_server.rb +3 -0
  65. data/test/configs/contact/contact.god +74 -0
  66. data/test/configs/contact/simple_server.rb +3 -0
  67. data/test/configs/daemon_events/daemon_events.god +37 -0
  68. data/test/configs/daemon_events/simple_server.rb +8 -0
  69. data/test/configs/daemon_events/simple_server_stop.rb +11 -0
  70. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  71. data/test/configs/daemon_polls/simple_server.rb +6 -0
  72. data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
  73. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  74. data/test/configs/matias/matias.god +50 -0
  75. data/test/configs/real.rb +59 -0
  76. data/test/configs/running_load/running_load.god +16 -0
  77. data/test/configs/stress/simple_server.rb +3 -0
  78. data/test/configs/stress/stress.god +15 -0
  79. data/test/configs/task/logs/.placeholder +0 -0
  80. data/test/configs/task/task.god +26 -0
  81. data/test/configs/test.rb +61 -0
  82. data/test/helper.rb +151 -0
  83. data/test/suite.rb +6 -0
  84. data/test/test_behavior.rb +21 -0
  85. data/test/test_condition.rb +50 -0
  86. data/test/test_conditions_disk_usage.rb +56 -0
  87. data/test/test_conditions_http_response_code.rb +109 -0
  88. data/test/test_conditions_process_running.rb +44 -0
  89. data/test/test_conditions_tries.rb +67 -0
  90. data/test/test_contact.rb +109 -0
  91. data/test/test_dependency_graph.rb +62 -0
  92. data/test/test_driver.rb +11 -0
  93. data/test/test_event_handler.rb +80 -0
  94. data/test/test_god.rb +598 -0
  95. data/test/test_handlers_kqueue_handler.rb +16 -0
  96. data/test/test_logger.rb +63 -0
  97. data/test/test_metric.rb +72 -0
  98. data/test/test_process.rb +246 -0
  99. data/test/test_registry.rb +15 -0
  100. data/test/test_socket.rb +42 -0
  101. data/test/test_sugar.rb +42 -0
  102. data/test/test_system_portable_poller.rb +17 -0
  103. data/test/test_system_process.rb +30 -0
  104. data/test/test_task.rb +262 -0
  105. data/test/test_timeline.rb +37 -0
  106. data/test/test_trigger.rb +59 -0
  107. data/test/test_watch.rb +279 -0
  108. metadata +186 -0
data/test/helper.rb ADDED
@@ -0,0 +1,151 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. lib god])
2
+ God::EventHandler.load
3
+
4
+ require 'test/unit'
5
+ require 'set'
6
+
7
+ include God
8
+
9
+ if Process.uid != 0
10
+ abort <<-EOF
11
+ \n
12
+ *********************************************************************
13
+ * *
14
+ * You need to run these tests as root *
15
+ * chroot and netlink (linux only) require it *
16
+ * *
17
+ *********************************************************************
18
+ EOF
19
+ end
20
+
21
+ begin
22
+ require 'mocha'
23
+ rescue LoadError
24
+ unless gems ||= false
25
+ require 'rubygems'
26
+ gems = true
27
+ retry
28
+ else
29
+ abort "=> You need the Mocha gem to run these tests."
30
+ end
31
+ end
32
+
33
+ module God
34
+ module Conditions
35
+ class FakeCondition < Condition
36
+ def test
37
+ true
38
+ end
39
+ end
40
+
41
+ class FakePollCondition < PollCondition
42
+ def test
43
+ true
44
+ end
45
+ end
46
+
47
+ class FakeEventCondition < EventCondition
48
+ def register
49
+ end
50
+ def deregister
51
+ end
52
+ end
53
+ end
54
+
55
+ module Behaviors
56
+ class FakeBehavior < Behavior
57
+ def before_start
58
+ 'foo'
59
+ end
60
+ def after_start
61
+ 'bar'
62
+ end
63
+ end
64
+ end
65
+
66
+ module Contacts
67
+ class FakeContact < Contact
68
+ end
69
+
70
+ class InvalidContact
71
+ end
72
+ end
73
+
74
+ def self.reset
75
+ self.watches = nil
76
+ self.groups = nil
77
+ self.server = nil
78
+ self.inited = nil
79
+ self.host = nil
80
+ self.port = nil
81
+ self.pid_file_directory = nil
82
+ self.registry.reset
83
+ end
84
+ end
85
+
86
+ def silence_warnings
87
+ old_verbose, $VERBOSE = $VERBOSE, nil
88
+ yield
89
+ ensure
90
+ $VERBOSE = old_verbose
91
+ end
92
+
93
+ def no_stdout
94
+ old_stdout = $stdout.dup
95
+ $stdout.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
96
+ yield
97
+ $stdout.reopen(old_stdout)
98
+ end
99
+
100
+ def no_stderr
101
+ old_stderr = $stderr.dup
102
+ $stderr.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
103
+ yield
104
+ $stderr.reopen(old_stderr)
105
+ end
106
+
107
+ module Kernel
108
+ def abort(text)
109
+ raise SystemExit
110
+ end
111
+ def exit(code)
112
+ raise SystemExit
113
+ end
114
+ end
115
+
116
+ module Test::Unit::Assertions
117
+ def assert_abort
118
+ assert_raise SystemExit do
119
+ yield
120
+ end
121
+ end
122
+ end
123
+
124
+ # This allows you to be a good OOP citizen and honor encapsulation, but
125
+ # still make calls to private methods (for testing) by doing
126
+ #
127
+ # obj.bypass.private_thingie(arg1, arg2)
128
+ #
129
+ # Which is easier on the eye than
130
+ #
131
+ # obj.send(:private_thingie, arg1, arg2)
132
+ #
133
+ class Object
134
+ class Bypass
135
+ instance_methods.each do |m|
136
+ undef_method m unless m =~ /^__/
137
+ end
138
+
139
+ def initialize(ref)
140
+ @ref = ref
141
+ end
142
+
143
+ def method_missing(sym, *args)
144
+ @ref.__send__(sym, *args)
145
+ end
146
+ end
147
+
148
+ def bypass
149
+ Bypass.new(self)
150
+ end
151
+ end
data/test/suite.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'test/unit'
2
+
3
+ tests = Dir["#{File.dirname(__FILE__)}/test_*.rb"]
4
+ tests.each do |file|
5
+ require file
6
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestBehavior < Test::Unit::TestCase
4
+ def test_generate_should_return_an_object_corresponding_to_the_given_type
5
+ assert_equal Behaviors::FakeBehavior, Behavior.generate(:fake_behavior, nil).class
6
+ end
7
+
8
+ def test_generate_should_raise_on_invalid_type
9
+ assert_raise NoSuchBehaviorError do
10
+ Behavior.generate(:foo, nil)
11
+ end
12
+ end
13
+
14
+ def test_complain
15
+ Syslog.expects(:err).with('foo')
16
+ # Kernel.expects(:puts).with('foo')
17
+ no_stdout do
18
+ assert !Behavior.allocate.bypass.complain('foo')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class BadlyImplementedCondition < PollCondition
4
+ end
5
+
6
+ class TestCondition < Test::Unit::TestCase
7
+
8
+ # generate
9
+
10
+ def test_generate_should_return_an_object_corresponding_to_the_given_type
11
+ assert_equal Conditions::ProcessRunning, Condition.generate(:process_running, nil).class
12
+ end
13
+
14
+ def test_generate_should_raise_on_invalid_type
15
+ assert_raise NoSuchConditionError do
16
+ Condition.generate(:foo, nil)
17
+ end
18
+ end
19
+
20
+ def test_generate_should_abort_on_event_condition_without_loaded_event_system
21
+ God::EventHandler.stubs(:operational?).returns(false)
22
+ assert_abort do
23
+ God::EventHandler.start
24
+ Condition.generate(:process_exits, nil).class
25
+ end
26
+ end
27
+
28
+ def test_generate_should_return_a_good_error_message_for_invalid_types
29
+ emsg = "No Condition found with the class name God::Conditions::FooBar"
30
+ rmsg = nil
31
+
32
+ begin
33
+ Condition.generate(:foo_bar, nil)
34
+ rescue => e
35
+ rmsg = e.message
36
+ end
37
+
38
+ assert_equal emsg, rmsg
39
+ end
40
+
41
+ # test
42
+
43
+ def test_test_should_raise_if_not_defined_in_subclass
44
+ c = BadlyImplementedCondition.new
45
+
46
+ assert_raise AbstractMethodNotOverriddenError do
47
+ c.test
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestConditionsDiskUsage < Test::Unit::TestCase
4
+ # valid?
5
+
6
+ def test_valid_should_return_false_if_no_above_given
7
+ c = Conditions::DiskUsage.new
8
+ c.mount_point = '/'
9
+ c.watch = stub(:name => 'foo')
10
+
11
+ no_stdout do
12
+ assert_equal false, c.valid?
13
+ end
14
+ end
15
+
16
+ def test_valid_should_return_false_if_no_mount_point_given
17
+ c = Conditions::DiskUsage.new
18
+ c.above = 90
19
+ c.watch = stub(:name => 'foo')
20
+
21
+ no_stdout do
22
+ assert_equal false, c.valid?
23
+ end
24
+ end
25
+
26
+ def test_valid_should_return_true_if_required_options_all_set
27
+ c = Conditions::DiskUsage.new
28
+ c.above = 90
29
+ c.mount_point = '/'
30
+ c.watch = stub(:name => 'foo')
31
+
32
+ assert_equal true, c.valid?
33
+ end
34
+
35
+ # test
36
+
37
+ def test_test_should_return_true_if_above_limit
38
+ c = Conditions::DiskUsage.new
39
+ c.above = 90
40
+ c.mount_point = '/'
41
+
42
+ c.expects(:`).returns('91')
43
+
44
+ assert_equal true, c.test
45
+ end
46
+
47
+ def test_test_should_return_false_if_below_limit
48
+ c = Conditions::DiskUsage.new
49
+ c.above = 90
50
+ c.mount_point = '/'
51
+
52
+ c.expects(:`).returns('90')
53
+
54
+ assert_equal false, c.test
55
+ end
56
+ end
@@ -0,0 +1,109 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestHttpResponseCode < Test::Unit::TestCase
4
+ def valid_condition
5
+ c = Conditions::HttpResponseCode.new()
6
+ c.watch = stub(:name => 'foo')
7
+ c.host = 'localhost'
8
+ c.port = 8080
9
+ c.path = '/'
10
+ c.timeout = 10
11
+ c.code_is = 200
12
+ c.times = 1
13
+ yield(c) if block_given?
14
+ c.prepare
15
+ c
16
+ end
17
+
18
+ # valid?
19
+
20
+ def test_valid_condition_is_valid
21
+ c = valid_condition
22
+ assert c.valid?
23
+ end
24
+
25
+ def test_valid_should_return_false_if_both_code_is_and_code_is_not_are_set
26
+ c = valid_condition do |cc|
27
+ cc.code_is_not = 500
28
+ end
29
+ no_stdout { assert !c.valid? }
30
+ end
31
+
32
+ def test_valid_should_return_false_if_no_host_set
33
+ c = valid_condition do |cc|
34
+ cc.host = nil
35
+ end
36
+ no_stdout { assert !c.valid? }
37
+ end
38
+
39
+ # test
40
+
41
+ def test_test_should_return_false_if_code_is_is_set_to_200_but_response_is_500
42
+ c = valid_condition
43
+ Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 500)))
44
+ assert_equal false, c.test
45
+ end
46
+
47
+ def test_test_should_return_false_if_code_is_not_is_set_to_200_and_response_is_200
48
+ c = valid_condition do |cc|
49
+ cc.code_is = nil
50
+ cc.code_is_not = [200]
51
+ end
52
+ Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200)))
53
+ assert_equal false, c.test
54
+ end
55
+
56
+ def test_test_should_return_true_if_code_is_is_set_to_200_and_response_is_200
57
+ c = valid_condition
58
+ Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200)))
59
+ assert_equal true, c.test
60
+ end
61
+
62
+ def test_test_should_return_false_if_code_is_not_is_set_to_200_but_response_is_500
63
+ c = valid_condition do |cc|
64
+ cc.code_is = nil
65
+ cc.code_is_not = [200]
66
+ end
67
+ Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 500)))
68
+ assert_equal true, c.test
69
+ end
70
+
71
+ def test_test_should_return_false_if_code_is_is_set_to_200_but_response_times_out
72
+ c = valid_condition
73
+ Net::HTTP.expects(:start).raises(Timeout::Error, '')
74
+ assert_equal false, c.test
75
+ end
76
+
77
+ def test_test_should_return_true_if_code_is_not_is_set_to_200_and_response_times_out
78
+ c = valid_condition do |cc|
79
+ cc.code_is = nil
80
+ cc.code_is_not = [200]
81
+ end
82
+ Net::HTTP.expects(:start).raises(Timeout::Error, '')
83
+ assert_equal true, c.test
84
+ end
85
+
86
+ def test_test_should_return_false_if_code_is_is_set_to_200_but_cant_connect
87
+ c = valid_condition
88
+ Net::HTTP.expects(:start).raises(Errno::ECONNREFUSED, '')
89
+ assert_equal false, c.test
90
+ end
91
+
92
+ def test_test_should_return_true_if_code_is_not_is_set_to_200_and_cant_connect
93
+ c = valid_condition do |cc|
94
+ cc.code_is = nil
95
+ cc.code_is_not = [200]
96
+ end
97
+ Net::HTTP.expects(:start).raises(Errno::ECONNREFUSED, '')
98
+ assert_equal true, c.test
99
+ end
100
+
101
+ def test_test_should_return_true_if_code_is_is_set_to_200_and_response_is_200_twice_for_times_two_of_two
102
+ c = valid_condition do |cc|
103
+ cc.times = [2, 2]
104
+ end
105
+ Net::HTTP.expects(:start).yields(stub(:read_timeout= => nil, :get => stub(:code => 200))).times(2)
106
+ assert_equal false, c.test
107
+ assert_equal true, c.test
108
+ end
109
+ end
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestConditionsProcessRunning < Test::Unit::TestCase
4
+ def test_missing_pid_file_returns_opposite
5
+ [true, false].each do |r|
6
+ c = Conditions::ProcessRunning.new
7
+ c.running = r
8
+
9
+ c.stubs(:watch).returns(stub(:pid => 123, :name => 'foo'))
10
+
11
+ # no_stdout do
12
+ assert_equal !r, c.test
13
+ # end
14
+ end
15
+ end
16
+
17
+ def test_not_running_returns_opposite
18
+ [true, false].each do |r|
19
+ c = Conditions::ProcessRunning.new
20
+ c.running = r
21
+
22
+ File.stubs(:exist?).returns(true)
23
+ c.stubs(:watch).returns(stub(:pid => 123))
24
+ File.stubs(:read).returns('5')
25
+ System::Process.any_instance.stubs(:exists?).returns(false)
26
+
27
+ assert_equal !r, c.test
28
+ end
29
+ end
30
+
31
+ def test_running_returns_same
32
+ [true, false].each do |r|
33
+ c = Conditions::ProcessRunning.new
34
+ c.running = r
35
+
36
+ File.stubs(:exist?).returns(true)
37
+ c.stubs(:watch).returns(stub(:pid => 123))
38
+ File.stubs(:read).returns('5')
39
+ System::Process.any_instance.stubs(:exists?).returns(true)
40
+
41
+ assert_equal r, c.test
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,67 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestConditionsTries < Test::Unit::TestCase
4
+ # valid?
5
+
6
+ def test_valid_should_return_false_if_times_not_set
7
+ c = Conditions::Tries.new
8
+ c.watch = stub(:name => 'foo')
9
+ no_stdout { assert !c.valid? }
10
+ end
11
+ end
12
+
13
+
14
+ class TestConditionsTries < Test::Unit::TestCase
15
+ def setup
16
+ @c = Conditions::Tries.new
17
+ @c.times = 3
18
+ @c.prepare
19
+ end
20
+
21
+ # prepare
22
+
23
+ def test_prepare_should_create_timeline
24
+ assert 3, @c.instance_variable_get(:@timeline).instance_variable_get(:@max_size)
25
+ end
26
+
27
+ # test
28
+
29
+ def test_test_should_return_true_if_called_three_times_within_one_second
30
+ assert !@c.test
31
+ assert !@c.test
32
+ assert @c.test
33
+ end
34
+
35
+ # reset
36
+
37
+ def test_test_should_return_false_on_fourth_call_if_called_three_times_within_one_second
38
+ 3.times { @c.test }
39
+ @c.reset
40
+ assert !@c.test
41
+ end
42
+ end
43
+
44
+
45
+ class TestConditionsTriesWithin < Test::Unit::TestCase
46
+ def setup
47
+ @c = Conditions::Tries.new
48
+ @c.times = 3
49
+ @c.within = 1.seconds
50
+ @c.prepare
51
+ end
52
+
53
+ # test
54
+
55
+ def test_test_should_return_true_if_called_three_times_within_one_second
56
+ assert !@c.test
57
+ assert !@c.test
58
+ assert @c.test
59
+ end
60
+
61
+ def test_test_should_return_false_if_called_three_times_within_two_seconds
62
+ assert !@c.test
63
+ assert !@c.test
64
+ assert sleep(1.1)
65
+ assert !@c.test
66
+ end
67
+ end
@@ -0,0 +1,109 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestContact < Test::Unit::TestCase
4
+ def test_exists
5
+ God::Contact
6
+ end
7
+
8
+ # generate
9
+
10
+ def test_generate_should_raise_on_invalid_kind
11
+ assert_raise(NoSuchContactError) do
12
+ Contact.generate(:invalid)
13
+ end
14
+ end
15
+
16
+ def test_generate_should_abort_on_invalid_contact
17
+ assert_abort do
18
+ Contact.generate(:invalid_contact)
19
+ end
20
+ end
21
+
22
+ # normalize
23
+
24
+ def test_normalize_should_accept_a_string
25
+ input = 'tom'
26
+ output = {:contacts => ['tom']}
27
+ assert_equal(output, Contact.normalize(input))
28
+ end
29
+
30
+ def test_normalize_should_accept_an_array_of_strings
31
+ input = ['tom', 'kevin']
32
+ output = {:contacts => ['tom', 'kevin']}
33
+ assert_equal(output, Contact.normalize(input))
34
+ end
35
+
36
+ def test_normalize_should_accept_a_hash_with_contacts_string
37
+ input = {:contacts => 'tom'}
38
+ output = {:contacts => ['tom']}
39
+ assert_equal(output, Contact.normalize(input))
40
+ end
41
+
42
+ def test_normalize_should_accept_a_hash_with_contacts_array_of_strings
43
+ input = {:contacts => ['tom', 'kevin']}
44
+ output = {:contacts => ['tom', 'kevin']}
45
+ assert_equal(output, Contact.normalize(input))
46
+ end
47
+
48
+ def test_normalize_should_stringify_priority
49
+ input = {:contacts => 'tom', :priority => 1}
50
+ output = {:contacts => ['tom'], :priority => '1'}
51
+ assert_equal(output, Contact.normalize(input))
52
+ end
53
+
54
+ def test_normalize_should_stringify_category
55
+ input = {:contacts => 'tom', :category => :product}
56
+ output = {:contacts => ['tom'], :category => 'product'}
57
+ assert_equal(output, Contact.normalize(input))
58
+ end
59
+
60
+ def test_normalize_should_raise_on_non_string_array_hash
61
+ input = 1
62
+ assert_raise ArgumentError do
63
+ Contact.normalize(input)
64
+ end
65
+ end
66
+
67
+ def test_normalize_should_raise_on_non_string_array_contacts_key
68
+ input = {:contacts => 1}
69
+ assert_raise ArgumentError do
70
+ Contact.normalize(input)
71
+ end
72
+ end
73
+
74
+ def test_normalize_should_raise_on_non_string_containing_array
75
+ input = [1]
76
+ assert_raise ArgumentError do
77
+ Contact.normalize(input)
78
+ end
79
+ end
80
+
81
+ def test_normalize_should_raise_on_non_string_containing_array_contacts_key
82
+ input = {:contacts => [1]}
83
+ assert_raise ArgumentError do
84
+ Contact.normalize(input)
85
+ end
86
+ end
87
+
88
+ def test_normalize_should_raise_on_absent_contacts_key
89
+ input = {}
90
+ assert_raise ArgumentError do
91
+ Contact.normalize(input)
92
+ end
93
+ end
94
+
95
+ def test_normalize_should_raise_on_extra_keys
96
+ input = {:contacts => ['tom'], :priority => 1, :category => 'product', :extra => 'foo'}
97
+ assert_raise ArgumentError do
98
+ Contact.normalize(input)
99
+ end
100
+ end
101
+
102
+ # notify
103
+
104
+ def test_notify_should_be_abstract
105
+ assert_raise(AbstractMethodNotOverriddenError) do
106
+ Contact.new.notify(:a, :b, :c, :d, :e)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestDependencyGraph < Test::Unit::TestCase
4
+ def setup
5
+ @dg = DependencyGraph.new
6
+ end
7
+
8
+ # new
9
+
10
+ def test_new_should_accept_zero_arguments
11
+ assert @dg.instance_of?(DependencyGraph)
12
+ end
13
+
14
+ # add
15
+
16
+ def test_add_should_create_and_store_two_new_nodes
17
+ @dg.add('foo', 'bar')
18
+ assert_equal 2, @dg.nodes.size
19
+ assert @dg.nodes['foo'].instance_of?(DependencyGraph::Node)
20
+ assert @dg.nodes['bar'].instance_of?(DependencyGraph::Node)
21
+ end
22
+
23
+ def test_add_should_record_dependency
24
+ @dg.add('foo', 'bar')
25
+ assert_equal 1, @dg.nodes['foo'].dependencies.size
26
+ assert_equal @dg.nodes['bar'], @dg.nodes['foo'].dependencies.first
27
+ end
28
+
29
+ def test_add_should_ignore_dups
30
+ @dg.add('foo', 'bar')
31
+ @dg.add('foo', 'bar')
32
+ assert_equal 2, @dg.nodes.size
33
+ assert_equal 1, @dg.nodes['foo'].dependencies.size
34
+ end
35
+ end
36
+
37
+
38
+ class TestDependencyGraphNode < Test::Unit::TestCase
39
+ def setup
40
+ @foo = DependencyGraph::Node.new('foo')
41
+ @bar = DependencyGraph::Node.new('bar')
42
+ end
43
+
44
+ # new
45
+
46
+ def test_new_should_accept_zero_arguments
47
+ assert @foo.instance_of?(DependencyGraph::Node)
48
+ end
49
+
50
+ # add
51
+
52
+ def test_add_should_store_node_as_dependency
53
+ @foo.add(@bar)
54
+ assert_equal 1, @foo.dependencies.size
55
+ end
56
+
57
+ # has_node?
58
+
59
+ def test_has_node
60
+ assert @foo.has_node?(@foo)
61
+ end
62
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestDriver < Test::Unit::TestCase
4
+ def setup
5
+
6
+ end
7
+
8
+ def test_
9
+
10
+ end
11
+ end