2011-08-23 11:01:48 +00:00
require 'test_helper'
require 'fixtures/runner_listeners'
require 'fixtures/master_listeners'
2010-01-29 16:45:42 +00:00
class MasterTest < Test :: Unit :: TestCase
context " with a file to test and a destination to verify " do
setup do
2010-02-16 21:13:51 +00:00
# avoid having other tests interfering with us
2010-02-18 18:11:00 +00:00
sleep ( 0 . 2 )
2010-01-29 19:56:02 +00:00
FileUtils . rm_f ( target_file )
2010-01-29 16:45:42 +00:00
end
teardown do
2010-01-29 19:56:02 +00:00
FileUtils . rm_f ( target_file )
2010-01-29 16:45:42 +00:00
end
should " run a test " do
2010-01-29 20:26:32 +00:00
Hydra :: Master . new (
:files = > [ test_file ]
)
2010-01-29 19:56:02 +00:00
assert File . exists? ( target_file )
assert_equal " HYDRA " , File . read ( target_file )
2010-01-29 16:45:42 +00:00
end
2010-02-17 21:28:32 +00:00
2010-08-28 02:35:11 +00:00
# this test simulates what happens when we have 2 tests with the same
# class name but with different parent classes. This can happen when
# we have a functional and an integration test class with the same name.
2011-08-31 19:12:47 +00:00
#
# ...but I can't even get this test to work in the expected way (jb)
should_eventually " run even with a test that will not require " do
2010-08-29 05:17:26 +00:00
class FileOutputListener < Hydra :: Listener :: Abstract
attr_accessor :output
def initialize ( & block )
self . output = { }
end
def file_end ( file , output )
self . output [ file ] = output
end
end
listener = FileOutputListener . new
2010-08-28 02:35:11 +00:00
sync_test = File . join ( File . dirname ( __FILE__ ) , 'fixtures' , 'sync_test.rb' )
Hydra :: Master . new (
# we want the actual test to run last to make sure the runner can still run tests
:files = > [ sync_test , conflicting_test_file , test_file ] ,
2010-08-29 05:17:26 +00:00
:autosort = > false ,
:listeners = > [ listener ]
2010-08-28 02:35:11 +00:00
)
2010-08-29 05:17:26 +00:00
assert_match / superclass mismatch for class SyncTest / , listener . output [ conflicting_test_file ]
assert_match conflicting_test_file , listener . output [ conflicting_test_file ]
2010-08-28 02:35:11 +00:00
assert File . exists? ( target_file )
assert_equal " HYDRA " , File . read ( target_file )
end
2010-04-20 10:33:28 +00:00
should " run a spec with pending examples " do
progress_bar = Hydra :: Listener :: ProgressBar . new ( StringIO . new )
Hydra :: Master . new (
:files = > [ rspec_file_with_pending ] ,
:listeners = > [ progress_bar ]
)
assert File . exists? ( target_file )
assert_equal " HYDRA " , File . read ( target_file )
assert_equal false , progress_bar . instance_variable_get ( '@errors' )
end
2010-02-17 21:28:32 +00:00
should " generate a report " do
2010-03-25 16:15:01 +00:00
Hydra :: Master . new ( :files = > [ test_file ] )
2010-02-17 21:28:32 +00:00
assert File . exists? ( target_file )
assert_equal " HYDRA " , File . read ( target_file )
2010-06-09 18:24:32 +00:00
report_file = File . join ( Dir . consistent_tmpdir , 'hydra_heuristics.yml' )
2010-02-17 21:28:32 +00:00
assert File . exists? ( report_file )
2010-03-25 16:15:01 +00:00
assert report = YAML . load_file ( report_file )
assert_not_nil report [ test_file ]
2010-02-17 21:28:32 +00:00
end
2010-01-29 20:26:32 +00:00
should " run a test 6 times on 1 worker with 2 runners " do
Hydra :: Master . new (
:files = > [ test_file ] * 6 ,
2010-02-04 15:33:21 +00:00
:workers = > [ { :type = > :local , :runners = > 2 } ]
2010-01-29 20:26:32 +00:00
)
assert File . exists? ( target_file )
assert_equal " HYDRA " * 6 , File . read ( target_file )
end
2010-02-04 16:18:06 +00:00
# The test being run sleeps for 5 seconds. So, if this was run in
# series, it would take at least 50 seconds. This test ensures that
2010-01-29 20:26:32 +00:00
# in runs in less than that amount of time. Since there are 10
2010-02-04 16:18:06 +00:00
# runners to run the file 10 times, it should only take 5-10 seconds
2010-01-29 20:26:32 +00:00
# based on overhead.
should " run a slow test 10 times on 1 worker with 10 runners quickly " do
start = Time . now
Hydra :: Master . new (
:files = > [ File . join ( File . dirname ( __FILE__ ) , 'fixtures' , 'slow.rb' ) ] * 10 ,
:workers = > [
{ :type = > :local , :runners = > 10 }
]
)
finish = Time . now
2010-02-04 16:18:06 +00:00
assert ( finish - start ) < 30 , " took #{ finish - start } seconds "
2010-01-29 20:27:48 +00:00
end
2010-01-29 20:26:32 +00:00
2010-01-29 20:27:48 +00:00
should " run a slow test 10 times on 2 workers with 5 runners each quickly " do
start = Time . now
Hydra :: Master . new (
:files = > [ File . join ( File . dirname ( __FILE__ ) , 'fixtures' , 'slow.rb' ) ] * 10 ,
:workers = > [
{ :type = > :local , :runners = > 5 } ,
{ :type = > :local , :runners = > 5 }
]
)
finish = Time . now
2010-01-29 20:26:32 +00:00
assert ( finish - start ) < 15 , " took #{ finish - start } seconds "
end
2010-01-29 22:21:48 +00:00
should " run a test via ssh " do
Hydra :: Master . new (
:files = > [ test_file ] ,
:workers = > [ {
:type = > :ssh ,
:connect = > 'localhost' ,
2011-05-30 17:40:44 +00:00
:directory = > remote_dir_path ,
:runners = > 1
2010-02-03 21:03:16 +00:00
} ]
2010-01-29 22:21:48 +00:00
)
assert File . exists? ( target_file )
assert_equal " HYDRA " , File . read ( target_file )
end
2010-02-04 15:33:21 +00:00
should " run a test with config from a yaml file " do
Hydra :: Master . new (
:files = > [ test_file ] ,
:config = > File . join ( File . dirname ( __FILE__ ) , 'fixtures' , 'config.yml' )
)
assert File . exists? ( target_file )
assert_equal " HYDRA " , File . read ( target_file )
end
2010-02-09 20:40:35 +00:00
should " synchronize a test file over ssh with rsync " do
2010-06-09 18:24:32 +00:00
local = File . join ( Dir . consistent_tmpdir , 'hydra' , 'local' )
remote = File . join ( Dir . consistent_tmpdir , 'hydra' , 'remote' )
2010-02-09 20:40:35 +00:00
sync_test = File . join ( File . dirname ( __FILE__ ) , 'fixtures' , 'sync_test.rb' )
[ local , remote ] . each { | f | FileUtils . rm_rf f ; FileUtils . mkdir_p f }
# setup the folders:
# local:
# - test_a
# - test_c
# remote:
# - test_b
#
# add test_c to exludes
FileUtils . cp ( sync_test , File . join ( local , 'test_a.rb' ) )
FileUtils . cp ( sync_test , File . join ( local , 'test_c.rb' ) )
FileUtils . cp ( sync_test , File . join ( remote , 'test_b.rb' ) )
# ensure a is not on remote
assert ! File . exists? ( File . join ( remote , 'test_a.rb' ) ) , " A should not be on remote "
# ensure c is not on remote
assert ! File . exists? ( File . join ( remote , 'test_c.rb' ) ) , " C should not be on remote "
# ensure b is on remote
assert File . exists? ( File . join ( remote , 'test_b.rb' ) ) , " B should be on remote "
Hydra :: Master . new (
:files = > [ 'test_a.rb' ] ,
:workers = > [ {
:type = > :ssh ,
:connect = > 'localhost' ,
:directory = > remote ,
2011-08-31 15:42:56 +00:00
:verbose = > true ,
2010-03-25 16:15:01 +00:00
:runners = > 1
2010-02-09 20:40:35 +00:00
} ] ,
:sync = > {
:directory = > local ,
:exclude = > [ 'test_c.rb' ]
}
)
# ensure a is copied
assert File . exists? ( File . join ( remote , 'test_a.rb' ) ) , " A was not copied "
# ensure c is not copied
assert ! File . exists? ( File . join ( remote , 'test_c.rb' ) ) , " C was copied, should be excluded "
# ensure b is deleted
assert ! File . exists? ( File . join ( remote , 'test_b.rb' ) ) , " B was not deleted "
end
2010-01-29 16:45:42 +00:00
end
2011-06-01 16:45:43 +00:00
context " with a runner_end event " do
setup do
# avoid having other tests interfering with us
sleep ( 0 . 2 )
FileUtils . rm_f ( target_file )
FileUtils . rm_f ( alternate_target_file )
2011-06-03 22:51:36 +00:00
@runner_began_flag = File . expand_path ( File . join ( Dir . consistent_tmpdir , 'runner_began_flag' ) ) #used to know when the worker is ready
FileUtils . rm_f ( @runner_began_flag )
2011-06-01 16:45:43 +00:00
@runner_listener = 'HydraExtension::RunnerListener::RunnerEndTest.new' # runner_end method that creates alternate_target_file
@master_listener = HydraExtension :: Listener :: WorkerBeganFlag . new #used to know when the runner is up
end
teardown do
FileUtils . rm_f ( target_file )
FileUtils . rm_f ( alternate_target_file )
end
context " running a local worker " do
2011-06-02 19:02:58 +00:00
should " run runner_end on successful termination " do
@pid = Process . fork do
2011-06-01 21:29:45 +00:00
Hydra :: Master . new (
2011-06-02 18:18:54 +00:00
:files = > [ test_file ] * 6 ,
:autosort = > false ,
:listeners = > [ @master_listener ] ,
:runner_listeners = > [ @runner_listener ] ,
:verbose = > false
)
2011-06-01 21:29:45 +00:00
end
2011-06-01 16:45:43 +00:00
Process . waitpid @pid
2011-06-02 19:02:58 +00:00
assert_file_exists alternate_target_file
2011-06-01 16:45:43 +00:00
end
should " run runner_end after interruption signal " do
2011-06-03 22:51:36 +00:00
add_infinite_worker_begin_to @master_listener
2011-06-02 19:02:58 +00:00
capture_stderr do # redirect stderr
@pid = Process . fork do
Hydra :: Master . new (
:files = > [ test_file ] ,
:autosort = > false ,
:listeners = > [ @master_listener ] ,
:runner_listeners = > [ @runner_listener ] ,
:verbose = > false
)
end
end
2011-06-01 16:45:43 +00:00
wait_for_runner_to_begin
2011-06-01 21:29:45 +00:00
2011-06-01 16:45:43 +00:00
Process . kill 'SIGINT' , @pid
Process . waitpid @pid
2011-06-02 19:02:58 +00:00
assert_file_exists alternate_target_file
2011-06-01 16:45:43 +00:00
end
end
context " running a remote worker " do
setup do
copy_worker_init_file # this method has a protection to avoid erasing an existing worker_init_file
2011-06-03 22:51:36 +00:00
end
teardown do
FileUtils . rm_f ( @remote_init_file ) unless @protect_init_file
end
should " run runner_end on successful termination " do
2011-06-01 21:29:45 +00:00
capture_stderr do # redirect stderr
@pid = Process . fork do
Hydra :: Master . new (
2011-06-02 19:02:58 +00:00
:files = > [ test_file ] ,
2011-06-02 18:18:54 +00:00
:autosort = > false ,
:listeners = > [ @master_listener ] ,
:runner_listeners = > [ @runner_listener ] ,
:workers = > [ {
:type = > :ssh ,
2011-08-31 19:12:47 +00:00
:connect = > 'localhost -o ControlMaster=no' ,
2011-06-02 18:18:54 +00:00
:directory = > remote_dir_path ,
:runners = > 1
} ] ,
:verbose = > false
)
2011-06-01 21:29:45 +00:00
end
2011-06-01 16:45:43 +00:00
end
Process . waitpid @pid
2011-08-31 19:12:47 +00:00
assert_file_exists target_file
2011-06-01 16:45:43 +00:00
end
end
end
2011-06-06 03:52:59 +00:00
context " redirecting runner's output and errors " do
setup do
# avoid having other tests interfering with us
sleep ( 0 . 2 )
FileUtils . rm_f ( target_file )
FileUtils . rm_f ( runner_log_file )
FileUtils . rm_f ( " #{ remote_dir_path } / #{ runner_log_file } " )
end
teardown do
FileUtils . rm_f ( target_file )
FileUtils . rm_f ( runner_log_file )
FileUtils . rm_f ( " #{ remote_dir_path } / #{ runner_log_file } " )
end
should " create a runner log file when usign local worker and passing a log file name " do
@pid = Process . fork do
Hydra :: Master . new (
:files = > [ test_file ] ,
:runner_log_file = > runner_log_file ,
:verbose = > false
)
end
Process . waitpid @pid
assert_file_exists target_file # ensure the test was successfully ran
assert_file_exists runner_log_file
end
should " create a runner log file when usign remote worker and passing a log file name " do
@pid = Process . fork do
Hydra :: Master . new (
:files = > [ test_file ] ,
:workers = > [ {
:type = > :ssh ,
:connect = > 'localhost' ,
:directory = > remote_dir_path ,
:runners = > 1
} ] ,
:verbose = > false ,
:runner_log_file = > runner_log_file
)
end
Process . waitpid @pid
assert_file_exists target_file # ensure the test was successfully ran
assert_file_exists " #{ remote_dir_path } / #{ runner_log_file } "
end
2011-06-06 15:02:24 +00:00
should " create the default runner log file when passing an incorrect log file path " do
default_log_file = " #{ remote_dir_path } / #{ Hydra :: Runner :: DEFAULT_LOG_FILE } " # hydra-runner.log"
FileUtils . rm_f ( default_log_file )
@pid = Process . fork do
Hydra :: Master . new (
:files = > [ test_file ] ,
:workers = > [ {
:type = > :ssh ,
:connect = > 'localhost' ,
:directory = > remote_dir_path ,
:runners = > 1
} ] ,
:verbose = > false ,
2011-08-31 15:42:56 +00:00
:runner_log_file = > " invalid-dir/ #{ runner_log_file } "
2011-06-06 15:02:24 +00:00
)
end
Process . waitpid @pid
assert_file_exists target_file # ensure the test was successfully ran
assert_file_exists default_log_file #default log file
assert ! File . exists? ( " #{ remote_dir_path } / #{ runner_log_file } " )
FileUtils . rm_f ( default_log_file )
end
2011-06-06 03:52:59 +00:00
end
2011-06-01 16:45:43 +00:00
private
2011-06-03 22:51:36 +00:00
2011-06-06 03:52:59 +00:00
def runner_log_file
2011-06-06 15:02:24 +00:00
" my-hydra-runner.log "
2011-06-06 03:52:59 +00:00
end
2011-06-03 22:51:36 +00:00
def add_infinite_worker_begin_to master_listener
class << master_listener
def worker_begin ( worker )
super
sleep 1 while true #ensure the process doesn't finish before killing it
end
end
end
2011-06-01 16:45:43 +00:00
# this requires that a worker_begin listener creates a file named worker_began_flag in tmp directory
def wait_for_runner_to_begin
2011-06-03 22:51:36 +00:00
assert_file_exists @runner_began_flag
2011-06-01 16:45:43 +00:00
end
# with a protection to avoid erasing something important in lib
def copy_worker_init_file
@remote_init_file = " #{ remote_dir_path } / #{ File . basename ( hydra_worker_init_file ) } "
if File . exists? ( @remote_init_file )
$stderr . puts " \n WARNING!!!: #{ @remote_init_file } exits and this test needs to create a new file here. Make sure there is nothing inportant in that file and remove it before running this test \n \n "
@protect_init_file = true
exit
end
# copy the hydra_worker_init to the correct location
FileUtils . cp ( hydra_worker_init_file , remote_dir_path )
end
2010-01-29 16:45:42 +00:00
end