def test_handles_output(self): spawner, process = self._makeSpawnerAndProcess() stdout_handler = FakeMethod() spawner.start("ls", stdout_handler=stdout_handler) write_and_flush(process.stdout_sink, "readme.txt\n") spawner.communicate() self.assertEqual([("readme.txt\n", )], stdout_handler.extract_args())
def test_handleUnpushedBranch_mails_branch_owner(self): exporter = ExportTranslationsToBranch(test_args=[]) exporter.logger = BufferLogger() productseries = self.factory.makeProductSeries() email = self.factory.getUniqueEmailAddress() branch_owner = self.factory.makePerson(email=email) productseries.translations_branch = self.factory.makeBranch( owner=branch_owner) exporter._exportToBranch = FakeMethod(failure=NotBranchError("Ow")) exporter._sendMail = FakeMethod() self.becomeDbUser('translationstobranch') exporter._exportToBranches([productseries]) self.assertEqual(1, exporter._sendMail.call_count) (sender, recipients, subject, text), kwargs = (exporter._sendMail.calls[-1]) self.assertIn(config.canonical.noreply_from_address, sender) self.assertIn(email, recipients) self.assertEqual("Launchpad: translations branch has not been set up.", subject) self.assertIn("problem with translations branch synchronization", text) self.assertIn(productseries.title, text) self.assertIn(productseries.translations_branch.bzr_identity, text) self.assertIn('bzr push lp://', text)
def test_scan_aborts_lost_slave_with_job(self): # SlaveScanner.scan uses BuilderInteractor.rescueIfLost to abort # slaves that don't have the expected job. slave = BuildingSlave('nontrivial') bq = FakeBuildQueue() # Instrument updateBuild. interactor = BuilderInteractor() interactor.updateBuild = FakeMethod() scanner = SlaveScanner('mock', MockBuilderFactory(MockBuilder(), bq), BufferLogger(), interactor_factory=FakeMethod(interactor), slave_factory=FakeMethod(slave), behavior_factory=FakeMethod(TrivialBehavior())) # XXX: checkCancellation needs more than a FakeBuildQueue. scanner.checkCancellation = FakeMethod(defer.succeed(False)) # A single scan will call status(), notice that the slave is # lost, abort() the slave, then reset() the job without calling # updateBuild(). yield scanner.scan() self.assertEqual(['status', 'abort'], slave.call_log) self.assertEqual(0, interactor.updateBuild.call_count) self.assertEqual(1, bq.reset.call_count)
def setUp(self): super(TestStoreChannelsWidget, self).setUp() field = List(__name__="channels", title="Store channels") self.context = self.factory.makeSnap() field = field.bind(self.context) request = LaunchpadTestRequest() self.widget = StoreChannelsWidget(field, None, request) # setup fake store client response for available channels/risks self.risks = [ { "name": "stable", "display_name": "Stable" }, { "name": "candidate", "display_name": "Candidate" }, { "name": "beta", "display_name": "Beta" }, { "name": "edge", "display_name": "Edge" }, ] snap_store_client = FakeMethod() snap_store_client.listChannels = FakeMethod(result=self.risks) self.useFixture(ZopeUtilityFixture(snap_store_client, ISnapStoreClient))
def test_handles_output(self): spawner, process = self._makeSpawnerAndProcess() stdout_handler = FakeMethod() spawner.start("ls", stdout_handler=stdout_handler) write_and_flush(process.stdout_sink, "readme.txt\n") spawner.communicate() self.assertEqual([("readme.txt\n", )], stdout_handler.extract_args())
def test_handles_error_output(self): spawner, process = self._makeSpawnerAndProcess() stderr_handler = FakeMethod() spawner.start("ls", stderr_handler=stderr_handler) write_and_flush(process.stderr_sink, "File not found.\n") spawner.communicate() self.assertEqual( [("File not found.\n", )], stderr_handler.extract_args())
def test_handles_output_before_completion(self): spawner, process = self._makeSpawnerAndProcess(returncode=0) handler = FakeMethod() spawner.start( "hello", stdout_handler=handler, completion_handler=handler) write_and_flush(process.stdout_sink, "Hello\n") spawner.complete() self.assertEqual([("Hello\n", ), (0, )], handler.extract_args())
def test_handles_error_output(self): spawner, process = self._makeSpawnerAndProcess() stderr_handler = FakeMethod() spawner.start("ls", stderr_handler=stderr_handler) write_and_flush(process.stderr_sink, "File not found.\n") spawner.communicate() self.assertEqual([("File not found.\n", )], stderr_handler.extract_args())
def test_handles_output_before_completion(self): spawner, process = self._makeSpawnerAndProcess(returncode=0) handler = FakeMethod() spawner.start("hello", stdout_handler=handler, completion_handler=handler) write_and_flush(process.stdout_sink, "Hello\n") spawner.complete() self.assertEqual([("Hello\n", ), (0, )], handler.extract_args())
class FakeUploadPolicy: def __init__(self, spph): self.distroseries = spph.distroseries self.archive = spph.distroseries.main_archive self.pocket = spph.pocket self.redirect_warning = None setDistroSeriesAndPocket = FakeMethod() validateUploadType = FakeMethod() checkUpload = FakeMethod()
def test_createIndexes_marks_index_creation_complete(self): # createIndexes calls markIndexCreationComplete for the suite. distro = self.makeDistroWithPublishDirectory() series = self.factory.makeDistroSeries(distribution=distro) script = self.makeScript(distro) script.markIndexCreationComplete = FakeMethod() script.runPublishDistro = FakeMethod() suite = get_a_suite(series) script.createIndexes(distro, [suite]) self.assertEqual([((distro, suite), {})], script.markIndexCreationComplete.calls)
def test_correct_opal_signing_command_executed_no_keys(self): # Check that calling signOpal() will generate no commands when # no keys are present. self.setUpOpalKeys(create=False) fake_call = FakeMethod(result=0) self.useFixture(MonkeyPatch("subprocess.call", fake_call)) upload = SigningUpload() upload.generateOpalKeys = FakeMethod() upload.setTargetDirectory(self.archive, "test_1.0_amd64.tar.gz", "distroseries") upload.signOpal('t.opal') self.assertEqual(0, fake_call.call_count) self.assertEqual(0, upload.generateOpalKeys.call_count)
def test_commit_uses_getBzrCommitterID(self): # commit() passes self.getBzrCommitterID() to bzr as the # committer. bzr_id = self.factory.getUniqueString() self.committer.getBzrCommitterID = FakeMethod(result=bzr_id) fake_commit = FakeMethod() self.committer.transform_preview.commit = fake_commit self.committer.writeFile('x', b'y') self.committer.commit('') commit_args, commit_kwargs = fake_commit.calls[-1] self.assertEqual(bzr_id, commit_kwargs['committer'])
def process(self): self.tarfile.close() self.buffer.close() upload = UefiUpload() upload.signUefi = FakeMethod() upload.signKmod = FakeMethod() # Under no circumstances is it safe to execute actual commands. fake_call = FakeMethod(result=0) self.useFixture(MonkeyPatch("subprocess.call", fake_call)) upload.process(self.archive, self.path, self.suite) self.assertEqual(0, fake_call.call_count) return upload
def test_handles_multiple_processes(self): spawner = CommandSpawner() handler = FakeMethod() first_process = FakeProcess(returncode=1) instrument_spawn(spawner, first_process) spawner.start(["/bin/echo", "1"], completion_handler=handler) second_process = FakeProcess(returncode=2) instrument_spawn(spawner, second_process) spawner.start(["/bin/echo", "2"], completion_handler=handler) spawner.complete() self.assertContentEqual([(1, ), (2, )], handler.extract_args())
def test_handles_multiple_processes(self): spawner = CommandSpawner() handler = FakeMethod() first_process = FakeProcess(returncode=1) instrument_spawn(spawner, first_process) spawner.start(["/bin/echo", "1"], completion_handler=handler) second_process = FakeProcess(returncode=2) instrument_spawn(spawner, second_process) spawner.start(["/bin/echo", "2"], completion_handler=handler) spawner.complete() self.assertContentEqual([(1, ), (2, )], handler.extract_args())
class FakeChangesFile: def __init__(self, spph, file_path): self.files = [] self.filepath = file_path self.filename = os.path.basename(file_path) self.architectures = ['i386'] self.suite_name = '-'.join([spph.distroseries.name, spph.pocket.name]) self.raw_content = open(file_path).read() self.signingkey = None parseChanges = FakeMethod([]) checkFileName = FakeMethod([]) processAddresses = FakeMethod([]) processFiles = FakeMethod([]) verify = FakeMethod([UploadError("Deliberately broken")])
def test_failed_index_creation_is_not_marked_complete(self): # If index creation fails, it is not marked as having been # completed. The next run will retry. class Boom(Exception): """Simulated failure.""" series = self.factory.makeDistroSeries() script = self.makeScript(series.distribution) script.markIndexCreationComplete = FakeMethod() script.runPublishDistro = FakeMethod(failure=Boom("Sorry!")) try: script.createIndexes(series.distribution, [get_a_suite(series)]) except: pass self.assertEqual([], script.markIndexCreationComplete.calls)
def test_correct_opal_keygen_command_executed(self): # Check that calling generateOpalKeys() will generate the # expected command. self.setUpPPA() self.setUpOpalKeys(create=False) fake_call = FakeMethod(result=0) self.useFixture(MonkeyPatch("subprocess.call", fake_call)) upload = SigningUpload() upload.setTargetDirectory(self.archive, "test_1.0_amd64.tar.gz", "distroseries") upload.generateOpalKeys() self.assertEqual(2, fake_call.call_count) # Assert the actual command matches. args = fake_call.calls[0][0][0] # Sanitise the keygen tmp file. if args[11].endswith('.keygen'): args[11] = 'XXX.keygen' expected_cmd = [ 'openssl', 'req', '-new', '-nodes', '-utf8', '-sha512', '-days', '3650', '-batch', '-x509', '-config', 'XXX.keygen', '-outform', 'PEM', '-out', self.opal_pem, '-keyout', self.opal_pem ] self.assertEqual(expected_cmd, args) args = fake_call.calls[1][0][0] expected_cmd = [ 'openssl', 'x509', '-in', self.opal_pem, '-outform', 'DER', '-out', self.opal_x509 ] self.assertEqual(expected_cmd, args)
class FakeScript(LaunchpadScript): """A dummy script that only records which feature controller is active.""" observed_feature_controller = object() def __init__(self, name): super(FakeScript, self).__init__(name=name, test_args=[]) def main(self): self.observed_feature_controller = get_relevant_feature_controller() # Shortcut some underpinnings of LaunchpadScript.run that we can't # afford to have happen in tests. _init_zca = FakeMethod() _init_db = FakeMethod() record_activity = FakeMethod()
def test_prepareFreshSeries_copies_custom_uploads(self): distro = self.makeDistroWithPublishDirectory() old_series = self.factory.makeDistroSeries(distribution=distro, status=SeriesStatus.CURRENT) new_series = self.factory.makeDistroSeries(distribution=distro, previous_series=old_series, status=SeriesStatus.FROZEN) self.factory.makeDistroArchSeries(distroseries=new_series, architecturetag='i386') custom_upload = self.factory.makeCustomPackageUpload( distroseries=old_series, custom_type=PackageUploadCustomFormat.DEBIAN_INSTALLER, filename='debian-installer-images_1.0-20110805_i386.tar.gz') script = self.makeScript(distro) script.createIndexes = FakeMethod() script.setUp() have_fresh_series = script.prepareFreshSeries(distro) self.assertTrue(have_fresh_series) [copied_upload ] = new_series.getPackageUploads(name=u'debian-installer-images', exact_match=False) [copied_custom] = copied_upload.customfiles self.assertEqual( custom_upload.customfiles[0].libraryfilealias.filename, copied_custom.libraryfilealias.filename)
def test_fail_to_resume_slave_resets_job(self): # If an attempt to resume and dispatch a slave fails, it should # reset the job via job.reset() # Make a slave with a failing resume() method. slave = OkSlave() slave.resume = lambda: deferLater(reactor, 0, defer.fail, Failure(('out', 'err', 1))) # Reset sampledata builder. builder = removeSecurityProxy( getUtility(IBuilderSet)[BOB_THE_BUILDER_NAME]) self._resetBuilder(builder) self.assertEqual(0, builder.failure_count) self.patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(slave)) builder.vm_host = "fake_vm_host" scanner = self._getScanner() # Get the next job that will be dispatched. job = removeSecurityProxy(builder._findBuildCandidate()) job.virtualized = True builder.virtualized = True transaction.commit() yield scanner.singleCycle() # The failure_count will have been incremented on the builder, we # can check that to see that a dispatch attempt did indeed occur. self.assertEqual(1, builder.failure_count) # There should also be no builder set on the job. self.assertIsNone(job.builder) build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job) self.assertEqual(build.status, BuildStatus.NEEDSBUILD)
def test_countCalls(self): # A FakeMethod counts the number of times it's been invoked. func = FakeMethod() for count in range(3): self.assertEqual(count, func.call_count) func() self.assertEqual(count + 1, func.call_count)
def test_multiple_parents_do_not_close_bugs(self): # The initialization does not close the bugs on the copied # publications (and thus does not try to access the bug table). parent1, parent2 = self.setUpParents(packages1={'p1': '0.1-1'}, packages2={'p2': '2.1'}) child = self.factory.makeDistroSeries() switch_dbuser('initializedistroseries') # Patch close_bugs_for_sourcepublication to be able to record if # the method has been called. fakeCloseBugs = FakeMethod() from lp.soyuz.scripts import packagecopier as packagecopier_module self.patch(packagecopier_module, 'close_bugs_for_sourcepublication', fakeCloseBugs) child = self._fullInitialize([parent1, parent2], child=child) # Make sure the initialization was successful. self.assertBinPackagesAndVersions(child, [(u'p1', u'0.1-1'), (u'p2', u'2.1')]) # Assert that close_bugs_for_sourcepublication has not been # called. self.assertEqual(0, fakeCloseBugs.call_count) # Switch back to launchpad_main to be able to cleanup the # feature flags. switch_dbuser('launchpad_main')
def test_scan_skipped_if_builderfactory_stale(self): # singleCycle does nothing if the BuilderFactory's update # timestamp is older than the end of the previous scan. This # prevents eg. a scan after a dispatch from failing to notice # that a build has been dispatched. pbf = PrefetchedBuilderFactory() pbf.update() scanner = self._getScanner(builder_factory=pbf) fake_scan = FakeMethod() def _fake_scan(): fake_scan() return defer.succeed(None) scanner.scan = _fake_scan self.assertEqual(0, fake_scan.call_count) # An initial cycle triggers a scan. yield scanner.singleCycle() self.assertEqual(1, fake_scan.call_count) # But a subsequent cycle without updating BuilderFactory's data # is a no-op. yield scanner.singleCycle() self.assertEqual(1, fake_scan.call_count) # Updating the BuilderFactory causes scans to resume. pbf.update() yield scanner.singleCycle() self.assertEqual(2, fake_scan.call_count)
def test_reportApprovalConflict_sets_error_output_just_once(self): # Repeated occurrence of the same approval conflict will not # result in repeated setting of error_output. series = self.factory.makeProductSeries() domain = self.factory.getUniqueString() templates = [ self.factory.makePOTemplate(productseries=series, translation_domain=domain) for counter in range(3) ] entry = removeSecurityProxy( self.factory.makeTranslationImportQueueEntry()) entry.reportApprovalConflict(domain, len(templates), templates) original_error = entry.error_output transaction.commit() # Try reporting the conflict again, with the templates # reshuffled to see if reportApprovalConflict can be fooled into # thinking it's a different error. Make as sure as we can that # entry.error_output is not modified. slave_entry = ISlaveStore(entry).get(TranslationImportQueueEntry, entry.id) slave_entry.setErrorOutput = FakeMethod() slave_entry.reportApprovalConflict(domain, len(templates), reversed(templates)) self.assertEqual(original_error, slave_entry.error_output) self.assertIn(domain, original_error) self.assertEqual(0, slave_entry.setErrorOutput.call_count)
def process(self): self.archive.close() self.buffer.close() upload = UefiUpload() upload.sign = FakeMethod() upload.process(self.pubconf, self.path, self.suite) return upload
def _assertFailureCounting(self, builder_count, job_count, expected_builder_count, expected_job_count): # If scan() fails with an exception, failure_counts should be # incremented. What we do with the results of the failure # counts is tested below separately, this test just makes sure that # scan() is setting the counts. def failing_scan(): return defer.fail(Exception("fake exception")) scanner = self._getScanner() scanner.scan = failing_scan from lp.buildmaster import manager as manager_module self.patch(manager_module, 'assessFailureCounts', FakeMethod()) builder = getUtility(IBuilderSet)[scanner.builder_name] builder.failure_count = builder_count naked_job = removeSecurityProxy(builder.currentjob.specific_job) naked_job.build.failure_count = job_count # The _scanFailed() calls abort, so make sure our existing # failure counts are persisted. transaction.commit() # singleCycle() calls scan() which is our fake one that throws an # exception. yield scanner.singleCycle() # Failure counts should be updated, and the assessment method # should have been called. The actual behaviour is tested below # in TestFailureAssessments. self.assertEqual(expected_builder_count, builder.failure_count) self.assertEqual(expected_job_count, builder.currentjob.specific_job.build.failure_count) self.assertEqual(1, manager_module.assessFailureCounts.call_count)
def setUp(self): super(TestHandleStatusMixin, self).setUp() self.factory = LaunchpadObjectFactory() self.build = self.makeBuild() # For the moment, we require a builder for the build so that # handleStatus_OK can get a reference to the slave. self.builder = self.factory.makeBuilder() self.build.buildqueue_record.markAsBuilding(self.builder) self.slave = WaitingSlave('BuildStatus.OK') self.slave.valid_file_hashes.append('test_file_hash') self.interactor = BuilderInteractor() self.behaviour = self.interactor.getBuildBehaviour( self.build.buildqueue_record, self.builder, self.slave) # We overwrite the buildmaster root to use a temp directory. tempdir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, tempdir) self.upload_root = tempdir tmp_builddmaster_root = """ [builddmaster] root: %s """ % self.upload_root config.push('tmp_builddmaster_root', tmp_builddmaster_root) # We stub out our builds getUploaderCommand() method so # we can check whether it was called as well as # verifySuccessfulUpload(). removeSecurityProxy( self.build).verifySuccessfulUpload = FakeMethod(result=True)
def test_publish_recovers_working_dists_on_ctrl_C(self): # If the user hits ctrl-C while publishing, the publish method # recovers its working directory. failure = KeyboardInterrupt("Ctrl-C!") script = self.makeScript() script.publishDistroUploads = FakeMethod(failure=failure) script.recoverArchiveWorkingDir = FakeMethod() script.setUp() try: script.publish(script.distributions[0]) except KeyboardInterrupt: pass self.assertEqual(1, script.recoverArchiveWorkingDir.call_count)
def test_run(self): _, _, job = self.makeJob() method = FakeMethod() removeSecurityProxy(job).attachTranslationFiles = method transaction.commit() _, job.run() self.assertEqual(method.call_count, 1)
def test_security_run_publishes_only_security_updates(self): script = self.makeScript(extra_args=['--security-only']) script.publish = FakeMethod() script.main() self.assertEqual(1, script.publish.call_count) args, kwargs = script.publish.calls[0] self.assertEqual({'security_only': True}, kwargs)
def test_takeArguments(self): # A FakeMethod invocation accepts any arguments it gets. func = FakeMethod() func() func(1) func(2, kwarg=3) self.assertEqual(3, func.call_count)
def test_does_not_call_completion_handler_twice(self): spawner, process = self._makeSpawnerAndProcess(returncode=0) completion_handler = FakeMethod() spawner.start("echo", completion_handler=completion_handler) spawner.complete() spawner.complete() self.assertEqual(1, completion_handler.call_count)