DTR 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,2 +1,3 @@
1
1
  = DTR Changelog
2
+ * changed to rinda service model
2
3
 
data/README CHANGED
@@ -4,20 +4,25 @@ Supporting DTR version: 0.0.x
4
4
 
5
5
  This package contains DTR, a distributed test runner program for decreasing build time.
6
6
 
7
- DTR works in two parts: DTR Client and DTR Server.
8
- DTR Server controls all tests running or setting up test env. DTR Clients is always
9
- waiting for commands from DTR server to:
10
- * set up test env
11
- * run test and update report to DTR Server
12
-
13
7
  DTR has the following features:
14
8
 
15
- * Run tests in mutli-processes/machines
9
+ * Run tests in mutli processes/machines.
10
+
11
+ * Hot plug distributed runners.
12
+
13
+ * Runtime injection, all tests run in same environment including TestRunner.
14
+
15
+ DTR works in three parts: DTR Server, Runner and Test Suite Injection.
16
16
 
17
- * Setup test env before running test.
17
+ * DTR Server is a Rinda Server which allows DRb services and clients to automatically find each other without knowing where they live.
18
18
 
19
- You may need to consider using sychronize tools (likes rsync(http://samba.anu.edu.au/rsync/))
20
- to synchronize project files between machines.
19
+ * Runner is a DRb service host on distributed machines to run tests.
20
+
21
+ * Test Suite Injection works by loading 'dtr/inject_with_svn.rb' with all test files.
22
+
23
+ DTR only supports Subversion to update codebase now, you may need to consider using
24
+ sychronize tools (likes rsync(http://samba.anu.edu.au/rsync/)) to synchronize project
25
+ files between machines.
21
26
 
22
27
  == Download
23
28
 
@@ -60,46 +65,49 @@ If you wish to run the unit and functional tests that come with DTR:
60
65
 
61
66
  == Simple Example
62
67
 
63
- Once installed, you can run DTR client at your project directory as follows ...
68
+ Once installed, you can run DTR server anywhere:
69
+
70
+ % dtr -s
64
71
 
65
- % dtr --server druby://build_server_ip:1314 --name client_name --port 3344
66
- (The default port of dtr server is '1314')
72
+ After server started, you can run DTR runner at your project directory as follows:
73
+
74
+ % dtr --server_address dtr_server_ip -r runner_name
67
75
 
68
76
  Type "dtr --help" for an up-to-date option summary.
69
77
  Invoking <tt>dtr</tt> without any options causes dtr to run
70
- with option '--server druby://localhost:1314 --port 3344'
78
+ with option '--server_address localhost'
79
+
80
+ Most of time your project test suite need setup environment before run tests, you
81
+ can set setup command by option '--setup', for example:
71
82
 
72
- In your Rakefile, you can custom a task to let DTR server run tests:
83
+ % dtr --server_address dtr_server_ip --r runner1 --setup "rake db:test:prepare"
84
+
85
+ At last, you need to add 'dtr/inject_with_svn.rb' into test_files of your test
86
+ task in your Rakefile, and for load it, you also need add dtr lib path:
73
87
 
74
- require "rubygems"
75
88
  require 'dtr'
76
89
 
77
- task :cruise do
78
- tests = FileList["test/unit/**/*test.rb].to_a
79
- fail "Failed" unless DTR.run(tests, ['druby://client_1_ip:3344', 'druby://localhost:3344'])
90
+ Rake::TestTask.new(:dtr_tests) do |t|
91
+ t.libs << DTR.lib_path
92
+ t.test_files = FileList['dtr/inject_with_svn.rb', 'test/*test.rb']
93
+ t.warning = false
94
+ t.verbose = false
80
95
  end
81
96
 
82
97
  == Run tests in multi-processes on one machine
83
98
 
84
99
  In your Rakefile:
85
100
 
86
- task :dtr => ["start_clients", "db:test:prepare"] do
87
- fail "Failed" unless DTR.run(FileList["test/unit/**/*test.rb].to_a, ['druby://localhost:3345', 'druby://localhost:3346'])
88
- ensure
89
- DTR::ClientServer.stop_all
90
- end
91
-
92
- task :start_clients do
93
- DTR::ClientServer.new(:client_name => "client 1", :port => "3345").start
94
- puts "client 1 started"
95
- DTR::ClientServer.new(:client_name => "client 2", :port => "3346").start
96
- puts "client 2 started"
97
- sleep(2)
101
+ require 'dtr/raketasks'
102
+
103
+ DTR::MPTask.new :test do |t|
104
+ t.test_files = FileList['test/*test.rb']
105
+ t.processes = 2 #default is 2
98
106
  end
99
107
 
100
108
  == Credits
101
109
 
102
- [<b>Josh Price</b>] For fixing tests packer.
110
+ [<b>Josh Price</b>] For fixing tests packer in release 0.0.1.
103
111
 
104
112
  [<b>Wang Pengchao</b>] For share of lots of ideas.
105
113
 
@@ -126,22 +134,31 @@ DTR client is invoked from the command line using:
126
134
  % dtr [<em>options</em> ...]
127
135
 
128
136
  Options are:
129
- -s, --server_uri SERVER_URI DTR server uri
130
- -n, --name NAME DTR client name, the default is string 'client' with a time stamp.
131
- -o, --output_dir OUTPUT_DIR the dir for DTR client to output logs, the default is 'dtr_tmp'.
132
- -i, --setup COMMAND Define the command for initializing test environment, the default is 'rake db:test:prepare'
133
- -p, --port PORT Define DTR client port, the default is 3344
134
- -t, --trace Turn on invoke/execute tracing.
135
- -u, --stdout Print all log into stdout.
137
+ -s, --server Start DTR service server. There must be a DTR
138
+ server running.
139
+ -r runner1_name,runner2_name Start DTR test runner agent. The name should
140
+ be uniq of all runners. Every runner will be
141
+ start in different process. The daemons gem
142
+ must be installed, when start multiple runners
143
+ -i, --setup COMMAND Set the command for initializing test environment
144
+ for test runner, the default is no setup command
145
+ -a, --server_address ADDRESS Set server address. The default is 'localhost'.
146
+ It should be domain name or ip address, for
147
+ example: 192.168.0.1
148
+ -D, --daemon Start server/runners in daemon mode. The daemon
149
+ gem must be installed
150
+ -S, --stop_server Stop server run in daemon mode.
151
+ -R, --stop_runners Stop runners run in daemon mode.
152
+ -d, --debug Output debug log
136
153
  -v, --version Show version
137
154
  -h, --help Show this help doc
138
155
 
139
156
  = Other stuff
140
157
 
141
158
  Author:: Li Xiao <swing1979@gmail.com>
142
- Requires:: Ruby 1.8.0 or later
159
+ Requires:: Ruby 1.8.6 or later
143
160
  License:: Copyright 2007 by Li Xiao.
144
- Released under an Apache License. See the LICENSE file
161
+ Released under an Apache License 2. See the LICENSE file
145
162
  included in the distribution.
146
163
 
147
164
  == Warranty
data/Rakefile CHANGED
@@ -32,7 +32,7 @@ end
32
32
 
33
33
  $package_version = CURRENT_VERSION
34
34
 
35
- SRC_RB = FileList['lib/**/*.rb']
35
+ SRC_RB = FileList['lib/**/*.rb', 'lib/**/*.rake']
36
36
 
37
37
  # The default task is run if rake is given no explicit arguments.
38
38
 
@@ -46,9 +46,9 @@ end
46
46
 
47
47
  # Common Abbreviations ...
48
48
 
49
- task :test_all => [:test_units, :test_functionals]
49
+ task :test_all => [:test_units, :tf]
50
50
  task :tu => :test_units
51
- task :tf => :test_functionals
51
+ task :tf => [:start_dtr_server, :start_dtr_runners, :test_functionals, :stop_dtr_runners, :stop_dtr_server]
52
52
  task :test => :test_units
53
53
 
54
54
  Rake::TestTask.new(:test_units) do |t|
@@ -63,6 +63,22 @@ Rake::TestTask.new(:test_functionals) do |t|
63
63
  t.verbose = false
64
64
  end
65
65
 
66
+ task :start_dtr_server do
67
+ ruby "-I#{File.dirname(__FILE__) + "/lib"} #{File.dirname(__FILE__) + "/bin/dtr"} -s -D"
68
+ end
69
+
70
+ task :start_dtr_runners do
71
+ ruby "-I#{File.dirname(__FILE__) + "/lib"} #{File.dirname(__FILE__) + "/bin/dtr"} -r r1,r2,r3 -D"
72
+ end
73
+
74
+ task :stop_dtr_runners do
75
+ ruby "-I#{File.dirname(__FILE__) + "/lib"} #{File.dirname(__FILE__) + "/bin/dtr"} -R"
76
+ end
77
+
78
+ task :stop_dtr_server do
79
+ ruby "-I#{File.dirname(__FILE__) + "/lib"} #{File.dirname(__FILE__) + "/bin/dtr"} -S"
80
+ end
81
+
66
82
  begin
67
83
  require 'rcov/rcovtask'
68
84
 
@@ -119,6 +135,7 @@ PKG_FILES = FileList[
119
135
  '[A-Z]*',
120
136
  'bin/**/*',
121
137
  'lib/**/*.rb',
138
+ 'lib/**/*.rake',
122
139
  'test/**/*.rb',
123
140
  'doc/**/*'
124
141
  ]
@@ -350,19 +367,63 @@ task :install_jamis_template do
350
367
  install "doc/jamis.rb", dest_dir, :verbose => true
351
368
  end
352
369
 
370
+ require 'logger'
371
+
372
+ def logger
373
+ logger = Logger.new STDOUT
374
+ logger.level = Logger::DEBUG
375
+ logger
376
+ end
353
377
 
354
- task :run_dtr_lots do
378
+ task :c1 do
355
379
  Dir.chdir('testdata') do
356
- begin
357
- FileUtils.makedirs 'run_dtr_lots'
358
- test_files = Array.new(10) do |index|
359
- test_file = "run_dtr_lots/test#{index}.rb"
360
- FileUtils.copy_file 'a_test_case.rb', test_file
361
- test_file
362
- end
363
- DTR.run test_files, ['druby://localhost:3344']
364
- ensure
365
- FileUtils.rm_rf 'run_dtr_lots'
366
- end
380
+ DTR.launch_runners(['c1'], nil)
381
+ end
382
+ end
383
+
384
+ task :c3 do
385
+ Dir.chdir('testdata') do
386
+ DTR.launch_runners(['c1', 'c2', 'c3'], nil)
387
+ end
388
+ end
389
+ task :c10 do
390
+ Dir.chdir('testdata') do
391
+ DTR.launch_runners(['c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10'], nil)
367
392
  end
368
393
  end
394
+
395
+ task :runners do
396
+ runners = DTR.runners
397
+ if runners.empty?
398
+ puts "No runner available!"
399
+ else
400
+ puts runners.collect{|r| r.name}.join(", ")
401
+ end
402
+ end
403
+
404
+ task :c2 do
405
+ DTROPTIONS[:names] = ['c1', 'c2']
406
+ DTROPTIONS[:setup] = nil
407
+ Dir.chdir('testdata') do
408
+ DTR.start_runners
409
+ end
410
+ end
411
+
412
+ task :server do
413
+ DTR.start_server
414
+ end
415
+
416
+ Rake::TestTask.new(:dtr) do |t|
417
+ t.libs << DTR.lib_path
418
+ t.test_files = FileList['dtr/inject_with_svn.rb', 'testdata/*.rb']
419
+ t.warning = true
420
+ t.verbose = false
421
+ end
422
+
423
+ require 'dtr/raketasks'
424
+
425
+ DTR::MPTask.new :mt do |t|
426
+ t.test_files = FileList['testdata/*.rb']
427
+ t.processes = 2
428
+ end
429
+
data/TODO CHANGED
@@ -3,9 +3,19 @@
3
3
  Send suggestions for this list to swing1979@gmail.com
4
4
 
5
5
  === To Do
6
- 17. check thread safe
7
6
  18. integrate with cc.rb
8
7
  19. error log trace has file path on client
9
- 20. rake task
10
8
  21. good example in README
9
+ 29. test hot plug runner, it works bad on Windows
10
+ 32. start runner by scenario_tests
11
+ 33. error msg should not displayed when ctrl-C shutdown runners
11
12
  (moved DONE list to CHANGES file)
13
+ !20. rake task
14
+ !22. give warning message when there is no runner available
15
+ !24. make sure we don't need to stop drb service by ourselves, or do we need to close rinda bus?
16
+ !25. get svn revision
17
+ !27. ring server's log: seems no
18
+ !28. runner should give an info when loaded files not included 'dtr/inject' and 'dtr/service_provider'
19
+ !30. should update to HEAD when first time to init env
20
+ !31. load libs
21
+
data/bin/dtr CHANGED
@@ -1,4 +1,5 @@
1
- #!/usr/bin/env ruby -w
1
+ require 'optparse'
2
+
2
3
  begin
3
4
  require 'dtr'
4
5
  rescue LoadError
@@ -6,59 +7,79 @@ rescue LoadError
6
7
  require 'dtr'
7
8
  end
8
9
 
9
- require 'optparse'
10
- require 'logger'
11
-
12
10
  opts = OptionParser.new do |opts|
13
- opts.banner = "DTR client server usage: #{$0} [options]"
11
+ opts.banner = "DTR usage: #{$0} [options]"
14
12
  opts.separator ""
15
13
  opts.separator "Synopsis:"
16
- opts.separator "dtr -s 'DTR server uri'"
14
+ opts.separator "dtr -s"
15
+ opts.separator "dtr -r runner1_name, runner2_name"
17
16
  opts.separator ""
18
17
  opts.separator "Options:"
19
18
 
20
- opts.on("-s", "--server_uri SERVER_URI", "DTR server uri") do |server_uri|
21
- DTROPTIONS[:server_uri] = server_uri.untaint
19
+ opts.on_tail("-s", "--server", "Start DTR service server. There must be a DTR server running.") do |server_uri|
20
+ DTROPTIONS[:start_server] = true
22
21
  end
23
22
 
24
- opts.on("-n", "--name NAME", "DTR client server name, the default is string 'client' with a time stamp.") do |name|
25
- DTROPTIONS[:client_name] = name.untaint
23
+ opts.on("-r runner1_name,runner2_name", Array, "Start DTR test runner agent. The name should be uniq of all runners. Every runner will be start in different process. The daemon gem must be installed, when start multiple runners") do |names|
24
+ DTROPTIONS[:names] = names.collect{|name| name.untaint}
26
25
  end
27
-
28
- opts.on("-o", "--output_dir OUTPUT_DIR", "the dir for DTR client server to output logs, the default is 'dtr_tmp'.") do |output_dir|
29
- DTROPTIONS[:tmp_dir] = output_dir.untaint
26
+
27
+ opts.on("-a", "--server_address ADDRESS", "Set server address. The default is 'localhost'. It should be domain name or ip address, for example: 192.168.0.1") do |address|
28
+ DTR.broadcast_list = [address]
30
29
  end
31
30
 
32
- opts.on("-i", "--setup COMMAND", "Define the command for initializing test environment, the default is 'rake db:test:prepare'") do |command|
31
+ opts.on("-i", "--setup COMMAND", "Set the command for initializing test environment for test runner, the default is no setup command") do |command|
33
32
  DTROPTIONS[:setup] = command.untaint
34
33
  end
35
-
36
- opts.on("-p", "--port PORT", "Define DTR client server port, the default is 3344") do |port|
37
- DTROPTIONS[:port] = port.untaint
34
+
35
+ opts.on_tail("-D", "--daemon", "Start server/runners in daemon mode. The daemon gem must be installed") do
36
+ DTROPTIONS[:daemon] = true
38
37
  end
39
-
40
- opts.on_tail("-t", "--trace", "Turn on invoke/execute tracing.") do
41
- DTROPTIONS[:log_level] = Logger::DEBUG
38
+
39
+ opts.on_tail("-S", "--stop_server", "Stop server run in daemon mode.") do
40
+ DTR.stop_server_daemon_mode
42
41
  end
43
42
 
44
- opts.on_tail("-u", "--stdout", "Print all log into stdout.") do
45
- DTROPTIONS[:output_model] = :stdout
43
+ opts.on_tail("-R", "--stop_runners", "Stop runners run in daemon mode.") do
44
+ DTR.stop_runners_daemon_mode
45
+ end
46
+
47
+ opts.on_tail("-d", "--debug", "output debug log") do
48
+ $logger = true
46
49
  end
47
50
 
48
51
  opts.on_tail("-v", "--version", "Show version") do
49
52
  puts "dtr, version " + DTRVERSION
50
- DTROPTIONS[:exit] = true
51
53
  end
52
54
 
53
55
  opts.on_tail("-h", "--help", "Show this help doc") do
54
56
  puts opts
55
- DTROPTIONS[:exit] = true
56
57
  end
57
58
  end
58
59
 
59
- begin
60
- opts.parse!
61
- DTR.start_client_server unless DTROPTIONS[:exit]
62
- rescue Exception => e
63
- logger.error { e }
60
+ opts.parse!
61
+
62
+ if defined?($logger)
63
+ require 'logger'
64
+ $logger = Logger.new(STDOUT)
65
+ $logger.level = Logger::DEBUG
66
+ def logger
67
+ $logger
68
+ end
69
+ end
70
+
71
+ if DTROPTIONS[:names]
72
+ if DTROPTIONS[:daemon]
73
+ DTR.start_runners_daemon_mode
74
+ else
75
+ DTR.start_runners
76
+ end
77
+ end
78
+
79
+ if DTROPTIONS[:start_server]
80
+ if DTROPTIONS[:daemon]
81
+ DTR.start_server_daemon_mode
82
+ else
83
+ DTR.start_server
84
+ end
64
85
  end
data/install.rb CHANGED
@@ -31,7 +31,7 @@ def installBIN(from, opfile)
31
31
  File.open(from) do |ip|
32
32
  File.open(tmp_file, "w") do |op|
33
33
  ruby = File.join($realbindir, $ruby)
34
- op.puts "#!#{ruby} -w"
34
+ op.puts "#!#{ruby}"
35
35
  op.write ip.read
36
36
  end
37
37
  end
@@ -72,7 +72,7 @@ File::chmod(0755, dtr_dest)
72
72
 
73
73
  # The library files
74
74
 
75
- files = Dir.chdir('lib') { Dir['**/*.rb'] }
75
+ files = Dir.chdir('lib') { Dir['**/*.rb', '**/*.rake'] }
76
76
 
77
77
  for fn in files
78
78
  fn_dir = File.dirname(fn)
@@ -86,4 +86,3 @@ end
86
86
  # and the executable
87
87
 
88
88
  installBIN("bin/dtr", "dtr")
89
- installBIN("bin/dtrserve", "dtrserve")
data/lib/dtr.rb CHANGED
@@ -1,88 +1,82 @@
1
- require "dtr/drb_dtr"
2
- require "fileutils"
3
- require "logger"
4
1
 
5
- DTRVERSION="0.0.1"
2
+ DTRVERSION="0.0.2"
6
3
  DTROPTIONS = {
7
- #dtr client
8
- :client_name => "client(#{Time.now})",
9
- :setup => "rake db:test:prepare",
10
- :port => "3344",
11
- :server_uri => "druby://localhost:1314",
12
- #dtr server
13
- :server_port => "1314",
14
- :wait_a_moment => 5,
15
- :output_model => :log,
16
- :raise_on_no_alive_client => false,
17
- #both
18
- :tmp_dir => "tmp/dtr",
19
- :log_level => Logger::INFO
4
+ #:setup => nil
5
+ #:names => ["DTR(#{Time.now})"]
20
6
  }
21
7
 
22
- unless defined?(logger)
23
- def logger
24
- return $logger if defined?($logger) && $logger
25
- DTR.ensure_temp_dir_exist
26
- $logger = DTROPTIONS[:output_model] == :stdout ? Logger.new(STDOUT) : Logger.new("#{DTROPTIONS[:tmp_dir]}/runtime.log", 2, 1024000)
27
- $logger.level = DTROPTIONS[:log_level]
28
- $logger
29
- end
30
- end
31
-
32
8
  module DTR
33
9
 
34
- def start_client_server(my_port=DTROPTIONS[:port], server_uri=DTROPTIONS[:server_uri])
35
- my_uri = "druby://:" << my_port
36
-
37
- DTROPTIONS[:tmp_dir] = DTROPTIONS[:tmp_dir] + '/' + DTROPTIONS[:client_name].gsub(/[^\d\w]+/, '_')
38
- logger.info { "Initializing client server at '#{my_uri}'..." }
39
- logger.info { "Working dir: #{Dir.pwd}" }
40
- logger.info { "Listening server at '#{server_uri}'..." }
41
- ensure_temp_dir_exist
42
- server = DrbTestRunnerClientServer.new my_uri, server_uri
43
- server.start
10
+ def start_server
11
+ require 'dtr/service_provider'
12
+ ServiceProvider.new.start
44
13
  end
45
-
46
- def run(tests, clients, opts={})
47
- opts = {:my_uri => "druby://:#{DTROPTIONS[:server_port]}", :run_setup_before_start => false}.merge(opts)
48
- server = DrbTestRunnerServer.new opts[:my_uri], tests, clients
49
- server.start opts[:run_setup_before_start]
50
- server.succeeded?
14
+
15
+ def start_runners
16
+ launch_runners(DTROPTIONS[:names], DTROPTIONS[:setup])
51
17
  end
52
-
53
- def ensure_temp_dir_exist
54
- raise "Tmp dir(#{DTROPTIONS[:tmp_dir]}) is a file!" if File.file?(DTROPTIONS[:tmp_dir])
55
- unless File.exist?(DTROPTIONS[:tmp_dir])
56
- FileUtils.makedirs(DTROPTIONS[:tmp_dir])
18
+
19
+ def launch_runners(names, setup=nil)
20
+ require 'dtr/runner'
21
+ names = names || "DTR(#{Time.now})"
22
+ DTR::RunnerProtectProcess.start(names, setup)
23
+ end
24
+
25
+ def lib_path
26
+ File.expand_path(File.dirname(__FILE__))
27
+ end
28
+
29
+ def broadcast_list=(list)
30
+ require 'dtr/service_provider'
31
+ ServiceProvider.broadcast_list = list
32
+ end
33
+
34
+ def runners
35
+ require 'dtr/service_provider'
36
+ ServiceProvider.new.runners
37
+ end
38
+
39
+ def stop_runners_daemon_mode
40
+ with_daemon_gem do
41
+ Daemons.run_proc "dtr_runners", :ARGV => ['stop']
57
42
  end
58
43
  end
59
-
60
- module_function :start_client_server, :run, :ensure_temp_dir_exist
61
-
62
- class ClientServer
63
- @@servers = []
64
-
65
- def self.stop_all
66
- logger.info { "client servers: #{@@servers.join(", ")}" }
67
- @@servers.each do |server|
68
- Process.kill "TERM", server
69
- logger.info { "Killed #{server}" }
44
+
45
+ def start_runners_daemon_mode
46
+ with_daemon_gem do
47
+ pwd = Dir.pwd
48
+ Daemons.run_proc "dtr_runners", :ARGV => ['start'], :backtrace => true, :log_output => true do
49
+ Dir.chdir(pwd) do
50
+ start_runners
51
+ end
70
52
  end
71
53
  end
72
-
73
- def initialize(opts={})
74
- @opts = DTROPTIONS.merge opts
75
- end
76
-
77
- def start
78
- @@servers << Process.fork do
79
- DTROPTIONS.merge! @opts
80
- trap("TERM") do
81
- exit!
82
- end
83
- DTR.start_client_server
54
+ end
55
+
56
+ def start_server_daemon_mode
57
+ with_daemon_gem do
58
+ Daemons.run_proc "dtr_server", :ARGV => ['start'] do
59
+ start_server
84
60
  end
85
61
  end
62
+ sleep(2)
63
+ end
64
+
65
+ def stop_server_daemon_mode
66
+ with_daemon_gem do
67
+ Daemons.run_proc "dtr_server", :ARGV => ['stop']
68
+ end
69
+ end
70
+
71
+ def with_daemon_gem
72
+ require "rubygems"
73
+ begin
74
+ require "daemons"
75
+ rescue LoadError
76
+ raise "The daemons gem must be installed"
77
+ end
78
+ yield
86
79
  end
87
80
 
81
+ module_function :start_server, :start_runners, :launch_runners, :lib_path, :broadcast_list=, :runners, :with_daemon_gem, :start_runners_daemon_mode, :stop_runners_daemon_mode, :start_server_daemon_mode, :stop_server_daemon_mode
88
82
  end