dtr 0.0.4 → 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 (93) hide show
  1. data/CHANGES +7 -0
  2. data/LICENSE.txt +203 -0
  3. data/README.rdoc +208 -0
  4. data/Rakefile +64 -205
  5. data/TODO +8 -2
  6. data/bin/dtr +27 -60
  7. data/dtr.gemspec +8 -11
  8. data/lib/dtr.rb +5 -94
  9. data/lib/dtr/agent.rb +38 -0
  10. data/lib/dtr/agent/brain.rb +57 -0
  11. data/lib/dtr/agent/herald.rb +60 -0
  12. data/lib/dtr/agent/runner.rb +87 -0
  13. data/lib/dtr/agent/sync_codebase.rb +44 -0
  14. data/lib/dtr/agent/sync_logger.rb +70 -0
  15. data/lib/dtr/agent/test_case.rb +53 -0
  16. data/lib/dtr/agent/test_unit.rb +40 -0
  17. data/lib/dtr/agent/worker.rb +89 -0
  18. data/lib/dtr/agent/working_env_ext.rb +47 -0
  19. data/lib/dtr/facade.rb +65 -0
  20. data/lib/dtr/master.rb +40 -0
  21. data/lib/dtr/monitor.rb +95 -0
  22. data/lib/dtr/raketasks.rb +155 -22
  23. data/lib/dtr/shared.rb +24 -0
  24. data/lib/dtr/shared/adapter.rb +115 -0
  25. data/lib/dtr/shared/configuration.rb +104 -0
  26. data/lib/dtr/shared/message_decorator.rb +28 -0
  27. data/lib/dtr/shared/ruby_ext.rb +129 -0
  28. data/lib/dtr/shared/service.rb +19 -0
  29. data/lib/dtr/shared/service/agent.rb +37 -0
  30. data/lib/dtr/shared/service/file.rb +28 -0
  31. data/lib/dtr/shared/service/rinda.rb +48 -0
  32. data/lib/dtr/shared/service/runner.rb +34 -0
  33. data/lib/dtr/shared/service/working_env.rb +28 -0
  34. data/lib/dtr/shared/sync_codebase.rb +18 -0
  35. data/lib/dtr/shared/sync_codebase/copiable_package.rb +40 -0
  36. data/lib/dtr/shared/sync_codebase/master_ext.rb +40 -0
  37. data/lib/dtr/shared/sync_codebase/package.rb +53 -0
  38. data/lib/dtr/shared/sync_codebase/sync_service.rb +36 -0
  39. data/lib/dtr/shared/sync_logger.rb +64 -0
  40. data/lib/dtr/shared/utils.rb +17 -0
  41. data/lib/dtr/shared/utils/cmd.rb +30 -0
  42. data/lib/dtr/shared/utils/env_store.rb +60 -0
  43. data/lib/dtr/shared/utils/logger.rb +87 -0
  44. data/lib/dtr/shared/working_env.rb +38 -0
  45. data/lib/dtr/test_unit.rb +9 -275
  46. data/lib/dtr/test_unit/drb_test_runner.rb +48 -0
  47. data/lib/dtr/test_unit/injection.rb +29 -0
  48. data/lib/dtr/test_unit/test_case_injection.rb +37 -0
  49. data/lib/dtr/test_unit/test_suite_injection.rb +24 -0
  50. data/lib/dtr/test_unit/testrunnermediator_injection.rb +72 -0
  51. data/lib/dtr/test_unit/thread_safe_test_result.rb +38 -0
  52. data/lib/dtr/test_unit/worker_club.rb +72 -0
  53. data/lib/dtr/test_unit_injection.rb +1 -2
  54. data/test/acceptance/agent_working_env_test.rb +86 -0
  55. data/test/acceptance/dtr_package_task_test.rb +36 -0
  56. data/test/acceptance/general_test.rb +331 -0
  57. data/test/acceptance/raketasks_test.rb +23 -0
  58. data/test/acceptance/sync_codebase_test.rb +66 -0
  59. data/test/acceptance/sync_logger_test.rb +32 -0
  60. data/test/agent_helper.rb +37 -0
  61. data/test/logger_stub.rb +34 -0
  62. data/test/test_helper.rb +71 -0
  63. data/test/unit/adapter_test.rb +149 -0
  64. data/test/unit/configuration_test.rb +44 -0
  65. data/test/unit/facade_test.rb +41 -0
  66. data/test/unit/logger_test.rb +72 -0
  67. data/test/unit/test_unit_test.rb +26 -0
  68. data/test/unit/working_env_test.rb +71 -0
  69. data/testdata/Rakefile +11 -0
  70. data/testdata/a_failed_test_case.rb +8 -0
  71. data/testdata/a_file_system_test_case.rb +8 -0
  72. data/testdata/a_test_case.rb +13 -0
  73. data/testdata/a_test_case2.rb +6 -0
  74. data/testdata/an_error_test_case.rb +9 -0
  75. data/testdata/another_project/Rakefile +6 -0
  76. data/testdata/another_project/passed_test_case.rb +7 -0
  77. data/testdata/hacked_run_method_test_case.rb +15 -0
  78. data/testdata/is_required_by_a_test.rb +9 -0
  79. data/testdata/lib/lib_test_case.rb +7 -0
  80. data/testdata/package_task_test_rakefile +8 -0
  81. data/testdata/raketasks/Rakefile +7 -0
  82. data/testdata/raketasks/success_test_case.rb +6 -0
  83. data/testdata/scenario_test_case.rb +34 -0
  84. data/testdata/setup_agent_env_test_case.rb +9 -0
  85. data/testdata/sleep_3_secs_test_case.rb +9 -0
  86. data/testdata/verify_dir_pwd/Rakefile +6 -0
  87. data/testdata/verify_dir_pwd/verify_dir_pwd_test_case.rb +10 -0
  88. metadata +101 -34
  89. data/README +0 -291
  90. data/install.rb +0 -88
  91. data/lib/dtr/base.rb +0 -172
  92. data/lib/dtr/runner.rb +0 -270
  93. data/lib/dtr/service_provider.rb +0 -160
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ include DTR::AgentHelper
3
+
4
+ class RakeTasksTest < Test::Unit::TestCase
5
+ def test_test_task
6
+ FileUtils.mkdir_p("raketasks_test_agent")
7
+ Dir.chdir('raketasks_test_agent') do
8
+ start_agents
9
+ end
10
+ test_dir = File.expand_path(File.dirname(__FILE__) + '/../../testdata/raketasks')
11
+ Dir.chdir(test_dir) do
12
+ output = %x[rake dtr]
13
+ expected = <<-OUTPUT
14
+ 1 tests, 1 assertions, 0 failures, 0 errors
15
+ OUTPUT
16
+ assert_equal 0, $?.exitstatus
17
+ assert output.include?(expected), "should include #{expected}"
18
+ end
19
+ ensure
20
+ stop_agents
21
+ FileUtils.rm_rf("raketasks_test_agent")
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ include DTR::AgentHelper
3
+
4
+ class SyncCodebaseTest < Test::Unit::TestCase
5
+ include DTR::Service::File
6
+ include DTR::SyncCodebase::SyncService
7
+
8
+ def test_sync_codebase
9
+ testdata_dir = File.expand_path(File.dirname(__FILE__) + '/../../testdata')
10
+
11
+ master = Process.fork do
12
+ DTR.configuration.with_rinda_server do
13
+ Dir.chdir(testdata_dir) do
14
+ DTR::Cmd.execute('rake dtr_repackage')
15
+ provide_file DTR::SyncCodebase::CopiablePackage.new
16
+ DRb.thread.join
17
+ end
18
+ end
19
+ end
20
+ #sleep for waiting rinda server start
21
+ sleep(1)
22
+ client = Process.fork do
23
+ start_service
24
+ Dir.mkdir("test_sync_codebase")
25
+ Dir.chdir("test_sync_codebase") do
26
+ sync_codebase
27
+ end
28
+ end
29
+ Process.waitpid client
30
+ assert File.directory?("test_sync_codebase/#{package_name}")
31
+ assert !File.exists?("test_sync_codebase/#{package_copy_file}")
32
+ ensure
33
+ stop_service rescue nil
34
+ DTR.kill_process master
35
+ DTR.kill_process client
36
+ FileUtils.rm_rf("test_sync_codebase")
37
+ Dir.chdir(testdata_dir) do
38
+ DTR::Cmd.execute('rake dtr_clobber_package')
39
+ end
40
+ end
41
+
42
+ def test_should_not_sync_codebase_and_setup_working_dir_when_agent_is_in_same_dir_with_master_process
43
+ @master_dir = File.expand_path(File.dirname(__FILE__) + '/../../testdata/verify_dir_pwd')
44
+ @agent = start_agent_at @master_dir, 2, false
45
+ begin
46
+ assert_fork_process_exits_ok do
47
+ Dir.chdir(@master_dir) do
48
+ require 'verify_dir_pwd_test_case'
49
+ end
50
+ $argv_dup = ['verify_dir_pwd_test_case.rb']
51
+ suite = Test::Unit::TestSuite.new('test_should_not_sync_codebase_and_setup_working_dir')
52
+ suite << VerifyDirPwdTestCase.suite
53
+
54
+ Dir.chdir(@master_dir) do
55
+ result = runit(suite)
56
+ assert result.passed?
57
+ assert_equal 1, result.run_count
58
+ end
59
+ end
60
+ ensure
61
+ DTR.kill_process @agent
62
+ Process.waitall
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ include DTR::AgentHelper
4
+
5
+ class SyncLoggerTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ start_agents
9
+ end
10
+
11
+ def teardown
12
+ stop_agents
13
+ end
14
+
15
+ def test_master_process_should_get_log_of_agents
16
+ assert_fork_process_exits_ok do
17
+ @logger = LoggerStub.new
18
+ DTR.logger = @logger
19
+
20
+ $argv_dup = ['a_test_case.rb']
21
+ suite = Test::Unit::TestSuite.new('master_process_should_get_log_of_agents')
22
+ suite << ATestCase.suite
23
+ runit(suite)
24
+
25
+ logs = @logger.logs.flatten.join("\n")
26
+ assert(/From #{Socket.gethostname}: => Herald starts off\.\.\./ =~ logs)
27
+ assert(/From #{Socket.gethostname}: runner0: test files loaded/ =~ logs)
28
+ #when use Delegator to implement UndumpedLogger, there are lots of 'nil' in the log
29
+ assert(/nil/ !~ logs)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ require 'fileutils'
2
+ module DTR
3
+ module AgentHelper
4
+ GROUP = 'dtr acceptance tests'
5
+ def start_agents(size = 3)
6
+ @agents_dir = File.join(Dir.pwd, 'agents')
7
+ @agents = []
8
+ @agents << start_agent_at(File.join(@agents_dir, 'agent1'), size)
9
+ # @agents << start_agent_at(File.join(@agents_dir, 'agent2'), 1)
10
+ end
11
+
12
+ def start_agent_at(agent_dir, size, clean_dir=true)
13
+ FileUtils.rm_rf(agent_dir) if clean_dir
14
+ FileUtils.mkdir_p(agent_dir)
15
+ runner_names = []
16
+ size.times {|i| runner_names << "runner#{i}"}
17
+ Process.fork do
18
+ Dir.chdir(agent_dir) do
19
+ DTR.configuration.group = GROUP
20
+ DTR.launch_agent(runner_names, nil)
21
+ end
22
+ end
23
+ end
24
+
25
+ def stop_agents
26
+ if @agents
27
+ @agents.each do |agent|
28
+ DTR.kill_process agent
29
+ end
30
+ Process.waitall
31
+ sleep 1
32
+ end
33
+ ensure
34
+ FileUtils.rm_rf(@agents_dir) rescue nil
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ class LoggerStub
2
+ def initialize
3
+ @store = DTR::EnvStore.new
4
+ clear
5
+ end
6
+ def debug(message=nil, &block)
7
+ output(:debug, message, &block)
8
+ end
9
+
10
+ def info(message=nil, &block)
11
+ output(:info, message, &block)
12
+ end
13
+
14
+ def error(message=nil, &block)
15
+ output(:error, message, &block)
16
+ end
17
+
18
+ def level
19
+ Logger::INFO
20
+ end
21
+
22
+ def output(level, msg=nil, &block)
23
+ message = block_given? ? block.call : msg.to_s
24
+ @store << [:logs, [level, message]]
25
+ end
26
+
27
+ def logs
28
+ @store[:logs]
29
+ end
30
+
31
+ def clear
32
+ @store[:logs] = []
33
+ end
34
+ end
@@ -0,0 +1,71 @@
1
+ require 'test/unit'
2
+ require 'test/unit/ui/console/testrunner'
3
+
4
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
5
+
6
+ require 'rubygems'
7
+ require 'growling_test'
8
+ require 'dtr'
9
+ require 'dtr/test_unit'
10
+ DTR.configuration.master_heartbeat_interval = 2
11
+ DTR.configuration.follower_listen_heartbeat_timeout = 3
12
+
13
+ require File.dirname(__FILE__) + '/agent_helper'
14
+ require File.dirname(__FILE__) + '/logger_stub'
15
+
16
+ ENV['DTR_ENV'] = 'test'
17
+
18
+ module Test
19
+ module Unit
20
+ class TestCase
21
+ def assert_false(o)
22
+ assert !o
23
+ end
24
+ def assert_fork_process_exits_ok(&block)
25
+ pid = Process.fork do
26
+ Dir.chdir(File.expand_path(File.dirname(__FILE__) + "/../testdata/")) do
27
+ setup_test_env
28
+ with_agent_helper_group(&block)
29
+ end
30
+ exit 0
31
+ end
32
+ Process.waitpid pid
33
+ assert_equal 0, $?.exitstatus
34
+ ensure
35
+ DTR.kill_process pid
36
+ end
37
+
38
+ def with_agent_helper_group(&block)
39
+ DTR.configuration.group = DTR::AgentHelper::GROUP
40
+ begin
41
+ block.call
42
+ ensure
43
+ DTR.configuration.group = nil
44
+ end
45
+ end
46
+
47
+ def setup_test_env
48
+ require 'a_test_case'
49
+ require 'a_test_case2'
50
+ require 'a_failed_test_case'
51
+ require 'an_error_test_case'
52
+ require 'a_file_system_test_case'
53
+ require 'scenario_test_case'
54
+ require 'setup_agent_env_test_case'
55
+ DTR.inject
56
+ end
57
+
58
+ def runit(suite)
59
+ Test::Unit::UI::Console::TestRunner.run(suite, Test::Unit::UI::SILENT)
60
+ end
61
+ def clear_configuration
62
+ DTR::EnvStore.destroy
63
+ DTR.configuration.load
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ class Test::Unit::TestResult
70
+ attr_reader :failures, :errors
71
+ end
@@ -0,0 +1,149 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ include DTR::AgentHelper
4
+
5
+ class AdapterTest < Test::Unit::TestCase
6
+ include DTR::Adapter::Master
7
+ include DTR::Adapter::Follower
8
+
9
+ def setup
10
+ @host_ip = nil
11
+ @timeout = false
12
+ @messages = []
13
+ DTR.logger('test.log')
14
+ DTR.configuration.follower_listen_heartbeat_timeout = 1
15
+ end
16
+
17
+ def teardown
18
+ clear_configuration
19
+ end
20
+
21
+ def test_should_be_sleep_if_never_wakeup
22
+ assert sleep?
23
+ assert !wakeup?
24
+ assert sleep?
25
+ do_wakeup_agents
26
+ assert wakeup?
27
+ do_wakeup_agents
28
+ assert !sleep?
29
+ end
30
+
31
+ def test_wakeup_by_broadcast_message
32
+ assert !wakeup?
33
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 4567")
34
+ assert wakeup?
35
+ end
36
+
37
+ def test_should_be_sleep_after_hypnotized_waked_up_agents
38
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 4567")
39
+ assert wakeup?
40
+ hypnotize_agents
41
+ assert sleep?
42
+ end
43
+
44
+ def test_do_wakeup_agents
45
+ assert !wakeup?
46
+ do_wakeup_agents
47
+ assert wakeup?
48
+
49
+ do_wakeup_agents
50
+ assert !sleep?
51
+ end
52
+
53
+ def test_hypnotize_agents_after_did_waked_up_agents
54
+ do_wakeup_agents
55
+ assert wakeup?
56
+ hypnotize_agents
57
+ assert sleep?
58
+ end
59
+
60
+ def test_should_not_be_sleep_when_sleep_message_is_sent_from_different_port_with_wakeup_message
61
+ @host_ip = '10.18.1.1'
62
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
63
+ assert wakeup?
64
+ #sleep message should be ignored
65
+ broadcast('address', "#{DTR::Adapter::SLEEP_MESSAGE} 4567")
66
+ #wakup message for keep it wakeup
67
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
68
+ assert !sleep?
69
+ end
70
+
71
+ def test_should_not_be_sleep_when_sleep_message_is_sent_from_different_hostname_with_wakeup_message
72
+ @host_ip = '10.18.1.1'
73
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
74
+ assert wakeup?
75
+ #sleep message should be ignored
76
+ @host_ip = '192.168.1.1'
77
+ broadcast('address', "#{DTR::Adapter::SLEEP_MESSAGE} 1234")
78
+ #wakup message for keep it wakeup
79
+ @host_ip = '10.18.1.1'
80
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
81
+ assert !sleep?
82
+ end
83
+
84
+ def test_should_update_rinda_server_port_parsed_from_wakeup_message
85
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 4567")
86
+ assert wakeup?
87
+ assert_equal 4567, DTR.configuration.rinda_server_port
88
+ end
89
+
90
+ def test_should_be_sleep_when_timeout_on_listen
91
+ do_wakeup_agents
92
+ assert wakeup?
93
+ @timeout = true
94
+ assert sleep?
95
+ end
96
+
97
+ def test_should_be_sleep_when_timeout_on_listen_to_host_sending_wakeup_message
98
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
99
+ assert wakeup?
100
+ @host_ip = 'dtr.remote'
101
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
102
+ sleep(2)
103
+ assert sleep?
104
+ end
105
+
106
+ def test_should_match_group_configured_when_receive_wakeup_cmd
107
+ DTR.configuration.group = 'mingle'
108
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
109
+ assert !wakeup?
110
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234 mingle")
111
+ assert wakeup?
112
+ end
113
+
114
+ def test_should_not_need_match_group_configured_when_receive_sleep_cmd
115
+ DTR.configuration.group = 'mingle'
116
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234 mingle")
117
+ assert wakeup?
118
+ broadcast('address', "#{DTR::Adapter::SLEEP_MESSAGE} 1234")
119
+ assert sleep?
120
+ end
121
+
122
+ def test_do_wakeup_agents_should_include_group_configured
123
+ DTR.configuration.group = 'mingle'
124
+ do_wakeup_agents
125
+ assert wakeup?
126
+ end
127
+
128
+ def test_should_reset_broadcast_configuration_as_master_process_ip
129
+ @host_ip = '10.18.1.1'
130
+ broadcast('address', "#{DTR::Adapter::WAKEUP_MESSAGE} 1234")
131
+ assert wakeup?
132
+ assert_equal ['10.18.1.1'], DTR.configuration.broadcast_list
133
+ end
134
+
135
+ def listen
136
+ raise Timeout::Error.new('timeout') if @timeout
137
+ cmd, port, group, host_ip = @messages.shift.to_s.split
138
+ if host_ip.nil?
139
+ host_ip = group
140
+ group = nil
141
+ end
142
+ [cmd, "#{host_ip}:#{port}", group]
143
+ end
144
+
145
+ def broadcast(it, msg)
146
+ host_ip = @host_ip || Socket.gethostname
147
+ @messages << "#{msg} #{host_ip}"
148
+ end
149
+ end
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ConfigurationTest < Test::Unit::TestCase
4
+ def teardown
5
+ clear_configuration
6
+ end
7
+
8
+ def test_should_not_save_rinda_server_port
9
+ DTR.configuration.rinda_server_port = '3456'
10
+ assert_equal '3456', DTR.configuration.rinda_server_port
11
+ assert_nil DTR::EnvStore.new[:rinda_server_port]
12
+ end
13
+
14
+ def test_group_defualt_is_dangerous_group
15
+ assert_nil DTR.configuration.group
16
+ end
17
+
18
+ def test_group
19
+ DTR.configuration.group = 'mingle'
20
+ assert_equal 'mingle', DTR.configuration.group
21
+ DTR.configuration.save
22
+ assert_equal 'mingle', DTR::EnvStore.new[:group]
23
+ end
24
+
25
+ def test_should_save_as_nil_when_group_is_blank
26
+ DTR.configuration.group = ''
27
+ assert_nil DTR.configuration.group
28
+ DTR.configuration.save
29
+ assert_nil DTR::EnvStore.new[:group]
30
+ end
31
+
32
+ def test_shoul_convert_space_in_group_name_to_underscore
33
+ DTR.configuration.group = 'mingle group'
34
+ assert_equal 'mingle_group', DTR.configuration.group
35
+ DTR.configuration.save
36
+ assert_equal 'mingle_group', DTR::EnvStore.new[:group]
37
+ end
38
+
39
+ def test_load
40
+ DTR::EnvStore.new[:group] = 'new group'
41
+ DTR.configuration.load
42
+ assert_equal 'new group', DTR.configuration.group
43
+ end
44
+ end