job_unittest.py revision e39c3c0dbe16caed55f4538af78dbf057deb7fad
1#!/usr/bin/python 2 3import os, unittest, shutil, sys, time 4import common 5 6from autotest_lib.client.bin import job, boottool, config, sysinfo, harness 7from autotest_lib.client.bin import test, xen, kernel, autotest_utils, cpuset 8from autotest_lib.client.bin import autotest_utils 9from autotest_lib.client.common_lib import packages, utils, error, log 10from autotest_lib.client.common_lib.test_utils import mock 11 12 13class first_line_comparator(mock.argument_comparator): 14 def __init__(self, first_line): 15 self.first_line = first_line 16 17 18 def is_satisfied_by(self, parameter): 19 return self.first_line == parameter.splitlines()[0] 20 21 22class TestBaseJob(unittest.TestCase): 23 def setUp(self): 24 # make god 25 self.god = mock.mock_god() 26 27 # need to set some environ variables 28 self.autodir = "autodir" 29 os.environ['AUTODIR'] = self.autodir 30 31 # set up some variables 32 self.control = "control" 33 self.jobtag = "jobtag" 34 35 # stub out some stuff 36 self.god.stub_function(os.path, 'exists') 37 self.god.stub_function(os.path, 'isdir') 38 self.god.stub_function(os, 'mkdir') 39 self.god.stub_function(shutil, 'copyfile') 40 self.god.stub_function(job, 'open') 41 self.god.stub_function(utils, 'system') 42 self.god.stub_function(autotest_utils, 'drop_caches') 43 self.god.stub_function(harness, 'select') 44 self.god.stub_function(sysinfo, 'log_per_reboot_data') 45 46 self.god.stub_class(config, 'config') 47 self.god.stub_class(boottool, 'boottool') 48 self.god.stub_class(sysinfo, 'sysinfo') 49 50 51 def tearDown(self): 52 self.god.unstub_all() 53 54 55 def construct_job(self, cont): 56 # will construct class instance using __new__ 57 self.job = job.base_job.__new__(job.base_job) 58 59 # now some specific stubs 60 self.god.stub_function(self.job, '_load_state') 61 self.god.stub_function(self.job, '_init_group_level') 62 self.god.stub_function(self.job, 'config_get') 63 self.god.stub_function(self.job, 'record') 64 self.god.stub_function(self.job, '_increment_group_level') 65 self.god.stub_function(self.job, '_decrement_group_level') 66 self.god.stub_function(self.job, 'get_state') 67 68 # other setup 69 tmpdir = os.path.join(self.autodir, 'tmp') 70 results = os.path.join(self.autodir, 'results') 71 download = os.path.join(self.autodir, 'tests', 'download') 72 resultdir = os.path.join(self.autodir, 'results', self.jobtag) 73 pkgdir = os.path.join(self.autodir, 'packages') 74 75 # record 76 autotest_utils.drop_caches.expect_call() 77 self.job._load_state.expect_call() 78 self.job.get_state.expect_call("__run_test_cleanup", 79 default=True).and_return(True) 80 job_sysinfo = sysinfo.sysinfo.expect_new(resultdir) 81 self.job.get_state.expect_call("__sysinfo", 82 None).and_return(None) 83 self.job.get_state.expect_call("__last_boot_tag", 84 default=None).and_return(None) 85 if not cont: 86 os.path.exists.expect_call(tmpdir).and_return(False) 87 os.mkdir.expect_call(tmpdir) 88 os.path.exists.expect_call(pkgdir).and_return(False) 89 os.mkdir.expect_call(pkgdir) 90 os.path.exists.expect_call(results).and_return(False) 91 os.mkdir.expect_call(results) 92 os.path.exists.expect_call(download).and_return(False) 93 os.mkdir.expect_call(download) 94 os.path.exists.expect_call(resultdir).and_return(True) 95 utils.system.expect_call('rm -rf ' + resultdir) 96 os.mkdir.expect_call(resultdir) 97 os.mkdir.expect_call(os.path.join(resultdir, 'debug')) 98 os.mkdir.expect_call(os.path.join(resultdir, 99 'analysis')) 100 shutil.copyfile.expect_call(mock.is_string_comparator(), 101 os.path.join(resultdir, 'control')) 102 103 self.job._init_group_level.expect_call() 104 self.config = config.config.expect_new(self.job) 105 my_harness = self.god.create_mock_class(harness.harness, 106 'my_harness') 107 harness.select.expect_call(None, 108 self.job).and_return(my_harness) 109 self.job.config_get.expect_call( 110 'boottool.executable').and_return(None) 111 bootloader = boottool.boottool.expect_new(None) 112 job_sysinfo.log_per_reboot_data.expect_call() 113 if not cont: 114 self.job.record.expect_call('START', None, None) 115 self.job._increment_group_level.expect_call() 116 117 my_harness.run_start.expect_call() 118 self.job.get_state.expect_call('__monitor_disk', 119 default=0.0).and_return(0.0) 120 121 # finish constructor 122 self.job.__init__(self.control, self.jobtag, cont) 123 124 # check 125 self.god.check_playback() 126 127 128 def test_constructor(self): 129 self.construct_job(False) 130 131 132 def test_monitor_disk_usage(self): 133 self.construct_job(True) 134 135 # setup 136 self.god.stub_function(self.job, 'set_state') 137 138 # record 139 max_rate = 10.0 140 self.job.set_state.expect_call('__monitor_disk', max_rate) 141 142 # test 143 self.job.monitor_disk_usage(max_rate) 144 self.god.check_playback() 145 146 147 def test_relative_path(self): 148 self.construct_job(True) 149 dummy = "asdf" 150 ret = self.job.relative_path(os.path.join(self.job.resultdir, dummy)) 151 self.assertEquals(ret, dummy) 152 153 154 def test_control_functions(self): 155 self.construct_job(True) 156 control_file = "blah" 157 self.job.control_set(control_file) 158 self.assertEquals(self.job.control_get(), os.path.abspath(control_file)) 159 160 161 def test_harness_select(self): 162 self.construct_job(True) 163 164 # record 165 which = "which" 166 harness.select.expect_call(which, self.job).and_return(None) 167 168 # run and test 169 self.job.harness_select(which) 170 self.god.check_playback() 171 172 173 def test_config_set(self): 174 self.construct_job(True) 175 176 # record 177 name = "foo" 178 val = 10 179 self.config.set.expect_call(name, val) 180 181 # run and test 182 self.job.config_set(name, val) 183 self.god.check_playback() 184 185 186 def test_config_get(self): 187 self.construct_job(True) 188 189 # unstub config_get 190 self.god.unstub(self.job, 'config_get') 191 # record 192 name = "foo" 193 val = 10 194 self.config.get.expect_call(name).and_return(val) 195 196 # run and test 197 self.job.config_get(name) 198 self.god.check_playback() 199 200 201 def test_setup_dirs_raise(self): 202 self.construct_job(True) 203 204 # setup 205 results_dir = 'foo' 206 tmp_dir = 'bar' 207 208 # record 209 os.path.exists.expect_call(tmp_dir).and_return(True) 210 os.path.isdir.expect_call(tmp_dir).and_return(False) 211 212 # test 213 self.assertRaises(ValueError, self.job.setup_dirs, results_dir, tmp_dir) 214 self.god.check_playback() 215 216 217 def test_setup_dirs(self): 218 self.construct_job(True) 219 220 # setup 221 results_dir1 = os.path.join(self.job.resultdir, 'build') 222 results_dir2 = os.path.join(self.job.resultdir, 'build.2') 223 results_dir3 = os.path.join(self.job.resultdir, 'build.3') 224 tmp_dir = 'bar' 225 226 # record 227 os.path.exists.expect_call(tmp_dir).and_return(False) 228 os.mkdir.expect_call(tmp_dir) 229 os.path.isdir.expect_call(tmp_dir).and_return(True) 230 os.path.exists.expect_call(results_dir1).and_return(True) 231 os.path.exists.expect_call(results_dir2).and_return(True) 232 os.path.exists.expect_call(results_dir3).and_return(False) 233 os.path.exists.expect_call(results_dir3).and_return(False) 234 os.mkdir.expect_call(results_dir3) 235 236 # test 237 self.assertEqual(self.job.setup_dirs(None, tmp_dir), 238 (results_dir3, tmp_dir)) 239 self.god.check_playback() 240 241 242 def test_xen(self): 243 self.construct_job(True) 244 245 # setup 246 self.god.stub_function(self.job, "setup_dirs") 247 self.god.stub_class(xen, "xen") 248 results = 'results_dir' 249 tmp = 'tmp' 250 build = 'xen' 251 base_tree = object() 252 253 # record 254 self.job.setup_dirs.expect_call(results, 255 tmp).and_return((results, tmp)) 256 myxen = xen.xen.expect_new(self.job, base_tree, results, tmp, build, 257 False, None) 258 259 # run job and check 260 axen = self.job.xen(base_tree, results, tmp) 261 self.god.check_playback() 262 self.assertEquals(myxen, axen) 263 264 265 def test_kernel_rpm(self): 266 self.construct_job(True) 267 268 # setup 269 self.god.stub_function(self.job, "setup_dirs") 270 self.god.stub_class(kernel, "rpm_kernel") 271 self.god.stub_function(kernel, "preprocess_path") 272 self.god.stub_function(self.job.pkgmgr, "fetch_pkg") 273 results = 'results_dir' 274 tmp = 'tmp' 275 build = 'xen' 276 path = "somepath.rpm" 277 packages_dir = os.path.join("autodir/packages", path) 278 279 # record 280 self.job.setup_dirs.expect_call(results, 281 tmp).and_return((results, tmp)) 282 kernel.preprocess_path.expect_call(path).and_return(path) 283 self.job.pkgmgr.fetch_pkg.expect_call(path, packages_dir, repo_url='') 284 mykernel = kernel.rpm_kernel.expect_new(self.job, packages_dir, 285 results) 286 287 # check 288 akernel = self.job.kernel(path, results, tmp) 289 self.god.check_playback() 290 self.assertEquals(mykernel, akernel) 291 292 293 def test_kernel(self): 294 self.construct_job(True) 295 296 # setup 297 self.god.stub_function(self.job, "setup_dirs") 298 self.god.stub_class(kernel, "kernel") 299 self.god.stub_function(kernel, "preprocess_path") 300 results = 'results_dir' 301 tmp = 'tmp' 302 build = 'linux' 303 path = "somepath.deb" 304 305 # record 306 self.job.setup_dirs.expect_call(results, 307 tmp).and_return((results, tmp)) 308 kernel.preprocess_path.expect_call(path).and_return(path) 309 mykernel = kernel.kernel.expect_new(self.job, path, results, tmp, 310 build, False) 311 312 # check 313 akernel = self.job.kernel(path, results, tmp) 314 self.god.check_playback() 315 self.assertEquals(mykernel, akernel) 316 317 318 def test_run_test_logs_test_error_from_unhandled_error(self): 319 self.construct_job(True) 320 321 # set up stubs 322 self.god.stub_function(self.job.pkgmgr, 'get_package_name') 323 self.god.stub_function(self.job, "_runtest") 324 325 # create an unhandled error object 326 class MyError(error.TestError): 327 pass 328 real_error = MyError("this is the real error message") 329 unhandled_error = error.UnhandledTestError(real_error) 330 331 # set up the recording 332 testname = "error_test" 333 outputdir = os.path.join(self.job.resultdir, testname) 334 self.job.pkgmgr.get_package_name.expect_call( 335 testname, 'test').and_return(("", testname)) 336 self.job.get_state.expect_call( 337 self.job._RUN_NUMBER_STATE, default=0).and_return(0) 338 self.job.get_state.expect_call( 339 self.job._KERNEL_IN_TAG_STATE, default=False).and_return(False) 340 os.path.exists.expect_call(outputdir).and_return(False) 341 os.mkdir.expect_call(outputdir) 342 self.job.record.expect_call("START", testname, testname) 343 self.job._increment_group_level.expect_call() 344 self.job._runtest.expect_call(testname, "", (), {}).and_raises( 345 unhandled_error) 346 self.job.record.expect_call("ERROR", testname, testname, 347 first_line_comparator(str(real_error))) 348 self.job._decrement_group_level.expect_call() 349 self.job.record.expect_call("END ERROR", testname, testname, 350 first_line_comparator(str(real_error))) 351 self.job.harness.run_test_complete.expect_call() 352 autotest_utils.drop_caches.expect_call() 353 354 # run and check 355 self.job.run_test(testname) 356 self.god.check_playback() 357 358 359 def test_run_test_logs_non_test_error_from_unhandled_error(self): 360 self.construct_job(True) 361 362 # set up stubs 363 self.god.stub_function(self.job.pkgmgr, 'get_package_name') 364 self.god.stub_function(self.job, "_runtest") 365 366 # create an unhandled error object 367 class MyError(Exception): 368 pass 369 real_error = MyError("this is the real error message") 370 unhandled_error = error.UnhandledTestError(real_error) 371 reason = first_line_comparator("Unhandled MyError: %s" % real_error) 372 373 # set up the recording 374 testname = "error_test" 375 outputdir = os.path.join(self.job.resultdir, testname) 376 self.job.pkgmgr.get_package_name.expect_call( 377 testname, 'test').and_return(("", testname)) 378 self.job.get_state.expect_call( 379 self.job._RUN_NUMBER_STATE, default=0).and_return(0) 380 self.job.get_state.expect_call( 381 self.job._KERNEL_IN_TAG_STATE, default=False).and_return(False) 382 os.path.exists.expect_call(outputdir).and_return(False) 383 os.mkdir.expect_call(outputdir) 384 self.job.record.expect_call("START", testname, testname) 385 self.job._increment_group_level.expect_call() 386 self.job._runtest.expect_call(testname, "", (), {}).and_raises( 387 unhandled_error) 388 self.job.record.expect_call("ERROR", testname, testname, reason) 389 self.job._decrement_group_level.expect_call() 390 self.job.record.expect_call("END ERROR", testname, testname, reason) 391 self.job.harness.run_test_complete.expect_call() 392 autotest_utils.drop_caches.expect_call() 393 394 # run and check 395 self.job.run_test(testname) 396 self.god.check_playback() 397 398 399 def new_container(self): 400 self.construct_job(True) 401 402 # set up stubs 403 self.god.stub_function(autotest_utils, "grep") 404 self.god.stub_function(os, "getpid") 405 self.god.stub_class(cpuset, "cpuset") 406 pid = 100 407 name = 'test%d' % pid 408 409 # record 410 autotest_utils.grep.expect_call('cpuset', 411 '/proc/filesystems').and_return(True) 412 os.getpid.expect_call().and_return(pid) 413 414 container = cpuset.cpuset.expect_new(name, job_size=None, job_pid=pid, 415 cpus=None, root=None, disk=None, 416 network=None, kswapd_merge=False) 417 418 # run test 419 self.job.new_container() 420 421 self.god.check_playback() 422 return container 423 424 425 def test_new_container(self): 426 container = self.new_container() 427 self.assertEquals(self.job.container, container) 428 429 430 def test_release_container(self): 431 self.new_container() 432 433 # record 434 self.job.container.release.expect_call() 435 436 # run 437 self.job.release_container() 438 self.god.check_playback() 439 self.assertEquals(self.job.container, None) 440 441 442 def test_record(self): 443 self.construct_job(True) 444 445 # steup 446 self.job.group_level = 1 447 status = '' 448 status_code = "PASS" 449 subdir = "subdir" 450 operation = "super_fun" 451 mytime = "1234" 452 msg_tag = "" 453 if "." in self.job.log_filename: 454 msg_tag = self.job.log_filename.split(".", 1)[1] 455 epoch_time = int(mytime) 456 local_time = time.localtime(epoch_time) 457 optional_fields = {} 458 optional_fields["timestamp"] = str(epoch_time) 459 optional_fields["localtime"] = time.strftime("%b %d %H:%M:%S", 460 local_time) 461 fields = [status_code, subdir, operation] 462 fields += ["%s=%s" % x for x in optional_fields.iteritems()] 463 fields.append(status) 464 msg = '\t'.join(str(x) for x in fields) 465 msg = '\t' * self.job.group_level + msg 466 467 self.god.stub_function(log, "is_valid_status") 468 self.god.stub_function(time, "time") 469 self.god.stub_function(self.job, "open") 470 471 472 # record 473 log.is_valid_status.expect_call(status_code).and_return(True) 474 time.time.expect_call().and_return(mytime) 475 self.job.harness.test_status_detail.expect_call(status_code, subdir, 476 operation, '', msg_tag) 477 self.job.harness.test_status.expect_call(msg, msg_tag) 478 myfile = self.god.create_mock_class(file, "file") 479 status_file = os.path.join(self.job.resultdir, self.job.log_filename) 480 self.job.open.expect_call(status_file, "a").and_return(myfile) 481 myfile.write.expect_call(msg + "\n") 482 483 dir = os.path.join(self.job.resultdir, subdir) 484 status_file = os.path.join(dir, self.job.DEFAULT_LOG_FILENAME) 485 self.job.open.expect_call(status_file, "a").and_return(myfile) 486 myfile.write.expect_call(msg + "\n") 487 488 489 # run test 490 self.god.unstub(self.job, "record") 491 self.job.record(status_code, subdir, operation) 492 self.god.check_playback() 493 494 495 def test_end_boot(self): 496 self.construct_job(True) 497 498 # set up the job class 499 self.job.group_level = 2 500 501 self.job._decrement_group_level.expect_call() 502 self.job.record.expect_call("END GOOD", "sub", "reboot", 503 optional_fields={"kernel": "2.6.15-smp", 504 "patch0": "patchname"}) 505 506 # run test 507 self.job.end_reboot("sub", "2.6.15-smp", ["patchname"]) 508 self.god.check_playback() 509 510 511 def test_end_boot_and_verify_success(self): 512 self.construct_job(True) 513 514 # set up the job class 515 self.job.group_level = 2 516 517 self.god.stub_function(autotest_utils, "running_os_ident") 518 autotest_utils.running_os_ident.expect_call().and_return("2.6.15-smp") 519 520 self.god.stub_function(utils, "read_one_line") 521 utils.read_one_line.expect_call("/proc/cmdline").and_return( 522 "blah more-blah root=lala IDENT=81234567 blah-again") 523 524 self.job.record.expect_call("GOOD", "sub", "reboot.verify", 525 "2.6.15-smp") 526 self.job._decrement_group_level.expect_call() 527 self.job.record.expect_call("END GOOD", "sub", "reboot", 528 optional_fields={"kernel": "2.6.15-smp"}) 529 530 # run test 531 self.job.end_reboot_and_verify(81234567, "2.6.15-smp", "sub") 532 self.god.check_playback() 533 534 535 def test_end_boot_and_verify_failure(self): 536 self.construct_job(True) 537 538 # set up the job class 539 self.job.group_level = 2 540 541 self.god.stub_function(autotest_utils, "running_os_ident") 542 autotest_utils.running_os_ident.expect_call().and_return("2.6.15-smp") 543 544 self.god.stub_function(utils, "read_one_line") 545 utils.read_one_line.expect_call("/proc/cmdline").and_return( 546 "blah more-blah root=lala IDENT=81234567 blah-again") 547 548 self.job.record.expect_call("ABORT", "sub", "reboot.verify", 549 "boot failure") 550 self.job._decrement_group_level.expect_call() 551 self.job.record.expect_call("END ABORT", "sub", "reboot", 552 optional_fields={"kernel": "2.6.15-smp"}) 553 554 # run test 555 self.assertRaises(error.JobError, self.job.end_reboot_and_verify, 556 91234567, "2.6.16-smp", "sub") 557 self.god.check_playback() 558 559 560if __name__ == "__main__": 561 unittest.main() 562