hydra 0.24.0 → 6.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/CONTRIBUTING.md +75 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +14 -0
- data/README.md +36 -0
- data/RELEASE-POLICY.md +10 -0
- data/Rakefile +1 -56
- data/hydra.gemspec +29 -124
- data/lib/hydra.rb +5 -16
- data/lib/hydra/version.rb +3 -0
- metadata +180 -108
- data/.document +0 -5
- data/LICENSE +0 -20
- data/README.rdoc +0 -43
- data/TODO +0 -18
- data/VERSION +0 -1
- data/caliper.yml +0 -6
- data/hydra-icon-64x64.png +0 -0
- data/hydra_gray.png +0 -0
- data/lib/hydra/cucumber/formatter.rb +0 -29
- data/lib/hydra/cucumber/partial_html.rb +0 -24
- data/lib/hydra/hash.rb +0 -16
- data/lib/hydra/js/lint.js +0 -5150
- data/lib/hydra/listener/abstract.rb +0 -39
- data/lib/hydra/listener/cucumber.css +0 -279
- data/lib/hydra/listener/cucumber_html_report.rb +0 -148
- data/lib/hydra/listener/jquery-min.js +0 -154
- data/lib/hydra/listener/minimal_output.rb +0 -24
- data/lib/hydra/listener/notifier.rb +0 -17
- data/lib/hydra/listener/progress_bar.rb +0 -48
- data/lib/hydra/listener/report_generator.rb +0 -33
- data/lib/hydra/master.rb +0 -248
- data/lib/hydra/message.rb +0 -47
- data/lib/hydra/message/master_messages.rb +0 -19
- data/lib/hydra/message/runner_messages.rb +0 -46
- data/lib/hydra/message/worker_messages.rb +0 -52
- data/lib/hydra/messaging_io.rb +0 -49
- data/lib/hydra/pipe.rb +0 -61
- data/lib/hydra/runner.rb +0 -312
- data/lib/hydra/runner_listener/abstract.rb +0 -23
- data/lib/hydra/safe_fork.rb +0 -31
- data/lib/hydra/spec/autorun_override.rb +0 -3
- data/lib/hydra/spec/hydra_formatter.rb +0 -26
- data/lib/hydra/ssh.rb +0 -41
- data/lib/hydra/stdio.rb +0 -16
- data/lib/hydra/sync.rb +0 -99
- data/lib/hydra/tasks.rb +0 -375
- data/lib/hydra/tmpdir.rb +0 -11
- data/lib/hydra/trace.rb +0 -24
- data/lib/hydra/worker.rb +0 -170
- data/test/fixtures/assert_true.rb +0 -7
- data/test/fixtures/config.yml +0 -4
- data/test/fixtures/conflicting.rb +0 -10
- data/test/fixtures/features/step_definitions.rb +0 -21
- data/test/fixtures/features/write_alternate_file.feature +0 -7
- data/test/fixtures/features/write_file.feature +0 -7
- data/test/fixtures/hello_world.rb +0 -3
- data/test/fixtures/hydra_worker_init.rb +0 -2
- data/test/fixtures/js_file.js +0 -4
- data/test/fixtures/json_data.json +0 -4
- data/test/fixtures/many_outputs_to_console.rb +0 -9
- data/test/fixtures/master_listeners.rb +0 -10
- data/test/fixtures/runner_listeners.rb +0 -23
- data/test/fixtures/slow.rb +0 -9
- data/test/fixtures/sync_test.rb +0 -8
- data/test/fixtures/task_test_config.yml +0 -6
- data/test/fixtures/write_file.rb +0 -10
- data/test/fixtures/write_file_alternate_spec.rb +0 -10
- data/test/fixtures/write_file_spec.rb +0 -9
- data/test/fixtures/write_file_with_pending_spec.rb +0 -11
- data/test/master_test.rb +0 -383
- data/test/message_test.rb +0 -31
- data/test/pipe_test.rb +0 -38
- data/test/runner_test.rb +0 -196
- data/test/ssh_test.rb +0 -25
- data/test/sync_test.rb +0 -113
- data/test/task_test.rb +0 -21
- data/test/test_helper.rb +0 -107
- data/test/worker_test.rb +0 -60
@@ -1,23 +0,0 @@
|
|
1
|
-
module Hydra #:nodoc:
|
2
|
-
module RunnerListener #:nodoc:
|
3
|
-
# Abstract listener that implements all the events
|
4
|
-
# but does nothing.
|
5
|
-
class Abstract
|
6
|
-
# Create a new listener.
|
7
|
-
#
|
8
|
-
# Output: The IO object for outputting any information.
|
9
|
-
# Defaults to STDOUT, but you could pass a file in, or STDERR
|
10
|
-
def initialize(output = $stdout)
|
11
|
-
@output = output
|
12
|
-
end
|
13
|
-
|
14
|
-
# Fired by the runner just before requesting the first file
|
15
|
-
def runner_begin( runner )
|
16
|
-
end
|
17
|
-
|
18
|
-
# Fired by the runner just after stoping
|
19
|
-
def runner_end( runner )
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/hydra/safe_fork.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
class SafeFork
|
2
|
-
def self.fork
|
3
|
-
begin
|
4
|
-
# remove our connection so it doesn't get cloned
|
5
|
-
connection = ActiveRecord::Base.remove_connection if defined?(ActiveRecord)
|
6
|
-
# fork a process
|
7
|
-
child = Process.fork do
|
8
|
-
begin
|
9
|
-
# create a new connection and perform the action
|
10
|
-
begin
|
11
|
-
ActiveRecord::Base.establish_connection((connection || {}).merge({:allow_concurrency => true})) if defined?(ActiveRecord)
|
12
|
-
rescue ActiveRecord::AdapterNotSpecified
|
13
|
-
# AR was defined but we didn't have a connection
|
14
|
-
end
|
15
|
-
yield
|
16
|
-
ensure
|
17
|
-
# make sure we remove the connection before we're done
|
18
|
-
ActiveRecord::Base.remove_connection if defined?(ActiveRecord)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
ensure
|
22
|
-
# make sure we re-establish the connection before returning to the main instance
|
23
|
-
begin
|
24
|
-
ActiveRecord::Base.establish_connection((connection || {}).merge({:allow_concurrency => true})) if defined?(ActiveRecord)
|
25
|
-
rescue ActiveRecord::AdapterNotSpecified
|
26
|
-
# AR was defined but we didn't have a connection
|
27
|
-
end
|
28
|
-
end
|
29
|
-
return child
|
30
|
-
end
|
31
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'rspec/core/formatters/progress_formatter'
|
2
|
-
module RSpec
|
3
|
-
module Core
|
4
|
-
module Formatters
|
5
|
-
class HydraFormatter < ProgressFormatter
|
6
|
-
def example_passed(example)
|
7
|
-
end
|
8
|
-
|
9
|
-
def example_pending(example)
|
10
|
-
end
|
11
|
-
|
12
|
-
def example_failed(example)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Stifle the post-test summary
|
16
|
-
def dump_summary(duration, example, failure, pending)
|
17
|
-
end
|
18
|
-
|
19
|
-
# Stifle pending specs
|
20
|
-
def dump_pending
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
data/lib/hydra/ssh.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'open3'
|
2
|
-
require 'hydra/messaging_io'
|
3
|
-
module Hydra #:nodoc:
|
4
|
-
# Read and write with an ssh connection. For example:
|
5
|
-
# @ssh = Hydra::SSH.new(
|
6
|
-
# 'localhost', # connect to this machine
|
7
|
-
# '/home/user', # move to the home directory
|
8
|
-
# "ruby hydra/test/echo_the_dolphin.rb" # run the echo script
|
9
|
-
# )
|
10
|
-
# @message = Hydra::Messages::TestMessage.new("Hey there!")
|
11
|
-
# @ssh.write @message
|
12
|
-
# puts @ssh.gets.text
|
13
|
-
# => "Hey there!"
|
14
|
-
#
|
15
|
-
# Note that what ever process you run should respond with Hydra messages.
|
16
|
-
class SSH
|
17
|
-
include Open3
|
18
|
-
include Hydra::MessagingIO
|
19
|
-
|
20
|
-
# Initialize new SSH connection.
|
21
|
-
# The first parameter is passed directly to ssh for starting a connection.
|
22
|
-
# The second parameter is the directory to CD into once connected.
|
23
|
-
# The third parameter is the command to run
|
24
|
-
# So you can do:
|
25
|
-
# Hydra::SSH.new('-p 3022 user@server.com', '/home/user/Desktop', 'ls -l')
|
26
|
-
# To connect to server.com as user on port 3022, then CD to their desktop, then
|
27
|
-
# list all the files.
|
28
|
-
def initialize(connection_options, directory, command)
|
29
|
-
@writer, @reader, @error = popen3("ssh -tt #{connection_options}")
|
30
|
-
@writer.write("mkdir -p #{directory}\n")
|
31
|
-
@writer.write("cd #{directory}\n")
|
32
|
-
@writer.write(command+"\n")
|
33
|
-
end
|
34
|
-
|
35
|
-
# Close the SSH connection
|
36
|
-
def close
|
37
|
-
@writer.write "exit\n"
|
38
|
-
super
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/hydra/stdio.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'hydra/messaging_io'
|
2
|
-
module Hydra #:nodoc:
|
3
|
-
# Read and write via stdout and stdin.
|
4
|
-
class Stdio
|
5
|
-
include Hydra::MessagingIO
|
6
|
-
|
7
|
-
# Initialize new Stdio
|
8
|
-
def initialize()
|
9
|
-
@reader = $stdin
|
10
|
-
@writer = $stdout
|
11
|
-
@reader.sync = true
|
12
|
-
@writer.sync = true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
data/lib/hydra/sync.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
module Hydra #:nodoc:
|
3
|
-
# Hydra class responsible for delegate work down to workers.
|
4
|
-
#
|
5
|
-
# The Sync is run once for each remote worker.
|
6
|
-
class Sync
|
7
|
-
traceable('SYNC')
|
8
|
-
self.class.traceable('SYNC MANY')
|
9
|
-
|
10
|
-
attr_reader :connect, :ssh_opts, :remote_dir
|
11
|
-
|
12
|
-
# Create a new Sync instance to rsync source from the local machine to a remote worker
|
13
|
-
#
|
14
|
-
# Arguments:
|
15
|
-
# * :worker_opts
|
16
|
-
# * A hash of the configuration options for a worker.
|
17
|
-
# * :sync
|
18
|
-
# * A hash of settings specifically for copying the source directory to be tested
|
19
|
-
# to the remote worked
|
20
|
-
# * :verbose
|
21
|
-
# * Set to true to see lots of Hydra output (for debugging)
|
22
|
-
def initialize(worker_opts, sync_opts, verbose = false)
|
23
|
-
worker_opts ||= {}
|
24
|
-
worker_opts.stringify_keys!
|
25
|
-
@verbose = verbose
|
26
|
-
@connect = worker_opts.fetch('connect') { raise "You must specify an SSH connection target" }
|
27
|
-
@ssh_opts = worker_opts.fetch('ssh_opts') { "" }
|
28
|
-
@remote_dir = worker_opts.fetch('directory') { raise "You must specify a remote directory" }
|
29
|
-
|
30
|
-
return unless sync_opts
|
31
|
-
sync_opts.stringify_keys!
|
32
|
-
@local_dir = sync_opts.fetch('directory') { raise "You must specify a synchronization directory" }
|
33
|
-
@exclude_paths = sync_opts.fetch('exclude') { [] }
|
34
|
-
|
35
|
-
trace "Initialized"
|
36
|
-
trace " Worker: (#{worker_opts.inspect})"
|
37
|
-
trace " Sync: (#{sync_opts.inspect})"
|
38
|
-
|
39
|
-
sync
|
40
|
-
end
|
41
|
-
|
42
|
-
def sync
|
43
|
-
#trace "Synchronizing with #{connect}\n\t#{sync_opts.inspect}"
|
44
|
-
exclude_opts = @exclude_paths.inject(''){|memo, path| memo += "--exclude=#{path} "}
|
45
|
-
|
46
|
-
rsync_command = [
|
47
|
-
'rsync',
|
48
|
-
'-avz',
|
49
|
-
'--delete',
|
50
|
-
exclude_opts,
|
51
|
-
File.expand_path(@local_dir)+'/',
|
52
|
-
"-e \"ssh #{@ssh_opts}\"",
|
53
|
-
"#{@connect}:#{@remote_dir}"
|
54
|
-
].join(" ")
|
55
|
-
trace rsync_command
|
56
|
-
trace `#{rsync_command}`
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.sync_many opts
|
60
|
-
opts.stringify_keys!
|
61
|
-
config_file = opts.delete('config') { nil }
|
62
|
-
if config_file
|
63
|
-
opts.merge!(YAML.load_file(config_file).stringify_keys!)
|
64
|
-
end
|
65
|
-
@verbose = opts.fetch('verbose') { false }
|
66
|
-
@sync = opts.fetch('sync') { {} }
|
67
|
-
|
68
|
-
workers_opts = opts.fetch('workers') { [] }
|
69
|
-
@remote_worker_opts = []
|
70
|
-
workers_opts.each do |worker_opts|
|
71
|
-
worker_opts.stringify_keys!
|
72
|
-
if worker_opts['type'].to_s == 'ssh'
|
73
|
-
@remote_worker_opts << worker_opts
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
trace "Initialized"
|
78
|
-
trace " Sync: (#{@sync.inspect})"
|
79
|
-
trace " Workers: (#{@remote_worker_opts.inspect})"
|
80
|
-
|
81
|
-
Thread.abort_on_exception = true
|
82
|
-
trace "Processing workers"
|
83
|
-
@listeners = []
|
84
|
-
@remote_worker_opts.each do |worker_opts|
|
85
|
-
@listeners << Thread.new do
|
86
|
-
begin
|
87
|
-
trace "Syncing #{worker_opts.inspect}"
|
88
|
-
Sync.new worker_opts, @sync, @verbose
|
89
|
-
rescue
|
90
|
-
trace "Syncing failed [#{worker_opts.inspect}]"
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
@listeners.each{|l| l.join}
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
end
|
data/lib/hydra/tasks.rb
DELETED
@@ -1,375 +0,0 @@
|
|
1
|
-
require 'open3'
|
2
|
-
module Hydra #:nodoc:
|
3
|
-
# Hydra Task Common attributes and methods
|
4
|
-
class Task
|
5
|
-
include Rake::DSL if defined?(Rake::DSL)
|
6
|
-
|
7
|
-
# Name of the task. Default 'hydra'
|
8
|
-
attr_accessor :name
|
9
|
-
|
10
|
-
# Command line options
|
11
|
-
attr_accessor :options
|
12
|
-
|
13
|
-
# Files to test.
|
14
|
-
# You can add files manually via:
|
15
|
-
# t.files << [file1, file2, etc]
|
16
|
-
#
|
17
|
-
# Or you can use the add_files method
|
18
|
-
attr_accessor :files
|
19
|
-
|
20
|
-
# True if you want to see Hydra's message traces
|
21
|
-
attr_accessor :verbose
|
22
|
-
|
23
|
-
# Path to the hydra config file.
|
24
|
-
# If not set, it will check 'hydra.yml' and 'config/hydra.yml'
|
25
|
-
attr_accessor :config
|
26
|
-
|
27
|
-
# Automatically sort files using their historical runtimes.
|
28
|
-
# Defaults to true
|
29
|
-
# To disable:
|
30
|
-
# t.autosort = false
|
31
|
-
attr_accessor :autosort
|
32
|
-
|
33
|
-
# Event listeners. Defaults to the MinimalOutput listener.
|
34
|
-
# You can add additional listeners if you'd like. For example,
|
35
|
-
# on linux (with notify-send) you can add the notifier listener:
|
36
|
-
# t.listeners << Hydra::Listener::Notifier.new
|
37
|
-
attr_accessor :listeners
|
38
|
-
|
39
|
-
# Set to true if you want to run this task only on the local
|
40
|
-
# machine with one runner. A "Safe Mode" for some test
|
41
|
-
# files that may not play nice with others.
|
42
|
-
attr_accessor :serial
|
43
|
-
|
44
|
-
attr_accessor :environment
|
45
|
-
|
46
|
-
# Set to false if you don't want to show the total running time
|
47
|
-
attr_accessor :show_time
|
48
|
-
|
49
|
-
# Set to a valid file path if you want to save the output of the runners
|
50
|
-
# in a log file
|
51
|
-
attr_accessor :runner_log_file
|
52
|
-
|
53
|
-
#
|
54
|
-
# Search for the hydra config file
|
55
|
-
def find_config_file
|
56
|
-
@config ||= 'hydra.yml'
|
57
|
-
return @config if File.exists?(@config)
|
58
|
-
@config = File.join('config', 'hydra.yml')
|
59
|
-
return @config if File.exists?(@config)
|
60
|
-
@config = nil
|
61
|
-
end
|
62
|
-
|
63
|
-
# Add files to test by passing in a string to be run through Dir.glob.
|
64
|
-
# For example:
|
65
|
-
#
|
66
|
-
# t.add_files 'test/units/*.rb'
|
67
|
-
def add_files(pattern)
|
68
|
-
@files += Dir.glob(pattern)
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
# Define a test task that uses hydra to test the files.
|
74
|
-
#
|
75
|
-
# Hydra::TestTask.new('hydra') do |t|
|
76
|
-
# t.add_files 'test/unit/**/*_test.rb'
|
77
|
-
# t.add_files 'test/functional/**/*_test.rb'
|
78
|
-
# t.add_files 'test/integration/**/*_test.rb'
|
79
|
-
# t.verbose = false # optionally set to true for lots of debug messages
|
80
|
-
# t.autosort = false # disable automatic sorting based on runtime of tests
|
81
|
-
# end
|
82
|
-
class TestTask < Hydra::Task
|
83
|
-
|
84
|
-
# Create a new HydraTestTask
|
85
|
-
def initialize(name = :hydra)
|
86
|
-
@name = name
|
87
|
-
@files = []
|
88
|
-
@verbose = false
|
89
|
-
@autosort = true
|
90
|
-
@serial = false
|
91
|
-
@listeners = [Hydra::Listener::ProgressBar.new]
|
92
|
-
@show_time = true
|
93
|
-
@options = ''
|
94
|
-
|
95
|
-
yield self if block_given?
|
96
|
-
|
97
|
-
# Ensure we override rspec's at_exit
|
98
|
-
if defined?(RSpec)
|
99
|
-
RSpec::Core::Runner.disable_autorun!
|
100
|
-
end
|
101
|
-
|
102
|
-
unless @serial
|
103
|
-
@config = find_config_file
|
104
|
-
end
|
105
|
-
|
106
|
-
@opts = {
|
107
|
-
:verbose => @verbose,
|
108
|
-
:autosort => @autosort,
|
109
|
-
:files => @files,
|
110
|
-
:listeners => @listeners,
|
111
|
-
:environment => @environment,
|
112
|
-
:runner_log_file => @runner_log_file,
|
113
|
-
:options => @options
|
114
|
-
}
|
115
|
-
if @config
|
116
|
-
@opts.merge!(:config => @config)
|
117
|
-
else
|
118
|
-
@opts.merge!(:workers => [{:type => :local, :runners => 1}])
|
119
|
-
end
|
120
|
-
|
121
|
-
define
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
# Create the rake task defined by this HydraTestTask
|
126
|
-
def define
|
127
|
-
desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}")
|
128
|
-
task @name do
|
129
|
-
if Object.const_defined?('Rails') && Rails.env == 'development'
|
130
|
-
$stderr.puts %{WARNING: Rails Environment is "development". Make sure to set it properly (ex: "RAILS_ENV=test rake hydra")}
|
131
|
-
end
|
132
|
-
|
133
|
-
start = Time.now if @show_time
|
134
|
-
|
135
|
-
puts '********************'
|
136
|
-
puts @options.inspect
|
137
|
-
master = Hydra::Master.new(@opts)
|
138
|
-
|
139
|
-
$stdout.puts "\nFinished in #{'%.6f' % (Time.now - start)} seconds." if @show_time
|
140
|
-
|
141
|
-
unless master.failed_files.empty?
|
142
|
-
raise "Hydra: Not all tests passes"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Define a test task that uses hydra to profile your test files
|
149
|
-
#
|
150
|
-
# Hydra::ProfileTask.new('hydra:prof') do |t|
|
151
|
-
# t.add_files 'test/unit/**/*_test.rb'
|
152
|
-
# t.add_files 'test/functional/**/*_test.rb'
|
153
|
-
# t.add_files 'test/integration/**/*_test.rb'
|
154
|
-
# t.generate_html = true # defaults to false
|
155
|
-
# t.generate_text = true # defaults to true
|
156
|
-
# end
|
157
|
-
class ProfileTask < Hydra::Task
|
158
|
-
# boolean: generate html output from ruby-prof
|
159
|
-
attr_accessor :generate_html
|
160
|
-
# boolean: generate text output from ruby-prof
|
161
|
-
attr_accessor :generate_text
|
162
|
-
|
163
|
-
# Create a new Hydra ProfileTask
|
164
|
-
def initialize(name = 'hydra:profile')
|
165
|
-
@name = name
|
166
|
-
@files = []
|
167
|
-
@verbose = false
|
168
|
-
@generate_html = false
|
169
|
-
@generate_text = true
|
170
|
-
|
171
|
-
yield self if block_given?
|
172
|
-
|
173
|
-
# Ensure we override rspec's at_exit
|
174
|
-
require 'hydra/spec/autorun_override'
|
175
|
-
|
176
|
-
@config = find_config_file
|
177
|
-
|
178
|
-
@opts = {
|
179
|
-
:verbose => @verbose,
|
180
|
-
:files => @files
|
181
|
-
}
|
182
|
-
define
|
183
|
-
end
|
184
|
-
|
185
|
-
private
|
186
|
-
# Create the rake task defined by this HydraTestTask
|
187
|
-
def define
|
188
|
-
desc "Hydra Test Profile" + (@name == :hydra ? "" : " for #{@name}")
|
189
|
-
task @name do
|
190
|
-
require 'ruby-prof'
|
191
|
-
RubyProf.start
|
192
|
-
|
193
|
-
runner = Hydra::Runner.new(:io => File.new('/dev/null', 'w'))
|
194
|
-
@files.each do |file|
|
195
|
-
$stdout.write runner.run_file(file)
|
196
|
-
$stdout.flush
|
197
|
-
end
|
198
|
-
|
199
|
-
$stdout.write "\nTests complete. Generating profiling output\n"
|
200
|
-
$stdout.flush
|
201
|
-
|
202
|
-
result = RubyProf.stop
|
203
|
-
|
204
|
-
if @generate_html
|
205
|
-
printer = RubyProf::GraphHtmlPrinter.new(result)
|
206
|
-
out = File.new("ruby-prof.html", 'w')
|
207
|
-
printer.print(out, :min_self => 0.05)
|
208
|
-
out.close
|
209
|
-
$stdout.write "Profiling data written to [ruby-prof.html]\n"
|
210
|
-
end
|
211
|
-
|
212
|
-
if @generate_text
|
213
|
-
printer = RubyProf::FlatPrinter.new(result)
|
214
|
-
out = File.new("ruby-prof.txt", 'w')
|
215
|
-
printer.print(out, :min_self => 0.05)
|
216
|
-
out.close
|
217
|
-
$stdout.write "Profiling data written to [ruby-prof.txt]\n"
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
# Define a sync task that uses hydra to rsync the source tree under test to remote workers.
|
224
|
-
#
|
225
|
-
# This task is very useful to run before a remote db:reset task to make sure the db/schema.rb
|
226
|
-
# file is up to date on the remote workers.
|
227
|
-
#
|
228
|
-
# Hydra::SyncTask.new('hydra:sync') do |t|
|
229
|
-
# t.verbose = false # optionally set to true for lots of debug messages
|
230
|
-
# end
|
231
|
-
class SyncTask < Hydra::Task
|
232
|
-
|
233
|
-
# Create a new SyncTestTask
|
234
|
-
def initialize(name = :sync)
|
235
|
-
@name = name
|
236
|
-
@verbose = false
|
237
|
-
|
238
|
-
yield self if block_given?
|
239
|
-
|
240
|
-
@config = find_config_file
|
241
|
-
|
242
|
-
@opts = {
|
243
|
-
:verbose => @verbose
|
244
|
-
}
|
245
|
-
@opts.merge!(:config => @config) if @config
|
246
|
-
|
247
|
-
define
|
248
|
-
end
|
249
|
-
|
250
|
-
private
|
251
|
-
# Create the rake task defined by this HydraSyncTask
|
252
|
-
def define
|
253
|
-
desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}")
|
254
|
-
task @name do
|
255
|
-
Hydra::Sync.sync_many(@opts)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
# Setup a task that will be run across all remote workers
|
261
|
-
# Hydra::RemoteTask.new('db:reset')
|
262
|
-
#
|
263
|
-
# Then you can run:
|
264
|
-
# rake hydra:remote:db:reset
|
265
|
-
class RemoteTask < Hydra::Task
|
266
|
-
include Open3
|
267
|
-
# Create a new hydra remote task with the given name.
|
268
|
-
# The task will be named hydra:remote:<name>
|
269
|
-
def initialize(name, command=nil)
|
270
|
-
@name = name
|
271
|
-
@command = command
|
272
|
-
yield self if block_given?
|
273
|
-
@config = find_config_file
|
274
|
-
if @config
|
275
|
-
define
|
276
|
-
else
|
277
|
-
task "hydra:remote:#{@name}" do ; end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
private
|
282
|
-
def define
|
283
|
-
desc "Run #{@name} remotely on all workers"
|
284
|
-
task "hydra:remote:#{@name}" do
|
285
|
-
config = YAML.load_file(@config)
|
286
|
-
environment = config.fetch('environment') { 'test' }
|
287
|
-
workers = config.fetch('workers') { [] }
|
288
|
-
workers = workers.select{|w| w['type'] == 'ssh'}
|
289
|
-
@command = "RAILS_ENV=#{environment} rake #{@name}" unless @command
|
290
|
-
|
291
|
-
$stdout.write "==== Hydra Running #{@name} ====\n"
|
292
|
-
Thread.abort_on_exception = true
|
293
|
-
@listeners = []
|
294
|
-
@results = {}
|
295
|
-
workers.each do |worker|
|
296
|
-
@listeners << Thread.new do
|
297
|
-
begin
|
298
|
-
@results[worker] = if run_command(worker, @command)
|
299
|
-
"==== #{@name} passed on #{worker['connect']} ====\n"
|
300
|
-
else
|
301
|
-
"==== #{@name} failed on #{worker['connect']} ====\nPlease see above for more details.\n"
|
302
|
-
end
|
303
|
-
rescue
|
304
|
-
@results[worker] = "==== #{@name} failed for #{worker['connect']} ====\n#{$!.inspect}\n#{$!.backtrace.join("\n")}"
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
@listeners.each{|l| l.join}
|
309
|
-
$stdout.write "\n==== Hydra Running #{@name} COMPLETE ====\n\n"
|
310
|
-
$stdout.write @results.values.join("\n")
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
def run_command worker, command
|
315
|
-
$stdout.write "==== Hydra Running #{@name} on #{worker['connect']} ====\n"
|
316
|
-
ssh_opts = worker.fetch('ssh_opts') { '' }
|
317
|
-
writer, reader, error = popen3("ssh -tt #{ssh_opts} #{worker['connect']} ")
|
318
|
-
writer.write("cd #{worker['directory']}\n")
|
319
|
-
writer.write "echo BEGIN HYDRA\n"
|
320
|
-
writer.write(command + "\r")
|
321
|
-
writer.write "echo END HYDRA\n"
|
322
|
-
writer.write("exit\n")
|
323
|
-
writer.close
|
324
|
-
ignoring = true
|
325
|
-
passed = true
|
326
|
-
while line = reader.gets
|
327
|
-
line.chomp!
|
328
|
-
if line =~ /^rake aborted!$/
|
329
|
-
passed = false
|
330
|
-
end
|
331
|
-
if line =~ /echo END HYDRA$/
|
332
|
-
ignoring = true
|
333
|
-
end
|
334
|
-
$stdout.write "#{worker['connect']}: #{line}\n" unless ignoring
|
335
|
-
if line == 'BEGIN HYDRA'
|
336
|
-
ignoring = false
|
337
|
-
end
|
338
|
-
end
|
339
|
-
passed
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
# A Hydra global task is a task that is run both locally and remotely.
|
344
|
-
#
|
345
|
-
# For example:
|
346
|
-
#
|
347
|
-
# Hydra::GlobalTask.new('db:reset')
|
348
|
-
#
|
349
|
-
# Allows you to run:
|
350
|
-
#
|
351
|
-
# rake hydra:db:reset
|
352
|
-
#
|
353
|
-
# Then, db:reset will be run locally and on all remote workers. This
|
354
|
-
# makes it easy to setup your workers and run tasks all in a row.
|
355
|
-
#
|
356
|
-
# For example:
|
357
|
-
#
|
358
|
-
# rake hydra:db:reset hydra:factories hydra:tests
|
359
|
-
#
|
360
|
-
# Assuming you setup hydra:db:reset and hydra:db:factories as global
|
361
|
-
# tasks and hydra:tests as a Hydra::TestTask for all your tests
|
362
|
-
class GlobalTask < Hydra::Task
|
363
|
-
def initialize(name)
|
364
|
-
@name = name
|
365
|
-
define
|
366
|
-
end
|
367
|
-
|
368
|
-
private
|
369
|
-
def define
|
370
|
-
Hydra::RemoteTask.new(@name)
|
371
|
-
desc "Run #{@name.to_s} Locally and Remotely across all Workers"
|
372
|
-
task "hydra:#{@name.to_s}" => [@name.to_s, "hydra:remote:#{@name.to_s}"]
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|