1*9c5db199SXin Li#!/usr/bin/python3 2*9c5db199SXin Li# pylint: disable=missing-docstring 3*9c5db199SXin Li 4*9c5db199SXin Liimport logging 5*9c5db199SXin Liimport os 6*9c5db199SXin Liimport re 7*9c5db199SXin Liimport shutil 8*9c5db199SXin Liimport sys 9*9c5db199SXin Liimport tempfile 10*9c5db199SXin Liimport unittest 11*9c5db199SXin Li 12*9c5db199SXin Lifrom six.moves import range 13*9c5db199SXin Liimport six 14*9c5db199SXin Li 15*9c5db199SXin Liimport common 16*9c5db199SXin Lifrom autotest_lib.client.bin import job, sysinfo, harness 17*9c5db199SXin Lifrom autotest_lib.client.bin import utils 18*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 19*9c5db199SXin Lifrom autotest_lib.client.common_lib import logging_manager, logging_config 20*9c5db199SXin Lifrom autotest_lib.client.common_lib import base_job_unittest 21*9c5db199SXin Lifrom autotest_lib.client.common_lib.test_utils import mock 22*9c5db199SXin Li 23*9c5db199SXin Li 24*9c5db199SXin Liclass job_test_case(unittest.TestCase): 25*9c5db199SXin Li """Generic job TestCase class that defines a standard job setUp and 26*9c5db199SXin Li tearDown, with some standard stubs.""" 27*9c5db199SXin Li 28*9c5db199SXin Li job_class = job.base_client_job 29*9c5db199SXin Li 30*9c5db199SXin Li def setUp(self): 31*9c5db199SXin Li self.god = mock.mock_god(ut=self) 32*9c5db199SXin Li self.god.stub_with(job.base_client_job, '_get_environ_autodir', 33*9c5db199SXin Li classmethod(lambda cls: '/adir')) 34*9c5db199SXin Li self.job = self.job_class.__new__(self.job_class) 35*9c5db199SXin Li self.job._job_directory = base_job_unittest.stub_job_directory 36*9c5db199SXin Li 37*9c5db199SXin Li _, self.control_file = tempfile.mkstemp() 38*9c5db199SXin Li 39*9c5db199SXin Li 40*9c5db199SXin Li def tearDown(self): 41*9c5db199SXin Li self.god.unstub_all() 42*9c5db199SXin Li os.remove(self.control_file) 43*9c5db199SXin Li 44*9c5db199SXin Li 45*9c5db199SXin Liclass test_find_base_directories( 46*9c5db199SXin Li base_job_unittest.test_find_base_directories.generic_tests, 47*9c5db199SXin Li job_test_case): 48*9c5db199SXin Li 49*9c5db199SXin Li def test_autodir_equals_clientdir(self): 50*9c5db199SXin Li autodir, clientdir, _ = self.job._find_base_directories() 51*9c5db199SXin Li self.assertEqual(autodir, '/adir') 52*9c5db199SXin Li self.assertEqual(clientdir, '/adir') 53*9c5db199SXin Li 54*9c5db199SXin Li 55*9c5db199SXin Li def test_serverdir_is_none(self): 56*9c5db199SXin Li _, _, serverdir = self.job._find_base_directories() 57*9c5db199SXin Li self.assertEqual(serverdir, None) 58*9c5db199SXin Li 59*9c5db199SXin Li 60*9c5db199SXin Liclass abstract_test_init(base_job_unittest.test_init.generic_tests): 61*9c5db199SXin Li """Generic client job mixin used when defining variations on the 62*9c5db199SXin Li job.__init__ generic tests.""" 63*9c5db199SXin Li 64*9c5db199SXin Li PUBLIC_ATTRIBUTES = ( 65*9c5db199SXin Li base_job_unittest.test_init.generic_tests.PUBLIC_ATTRIBUTES - 66*9c5db199SXin Li set(['force_full_log_collection'])) 67*9c5db199SXin Li 68*9c5db199SXin Li OPTIONAL_ATTRIBUTES = ( 69*9c5db199SXin Li base_job_unittest.test_init.generic_tests.OPTIONAL_ATTRIBUTES - 70*9c5db199SXin Li set(['control', 'harness', 'force_full_log_collection'])) 71*9c5db199SXin Li 72*9c5db199SXin Li 73*9c5db199SXin Liclass test_init_minimal_options(abstract_test_init, job_test_case): 74*9c5db199SXin Li 75*9c5db199SXin Li def call_init(self): 76*9c5db199SXin Li # TODO(jadmanski): refactor more of the __init__ code to not need to 77*9c5db199SXin Li # stub out countless random APIs 78*9c5db199SXin Li self.god.stub_function_to_return(job.os, 'mkdir', None) 79*9c5db199SXin Li self.god.stub_function_to_return(job.os.path, 'exists', True) 80*9c5db199SXin Li self.god.stub_function_to_return(self.job, '_load_state', None) 81*9c5db199SXin Li self.god.stub_function_to_return(self.job, 'record', None) 82*9c5db199SXin Li self.god.stub_function_to_return(job.shutil, 'copyfile', None) 83*9c5db199SXin Li self.god.stub_function_to_return(job.logging_manager, 84*9c5db199SXin Li 'configure_logging', None) 85*9c5db199SXin Li class manager: 86*9c5db199SXin Li def start_logging(self): 87*9c5db199SXin Li return None 88*9c5db199SXin Li self.god.stub_function_to_return(job.logging_manager, 89*9c5db199SXin Li 'get_logging_manager', manager()) 90*9c5db199SXin Li class stub_sysinfo: 91*9c5db199SXin Li def log_per_reboot_data(self): 92*9c5db199SXin Li return None 93*9c5db199SXin Li self.god.stub_function_to_return(job.sysinfo, 'sysinfo', 94*9c5db199SXin Li stub_sysinfo()) 95*9c5db199SXin Li class stub_harness: 96*9c5db199SXin Li run_start = lambda self: None 97*9c5db199SXin Li self.god.stub_function_to_return(job.harness, 'select', stub_harness()) 98*9c5db199SXin Li class options: 99*9c5db199SXin Li tag = '' 100*9c5db199SXin Li verbose = False 101*9c5db199SXin Li cont = False 102*9c5db199SXin Li harness = 'stub' 103*9c5db199SXin Li harness_args = None 104*9c5db199SXin Li hostname = None 105*9c5db199SXin Li user = None 106*9c5db199SXin Li log = False 107*9c5db199SXin Li args = '' 108*9c5db199SXin Li output_dir = '' 109*9c5db199SXin Li 110*9c5db199SXin Li self.god.stub_function_to_return(job.utils, 'drop_caches', None) 111*9c5db199SXin Li 112*9c5db199SXin Li self.job._job_state = base_job_unittest.stub_job_state 113*9c5db199SXin Li self.job.__init__(self.control_file, options) 114*9c5db199SXin Li 115*9c5db199SXin Li 116*9c5db199SXin Liclass placeholder(object): 117*9c5db199SXin Li """A simple placeholder for attributes""" 118*9c5db199SXin Li pass 119*9c5db199SXin Li 120*9c5db199SXin Li 121*9c5db199SXin Liclass first_line_comparator(mock.argument_comparator): 122*9c5db199SXin Li def __init__(self, first_line): 123*9c5db199SXin Li self.first_line = first_line 124*9c5db199SXin Li 125*9c5db199SXin Li 126*9c5db199SXin Li def is_satisfied_by(self, parameter): 127*9c5db199SXin Li return self.first_line == parameter.splitlines()[0] 128*9c5db199SXin Li 129*9c5db199SXin Li 130*9c5db199SXin Liclass test_base_job(unittest.TestCase): 131*9c5db199SXin Li def setUp(self): 132*9c5db199SXin Li # make god 133*9c5db199SXin Li self.god = mock.mock_god(ut=self) 134*9c5db199SXin Li 135*9c5db199SXin Li # need to set some environ variables 136*9c5db199SXin Li self.autodir = "autodir" 137*9c5db199SXin Li os.environ['AUTODIR'] = self.autodir 138*9c5db199SXin Li 139*9c5db199SXin Li # set up some variables 140*9c5db199SXin Li _, self.control = tempfile.mkstemp() 141*9c5db199SXin Li self.jobtag = "jobtag" 142*9c5db199SXin Li 143*9c5db199SXin Li # get rid of stdout and logging 144*9c5db199SXin Li sys.stdout = six.StringIO() 145*9c5db199SXin Li logging_manager.configure_logging(logging_config.TestingConfig()) 146*9c5db199SXin Li logging.disable(logging.CRITICAL) 147*9c5db199SXin Li def placeholder_configure_logging(*args, **kwargs): 148*9c5db199SXin Li pass 149*9c5db199SXin Li self.god.stub_with(logging_manager, 'configure_logging', 150*9c5db199SXin Li placeholder_configure_logging) 151*9c5db199SXin Li real_get_logging_manager = logging_manager.get_logging_manager 152*9c5db199SXin Li def get_logging_manager_no_fds(manage_stdout_and_stderr=False, 153*9c5db199SXin Li redirect_fds=False): 154*9c5db199SXin Li return real_get_logging_manager(manage_stdout_and_stderr, False) 155*9c5db199SXin Li self.god.stub_with(logging_manager, 'get_logging_manager', 156*9c5db199SXin Li get_logging_manager_no_fds) 157*9c5db199SXin Li 158*9c5db199SXin Li # stub out some stuff 159*9c5db199SXin Li self.god.stub_function(os.path, 'exists') 160*9c5db199SXin Li self.god.stub_function(os.path, 'isdir') 161*9c5db199SXin Li self.god.stub_function(os, 'makedirs') 162*9c5db199SXin Li self.god.stub_function(os, 'mkdir') 163*9c5db199SXin Li self.god.stub_function(os, 'remove') 164*9c5db199SXin Li self.god.stub_function(shutil, 'rmtree') 165*9c5db199SXin Li self.god.stub_function(shutil, 'copyfile') 166*9c5db199SXin Li self.god.stub_function(job, 'open') 167*9c5db199SXin Li self.god.stub_function(utils, 'system') 168*9c5db199SXin Li self.god.stub_function(utils, 'drop_caches') 169*9c5db199SXin Li self.god.stub_function(harness, 'select') 170*9c5db199SXin Li self.god.stub_function(sysinfo, 'log_per_reboot_data') 171*9c5db199SXin Li 172*9c5db199SXin Li self.god.stub_class(job.local_host, 'LocalHost') 173*9c5db199SXin Li self.god.stub_class(sysinfo, 'sysinfo') 174*9c5db199SXin Li 175*9c5db199SXin Li self.god.stub_class_method(job.base_client_job, 176*9c5db199SXin Li '_cleanup_debugdir_files') 177*9c5db199SXin Li self.god.stub_class_method(job.base_client_job, '_cleanup_results_dir') 178*9c5db199SXin Li 179*9c5db199SXin Li self.god.stub_with(job.base_job.job_directory, '_ensure_valid', 180*9c5db199SXin Li lambda *_: None) 181*9c5db199SXin Li 182*9c5db199SXin Li 183*9c5db199SXin Li def tearDown(self): 184*9c5db199SXin Li sys.stdout = sys.__stdout__ 185*9c5db199SXin Li self.god.unstub_all() 186*9c5db199SXin Li os.remove(self.control) 187*9c5db199SXin Li 188*9c5db199SXin Li 189*9c5db199SXin Li def _setup_pre_record_init(self, cont): 190*9c5db199SXin Li self.god.stub_function(self.job, '_load_state') 191*9c5db199SXin Li 192*9c5db199SXin Li resultdir = os.path.join(self.autodir, 'results', self.jobtag) 193*9c5db199SXin Li tmpdir = os.path.join(self.autodir, 'tmp') 194*9c5db199SXin Li if not cont: 195*9c5db199SXin Li job.base_client_job._cleanup_debugdir_files.expect_call() 196*9c5db199SXin Li job.base_client_job._cleanup_results_dir.expect_call() 197*9c5db199SXin Li 198*9c5db199SXin Li self.job._load_state.expect_call() 199*9c5db199SXin Li 200*9c5db199SXin Li my_harness = self.god.create_mock_class(harness.harness, 201*9c5db199SXin Li 'my_harness') 202*9c5db199SXin Li harness.select.expect_call(None, 203*9c5db199SXin Li self.job, 204*9c5db199SXin Li None).and_return(my_harness) 205*9c5db199SXin Li 206*9c5db199SXin Li return resultdir, my_harness 207*9c5db199SXin Li 208*9c5db199SXin Li 209*9c5db199SXin Li def _setup_post_record_init(self, cont, resultdir, my_harness): 210*9c5db199SXin Li # now some specific stubs 211*9c5db199SXin Li self.god.stub_function(self.job, 'config_get') 212*9c5db199SXin Li self.god.stub_function(self.job, 'config_set') 213*9c5db199SXin Li self.god.stub_function(self.job, 'record') 214*9c5db199SXin Li 215*9c5db199SXin Li # other setup 216*9c5db199SXin Li results = os.path.join(self.autodir, 'results') 217*9c5db199SXin Li download = os.path.join(self.autodir, 'tests', 'download') 218*9c5db199SXin Li pkgdir = os.path.join(self.autodir, 'packages') 219*9c5db199SXin Li 220*9c5db199SXin Li utils.drop_caches.expect_call() 221*9c5db199SXin Li job_sysinfo = sysinfo.sysinfo.expect_new(resultdir) 222*9c5db199SXin Li if not cont: 223*9c5db199SXin Li os.path.exists.expect_call(download).and_return(False) 224*9c5db199SXin Li os.mkdir.expect_call(download) 225*9c5db199SXin Li shutil.copyfile.expect_call(mock.is_string_comparator(), 226*9c5db199SXin Li os.path.join(resultdir, 'control')) 227*9c5db199SXin Li 228*9c5db199SXin Li job.local_host.LocalHost.expect_new(hostname='localhost') 229*9c5db199SXin Li job_sysinfo.log_per_reboot_data.expect_call() 230*9c5db199SXin Li if not cont: 231*9c5db199SXin Li self.job.record.expect_call('START', None, None) 232*9c5db199SXin Li 233*9c5db199SXin Li my_harness.run_start.expect_call() 234*9c5db199SXin Li 235*9c5db199SXin Li 236*9c5db199SXin Li def construct_job(self, cont): 237*9c5db199SXin Li # will construct class instance using __new__ 238*9c5db199SXin Li self.job = job.base_client_job.__new__(job.base_client_job) 239*9c5db199SXin Li 240*9c5db199SXin Li # record 241*9c5db199SXin Li resultdir, my_harness = self._setup_pre_record_init(cont) 242*9c5db199SXin Li self._setup_post_record_init(cont, resultdir, my_harness) 243*9c5db199SXin Li 244*9c5db199SXin Li # finish constructor 245*9c5db199SXin Li options = placeholder() 246*9c5db199SXin Li options.tag = self.jobtag 247*9c5db199SXin Li options.cont = cont 248*9c5db199SXin Li options.harness = None 249*9c5db199SXin Li options.harness_args = None 250*9c5db199SXin Li options.log = False 251*9c5db199SXin Li options.verbose = False 252*9c5db199SXin Li options.hostname = 'localhost' 253*9c5db199SXin Li options.user = 'my_user' 254*9c5db199SXin Li options.args = '' 255*9c5db199SXin Li options.output_dir = '' 256*9c5db199SXin Li self.job.__init__(self.control, options) 257*9c5db199SXin Li 258*9c5db199SXin Li # check 259*9c5db199SXin Li self.god.check_playback() 260*9c5db199SXin Li 261*9c5db199SXin Li 262*9c5db199SXin Li def get_partition_mock(self, devname): 263*9c5db199SXin Li """ 264*9c5db199SXin Li Create a mock of a partition object and return it. 265*9c5db199SXin Li """ 266*9c5db199SXin Li class mock(object): 267*9c5db199SXin Li device = devname 268*9c5db199SXin Li get_mountpoint = self.god.create_mock_function('get_mountpoint') 269*9c5db199SXin Li return mock 270*9c5db199SXin Li 271*9c5db199SXin Li 272*9c5db199SXin Li def test_constructor_first_run(self): 273*9c5db199SXin Li self.construct_job(False) 274*9c5db199SXin Li 275*9c5db199SXin Li 276*9c5db199SXin Li def test_constructor_continuation(self): 277*9c5db199SXin Li self.construct_job(True) 278*9c5db199SXin Li 279*9c5db199SXin Li 280*9c5db199SXin Li def test_constructor_post_record_failure(self): 281*9c5db199SXin Li """ 282*9c5db199SXin Li Test post record initialization failure. 283*9c5db199SXin Li """ 284*9c5db199SXin Li self.job = job.base_client_job.__new__(job.base_client_job) 285*9c5db199SXin Li options = placeholder() 286*9c5db199SXin Li options.tag = self.jobtag 287*9c5db199SXin Li options.cont = False 288*9c5db199SXin Li options.harness = None 289*9c5db199SXin Li options.harness_args = None 290*9c5db199SXin Li options.log = False 291*9c5db199SXin Li options.verbose = False 292*9c5db199SXin Li options.hostname = 'localhost' 293*9c5db199SXin Li options.user = 'my_user' 294*9c5db199SXin Li options.args = '' 295*9c5db199SXin Li options.output_dir = '' 296*9c5db199SXin Li error = Exception('fail') 297*9c5db199SXin Li 298*9c5db199SXin Li self.god.stub_function(self.job, '_post_record_init') 299*9c5db199SXin Li self.god.stub_function(self.job, 'record') 300*9c5db199SXin Li 301*9c5db199SXin Li self._setup_pre_record_init(False) 302*9c5db199SXin Li self.job._post_record_init.expect_call( 303*9c5db199SXin Li self.control, options, True).and_raises(error) 304*9c5db199SXin Li self.job.record.expect_call( 305*9c5db199SXin Li 'ABORT', None, None,'client.bin.job.__init__ failed: %s' % 306*9c5db199SXin Li str(error)) 307*9c5db199SXin Li 308*9c5db199SXin Li self.assertRaises( 309*9c5db199SXin Li Exception, self.job.__init__, self.control, options, 310*9c5db199SXin Li drop_caches=True) 311*9c5db199SXin Li 312*9c5db199SXin Li # check 313*9c5db199SXin Li self.god.check_playback() 314*9c5db199SXin Li 315*9c5db199SXin Li 316*9c5db199SXin Li def test_control_functions(self): 317*9c5db199SXin Li self.construct_job(True) 318*9c5db199SXin Li control_file = "blah" 319*9c5db199SXin Li self.job.control_set(control_file) 320*9c5db199SXin Li self.assertEquals(self.job.control_get(), os.path.abspath(control_file)) 321*9c5db199SXin Li 322*9c5db199SXin Li 323*9c5db199SXin Li def test_harness_select(self): 324*9c5db199SXin Li self.construct_job(True) 325*9c5db199SXin Li 326*9c5db199SXin Li # record 327*9c5db199SXin Li which = "which" 328*9c5db199SXin Li harness_args = '' 329*9c5db199SXin Li harness.select.expect_call(which, self.job, 330*9c5db199SXin Li harness_args).and_return(None) 331*9c5db199SXin Li 332*9c5db199SXin Li # run and test 333*9c5db199SXin Li self.job.harness_select(which, harness_args) 334*9c5db199SXin Li self.god.check_playback() 335*9c5db199SXin Li 336*9c5db199SXin Li 337*9c5db199SXin Li def test_setup_dirs_raise(self): 338*9c5db199SXin Li self.construct_job(True) 339*9c5db199SXin Li 340*9c5db199SXin Li # setup 341*9c5db199SXin Li results_dir = 'foo' 342*9c5db199SXin Li tmp_dir = 'bar' 343*9c5db199SXin Li 344*9c5db199SXin Li # record 345*9c5db199SXin Li os.path.exists.expect_call(tmp_dir).and_return(True) 346*9c5db199SXin Li os.path.isdir.expect_call(tmp_dir).and_return(False) 347*9c5db199SXin Li 348*9c5db199SXin Li # test 349*9c5db199SXin Li self.assertRaises(ValueError, self.job.setup_dirs, results_dir, tmp_dir) 350*9c5db199SXin Li self.god.check_playback() 351*9c5db199SXin Li 352*9c5db199SXin Li 353*9c5db199SXin Li def test_setup_dirs(self): 354*9c5db199SXin Li self.construct_job(True) 355*9c5db199SXin Li 356*9c5db199SXin Li # setup 357*9c5db199SXin Li results_dir1 = os.path.join(self.job.resultdir, 'build') 358*9c5db199SXin Li results_dir2 = os.path.join(self.job.resultdir, 'build.2') 359*9c5db199SXin Li results_dir3 = os.path.join(self.job.resultdir, 'build.3') 360*9c5db199SXin Li tmp_dir = 'bar' 361*9c5db199SXin Li 362*9c5db199SXin Li # record 363*9c5db199SXin Li os.path.exists.expect_call(tmp_dir).and_return(False) 364*9c5db199SXin Li os.mkdir.expect_call(tmp_dir) 365*9c5db199SXin Li os.path.isdir.expect_call(tmp_dir).and_return(True) 366*9c5db199SXin Li os.path.exists.expect_call(results_dir1).and_return(True) 367*9c5db199SXin Li os.path.exists.expect_call(results_dir2).and_return(True) 368*9c5db199SXin Li os.path.exists.expect_call(results_dir3).and_return(False) 369*9c5db199SXin Li os.path.exists.expect_call(results_dir3).and_return(False) 370*9c5db199SXin Li os.mkdir.expect_call(results_dir3) 371*9c5db199SXin Li 372*9c5db199SXin Li # test 373*9c5db199SXin Li self.assertEqual(self.job.setup_dirs(None, tmp_dir), 374*9c5db199SXin Li (results_dir3, tmp_dir)) 375*9c5db199SXin Li self.god.check_playback() 376*9c5db199SXin Li 377*9c5db199SXin Li 378*9c5db199SXin Li def test_run_test_logs_test_error_from_unhandled_error(self): 379*9c5db199SXin Li self.construct_job(True) 380*9c5db199SXin Li 381*9c5db199SXin Li # set up stubs 382*9c5db199SXin Li self.god.stub_function(self.job.pkgmgr, 'get_package_name') 383*9c5db199SXin Li self.god.stub_function(self.job, "_runtest") 384*9c5db199SXin Li 385*9c5db199SXin Li # create an unhandled error object 386*9c5db199SXin Li class MyError(error.TestError): 387*9c5db199SXin Li pass 388*9c5db199SXin Li real_error = MyError("this is the real error message") 389*9c5db199SXin Li unhandled_error = error.UnhandledTestError(real_error) 390*9c5db199SXin Li 391*9c5db199SXin Li # set up the recording 392*9c5db199SXin Li testname = "error_test" 393*9c5db199SXin Li outputdir = os.path.join(self.job.resultdir, testname) 394*9c5db199SXin Li self.job.pkgmgr.get_package_name.expect_call( 395*9c5db199SXin Li testname, 'test').and_return(("", testname)) 396*9c5db199SXin Li os.path.exists.expect_call(outputdir).and_return(False) 397*9c5db199SXin Li self.job.record.expect_call("START", testname, testname, 398*9c5db199SXin Li optional_fields=None) 399*9c5db199SXin Li self.job._runtest.expect_call(testname, "", None, (), {}).and_raises( 400*9c5db199SXin Li unhandled_error) 401*9c5db199SXin Li self.job.record.expect_call("ERROR", testname, testname, 402*9c5db199SXin Li first_line_comparator(str(real_error))) 403*9c5db199SXin Li self.job.record.expect_call("END ERROR", testname, testname) 404*9c5db199SXin Li self.job.harness.run_test_complete.expect_call() 405*9c5db199SXin Li utils.drop_caches.expect_call() 406*9c5db199SXin Li 407*9c5db199SXin Li # run and check 408*9c5db199SXin Li self.job.run_test(testname) 409*9c5db199SXin Li self.god.check_playback() 410*9c5db199SXin Li 411*9c5db199SXin Li 412*9c5db199SXin Li def test_run_test_logs_non_test_error_from_unhandled_error(self): 413*9c5db199SXin Li self.construct_job(True) 414*9c5db199SXin Li 415*9c5db199SXin Li # set up stubs 416*9c5db199SXin Li self.god.stub_function(self.job.pkgmgr, 'get_package_name') 417*9c5db199SXin Li self.god.stub_function(self.job, "_runtest") 418*9c5db199SXin Li 419*9c5db199SXin Li # create an unhandled error object 420*9c5db199SXin Li class MyError(Exception): 421*9c5db199SXin Li pass 422*9c5db199SXin Li real_error = MyError("this is the real error message") 423*9c5db199SXin Li unhandled_error = error.UnhandledTestError(real_error) 424*9c5db199SXin Li reason = first_line_comparator("Unhandled MyError: %s" % real_error) 425*9c5db199SXin Li 426*9c5db199SXin Li # set up the recording 427*9c5db199SXin Li testname = "error_test" 428*9c5db199SXin Li outputdir = os.path.join(self.job.resultdir, testname) 429*9c5db199SXin Li self.job.pkgmgr.get_package_name.expect_call( 430*9c5db199SXin Li testname, 'test').and_return(("", testname)) 431*9c5db199SXin Li os.path.exists.expect_call(outputdir).and_return(False) 432*9c5db199SXin Li self.job.record.expect_call("START", testname, testname, 433*9c5db199SXin Li optional_fields=None) 434*9c5db199SXin Li self.job._runtest.expect_call(testname, "", None, (), {}).and_raises( 435*9c5db199SXin Li unhandled_error) 436*9c5db199SXin Li self.job.record.expect_call("ERROR", testname, testname, reason) 437*9c5db199SXin Li self.job.record.expect_call("END ERROR", testname, testname) 438*9c5db199SXin Li self.job.harness.run_test_complete.expect_call() 439*9c5db199SXin Li utils.drop_caches.expect_call() 440*9c5db199SXin Li 441*9c5db199SXin Li # run and check 442*9c5db199SXin Li self.job.run_test(testname) 443*9c5db199SXin Li self.god.check_playback() 444*9c5db199SXin Li 445*9c5db199SXin Li 446*9c5db199SXin Li def test_report_reboot_failure(self): 447*9c5db199SXin Li self.construct_job(True) 448*9c5db199SXin Li 449*9c5db199SXin Li # record 450*9c5db199SXin Li self.job.record.expect_call("ABORT", "sub", "reboot.verify", 451*9c5db199SXin Li "boot failure") 452*9c5db199SXin Li self.job.record.expect_call("END ABORT", "sub", "reboot", 453*9c5db199SXin Li optional_fields={"kernel": "2.6.15-smp"}) 454*9c5db199SXin Li 455*9c5db199SXin Li # playback 456*9c5db199SXin Li self.job._record_reboot_failure("sub", "reboot.verify", "boot failure", 457*9c5db199SXin Li running_id="2.6.15-smp") 458*9c5db199SXin Li self.god.check_playback() 459*9c5db199SXin Li 460*9c5db199SXin Li 461*9c5db199SXin Li def _setup_check_post_reboot(self, mount_info, cpu_count): 462*9c5db199SXin Li # setup 463*9c5db199SXin Li self.god.stub_function(job.partition_lib, "get_partition_list") 464*9c5db199SXin Li self.god.stub_function(utils, "count_cpus") 465*9c5db199SXin Li 466*9c5db199SXin Li part_list = [self.get_partition_mock("/dev/hda1"), 467*9c5db199SXin Li self.get_partition_mock("/dev/hdb1")] 468*9c5db199SXin Li mount_list = ["/mnt/hda1", "/mnt/hdb1"] 469*9c5db199SXin Li 470*9c5db199SXin Li # record 471*9c5db199SXin Li job.partition_lib.get_partition_list.expect_call( 472*9c5db199SXin Li self.job, exclude_swap=False).and_return(part_list) 473*9c5db199SXin Li for i in range(len(part_list)): 474*9c5db199SXin Li part_list[i].get_mountpoint.expect_call().and_return(mount_list[i]) 475*9c5db199SXin Li if cpu_count is not None: 476*9c5db199SXin Li utils.count_cpus.expect_call().and_return(cpu_count) 477*9c5db199SXin Li self.job._state.set('client', 'mount_info', mount_info) 478*9c5db199SXin Li self.job._state.set('client', 'cpu_count', 8) 479*9c5db199SXin Li 480*9c5db199SXin Li 481*9c5db199SXin Li def test_check_post_reboot_success(self): 482*9c5db199SXin Li self.construct_job(True) 483*9c5db199SXin Li 484*9c5db199SXin Li mount_info = set([("/dev/hda1", "/mnt/hda1"), 485*9c5db199SXin Li ("/dev/hdb1", "/mnt/hdb1")]) 486*9c5db199SXin Li self._setup_check_post_reboot(mount_info, 8) 487*9c5db199SXin Li 488*9c5db199SXin Li # playback 489*9c5db199SXin Li self.job._check_post_reboot("sub") 490*9c5db199SXin Li self.god.check_playback() 491*9c5db199SXin Li 492*9c5db199SXin Li 493*9c5db199SXin Li def test_check_post_reboot_mounts_failure(self): 494*9c5db199SXin Li self.construct_job(True) 495*9c5db199SXin Li 496*9c5db199SXin Li mount_info = set([("/dev/hda1", "/mnt/hda1")]) 497*9c5db199SXin Li self._setup_check_post_reboot(mount_info, None) 498*9c5db199SXin Li 499*9c5db199SXin Li self.god.stub_function(self.job, "_record_reboot_failure") 500*9c5db199SXin Li 501*9c5db199SXin Li if six.PY2: 502*9c5db199SXin Li self.job._record_reboot_failure.expect_call( 503*9c5db199SXin Li "sub", 504*9c5db199SXin Li "reboot.verify_config", 505*9c5db199SXin Li "mounted partitions are different after" 506*9c5db199SXin Li " reboot (old entries: set([]), new entries: set([('/dev/hdb1'," 507*9c5db199SXin Li " '/mnt/hdb1')]))", 508*9c5db199SXin Li running_id=None) 509*9c5db199SXin Li else: 510*9c5db199SXin Li # Py3 string formatting of sets is a bit different... 511*9c5db199SXin Li self.job._record_reboot_failure.expect_call( 512*9c5db199SXin Li "sub", 513*9c5db199SXin Li "reboot.verify_config", 514*9c5db199SXin Li "mounted partitions are different after" 515*9c5db199SXin Li " reboot (old entries: set(), new entries: {('/dev/hdb1'," 516*9c5db199SXin Li " '/mnt/hdb1')})", 517*9c5db199SXin Li running_id=None) 518*9c5db199SXin Li 519*9c5db199SXin Li # playback 520*9c5db199SXin Li self.assertRaises(error.JobError, self.job._check_post_reboot, "sub") 521*9c5db199SXin Li self.god.check_playback() 522*9c5db199SXin Li 523*9c5db199SXin Li 524*9c5db199SXin Li def test_check_post_reboot_cpu_failure(self): 525*9c5db199SXin Li self.construct_job(True) 526*9c5db199SXin Li 527*9c5db199SXin Li mount_info = set([("/dev/hda1", "/mnt/hda1"), 528*9c5db199SXin Li ("/dev/hdb1", "/mnt/hdb1")]) 529*9c5db199SXin Li self._setup_check_post_reboot(mount_info, 4) 530*9c5db199SXin Li 531*9c5db199SXin Li self.god.stub_function(self.job, "_record_reboot_failure") 532*9c5db199SXin Li self.job._record_reboot_failure.expect_call( 533*9c5db199SXin Li 'sub', 'reboot.verify_config', 534*9c5db199SXin Li 'Number of CPUs changed after reboot (old count: 8, new count: 4)', 535*9c5db199SXin Li running_id=None) 536*9c5db199SXin Li 537*9c5db199SXin Li # playback 538*9c5db199SXin Li self.assertRaises(error.JobError, self.job._check_post_reboot, "sub") 539*9c5db199SXin Li self.god.check_playback() 540*9c5db199SXin Li 541*9c5db199SXin Li 542*9c5db199SXin Li def test_parse_args(self): 543*9c5db199SXin Li test_set = {"a='foo bar baz' b='moo apt'": 544*9c5db199SXin Li ["a='foo bar baz'", "b='moo apt'"], 545*9c5db199SXin Li "a='foo bar baz' only=gah": 546*9c5db199SXin Li ["a='foo bar baz'", "only=gah"], 547*9c5db199SXin Li "a='b c d' no=argh": 548*9c5db199SXin Li ["a='b c d'", "no=argh"]} 549*9c5db199SXin Li for t in test_set: 550*9c5db199SXin Li parsed_args = job.base_client_job._parse_args(t) 551*9c5db199SXin Li expected_args = test_set[t] 552*9c5db199SXin Li self.assertEqual(parsed_args, expected_args) 553*9c5db199SXin Li 554*9c5db199SXin Li 555*9c5db199SXin Li def test_run_test_timeout_parameter_is_propagated(self): 556*9c5db199SXin Li self.construct_job(True) 557*9c5db199SXin Li 558*9c5db199SXin Li # set up stubs 559*9c5db199SXin Li self.god.stub_function(self.job.pkgmgr, 'get_package_name') 560*9c5db199SXin Li self.god.stub_function(self.job, "_runtest") 561*9c5db199SXin Li 562*9c5db199SXin Li # create an unhandled error object 563*9c5db199SXin Li #class MyError(error.TestError): 564*9c5db199SXin Li # pass 565*9c5db199SXin Li #real_error = MyError("this is the real error message") 566*9c5db199SXin Li #unhandled_error = error.UnhandledTestError(real_error) 567*9c5db199SXin Li 568*9c5db199SXin Li # set up the recording 569*9c5db199SXin Li testname = "test" 570*9c5db199SXin Li outputdir = os.path.join(self.job.resultdir, testname) 571*9c5db199SXin Li self.job.pkgmgr.get_package_name.expect_call( 572*9c5db199SXin Li testname, 'test').and_return(("", testname)) 573*9c5db199SXin Li os.path.exists.expect_call(outputdir).and_return(False) 574*9c5db199SXin Li timeout = 60 575*9c5db199SXin Li optional_fields = {} 576*9c5db199SXin Li optional_fields['timeout'] = timeout 577*9c5db199SXin Li self.job.record.expect_call("START", testname, testname, 578*9c5db199SXin Li optional_fields=optional_fields) 579*9c5db199SXin Li self.job._runtest.expect_call(testname, "", timeout, (), {}) 580*9c5db199SXin Li self.job.record.expect_call("GOOD", testname, testname, 581*9c5db199SXin Li "completed successfully") 582*9c5db199SXin Li self.job.record.expect_call("END GOOD", testname, testname) 583*9c5db199SXin Li self.job.harness.run_test_complete.expect_call() 584*9c5db199SXin Li utils.drop_caches.expect_call() 585*9c5db199SXin Li 586*9c5db199SXin Li # run and check 587*9c5db199SXin Li self.job.run_test(testname, timeout=timeout) 588*9c5db199SXin Li self.god.check_playback() 589*9c5db199SXin Li 590*9c5db199SXin Li 591*9c5db199SXin Liclass test_name_pattern(unittest.TestCase): 592*9c5db199SXin Li """Tests for _NAME_PATTERN.""" 593*9c5db199SXin Li 594*9c5db199SXin Li def _one_name_pattern_test(self, line, want): 595*9c5db199SXin Li """Parametrized test.""" 596*9c5db199SXin Li match = re.match(job._NAME_PATTERN, line) 597*9c5db199SXin Li self.assertIsNotNone(match) 598*9c5db199SXin Li self.assertEqual(match.group(1), want) 599*9c5db199SXin Li 600*9c5db199SXin Li def test_name_pattern_nospace_single(self): 601*9c5db199SXin Li self._one_name_pattern_test("NAME='some_Test'", 'some_Test') 602*9c5db199SXin Li 603*9c5db199SXin Li def test_name_pattern_nospace_double(self): 604*9c5db199SXin Li self._one_name_pattern_test('NAME="some_Test"', 'some_Test') 605*9c5db199SXin Li 606*9c5db199SXin Li def test_name_pattern_space_single(self): 607*9c5db199SXin Li self._one_name_pattern_test("NAME = 'some_Test'", 'some_Test') 608*9c5db199SXin Li 609*9c5db199SXin Li def test_name_pattern_space_double(self): 610*9c5db199SXin Li self._one_name_pattern_test('NAME = "some_Test"', 'some_Test') 611*9c5db199SXin Li 612*9c5db199SXin Li 613*9c5db199SXin Liif __name__ == "__main__": 614*9c5db199SXin Li unittest.main() 615