job_unittest.py revision a536dbfc5e5a92a32520d31f856db8f4df4980d0
1#!/usr/bin/python 2 3import logging, os, unittest, shutil, sys, time, StringIO 4import common 5 6from autotest_lib.client.bin import job, boottool, config, sysinfo, harness 7from autotest_lib.client.bin import test, xen, kernel, utils 8from autotest_lib.client.common_lib import packages, error, log, logging_manager 9from autotest_lib.client.common_lib import logging_config 10from autotest_lib.client.common_lib.test_utils import mock 11 12 13class Dummy(object): 14 """A simple placeholder for attributes""" 15 pass 16 17 18class first_line_comparator(mock.argument_comparator): 19 def __init__(self, first_line): 20 self.first_line = first_line 21 22 23 def is_satisfied_by(self, parameter): 24 return self.first_line == parameter.splitlines()[0] 25 26 27class TestBaseJob(unittest.TestCase): 28 def setUp(self): 29 # make god 30 self.god = mock.mock_god() 31 32 # need to set some environ variables 33 self.autodir = "autodir" 34 os.environ['AUTODIR'] = self.autodir 35 36 # set up some variables 37 self.control = "control" 38 self.jobtag = "jobtag" 39 40 # get rid of stdout and logging 41 sys.stdout = StringIO.StringIO() 42 logging_manager.configure_logging(logging_config.TestingConfig()) 43 logging.disable(logging.CRITICAL) 44 def dummy_configure_logging(*args, **kwargs): 45 pass 46 self.god.stub_with(logging_manager, 'configure_logging', 47 dummy_configure_logging) 48 real_get_logging_manager = logging_manager.get_logging_manager 49 def get_logging_manager_no_fds(manage_stdout_and_stderr=False, 50 redirect_fds=False): 51 return real_get_logging_manager(manage_stdout_and_stderr, False) 52 self.god.stub_with(logging_manager, 'get_logging_manager', 53 get_logging_manager_no_fds) 54 55 # stub out some stuff 56 self.god.stub_function(os.path, 'exists') 57 self.god.stub_function(os.path, 'isdir') 58 self.god.stub_function(os, 'makedirs') 59 self.god.stub_function(os, 'mkdir') 60 self.god.stub_function(os, 'remove') 61 self.god.stub_function(shutil, 'rmtree') 62 self.god.stub_function(shutil, 'copyfile') 63 self.god.stub_function(job, 'open') 64 self.god.stub_function(utils, 'system') 65 self.god.stub_function(utils, 'drop_caches') 66 self.god.stub_function(harness, 'select') 67 self.god.stub_function(sysinfo, 'log_per_reboot_data') 68 69 self.god.stub_class(config, 'config') 70 self.god.stub_class(job.local_host, 'LocalHost') 71 self.god.stub_class(boottool, 'boottool') 72 self.god.stub_class(sysinfo, 'sysinfo') 73 74 self.god.stub_class_method(job.base_job, '_cleanup_results_dir') 75 76 77 def tearDown(self): 78 sys.stdout = sys.__stdout__ 79 self.god.unstub_all() 80 81 82 def _setup_pre_record_init(self, cont): 83 self.god.stub_function(self.job, '_init_group_level') 84 self.god.stub_function(self.job, '_load_state') 85 86 resultdir = os.path.join(self.autodir, 'results', self.jobtag) 87 tmpdir = os.path.join(self.autodir, 'tmp') 88 os.path.exists.expect_call(resultdir).and_return(False) 89 os.makedirs.expect_call(resultdir) 90 if not cont: 91 job.base_job._cleanup_results_dir.expect_call() 92 os.path.exists.expect_call(tmpdir).and_return(False) 93 os.mkdir.expect_call(tmpdir) 94 95 self.job._load_state.expect_call() 96 self.job._init_group_level.expect_call() 97 98 my_harness = self.god.create_mock_class(harness.harness, 99 'my_harness') 100 harness.select.expect_call(None, 101 self.job).and_return(my_harness) 102 103 return resultdir, my_harness 104 105 106 def _setup_post_record_init(self, cont, resultdir, my_harness): 107 # now some specific stubs 108 self.god.stub_function(self.job, 'config_get') 109 self.god.stub_function(self.job, 'config_set') 110 self.god.stub_function(self.job, 'record') 111 self.god.stub_function(self.job, '_increment_group_level') 112 self.god.stub_function(self.job, '_decrement_group_level') 113 self.god.stub_function(self.job, 'get_state') 114 self.god.stub_function(self.job, 'set_state') 115 116 # other setup 117 results = os.path.join(self.autodir, 'results') 118 download = os.path.join(self.autodir, 'tests', 'download') 119 pkgdir = os.path.join(self.autodir, 'packages') 120 121 utils.drop_caches.expect_call() 122 self.job.get_state.expect_call("__run_test_cleanup", 123 default=True).and_return(True) 124 job_sysinfo = sysinfo.sysinfo.expect_new(resultdir) 125 self.job.get_state.expect_call("__sysinfo", 126 None).and_return(None) 127 self.job.get_state.expect_call("__last_boot_tag", 128 default=None).and_return(None) 129 self.job.get_state.expect_call("__job_tag", 130 default=None).and_return('1337-gps') 131 if not cont: 132 os.path.exists.expect_call(pkgdir).and_return(False) 133 os.mkdir.expect_call(pkgdir) 134 os.path.exists.expect_call(results).and_return(False) 135 os.mkdir.expect_call(results) 136 os.path.exists.expect_call(download).and_return(False) 137 os.mkdir.expect_call(download) 138 os.makedirs.expect_call(os.path.join(resultdir, 'analysis')) 139 shutil.copyfile.expect_call(mock.is_string_comparator(), 140 os.path.join(resultdir, 'control')) 141 142 self.config = config.config.expect_new(self.job) 143 job.local_host.LocalHost.expect_new(hostname='localhost') 144 self.job.config_get.expect_call( 145 'boottool.executable').and_return(None) 146 bootloader = boottool.boottool.expect_new(None) 147 job_sysinfo.log_per_reboot_data.expect_call() 148 if not cont: 149 self.job.record.expect_call('START', None, None) 150 self.job._increment_group_level.expect_call() 151 152 my_harness.run_start.expect_call() 153 self.job.get_state.expect_call('__monitor_disk', 154 default=0.0).and_return(0.0) 155 156 self.god.stub_function(utils, 'read_one_line') 157 utils.read_one_line.expect_call('/proc/cmdline').and_return( 158 'blah more-blah root=lala IDENT=81234567 blah-again console=tty1') 159 self.job.config_set.expect_call('boot.default_args', 160 'more-blah console=tty1') 161 162 163 def construct_job(self, cont): 164 # will construct class instance using __new__ 165 self.job = job.base_job.__new__(job.base_job) 166 167 # record 168 resultdir, my_harness = self._setup_pre_record_init(cont) 169 self._setup_post_record_init(cont, resultdir, my_harness) 170 171 # finish constructor 172 options = Dummy() 173 options.tag = self.jobtag 174 options.cont = cont 175 options.harness = None 176 options.log = False 177 options.verbose = False 178 options.hostname = 'localhost' 179 options.autoserv_user = 'my_user' 180 self.job.__init__(self.control, options, 181 extra_copy_cmdline=['more-blah']) 182 183 # check 184 self.god.check_playback() 185 186 187 def get_partition_mock(self, devname): 188 """ 189 Create a mock of a partition object and return it. 190 """ 191 class mock(object): 192 device = devname 193 get_mountpoint = self.god.create_mock_function('get_mountpoint') 194 return mock 195 196 197 def test_constructor_first_run(self): 198 self.construct_job(False) 199 200 201 def test_constructor_continuation(self): 202 self.construct_job(True) 203 204 205 def test_constructor_post_record_failure(self): 206 """ 207 Test post record initialization failure. 208 """ 209 self.job = job.base_job.__new__(job.base_job) 210 options = Dummy() 211 options.tag = self.jobtag 212 options.cont = False 213 options.harness = None 214 options.log = False 215 options.verbose = False 216 options.hostname = 'localhost' 217 options.autoserv_user = 'my_user' 218 error = Exception('fail') 219 220 self.god.stub_function(self.job, '_post_record_init') 221 self.god.stub_function(self.job, 'record') 222 223 self._setup_pre_record_init(False) 224 self.job._post_record_init.expect_call( 225 self.control, options, True, ['more-blah']).and_raises(error) 226 self.job.record.expect_call( 227 'ABORT', None, None,'client.bin.job.__init__ failed: %s' % 228 str(error)) 229 230 self.assertRaises( 231 Exception, self.job.__init__, self.control, options, 232 drop_caches=True, extra_copy_cmdline=['more-blah']) 233 234 # check 235 self.god.check_playback() 236 237 238 def test_monitor_disk_usage(self): 239 self.construct_job(True) 240 241 # record 242 max_rate = 10.0 243 self.job.set_state.expect_call('__monitor_disk', max_rate) 244 245 # test 246 self.job.monitor_disk_usage(max_rate) 247 self.god.check_playback() 248 249 250 def test_relative_path(self): 251 self.construct_job(True) 252 dummy = "asdf" 253 ret = self.job.relative_path(os.path.join(self.job.resultdir, dummy)) 254 self.assertEquals(ret, dummy) 255 256 257 def test_control_functions(self): 258 self.construct_job(True) 259 control_file = "blah" 260 self.job.control_set(control_file) 261 self.assertEquals(self.job.control_get(), os.path.abspath(control_file)) 262 263 264 def test_harness_select(self): 265 self.construct_job(True) 266 267 # record 268 which = "which" 269 harness.select.expect_call(which, self.job).and_return(None) 270 271 # run and test 272 self.job.harness_select(which) 273 self.god.check_playback() 274 275 276 def test_config_set(self): 277 self.construct_job(True) 278 279 # unstub config_set 280 self.god.unstub(self.job, 'config_set') 281 # record 282 name = "foo" 283 val = 10 284 self.config.set.expect_call(name, val) 285 286 # run and test 287 self.job.config_set(name, val) 288 self.god.check_playback() 289 290 291 def test_config_get(self): 292 self.construct_job(True) 293 294 # unstub config_get 295 self.god.unstub(self.job, 'config_get') 296 # record 297 name = "foo" 298 val = 10 299 self.config.get.expect_call(name).and_return(val) 300 301 # run and test 302 self.job.config_get(name) 303 self.god.check_playback() 304 305 306 def test_setup_dirs_raise(self): 307 self.construct_job(True) 308 309 # setup 310 results_dir = 'foo' 311 tmp_dir = 'bar' 312 313 # record 314 os.path.exists.expect_call(tmp_dir).and_return(True) 315 os.path.isdir.expect_call(tmp_dir).and_return(False) 316 317 # test 318 self.assertRaises(ValueError, self.job.setup_dirs, results_dir, tmp_dir) 319 self.god.check_playback() 320 321 322 def test_setup_dirs(self): 323 self.construct_job(True) 324 325 # setup 326 results_dir1 = os.path.join(self.job.resultdir, 'build') 327 results_dir2 = os.path.join(self.job.resultdir, 'build.2') 328 results_dir3 = os.path.join(self.job.resultdir, 'build.3') 329 tmp_dir = 'bar' 330 331 # record 332 os.path.exists.expect_call(tmp_dir).and_return(False) 333 os.mkdir.expect_call(tmp_dir) 334 os.path.isdir.expect_call(tmp_dir).and_return(True) 335 os.path.exists.expect_call(results_dir1).and_return(True) 336 os.path.exists.expect_call(results_dir2).and_return(True) 337 os.path.exists.expect_call(results_dir3).and_return(False) 338 os.path.exists.expect_call(results_dir3).and_return(False) 339 os.mkdir.expect_call(results_dir3) 340 341 # test 342 self.assertEqual(self.job.setup_dirs(None, tmp_dir), 343 (results_dir3, tmp_dir)) 344 self.god.check_playback() 345 346 347 def test_xen(self): 348 self.construct_job(True) 349 350 # setup 351 self.god.stub_function(self.job, "setup_dirs") 352 self.god.stub_class(xen, "xen") 353 results = 'results_dir' 354 tmp = 'tmp' 355 build = 'xen' 356 base_tree = object() 357 358 # record 359 self.job.setup_dirs.expect_call(results, 360 tmp).and_return((results, tmp)) 361 myxen = xen.xen.expect_new(self.job, base_tree, results, tmp, build, 362 False, None) 363 364 # run job and check 365 axen = self.job.xen(base_tree, results, tmp) 366 self.god.check_playback() 367 self.assertEquals(myxen, axen) 368 369 370 def test_kernel_rpm(self): 371 self.construct_job(True) 372 373 # setup 374 self.god.stub_function(self.job, "setup_dirs") 375 self.god.stub_class(kernel, "rpm_kernel") 376 self.god.stub_function(kernel, "preprocess_path") 377 self.god.stub_function(self.job.pkgmgr, "fetch_pkg") 378 self.god.stub_function(utils, "get_os_vendor") 379 results = 'results_dir' 380 tmp = 'tmp' 381 build = 'xen' 382 path = "somepath.rpm" 383 packages_dir = os.path.join("autodir/packages", path) 384 385 # record 386 self.job.setup_dirs.expect_call(results, 387 tmp).and_return((results, tmp)) 388 kernel.preprocess_path.expect_call(path).and_return(path) 389 os.path.exists.expect_call(path).and_return(False) 390 self.job.pkgmgr.fetch_pkg.expect_call(path, packages_dir, repo_url='') 391 utils.get_os_vendor.expect_call() 392 mykernel = kernel.rpm_kernel.expect_new(self.job, [packages_dir], 393 results) 394 395 # check 396 akernel = self.job.kernel(path, results, tmp) 397 self.god.check_playback() 398 self.assertEquals(mykernel, akernel) 399 400 401 def test_kernel(self): 402 self.construct_job(True) 403 404 # setup 405 self.god.stub_function(self.job, "setup_dirs") 406 self.god.stub_class(kernel, "kernel") 407 self.god.stub_function(kernel, "preprocess_path") 408 results = 'results_dir' 409 tmp = 'tmp' 410 build = 'linux' 411 path = "somepath.deb" 412 413 # record 414 self.job.setup_dirs.expect_call(results, 415 tmp).and_return((results, tmp)) 416 kernel.preprocess_path.expect_call(path).and_return(path) 417 mykernel = kernel.kernel.expect_new(self.job, path, results, tmp, 418 build, False) 419 420 # check 421 akernel = self.job.kernel(path, results, tmp) 422 self.god.check_playback() 423 self.assertEquals(mykernel, akernel) 424 425 426 def test_run_test_logs_test_error_from_unhandled_error(self): 427 self.construct_job(True) 428 429 # set up stubs 430 self.god.stub_function(self.job.pkgmgr, 'get_package_name') 431 self.god.stub_function(self.job, "_runtest") 432 433 # create an unhandled error object 434 class MyError(error.TestError): 435 pass 436 real_error = MyError("this is the real error message") 437 unhandled_error = error.UnhandledTestError(real_error) 438 439 # set up the recording 440 testname = "error_test" 441 outputdir = os.path.join(self.job.resultdir, testname) 442 self.job.pkgmgr.get_package_name.expect_call( 443 testname, 'test').and_return(("", testname)) 444 self.job.get_state.expect_call( 445 self.job._RUN_NUMBER_STATE, default=0).and_return(0) 446 self.job.get_state.expect_call( 447 self.job._KERNEL_IN_TAG_STATE, default=False).and_return(False) 448 os.path.exists.expect_call(outputdir).and_return(False) 449 os.mkdir.expect_call(outputdir) 450 self.job.record.expect_call("START", testname, testname) 451 self.job._increment_group_level.expect_call() 452 self.job._runtest.expect_call(testname, "", (), {}).and_raises( 453 unhandled_error) 454 self.job.record.expect_call("ERROR", testname, testname, 455 first_line_comparator(str(real_error))) 456 self.job._decrement_group_level.expect_call() 457 self.job.record.expect_call("END ERROR", testname, testname) 458 self.job.harness.run_test_complete.expect_call() 459 utils.drop_caches.expect_call() 460 461 # run and check 462 self.job.run_test(testname) 463 self.god.check_playback() 464 465 466 def test_run_test_logs_non_test_error_from_unhandled_error(self): 467 self.construct_job(True) 468 469 # set up stubs 470 self.god.stub_function(self.job.pkgmgr, 'get_package_name') 471 self.god.stub_function(self.job, "_runtest") 472 473 # create an unhandled error object 474 class MyError(Exception): 475 pass 476 real_error = MyError("this is the real error message") 477 unhandled_error = error.UnhandledTestError(real_error) 478 reason = first_line_comparator("Unhandled MyError: %s" % real_error) 479 480 # set up the recording 481 testname = "error_test" 482 outputdir = os.path.join(self.job.resultdir, testname) 483 self.job.pkgmgr.get_package_name.expect_call( 484 testname, 'test').and_return(("", testname)) 485 self.job.get_state.expect_call( 486 self.job._RUN_NUMBER_STATE, default=0).and_return(0) 487 self.job.get_state.expect_call( 488 self.job._KERNEL_IN_TAG_STATE, default=False).and_return(False) 489 os.path.exists.expect_call(outputdir).and_return(False) 490 os.mkdir.expect_call(outputdir) 491 self.job.record.expect_call("START", testname, testname) 492 self.job._increment_group_level.expect_call() 493 self.job._runtest.expect_call(testname, "", (), {}).and_raises( 494 unhandled_error) 495 self.job.record.expect_call("ERROR", testname, testname, reason) 496 self.job._decrement_group_level.expect_call() 497 self.job.record.expect_call("END ERROR", testname, testname) 498 self.job.harness.run_test_complete.expect_call() 499 utils.drop_caches.expect_call() 500 501 # run and check 502 self.job.run_test(testname) 503 self.god.check_playback() 504 505 506 def test_record(self): 507 self.construct_job(True) 508 509 # steup 510 self.job.group_level = 1 511 status = '' 512 status_code = "PASS" 513 subdir = "subdir" 514 operation = "super_fun" 515 mytime = "1234" 516 msg_tag = "" 517 if "." in self.job.log_filename: 518 msg_tag = self.job.log_filename.split(".", 1)[1] 519 epoch_time = int(mytime) 520 local_time = time.localtime(epoch_time) 521 optional_fields = {} 522 optional_fields["timestamp"] = str(epoch_time) 523 optional_fields["localtime"] = time.strftime("%b %d %H:%M:%S", 524 local_time) 525 fields = [status_code, subdir, operation] 526 fields += ["%s=%s" % x for x in optional_fields.iteritems()] 527 fields.append(status) 528 msg = '\t'.join(str(x) for x in fields) 529 msg = '\t' * self.job.group_level + msg 530 531 self.god.stub_function(log, "is_valid_status") 532 self.god.stub_function(time, "time") 533 self.god.stub_function(self.job, "open") 534 535 536 # record 537 log.is_valid_status.expect_call(status_code).and_return(True) 538 time.time.expect_call().and_return(mytime) 539 self.job.harness.test_status_detail.expect_call(status_code, subdir, 540 operation, '', msg_tag) 541 self.job.harness.test_status.expect_call(msg, msg_tag) 542 myfile = self.god.create_mock_class(file, "file") 543 status_file = os.path.join(self.job.resultdir, self.job.log_filename) 544 self.job.open.expect_call(status_file, "a").and_return(myfile) 545 myfile.write.expect_call(msg + "\n") 546 547 dir = os.path.join(self.job.resultdir, subdir) 548 status_file = os.path.join(dir, self.job.DEFAULT_LOG_FILENAME) 549 self.job.open.expect_call(status_file, "a").and_return(myfile) 550 myfile.write.expect_call(msg + "\n") 551 552 553 # run test 554 self.god.unstub(self.job, "record") 555 self.job.record(status_code, subdir, operation) 556 self.god.check_playback() 557 558 559 def test_report_reboot_failure(self): 560 self.construct_job(True) 561 562 # record 563 self.job.record.expect_call("ABORT", "sub", "reboot.verify", 564 "boot failure") 565 self.job._decrement_group_level.expect_call() 566 self.job.record.expect_call("END ABORT", "sub", "reboot", 567 optional_fields={"kernel": "2.6.15-smp"}) 568 569 # playback 570 self.job._record_reboot_failure("sub", "reboot.verify", "boot failure", 571 running_id="2.6.15-smp") 572 self.god.check_playback() 573 574 575 def _setup_check_post_reboot(self, mount_info): 576 # setup 577 self.god.stub_function(job.partition_lib, "get_partition_list") 578 579 part_list = [self.get_partition_mock("/dev/hda1"), 580 self.get_partition_mock("/dev/hdb1")] 581 mount_list = ["/mnt/hda1", "/mnt/hdb1"] 582 583 # record 584 job.partition_lib.get_partition_list.expect_call(self.job).and_return( 585 part_list) 586 for i in xrange(len(part_list)): 587 part_list[i].get_mountpoint.expect_call().and_return(mount_list[i]) 588 self.job.get_state.expect_call("__mount_info").and_return(mount_info) 589 590 591 def test_check_post_reboot_success(self): 592 self.construct_job(True) 593 594 mount_info = set([("/dev/hda1", "/mnt/hda1"), 595 ("/dev/hdb1", "/mnt/hdb1")]) 596 self._setup_check_post_reboot(mount_info) 597 598 # playback 599 self.job._check_post_reboot("sub") 600 self.god.check_playback() 601 602 603 def test_check_post_reboot_mounts_failure(self): 604 self.construct_job(True) 605 606 mount_info = set([("/dev/hda1", "/mnt/hda1")]) 607 self._setup_check_post_reboot(mount_info) 608 609 self.god.stub_function(self.job, "_record_reboot_failure") 610 self.job._record_reboot_failure.expect_call("sub", 611 "reboot.verify_config", "mounted partitions are different after" 612 " reboot (old entries: set([]), new entries: set([('/dev/hdb1'," 613 " '/mnt/hdb1')]))", running_id=None) 614 615 # playback 616 self.assertRaises(error.JobError, self.job._check_post_reboot, "sub") 617 self.god.check_playback() 618 619 620 def test_end_boot(self): 621 self.construct_job(True) 622 self.god.stub_function(self.job, "_check_post_reboot") 623 624 # set up the job class 625 self.job.group_level = 2 626 627 self.job._check_post_reboot.expect_call("sub", running_id=None) 628 self.job._decrement_group_level.expect_call() 629 self.job.record.expect_call("END GOOD", "sub", "reboot", 630 optional_fields={"kernel": "2.6.15-smp", 631 "patch0": "patchname"}) 632 633 # run test 634 self.job.end_reboot("sub", "2.6.15-smp", ["patchname"]) 635 self.god.check_playback() 636 637 638 def test_end_boot_and_verify_success(self): 639 self.construct_job(True) 640 self.god.stub_function(self.job, "_check_post_reboot") 641 642 # set up the job class 643 self.job.group_level = 2 644 645 self.god.stub_function(utils, "running_os_ident") 646 utils.running_os_ident.expect_call().and_return("2.6.15-smp") 647 648 utils.read_one_line.expect_call("/proc/cmdline").and_return( 649 "blah more-blah root=lala IDENT=81234567 blah-again") 650 651 self.god.stub_function(utils, "running_os_full_version") 652 running_id = "2.6.15-smp" 653 utils.running_os_full_version.expect_call().and_return(running_id) 654 655 self.job.record.expect_call("GOOD", "sub", "reboot.verify", 656 running_id) 657 self.job._check_post_reboot.expect_call("sub", running_id=running_id) 658 self.job._decrement_group_level.expect_call() 659 self.job.record.expect_call("END GOOD", "sub", "reboot", 660 optional_fields={"kernel": running_id}) 661 662 # run test 663 self.job.end_reboot_and_verify(81234567, "2.6.15-smp", "sub") 664 self.god.check_playback() 665 666 667 def test_end_boot_and_verify_failure(self): 668 self.construct_job(True) 669 self.god.stub_function(self.job, "_record_reboot_failure") 670 671 # set up the job class 672 self.job.group_level = 2 673 674 self.god.stub_function(utils, "running_os_ident") 675 utils.running_os_ident.expect_call().and_return("2.6.15-smp") 676 677 utils.read_one_line.expect_call("/proc/cmdline").and_return( 678 "blah more-blah root=lala IDENT=81234567 blah-again") 679 680 self.job._record_reboot_failure.expect_call("sub", "reboot.verify", 681 "boot failure", running_id="2.6.15-smp") 682 683 # run test 684 self.assertRaises(error.JobError, self.job.end_reboot_and_verify, 685 91234567, "2.6.16-smp", "sub") 686 self.god.check_playback() 687 688 689 def test_default_tag(self): 690 self.construct_job(cont=False) 691 692 self.job.set_state.expect_call("__job_tag", None) 693 self.job.default_tag(None) 694 self.assertEqual(None, self.job.tag) 695 696 self.job.set_state.expect_call("__job_tag", '1337-gps') 697 self.job.default_tag('1337-gps') 698 self.assertEqual('1337-gps', self.job.tag) 699 700 self.construct_job(cont=True) 701 self.job.default_tag(None) 702 self.god.check_playback() 703 704 705if __name__ == "__main__": 706 unittest.main() 707