Class: Hydra::Master
- Inherits:
-
Object
- Object
- Hydra::Master
- Includes:
- Hydra::Messages::Master, Open3
- Defined in:
- lib/hydra/master.rb
Instance Attribute Summary collapse
-
#report_text ⇒ Object
readonly
A text report of the time it took to run each file.
Instance Method Summary collapse
-
#initialize(opts = { }) ⇒ Master
constructor
Create a new Master.
-
#process_results(worker, message) ⇒ Object
Process the results coming back from the worker.
-
#send_file(worker) ⇒ Object
Send a file down to a worker.
-
#worker_begin(worker) ⇒ Object
Message handling.
Constructor Details
#initialize(opts = { }) ⇒ Master
Create a new Master
Options:
-
:files
-
An array of test files to be run. These should be relative paths from the root of the project, since they may be run on different machines which may have different paths.
-
-
:workers
-
An array of hashes. Each hash should be the configuration options for a worker.
-
-
:listeners
-
An array of Hydra::Listener objects. See Hydra::Listener::MinimalOutput for an example listener
-
-
:verbose
-
Set to true to see lots of Hydra output (for debugging)
-
-
:autosort
-
Set to false to disable automatic sorting by historical run-time per file
-
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/hydra/master.rb', line 35 def initialize(opts = { }) opts.stringify_keys! config_file = opts.delete('config') { nil } if config_file begin config_erb = ERB.new(IO.read(config_file)).result(binding) rescue Exception => e raise(YmlLoadError,"config file was found, but could not be parsed with ERB.\n#{$!.inspect}") end begin config_yml = YAML::load(config_erb) rescue StandardError => e raise(YmlLoadError,"config file was found, but could not be parsed.\n#{$!.inspect}") end opts.merge!(config_yml.stringify_keys!) end @files = Array(opts.fetch('files') { nil }) raise "No files, nothing to do" if @files.empty? @incomplete_files = @files.dup @workers = [] @listeners = [] @stats = Hash.new(0) @event_listeners = Array(opts.fetch('listeners') { nil } ) @event_listeners.select{|l| l.is_a? String}.each do |l| @event_listeners.delete_at(@event_listeners.index(l)) listener = eval(l) @event_listeners << listener if listener.is_a?(Hydra::Listener::Abstract) end @verbose = opts.fetch('verbose') { false } @autosort = opts.fetch('autosort') { true } @sync = opts.fetch('sync') { nil } @environment = opts.fetch('environment') { 'test' } if @autosort sort_files_from_report @event_listeners << Hydra::Listener::ReportGenerator.new(File.new(heuristic_file, 'w')) end # default is one worker that is configured to use a pipe with one runner worker_cfg = opts.fetch('workers') { [ { 'type' => 'local', 'runners' => 1} ] } trace "Initialized" trace " Files: (#{@files.inspect})" trace " Workers: (#{worker_cfg.inspect})" trace " Verbose: (#{@verbose.inspect})" @event_listeners.each{|l| l.testing_begin(@files) } boot_workers worker_cfg report_fields = [:tests, :assertions, :errors, :failures] report = report_fields.map{|field| "#{field}: #{@stats[field]}"}.join(', ') puts report end |
Instance Attribute Details
#report_text ⇒ Object (readonly)
A text report of the time it took to run each file
143 144 145 |
# File 'lib/hydra/master.rb', line 143 def report_text @report_text end |
Instance Method Details
#process_results(worker, message) ⇒ Object
Process the results coming back from the worker.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/hydra/master.rb', line 112 def process_results(worker, ) if .stats .stats.each do |key, value| @stats[key] += value end end if .output =~ /ActiveRecord::StatementInvalid(.*)[Dd]eadlock/ or .output =~ /PGError: ERROR(.*)[Dd]eadlock/ or .output =~ /Mysql::Error: SAVEPOINT(.*)does not exist: ROLLBACK/ or .output =~ /Mysql::Error: Deadlock found/ trace "Deadlock detected running [#{.file}]. Will retry at the end" @files.push(.file) send_file(worker) else @incomplete_files.delete_at(@incomplete_files.index(.file)) trace "#{@incomplete_files.size} Files Remaining" @event_listeners.each{|l| l.file_end(.file, .output) } if @incomplete_files.empty? @workers.each do |worker| @event_listeners.each{|l| l.worker_end(worker) } end shutdown_all_workers else send_file(worker) end end end |
#send_file(worker) ⇒ Object
Send a file down to a worker.
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/hydra/master.rb', line 100 def send_file(worker) f = @files.shift if f trace "Sending #{f.inspect}" @event_listeners.each{|l| l.file_begin(f) } worker[:io].write(RunFile.new(:file => f)) else trace "No more files to send" end end |
#worker_begin(worker) ⇒ Object
Message handling
95 96 97 |
# File 'lib/hydra/master.rb', line 95 def worker_begin(worker) @event_listeners.each {|l| l.worker_begin(worker) } end |