jobmanager 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/FAQ.txt +151 -0
  2. data/History.txt +2 -0
  3. data/LICENSE +20 -0
  4. data/Manifest.txt +42 -0
  5. data/README.txt +395 -0
  6. data/Rakefile +17 -0
  7. data/bin/jobmanager +20 -0
  8. data/examples/email_settings.rb +14 -0
  9. data/examples/example.rb +23 -0
  10. data/examples/jobmanager.yaml +66 -0
  11. data/examples/mysql_backup.rb +18 -0
  12. data/lib/jobmanager.rb +1 -0
  13. data/lib/jobmanager/application.rb +455 -0
  14. data/lib/jobmanager/applicationconfig.rb +89 -0
  15. data/lib/jobmanager/applicationlogger.rb +306 -0
  16. data/lib/jobmanager/applicationoptionparser.rb +163 -0
  17. data/lib/jobmanager/system.rb +240 -0
  18. data/lib/jobmanager/teestream.rb +78 -0
  19. data/lib/jobmanager/util.rb +25 -0
  20. data/test/configs/all_values.yaml +33 -0
  21. data/test/configs/bad_email_condition.yaml +7 -0
  22. data/test/configs/bad_no_central_log_file.yaml +7 -0
  23. data/test/configs/bad_number_of_job_logs.yaml +7 -0
  24. data/test/configs/bad_timeout_zero.yaml +7 -0
  25. data/test/configs/email_settings.rb +16 -0
  26. data/test/configs/incomplete_1.yaml +23 -0
  27. data/test/configs/jobmanager_1.yaml +9 -0
  28. data/test/configs/jobmanager_2.yaml +11 -0
  29. data/test/configs/jobmanager_3.yaml +13 -0
  30. data/test/configs/jobmanager_4_bad_central_log_file.yaml +9 -0
  31. data/test/configs/jobmanager_4_bad_email_settings_file.yaml +9 -0
  32. data/test/configs/jobmanager_4_bad_job_logs_directory_1.yaml +9 -0
  33. data/test/configs/jobmanager_4_bad_job_logs_directory_2.yaml +9 -0
  34. data/test/configs/minimum_plus_email_settings.yaml +9 -0
  35. data/test/configs/minimum_required.yaml +5 -0
  36. data/test/helpers.rb +7 -0
  37. data/test/mock_syslog.rb +68 -0
  38. data/test/test_applicationlogger.rb +145 -0
  39. data/test/test_config.rb +208 -0
  40. data/test/test_jobmanager.rb +443 -0
  41. data/test/test_system.rb +206 -0
  42. data/test/test_teestream.rb +55 -0
  43. metadata +172 -0
@@ -0,0 +1,443 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require 'stringio'
5
+ require 'logger'
6
+ require 'zlib'
7
+ require 'fileutils'
8
+
9
+ require 'rubygems'
10
+ require 'relative'
11
+ require 'assertions'
12
+ require 'sys/host'
13
+
14
+ require 'configtoolkit'
15
+ require 'configtoolkit/yamlreader'
16
+ require 'configtoolkit/yamlwriter'
17
+ require 'configtoolkit/overridereader'
18
+
19
+ require 'jobmanager'
20
+
21
+ require 'test/unit'
22
+ require_relative('helpers')
23
+ require 'mock_syslog'
24
+
25
+ #
26
+ # This class essentially tests the bin/jobmanager application since
27
+ # the bin/jobmanager application does little more than call into the
28
+ # JobManager::Application class, which this test class directly tests.
29
+ #
30
+
31
+ class TestJobManager < Test::Unit::TestCase
32
+ include TestHelpers
33
+
34
+ CONFIG_DIR = PathRelativeToCaller.new("./configs")
35
+
36
+ LOG_DIR = "#{TEMP_DIR}/logs"
37
+
38
+ PROGRAM_NAME = $0
39
+ USER_NAME = Etc.getpwuid(Process::Sys.getuid()).name()
40
+ HOST_NAME = Sys::Host.hostname
41
+
42
+ # override the interactive shell calculation, and set to false
43
+ INTERACTIVE_SHELL_OVERRIDE = false
44
+
45
+ def setup
46
+ teardown()
47
+
48
+ FileUtils.mkdir_p(TEMP_DIR)
49
+ FileUtils.mkdir_p(LOG_DIR)
50
+
51
+ ActionMailer::Base.delivery_method = :test
52
+ ActionMailer::Base.deliveries = []
53
+ end
54
+
55
+ def teardown
56
+ FileUtils::rm_r(TEMP_DIR, :force => true)
57
+ end
58
+
59
+ # Invoke the JobManager::Application a number of times to launch the
60
+ # echo command. Confirm the output logs produced (the job log file
61
+ # and the central log file). Also, confirm that the job logs are
62
+ # properly rotated.
63
+ def test_jobmanager_1
64
+ config_file = File.join(CONFIG_DIR, "jobmanager_1.yaml")
65
+ config = File.open(config_file) { |fs| YAML::load(fs) }
66
+
67
+ user_name = USER_NAME
68
+ central_log_file = ERB.new(config["central_log_file"]).result(binding)
69
+ job_logs_directory = ERB.new(config["job_logs_directory"]).result(binding)
70
+
71
+ 1.upto(config["number_of_job_logs"] + 1) do |iteration|
72
+ args = [ "echo #{iteration}" ]
73
+
74
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
75
+ args,
76
+ config_file,
77
+ INTERACTIVE_SHELL_OVERRIDE)
78
+ jobmanager.run()
79
+
80
+ # Confirm that nothing was logged via syslog - The central log
81
+ # should be written to a file, not via syslog!
82
+ assert_equal("", $test_syslog_logger.string())
83
+ STDERR.print "\nJob Manager Pre Log Contents #1:\n"
84
+ STDERR.print $test_syslog_logger.string(), "\n"
85
+
86
+ jobmanager_log_contents = File.read(central_log_file)
87
+
88
+ print "\nJob Manager Log Contents #1:\n"
89
+ print jobmanager_log_contents, "\n"
90
+
91
+ lines = jobmanager_log_contents.split("\n")
92
+ assert_match(/^I, .* INFO .* \[#{USER_NAME}, echo\] Exited successfully$/, lines[1])
93
+
94
+ lines.each { |line| assert_no_match(/^ERROR/, line) }
95
+
96
+ # confirm correctness of the job log file.
97
+ job_log_file = "#{job_logs_directory}/echo.log.1"
98
+ assert(File.file?(job_log_file))
99
+
100
+ print "\nContents of #{job_log_file}:\n"
101
+ print File.read(job_log_file), "\n"
102
+
103
+ expected_contents = "#{iteration}\n"
104
+ assert_equal(expected_contents, File.read(job_log_file))
105
+ end
106
+
107
+ # confirm only number_of_job_logs log files have been kept (the
108
+ # rest discarded via the log rotation mechanism inside
109
+ # JobManager::Application).
110
+ assert_equal(config["number_of_job_logs"],
111
+ Dir.glob("#{job_logs_directory}/echo.log.*").length)
112
+ end
113
+
114
+ # Invoke the JobManager::Application to launch the echo command.
115
+ # Confirm the output logs produced (the job log file and the central
116
+ # log) are correct. This test configures JobManager::Application to
117
+ # log central log information via syslog, which has been mocked out
118
+ # for testing purposes. Confirm the email generated is correct, and
119
+ # that the job log is properly rotated and zipped.
120
+ def test_jobmanager_2
121
+ config_file = File.join(CONFIG_DIR, "jobmanager_2.yaml")
122
+ command_line_args = [ "-j", "ze_echoer",
123
+ "echo 1"
124
+ ]
125
+
126
+ # Load the ApplicationConfig class ourselves (the
127
+ # JobManager::Application class will also load the configuration
128
+ # separately).
129
+ yaml_reader = ConfigToolkit::YAMLReader.new(config_file)
130
+ command_parameters_hash = JobManager::ApplicationOptionParser.parse(PROGRAM_NAME, command_line_args.dup())
131
+ hash_reader = ConfigToolkit::HashReader.new(command_parameters_hash)
132
+ override_reader = ConfigToolkit::OverrideReader.new(yaml_reader, hash_reader)
133
+ config = JobManager::ApplicationConfig.load(override_reader)
134
+
135
+ # We need to test embedding the user_name variable in the
136
+ # email_settings_file parameter. Edit the email_settings_file to
137
+ # include this variable, and then write the new configuration to a
138
+ # temporary location. We will then pass this newly created
139
+ # configuration file to the JobManager::Application class.
140
+ config.email_settings_file = File.expand_path(TEMP_DIR) + "/<%=user_name%>/email_settings.rb"
141
+ new_config_file = "#{TEMP_DIR}/jobmanager_2.yaml"
142
+
143
+ # write the new config to a temporary location
144
+ File.open(new_config_file, "w") do |file_stream|
145
+ config.dump(ConfigToolkit::YAMLWriter.new(file_stream, true))
146
+ end
147
+
148
+ # copy the email settings file in the standard config directory to
149
+ # the email settings file referenced in the new config.
150
+ user_name = USER_NAME
151
+ evaluated_file = ERB.new(config.email_settings_file).result(binding)
152
+ FileUtils.mkdir_p(File.dirname(evaluated_file))
153
+ FileUtils.cp("#{CONFIG_DIR}/email_settings.rb", evaluated_file)
154
+
155
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
156
+ command_line_args.dup(),
157
+ new_config_file,
158
+ INTERACTIVE_SHELL_OVERRIDE)
159
+ jobmanager.run()
160
+
161
+ user_name = USER_NAME
162
+ job_logs_directory = ERB.new(config.job_logs_directory).result(binding)
163
+
164
+ # confirm correctness of the central log.
165
+ jobmanager_log_contents = $test_syslog_logger.string()
166
+
167
+ print "\nJob Manager Log Contents #2:\n"
168
+ print jobmanager_log_contents, "\n"
169
+
170
+ lines = jobmanager_log_contents.split("\n")
171
+ assert_match(/INFO \[#{USER_NAME}, ze_echoer\] Exited successfully$/, lines[1])
172
+ lines.each { |line| assert_no_match(/ERROR/, line) }
173
+
174
+ # confirm the correctness of the job log file.
175
+ job_log_files = Dir.glob("#{job_logs_directory}/ze_echoer.log.*.gz")
176
+
177
+ assert_equal(1, job_log_files.length)
178
+ job_log_file = job_log_files[0]
179
+
180
+ Zlib::GzipReader.open(job_log_file) do |gz|
181
+ expected_contents = "1\n"
182
+ actual_contents = gz.read
183
+ assert_equal(expected_contents, actual_contents)
184
+
185
+ print "\nContents of #{job_log_file}:\n"
186
+ print actual_contents, "\n"
187
+ end
188
+
189
+ #confirm the email generated is correct.
190
+ deliveries = ActionMailer::Base.deliveries
191
+ assert_equal(1, deliveries.length)
192
+
193
+ delivery = deliveries[0]
194
+
195
+ assert_equal("jobmanager results for job ze_echoer, command echo 1, user janet, host #{HOST_NAME}, result Success",
196
+ delivery.subject)
197
+ assert_match(/^INFO \[#{USER_NAME}, ze_echoer\] Exited successfully$/, delivery.body)
198
+ end
199
+
200
+ # test config w/ email + date extensions, command that exists but fails
201
+
202
+ # Invoke the JobManager::Application to launch the cat command with
203
+ # a bogus file, which will cause the command to fail. Confirm the
204
+ # output logs produced (the job log file and the central log) are
205
+ # correct. Confirm the email generated is correct.
206
+ def test_jobmanager_3
207
+ config_file = File.join(CONFIG_DIR, "jobmanager_3.yaml")
208
+ config = File.open(config_file) { |fs| YAML::load(fs) }
209
+
210
+ assert(JobManager::System.which("cat"))
211
+ args = [ "cat #{TEMP_DIR}/no_file" ]
212
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
213
+ args,
214
+ config_file,
215
+ INTERACTIVE_SHELL_OVERRIDE)
216
+ jobmanager.run()
217
+
218
+ # confirm the correctness of jobmanager.log.
219
+ jobmanager_log_contents = $test_syslog_logger.string()
220
+
221
+ print "\nJob Manager Log Contents #3:\n"
222
+ print jobmanager_log_contents, "\n"
223
+
224
+ lines = jobmanager_log_contents.split("\n")
225
+ assert_match(/^ERROR \[janet, cat\] Failed! - exited normally with exit code:/, jobmanager_log_contents)
226
+ lines.each { |line| assert_no_match(/Exited successfully/, line) }
227
+
228
+ # confirm the email generated is correct.
229
+ deliveries = ActionMailer::Base.deliveries
230
+ assert_equal(1, deliveries.length)
231
+
232
+ delivery = deliveries[0]
233
+
234
+ assert_equal("jobmanager results for cat : Failure", delivery.subject)
235
+ assert_match(/^ERROR \[#{USER_NAME}, cat\] Failed! - exited normally with exit code:/,
236
+ delivery.body)
237
+
238
+ end
239
+
240
+ #
241
+ # Test the following error cases:
242
+ # 1) The central log file can't be created/opened.
243
+ # 2) The email results file can't be created/opened.
244
+ # 3) The job logs directory can't be created.
245
+ # 4) The job logs directory exists but is permissioned such that a file can't be created inside.
246
+ #
247
+ def test_jobmanager_exceptions()
248
+ jobmanager_exception_bad_central_log_file()
249
+ teardown(); setup();
250
+
251
+ jobmanager_exception_bad_email_settings_file()
252
+ teardown(); setup();
253
+
254
+ jobmanager_exception_bad_job_logs_directory_1()
255
+ teardown(); setup();
256
+
257
+ jobmanager_exception_bad_job_logs_directory_2()
258
+
259
+ end
260
+
261
+ # In this test case, the job logs directory can't be created.
262
+ # Test that the error is properly raised, logged, and emailed.
263
+ def jobmanager_exception_bad_job_logs_directory_1()
264
+
265
+ # Permission the directory so that the central log file can't be created inside this directory.
266
+ FileUtils.mkdir_p("#{TEMP_DIR}/permissioned_directory")
267
+ FileUtils.chmod(0000, "#{TEMP_DIR}/permissioned_directory")
268
+
269
+ config_file = File.join(CONFIG_DIR, "jobmanager_4_bad_job_logs_directory_1.yaml")
270
+
271
+ assert_raise_message("Error creating job_logs_directory", JobManager::Application::ComposedError) do
272
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
273
+ args = [ "ls" ],
274
+ config_file,
275
+ INTERACTIVE_SHELL_OVERRIDE)
276
+
277
+ jobmanager.run()
278
+ end
279
+
280
+ # return the permissions
281
+ FileUtils.chmod(0755, "#{TEMP_DIR}/permissioned_directory")
282
+
283
+ # confirm nothing was written via syslog.
284
+ assert_equal("", $test_syslog_logger.string())
285
+
286
+ jobmanager_log_contents = File.read("temp/logs/jobmanager.log")
287
+
288
+ print "\nJob Manager Log Contents #4 (jobmanager_4_bad_job_logs_directory_1.yaml):\n"
289
+ print jobmanager_log_contents, "\n"
290
+
291
+ lines = jobmanager_log_contents.split("\n")
292
+ assert_match(/^E, .* : \[#{USER_NAME}, ls\] Error creating job_logs_directory: Error \(Errno::EACCES\): Permission denied - temp\/permissioned_directory\/job_logs_directory/,
293
+ lines[0])
294
+
295
+ # confirm the email generated is correct.
296
+ deliveries = ActionMailer::Base.deliveries
297
+ assert_equal(1, deliveries.length)
298
+
299
+ delivery = deliveries[0]
300
+
301
+ assert_equal("jobmanager results for ls on #{HOST_NAME} : Failure", delivery.subject)
302
+ assert_match(/^E, .* : \[#{USER_NAME}, ls\] Error creating job_logs_directory: Error \(Errno::EACCES\): Permission denied - temp\/permissioned_directory\/job_logs_directory/,
303
+ delivery.body)
304
+
305
+ end
306
+
307
+
308
+ # In this test case, the job logs directory exists but permissions prevent a job log from being created.
309
+ # Test that the error is properly raised, logged, and emailed.
310
+ def jobmanager_exception_bad_job_logs_directory_2()
311
+
312
+ # Permission the directory so that the central log file can't be created inside this directory.
313
+ FileUtils.mkdir_p("#{TEMP_DIR}/permissioned_directory")
314
+ FileUtils.chmod(0000, "#{TEMP_DIR}/permissioned_directory")
315
+
316
+ config_file = File.join(CONFIG_DIR, "jobmanager_4_bad_job_logs_directory_2.yaml")
317
+
318
+ assert_raise_message("Error opening job log file", JobManager::Application::ComposedError) do
319
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
320
+ args = [ "ls" ],
321
+ config_file,
322
+ INTERACTIVE_SHELL_OVERRIDE)
323
+
324
+ jobmanager.run()
325
+ end
326
+
327
+ # return the permissions
328
+ FileUtils.chmod(0755, "#{TEMP_DIR}/permissioned_directory")
329
+
330
+ # confirm nothing was written via syslog.
331
+ assert_equal("", $test_syslog_logger.string())
332
+
333
+ jobmanager_log_contents = File.read("temp/logs/jobmanager.log")
334
+
335
+ print "\nJob Manager Log Contents #4 (jobmanager_4_bad_job_logs_directory_2.yaml):\n"
336
+ print jobmanager_log_contents, "\n"
337
+
338
+ lines = jobmanager_log_contents.split("\n")
339
+ assert_match(/^E, .* : \[#{USER_NAME}, ls\] Error opening job log file: Error \(Errno::EACCES\): Permission denied - temp\/permissioned_directory\/ls\.log/,
340
+ lines[0])
341
+
342
+ # confirm the email generated is correct.
343
+ deliveries = ActionMailer::Base.deliveries
344
+ assert_equal(1, deliveries.length)
345
+
346
+ delivery = deliveries[0]
347
+
348
+ assert_equal("jobmanager results for ls on #{HOST_NAME} : Failure", delivery.subject)
349
+ assert_match(/^E, .* : \[#{USER_NAME}, ls\] Error opening job log file: Error \(Errno::EACCES\): Permission denied - temp\/permissioned_directory\/ls\.log/,
350
+ delivery.body)
351
+
352
+ end
353
+
354
+
355
+ # In this test case, the email settings file can't be opened.
356
+ # Test that the error is properly raised, logged, and not emailed.
357
+ def jobmanager_exception_bad_email_settings_file()
358
+
359
+ # Permission the directory so that the central log file can't be
360
+ # created inside this directory.
361
+ FileUtils.mkdir_p("#{TEMP_DIR}/permissioned_directory")
362
+ FileUtils.chmod(0000, "#{TEMP_DIR}/permissioned_directory")
363
+
364
+ config_file = File.join(CONFIG_DIR, "jobmanager_4_bad_email_settings_file.yaml")
365
+
366
+ assert(JobManager::System.which("cat"))
367
+
368
+ assert_raise_message("email_settings_file (/no_directory/no_file.rb) does not exist or is not readable.\n", JobManager::Application::Error) do
369
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
370
+ args = [ "ls" ],
371
+ config_file,
372
+ INTERACTIVE_SHELL_OVERRIDE)
373
+
374
+ jobmanager.run()
375
+ end
376
+
377
+ # return the permissions
378
+ FileUtils.chmod(0755, "#{TEMP_DIR}/permissioned_directory")
379
+
380
+ # confirm correctness of syslog.
381
+ jobmanager_log_contents = $test_syslog_logger.string()
382
+
383
+ print "\nJob Manager Log Contents #4 (jobmanager_4_bad_email_settings_file.yaml):\n"
384
+ print jobmanager_log_contents, "\n"
385
+
386
+ lines = jobmanager_log_contents.split("\n")
387
+ assert_equal("ERROR [janet, UNKNOWN] email_settings_file (/no_directory/no_file.rb) does not exist or is not readable.",
388
+ lines[0])
389
+
390
+ # confirm no email was generated.
391
+ deliveries = ActionMailer::Base.deliveries
392
+ assert_equal(0, deliveries.length)
393
+ end
394
+
395
+ # In this test case, the central log file can't be opened/created.
396
+ # Test that the error is properly raised, logged, and emailed.
397
+ def jobmanager_exception_bad_central_log_file()
398
+
399
+ # Permission the directory so that the central log file can't be created inside this directory.
400
+ FileUtils.mkdir_p("#{TEMP_DIR}/permissioned_directory")
401
+ FileUtils.chmod(0000, "#{TEMP_DIR}/permissioned_directory")
402
+
403
+ config_file = File.join(CONFIG_DIR, "jobmanager_4_bad_central_log_file.yaml")
404
+
405
+ assert_raise_message("Error Initializing Central Log",
406
+ JobManager::Application::ComposedError) do
407
+ jobmanager = JobManager::Application.new(PROGRAM_NAME,
408
+ args = [ "ls" ],
409
+ config_file,
410
+ INTERACTIVE_SHELL_OVERRIDE)
411
+
412
+ jobmanager.run()
413
+ end
414
+
415
+ # return the permissions
416
+ FileUtils.chmod(0755, "#{TEMP_DIR}/permissioned_directory")
417
+
418
+ # confirm correctness of syslog.
419
+ jobmanager_log_contents = $test_syslog_logger.string()
420
+
421
+ print "\nJob Manager Log Contents #4 (jobmanager_4_bad_central_log_file.yaml):\n"
422
+ print jobmanager_log_contents, "\n"
423
+
424
+ lines = jobmanager_log_contents.split("\n")
425
+ assert_equal("ERROR [#{USER_NAME}, UNKNOWN] Error Initializing Central Log: Error (Errno::EACCES): Permission denied - temp/permissioned_directory/jobmanager.log",
426
+ lines[0])
427
+
428
+ # confirm the email generated is correct.
429
+ deliveries = ActionMailer::Base.deliveries
430
+ assert_equal(1, deliveries.length)
431
+
432
+ delivery = deliveries[0]
433
+
434
+ assert_equal("jobmanager results for ls on #{HOST_NAME} : Failure", delivery.subject)
435
+ assert_match(/ERROR \[#{USER_NAME}, UNKNOWN\] Error Initializing Central Log: Error \(Errno::EACCES\): Permission denied - temp\/permissioned_directory\/jobmanager.log/,
436
+ delivery.body)
437
+
438
+ end
439
+
440
+ end
441
+
442
+
443
+
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'stringio'
4
+ require 'fileutils'
5
+
6
+ require 'rubygems'
7
+ require 'relative'
8
+
9
+ require 'test/unit'
10
+ require_relative('helpers')
11
+ require_relative('mock_syslog')
12
+
13
+ require 'jobmanager/system'
14
+ require 'jobmanager/applicationlogger'
15
+
16
+ #
17
+ # This class tests the JobManager::System module.
18
+ #
19
+
20
+ class TestSystem < Test::Unit::TestCase
21
+ include TestHelpers
22
+
23
+ SAMPLE_DIR = "#{TEMP_DIR}/samples"
24
+
25
+ SAMPLE_FILE = File.join(SAMPLE_DIR, "sample.dat")
26
+ EXPECTED_SAMPLE_CONTENTS = (1..10000).map { "This is a sample file." }.join("\n")
27
+
28
+ USER_NAME = Etc.getpwuid(Process::Sys.getuid()).name()
29
+
30
+ def setup
31
+ teardown()
32
+
33
+ FileUtils.mkdir_p(TEMP_DIR)
34
+ FileUtils.mkdir_p(SAMPLE_DIR)
35
+
36
+ File.open(SAMPLE_FILE, "w") do |file_stream|
37
+ file_stream << EXPECTED_SAMPLE_CONTENTS
38
+ end
39
+ end
40
+
41
+ def teardown
42
+ FileUtils::rm_r(TEMP_DIR, :force => true)
43
+ end
44
+
45
+ # Command w/ relative path (cat) - success
46
+ def test_simple_cat_success
47
+ command = "cat #{SAMPLE_FILE}"
48
+ run_simple_cat(command)
49
+ end
50
+
51
+ # Command w/ absolute path (eg. /bin/cat) - success
52
+ def test_absolute_path_command_success
53
+ exe = JobManager::System.which("cat")
54
+ command = "#{exe} #{SAMPLE_FILE}"
55
+
56
+ run_simple_cat(command)
57
+ end
58
+
59
+ # Command (cat) w/ large timeout - success
60
+ def test_simple_cat_with_timeout_success
61
+ command = "cat #{SAMPLE_FILE}"
62
+ optional_args = { :timeout => 100 }
63
+
64
+ run_simple_cat(command)
65
+ end
66
+
67
+ # Command w/ relative path (cat) - options (good path)
68
+ def test_simple_cat_with_environment_path_specified_success
69
+ exe = JobManager::System.which("cat")
70
+ path = exe.split()[0]
71
+
72
+ command = "#{exe} #{SAMPLE_FILE}"
73
+ optional_args = { :command_path => path }
74
+
75
+ run_simple_cat(command)
76
+ end
77
+
78
+ def create_logger(job_name)
79
+ return JobManager::ApplicationSyslogLogger.new("job_manager",
80
+ USER_NAME,
81
+ job_name)
82
+ end
83
+
84
+ # Command (cat) - cat nonexistent file
85
+ def test_simple_cat__failure
86
+ command = "cat #{SAMPLE_DIR}/no_file.dat"
87
+ job = "catter"
88
+ log_stream = StringIO.new
89
+ logger = create_logger(job)
90
+ success = JobManager::System.invoke_command(command,
91
+ log_stream,
92
+ logger)
93
+
94
+ logger.close
95
+
96
+ control_log_lines = logger.string.split("\n")
97
+ print "\n", control_log_lines.join("\n"), "\n"
98
+
99
+ assert_equal(false, success)
100
+
101
+ assert_match(/ERROR \[#{USER_NAME}, catter\] Failed! - exited normally with exit code:/,
102
+ control_log_lines[-1])
103
+ end
104
+
105
+ # Command (cat) - options (bad path)
106
+ def test_simple_cat_with_environment_path_specified_failure
107
+ command = "cat #{SAMPLE_FILE}"
108
+ job = "catter"
109
+ log_stream = StringIO.new
110
+ logger = create_logger(job)
111
+ optional_args = { :command_path => "/bad_directory_1:/bad_directory_2" }
112
+
113
+ success = JobManager::System.invoke_command(command,
114
+ log_stream,
115
+ logger,
116
+ optional_args)
117
+
118
+ logger.close
119
+
120
+ control_log_lines = logger.string.split("\n")
121
+ print "\n", control_log_lines.join("\n"), "\n"
122
+
123
+ assert_equal(false, success)
124
+ assert_equal("", log_stream.string())
125
+
126
+ assert_match(/ERROR \[#{USER_NAME}, catter\] File cat does not exist in path .* or is not executable!/,
127
+ control_log_lines[-1])
128
+ end
129
+
130
+ def run_simple_cat(command, optional_args = {})
131
+ job = "catter"
132
+ log_stream = StringIO.new
133
+ logger = create_logger(job)
134
+
135
+ success = JobManager::System.invoke_command(command,
136
+ log_stream,
137
+ logger,
138
+ optional_args)
139
+
140
+ logger.close
141
+
142
+ control_log_lines = logger.string.split("\n")
143
+ print "\n", control_log_lines.join("\n"), "\n"
144
+
145
+ assert_equal(true, success)
146
+ assert_equal(EXPECTED_SAMPLE_CONTENTS, log_stream.string())
147
+
148
+ assert_match(/INFO \[#{USER_NAME}, catter\] Exited successfully/,
149
+ control_log_lines[-1])
150
+ end
151
+
152
+ # Launch a sleep command w/ a timeout shorter than the sleep time.
153
+ def test_sleep_past_timeout
154
+ command = "sleep 100"
155
+ job = "catter"
156
+ log_stream = StringIO.new
157
+ logger = create_logger(job)
158
+ optional_args = { :timeout => 1 }
159
+
160
+ success = JobManager::System.invoke_command(command,
161
+ log_stream,
162
+ logger,
163
+ optional_args)
164
+
165
+ logger.close
166
+
167
+ control_log_lines = logger.string.split("\n")
168
+ print "\n", control_log_lines.join("\n"), "\n"
169
+
170
+ # verify that the sleep process has been timed out!
171
+ assert_equal(false, success)
172
+
173
+ assert_match(/ERROR \[#{USER_NAME}, catter\] Timed out after 1 seconds./,
174
+ control_log_lines[-3])
175
+ end
176
+
177
+ # Test whether the invoke_command properly recognizes when the process that has been
178
+ # forked has died due to a signal.
179
+ def test_sleep_and_kill
180
+ job_pid = nil
181
+
182
+ command = "sleep 1000"
183
+ job = "catter"
184
+ log_stream = StringIO.new
185
+ logger = create_logger(job)
186
+ optional_args = { :timeout => 100 }
187
+
188
+ success = JobManager::System.invoke_command(command,
189
+ log_stream,
190
+ logger,
191
+ optional_args) do |job_pid|
192
+ Process.kill("TERM", job_pid)
193
+ end
194
+
195
+ logger.close
196
+
197
+ control_log_lines = logger.string.split("\n")
198
+ print "\n", control_log_lines.join("\n"), "\n"
199
+
200
+ assert_equal(false, success)
201
+
202
+ assert_match(/ERROR \[#{USER_NAME}, catter\] Failed! - exited abnormally due to signal:/,
203
+ control_log_lines[-1])
204
+ end
205
+ end
206
+