def testGenLimit(self, gen_mock): """Verify generate_count arg works""" with parallel_unittest.ParallelMock(): # Generate nothing! ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, breakpad_dir=self.breakpad_dir, generate_count=0) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 0) # Generate just one. ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, breakpad_dir=self.breakpad_dir, generate_count=1) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 1) # The largest ELF should be processed first. call1 = (os.path.join(self.board_dir, 'iii/large-elf'), os.path.join(self.debug_dir, 'iii/large-elf.debug')) self.assertEquals(gen_mock.call_args_list[0][0], call1)
def testCleaningFalse(self, gen_mock): """Verify behavior of clean_breakpad=False""" with parallel_unittest.ParallelMock(): # Dir does not exist, and then does. self.assertNotExists(self.breakpad_dir) ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, generate_count=1, clean_breakpad=False) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 1) self.assertExists(self.breakpad_dir) # Dir exists before & after. # File exists before & after. dummy_file = os.path.join(self.breakpad_dir, 'fooooooooo') osutils.Touch(dummy_file) ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, generate_count=1, clean_breakpad=False) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 2) self.assertExists(dummy_file)
def _testUpload(self, inputs, sym_paths=None): """Helper for testing uploading of specific paths""" if sym_paths is None: sym_paths = inputs self.upload_mock.return_value = 0 with parallel_unittest.ParallelMock(): ret = upload_symbols.UploadSymbols(sym_paths=inputs, sleep=0, retry=False) self.assertEquals(ret, 0) self.assertEquals(self.upload_mock.call_count, len(sym_paths)) # Since upload order is arbitrary, we have to do a manual scan for each # path ourselves against the uploaded file list. found_syms = [ x[0][1].symbol_item.sym_file for x in self.upload_mock.call_args_list ] for found_sym in found_syms: for path in sym_paths: if found_sym.endswith(path): break else: raise AssertionError('Could not locate %s in %r' % (path, found_syms))
def setUp(self): # List of all stages that would have been called as part of this run. self.called_stages = [] # Simple new function that redirects RunStage to record all stages to be # run rather than mock them completely. These can be used in a test to # assert something has been called. def run_stage(_class_instance, stage_name, *_args, **_kwargs): self.called_stages.append(stage_name) # Parallel version. def run_parallel_stages(_class_instance, stages_list): for stage in stages_list: self.called_stages.append(type(stage)) self.buildroot = os.path.join(self.tempdir, 'buildroot') chroot_path = os.path.join(self.buildroot, constants.DEFAULT_CHROOT_DIR) osutils.SafeMakedirs(os.path.join(chroot_path, 'tmp')) # Parallel mock is used since some work in simple builders get done on a # separate process. self.StartPatcher(parallel_unittest.ParallelMock()) self.PatchObject(generic_builders.Builder, '_RunStage', new=run_stage) self.PatchObject(simple_builders.SimpleBuilder, '_RunParallelStages', new=run_parallel_stages) self.PatchObject(cbuildbot_run._BuilderRunBase, 'GetVersion', return_value='R32-1234.0.0') self._manager = parallel.Manager() self._manager.__enter__()
def setUp(self): options = _ParseCommandLine([ '--lacros', '--nostrip', '--build-dir', '/path/to/nowhere', '--device', 'monkey' ]) self.deploy = deploy_chrome.DeployChrome( options, self.tempdir, os.path.join(self.tempdir, 'staging')) # These methods being mocked are all side effects expected for a --lacros # deploy. self.deploy._EnsureTargetDir = mock.Mock() self.deploy._GetDeviceInfo = mock.Mock() self.deploy._CheckConnection = mock.Mock() self.deploy._MountRootfsAsWritable = mock.Mock() self.deploy._PrepareStagingDir = mock.Mock() self.deploy._CheckDeviceFreeSpace = mock.Mock() self._ran_start_command = False self.StartPatcher(parallel_unittest.ParallelMock()) # Common mocking shared between tests. def kill_procs_side_effect(): self.deploy._stopped_ui = True self.deploy._KillAshChromeIfNeeded = mock.Mock( side_effect=kill_procs_side_effect) def start_ui_side_effect(*args, **kwargs): # pylint: disable=unused-argument self._ran_start_command = True self.rc.AddCmdResult(partial_mock.In('start ui'), side_effect=start_ui_side_effect)
def Run(self, inst): self.PatchObject(chroot_util, 'UpdateChroot', side_effect=self.OnChrootUpdate) self.PatchObject(chroot_util, 'Emerge') with parallel_unittest.ParallelMock(): command_unittest.MockCommand.Run(self, inst)
def testUnmergeError(self): """Make sure random exit errors are not ignored""" self.rc.AddCmdResult(partial_mock.In('emerge'), returncode=123) with parallel_unittest.ParallelMock(): self.assertRaises(cros_build_lib.RunCommandError, cros_mark_as_stable.CleanStalePackages, '.', (), ['no/pkg'])
def testFileList(self, gen_mock): """Verify that file_list restricts the symbols generated""" with parallel_unittest.ParallelMock(): call1 = (os.path.join(self.board_dir, 'usr/sbin/elf'), os.path.join(self.debug_dir, 'usr/sbin/elf.debug')) # Filter with elf path. ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, breakpad_dir=self.breakpad_dir, file_list=[os.path.join(self.board_dir, 'usr', 'sbin', 'elf')]) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 1) self.assertEquals(gen_mock.call_args_list[0][0], call1) # Filter with debug symbols file path. gen_mock.reset_mock() ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, breakpad_dir=self.breakpad_dir, file_list=[ os.path.join(self.debug_dir, 'usr', 'sbin', 'elf.debug') ]) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 1) self.assertEquals(gen_mock.call_args_list[0][0], call1)
def RunTestsWithBotId(self, bot_id, options_tests=True): """Test with the config for the specified bot_id.""" self._Prepare(bot_id) self._run.options.tests = options_tests self._run.attrs.release_tag = '0.0.1' # Simulate images being ready. board_runattrs = self._run.GetBoardRunAttrs(self._current_board) board_runattrs.SetParallel('images_generated', True) generate_quick_provision_payloads_mock = self.PatchObject( commands, 'GenerateQuickProvisionPayloads') generate_update_payloads_mock = self.PatchObject( commands, 'GeneratePayloads') with parallel_unittest.ParallelMock(): with self.RunStageWithConfig(): if (self._run.config.upload_hw_test_artifacts and self._run.config.images): self.assertNotEqual( generate_update_payloads_mock.call_count, 0) self.assertNotEqual( generate_quick_provision_payloads_mock.call_count, 0) else: self.assertEqual(generate_update_payloads_mock.call_count, 0) self.assertEqual( generate_quick_provision_payloads_mock.call_count, 0)
def testExclusionList(self, gen_mock): """Verify files in directories of the exclusion list are excluded""" exclude_dirs = ['bin', 'usr', 'fake/dir/fake'] with parallel_unittest.ParallelMock(): ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir, exclude_dirs=exclude_dirs) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 1)
def testUploadSymbolFailureSimple(self): """Verify that when UploadSymbol fails, the error count is passed up""" def UploadSymbol(*_args, **kwargs): kwargs['num_errors'].value = 4 upload_symbols.UploadSymbol = mock.Mock(side_effect=UploadSymbol) with parallel_unittest.ParallelMock(): ret = upload_symbols.UploadSymbols('', breakpad_dir=self.tempdir, sleep=0) self.assertEquals(ret, 4)
def setUp(self): self.StartPatcher(generic_stages_unittest.ArchivingStageMixinMock()) self.StartPatcher(parallel_unittest.ParallelMock()) self.rc_mock = self.StartPatcher(cros_test_lib.RunCommandMock()) self.rc_mock.SetDefaultCmdResult(output='') self.stage = None
def setUp(self): self.StartPatcher(parallel_unittest.ParallelMock()) # Set up a general purpose cidb mock. Tests with more specific # mock requirements can replace this with a separate call to # SetupMockCidb cidb.CIDBConnectionFactory.SetupMockCidb(mock.MagicMock()) self._Prepare()
def testUploadCount(self): """Verify we can limit the number of uploaded symbols""" m = upload_symbols.UploadSymbol = mock.Mock(return_value=0) for c in xrange(3): m.reset_mock() with parallel_unittest.ParallelMock(): ret = upload_symbols.UploadSymbols('', breakpad_dir=self.tempdir, sleep=0, upload_count=c) self.assertEquals(ret, 0) self.assertEqual(m.call_count, c)
def testGenErrors(self, gen_mock): """Verify we handle errors from generation correctly""" def _SetError(*_args, **kwargs): kwargs['num_errors'].value += 1 return 1 gen_mock.side_effect = _SetError with parallel_unittest.ParallelMock(): ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir) self.assertEqual(ret, 3) self.assertEqual(gen_mock.call_count, 3)
def setUp(self): self.CreateMockOverlay('amd64-generic') self.StartPatcher(generic_stages_unittest.ArchivingStageMixinMock()) self.StartPatcher(parallel_unittest.ParallelMock()) self.rc_mock = self.StartPatcher(cros_test_lib.RunCommandMock()) self.rc_mock.SetDefaultCmdResult(output='') self.stage = None self.buildstore = FakeBuildStore()
def RunTestsWithReleaseConfig(self, release_tag): self._release_tag = release_tag with parallel_unittest.ParallelMock(): with self.RunStageWithConfig() as rc: cfg = self._run.config cmd = ['./build_image', '--version=%s' % (self._release_tag or '')] rc.assertCommandContains(cmd, expected=cfg['images']) rc.assertCommandContains(['./image_to_vm.sh'], expected=cfg['vm_tests']) cmd = ['./build_library/generate_au_zip.py', '-o', '/chroot/path'] rc.assertCommandContains(cmd, expected=cfg['images'])
def _testUploadURL(self, official, expected_url): """Helper for checking the url used""" m = upload_symbols.UploadSymbol = mock.Mock(return_value=0) with parallel_unittest.ParallelMock(): ret = upload_symbols.UploadSymbols('', official=official, breakpad_dir=self.tempdir, sleep=0) self.assertEqual(ret, 0) self.assertEqual(m.call_count, 3) for call_args in m.call_args_list: sym_file, url = call_args[0] self.assertEqual(url, expected_url) self.assertTrue(sym_file.endswith('.sym'))
def RunTestsWithReleaseConfig(self, release_tag): self._release_tag = release_tag with parallel_unittest.ParallelMock(): with self.RunStageWithConfig() as rc: cfg = self._run.config cmd = ['./build_image', '--version=%s' % (self._release_tag or '')] rc.assertCommandContains(cmd, expected=cfg['images']) rc.assertCommandContains( ['./image_to_vm.sh'], expected=cfg['vm_tests'] or cfg['tast_vm_tests'] )
def setUp(self): self.StartPatcher(generic_stages_unittest.ArchivingStageMixinMock()) self.StartPatcher(parallel_unittest.ParallelMock()) self.gen_mock = self.PatchObject(commands, 'GenerateBreakpadSymbols') self.upload_mock = self.PatchObject(commands, 'UploadSymbols') self.tar_mock = self.PatchObject(commands, 'GenerateDebugTarball') self.rc_mock = self.StartPatcher( cros_build_lib_unittest.RunCommandMock()) self.rc_mock.SetDefaultCmdResult(output='') self.stage = None
def testPerformStageWithSymbols(self): """Smoke test for an PerformStage when debugging is enabled""" # Disable parallelism, so we can see mock call counts afterwards. self.StartPatcher(parallel_unittest.ParallelMock()) self._TestPerformStage() self.assertEqual(self.gen_mock.call_count, 1) self.assertEqual(self.upload_mock.call_count, 1) self.assertEqual(self.tar_mock.call_count, 1) self.assertBoardAttrEqual('breakpad_symbols_generated', True) self.assertBoardAttrEqual('debug_tarball_generated', True)
def _testUploadURL(self, official, expected_url): """Helper for checking the url used""" self.upload_mock.return_value = 0 with parallel_unittest.ParallelMock(): ret = upload_symbols.UploadSymbols('', official=official, retry=False, breakpad_dir=self.tempdir, sleep=0) self.assertEqual(ret, 0) self.assertEqual(self.upload_mock.call_count, 3) for call_args in self.upload_mock.call_args_list: url, sym_element = call_args[0] self.assertEqual(url, expected_url) self.assertTrue( sym_element.symbol_item.sym_file.endswith('.sym'))
def testDedupeNotifyFailure(self): """Test that a dedupe server failure midway doesn't wedge things""" api_mock = mock.MagicMock() def _Contains(items): """Do not dedupe anything""" return items api_mock.contains.side_effect = _Contains # Use a list so the closure below can modify the value. item_count = [0] # Pick a number big enough to trigger a hang normally, but not so # big it adds a lot of overhead. item_limit = 50 def _Push(*_args): """Die in the middle of the push list""" item_count[0] += 1 if item_count[0] > (item_limit / 10): raise ValueError('time to die') api_mock.push.side_effect = _Push self.PatchObject(isolateserver, 'get_storage_api', return_value=api_mock) def _Uploader(*args, **kwargs): """Pass the uploaded symbol to the deduper""" sym_item = args[1] passed_queue = kwargs['passed_queue'] passed_queue.put(sym_item) self.upload_mock.side_effect = _Uploader self.upload_mock.return_value = 0 with parallel_unittest.ParallelMock(): ret = upload_symbols.UploadSymbols( '', sym_paths=[self.tempdir] * item_limit, sleep=0, dedupe_namespace='inva!id name$pace') self.assertEqual(ret, 0)
def testPerformStageNoSymbols(self): """Smoke test for an PerformStage when debugging is disabled""" # Disable parallelism, so we can see mock call counts afterwards. self.StartPatcher(parallel_unittest.ParallelMock()) extra_config = { 'archive_build_debug': False, 'vm_tests': False, 'upload_symbols': False, } result = self._TestPerformStage(extra_config) self.assertIsNone(result) self.assertEqual(self.gen_mock.call_count, 1) self.assertEqual(self.upload_mock.call_count, 0) self.assertEqual(self.tar_mock.call_count, 1) self.assertBoardAttrEqual('breakpad_symbols_generated', True) self.assertBoardAttrEqual('debug_tarball_generated', True)
def testFailedFileList(self): """Verify the failed file list is populated with the right content""" def UploadSymbol(*args, **kwargs): kwargs['failed_queue'].put(args[1].symbol_item.sym_file) kwargs['num_errors'].value = 4 self.upload_mock.side_effect = UploadSymbol with parallel_unittest.ParallelMock(): failed_list = os.path.join(self.tempdir, 'list') ret = upload_symbols.UploadSymbols('', breakpad_dir=self.tempdir, sleep=0, retry=False, failed_list=failed_list) self.assertEquals(ret, 4) # Need to sort the output as parallel/fs discovery can be unordered. got_list = sorted(osutils.ReadFile(failed_list).splitlines()) self.assertEquals(self.sym_paths, got_list)
def testMainSnapshots(self): """Test main with projects that need snapshots.""" self.mock_is_reachable.return_value = False args = self.main_args + ['--snapshot-ref', 'refs/snap'] with parallel_unittest.ParallelMock(): create_manifest_snapshot.main(args) snapshot_xml = osutils.ReadFile(self.output_file) self.mock_git_push.assert_has_calls([ mock.call(os.path.join(self.repo_root, 'project/a'), 'f01dab1e', git.RemoteRef('origin', 'refs/snap'), dry_run=False), mock.call(os.path.join(self.repo_root, 'project/b'), 'cafe1234', git.RemoteRef('origin', 'refs/snap'), dry_run=False), mock.call(os.path.join(self.repo_root, 'project/c'), 'deadbeef', git.RemoteRef('origin', 'refs/snap'), dry_run=False), mock.call(os.path.join(self.repo_root, 'dupe'), 'd1', git.RemoteRef('origin', 'refs/snap/dupe'), dry_run=False), mock.call(os.path.join(self.repo_root, 'dupe'), 'd2', git.RemoteRef('origin', 'refs/snap/dupe/1'), dry_run=False), ], any_order=True) expected = repo_manifest.Manifest.FromString(MANIFEST_XML) for project in expected.Projects(): if project.name == 'dupe': if project.revision == 'd1': project.upstream = 'refs/snap/dupe' else: project.upstream = 'refs/snap/dupe/1' else: project.upstream = 'refs/snap' expected_xml = repo_manifest_unittest.ManifestToString(expected) self.AssertXMLAlmostEqual(snapshot_xml, expected_xml)
def testSyncBoardPrebuilts(self): board = 'x86-foo' target = prebuilt.BuildTarget(board, 'aura') slave_targets = [prebuilt.BuildTarget('x86-bar', 'aura')] board_path = os.path.join(self.build_path, prebuilt._BOARD_PATH % {'board': board}) package_path = os.path.join(board_path, 'packages') url_suffix = prebuilt._REL_BOARD_PATH % { 'version': self.version, 'target': target, } packages_url_suffix = '%s/packages' % url_suffix.rstrip('/') url_value = '%s/%s/' % (self.binhost.rstrip('/'), packages_url_suffix.rstrip('/')) bar_binhost = url_value.replace('foo', 'bar') determine_mock = self.PatchObject(prebuilt, 'DeterminePrebuiltConfFile', side_effect=('bar', 'foo')) self.PatchObject(prebuilt.PrebuiltUploader, '_UploadSdkTarball') with parallel_unittest.ParallelMock(): multiprocessing.Process.exitcode = 0 uploader = prebuilt.PrebuiltUploader(self.upload_location, 'public-read', self.binhost, [], self.build_path, [], False, 'foo', False, target, slave_targets, self.version) uploader.SyncBoardPrebuilts(self.key, True, True, True, None, None, None, None, None) determine_mock.assert_has_calls([ mock.call(self.build_path, slave_targets[0]), mock.call(self.build_path, target), ]) self.upload_mock.assert_called_once_with(package_path, packages_url_suffix) self.rev_mock.assert_has_calls([ mock.call('bar', {self.key: bar_binhost}, dryrun=False), mock.call('foo', {self.key: url_value}, dryrun=False), ]) self.update_binhost_mock.assert_has_calls([ mock.call(mock.ANY, self.key, bar_binhost), mock.call(mock.ANY, self.key, url_value), ])
def testGenerateCrashStillNotifies(self): """Crashes in symbol generation should still notify external events.""" # self.skipTest('Test skipped due to crbug.com/363339') # Disable parallelism, so we can see mock call counts afterwards. self.StartPatcher(parallel_unittest.ParallelMock()) class TestError(Exception): """Unique test exception""" self.gen_mock.side_effect = TestError('mew') result = self._TestPerformStage() self.assertIsInstance(result[0], failures_lib.InfrastructureFailure) self.assertEqual(self.gen_mock.call_count, 1) self.assertEqual(self.upload_mock.call_count, 0) self.assertEqual(self.tar_mock.call_count, 0) self.assertBoardAttrEqual('breakpad_symbols_generated', False) self.assertBoardAttrEqual('debug_tarball_generated', False)
def testNormal(self, gen_mock): """Verify all the files we expect to get generated do""" with parallel_unittest.ParallelMock(): ret = cros_generate_breakpad_symbols.GenerateBreakpadSymbols( self.board, sysroot=self.board_dir) self.assertEquals(ret, 0) self.assertEquals(gen_mock.call_count, 3) # The largest ELF should be processed first. call1 = (os.path.join(self.board_dir, 'iii/large-elf'), os.path.join(self.debug_dir, 'iii/large-elf.debug')) self.assertEquals(gen_mock.call_args_list[0][0], call1) # The other ELFs can be called in any order. call2 = (os.path.join(self.board_dir, 'bin/elf'), os.path.join(self.debug_dir, 'bin/elf.debug')) call3 = (os.path.join(self.board_dir, 'usr/sbin/elf'), os.path.join(self.debug_dir, 'usr/sbin/elf.debug')) exp_calls = set((call2, call3)) actual_calls = set( (gen_mock.call_args_list[1][0], gen_mock.call_args_list[2][0])) self.assertEquals(exp_calls, actual_calls)
def setUp(self): """Setup patchers for specified bot id.""" # Mock out methods as needed. self.StartPatcher(parallel_unittest.ParallelMock()) self.StartPatcher(git_unittest.ManifestCheckoutMock()) self._CreateVersionFile() self.rc_mock = self.StartPatcher(cros_test_lib.RunCommandMock()) self.rc_mock.SetDefaultCmdResult() # We have a versioned manifest (generated by ManifestVersionSyncStage) and # the regular, user-maintained manifests. manifests = { '.repo/manifest.xml': VERSIONED_MANIFEST_CONTENTS, 'manifest/default.xml': MANIFEST_CONTENTS, 'manifest-internal/official.xml': MANIFEST_CONTENTS, } for m_path, m_content in manifests.iteritems(): full_path = os.path.join(self.build_root, m_path) osutils.SafeMakedirs(os.path.dirname(full_path)) osutils.WriteFile(full_path, m_content) self.norm_name = git.NormalizeRef(self.RELEASE_BRANCH_NAME)