def testApplyPartialFailures(self): """Test that can apply changes correctly when one change fails to apply. This tests a simple change order where 1 depends on 2 and 1 fails to apply. Only 1 should get tried as 2 will abort once it sees that 1 can't be applied. 3 with no dependencies should go through fine. Since patch1 fails to apply, we should also get a call to handle the failure. """ series = self.GetPatchSeries() patch1, patch2, patch3, patch4 = patches = self.GetPatches(4) self.SetPatchDeps(patch1) self.SetPatchDeps(patch2, [patch1.id]) self.SetPatchDeps(patch3) self.SetPatchDeps(patch4) self.SetPatchApply(patch1).AndRaise( cros_patch.ApplyPatchException(patch1)) self.SetPatchApply(patch3) self.SetPatchApply(patch4).AndRaise( cros_patch.ApplyPatchException(patch1, inflight=True)) self.mox.ReplayAll() self.assertResults(series, patches, [patch3], [patch2, patch1], [patch4]) self.mox.VerifyAll()
def testHandleApplyFailure(self): failures = [ cros_patch.ApplyPatchException(x) for x in self.GetPatches(4) ] notified_patches = failures[:2] unnotified_patches = failures[2:] master_pool = self.MakePool(dryrun=False) slave_pool = self.MakePool(is_master=False) self.mox.StubOutWithMock(gerrit.GerritHelper, 'RemoveCommitReady') for failure in notified_patches: master_pool._SendNotification( failure.patch, mox.StrContains('failed to apply your change'), failure=mox.IgnoreArg()) # This pylint suppressin shouldn't be necessary, but pylint is invalidly # thinking that the first arg isn't passed in; we suppress it to suppress # the pylnt bug. # pylint: disable=E1120 gerrit.GerritHelper.RemoveCommitReady(failure.patch, dryrun=False) self.mox.ReplayAll() master_pool._HandleApplyFailure(notified_patches) slave_pool._HandleApplyFailure(unnotified_patches) self.mox.VerifyAll()
def testFilterDependencyErrors(self): """Verify that dependency errors are correctly filtered out.""" failures = [cros_patch.ApplyPatchException(x) for x in self.GetPatches(2)] failures += [cros_patch.DependencyError(x, y) for x, y in zip(self.GetPatches(2), failures)] failures[0].patch.approval_timestamp = time.time() failures[-1].patch.approval_timestamp = time.time() self.mox.ReplayAll() result = validation_pool.ValidationPool._FilterDependencyErrors(failures) self.assertEquals(set(failures[:-1]), set(result)) self.mox.VerifyAll()
def testComplexCyclicalDeps(self, fail=False): """Verify handling of two interdependent cycles.""" series = self.GetPatchSeries() # Create two cyclically interdependent patch chains. # Example: Two patch series A1<-A2<-A3<-A4 and B1<-B2<-B3<-B4. A1 has a # CQ-DEPEND on B4 and B1 has a CQ-DEPEND on A4, so all of the patches must # be committed together. chain1, chain2 = chains = self.GetPatches(4), self.GetPatches(4) for chain in chains: (other_chain, ) = [x for x in chains if x != chain] self.SetPatchDeps(chain[0], [], cq=[other_chain[-1].id]) for i in range(1, len(chain)): self.SetPatchDeps(chain[i], [chain[i - 1].id]) # Apply the second-last patch first, so that the last patch in the series # will be pulled in via the CQ-DEPEND on the other patch chain. to_apply = [chain1[-2] ] + [x for x in (chain1 + chain2) if x != chain1[-2]] # Mark all the patches but the last ones as applied successfully. for patch in chain1 + chain2[:-1]: self.SetPatchApply(patch) if fail: # Pretend that chain2[-1] failed to apply. res = self.SetPatchApply(chain2[-1]) res.AndRaise(cros_patch.ApplyPatchException(chain1[-1])) applied = [] failed_tot = to_apply else: # We apply the patches in this order since the last patch in chain1 # is pulled in via CQ-DEPEND. self.SetPatchApply(chain2[-1]) applied = chain1[:2] + chain2[:-1] + chain1[2:] + chain2[-1:] failed_tot = [] self.mox.ReplayAll() self.assertResults(series, to_apply, applied=applied, failed_tot=failed_tot) self.mox.VerifyAll()
def MakeFailure(self, patch, inflight=True): return cros_patch.ApplyPatchException(patch, inflight=inflight)