Fix recursive Gerrit change query

We have a history memo list which we use to avoid infinite recursion
in the Gerrit change query, however instead of mutating it, we copy
it.  This avoids infinite recursion in some circumstances, but at the
cost of exponential repitition.  It may also allow infinite recursion
depending on the order of results in Gerrit query responses.

To correct this, mutate the memo list instead of duplicating it.

Change-Id: Ic892cf5aa2db2f5e11f8562f857d9ec0a6b60c0a
This commit is contained in:
James E. Blair 2022-03-28 14:08:08 -07:00
parent 9bd9301109
commit 38770a7867
3 changed files with 43 additions and 2 deletions

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fixed an issue in the Gerrit driver introduced in 5.2.0 which
could cause infinite loops while querying changes.

View File

@ -1536,6 +1536,44 @@ class TestGerritCircularDependencies(ZuulTestCase):
self.assertEqual(A.data["status"], "MERGED")
self.assertEqual(B.data["status"], "MERGED")
def test_submitted_together_git(self):
self.fake_gerrit._fake_submit_whole_topic = True
A = self.fake_gerrit.addFakeChange('org/project1', "master", "A",
topic='test-topic')
B = self.fake_gerrit.addFakeChange('org/project1', "master", "B",
topic='test-topic')
C = self.fake_gerrit.addFakeChange('org/project1', "master", "C",
topic='test-topic')
D = self.fake_gerrit.addFakeChange('org/project1', "master", "D",
topic='test-topic')
E = self.fake_gerrit.addFakeChange('org/project1', "master", "E",
topic='test-topic')
F = self.fake_gerrit.addFakeChange('org/project1', "master", "F",
topic='test-topic')
G = self.fake_gerrit.addFakeChange('org/project1', "master", "G",
topic='test-topic')
G.setDependsOn(F, 1)
F.setDependsOn(E, 1)
E.setDependsOn(D, 1)
D.setDependsOn(C, 1)
C.setDependsOn(B, 1)
B.setDependsOn(A, 1)
self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
self.waitUntilSettled()
self.assertEqual(len(C.patchsets[-1]["approvals"]), 1)
self.assertEqual(C.patchsets[-1]["approvals"][0]["type"], "Verified")
self.assertEqual(C.patchsets[-1]["approvals"][0]["value"], "1")
self.assertEqual(A.queried, 8)
self.assertEqual(B.queried, 8)
self.assertEqual(C.queried, 8)
self.assertEqual(D.queried, 8)
self.assertEqual(E.queried, 8)
self.assertEqual(F.queried, 8)
self.assertEqual(G.queried, 8)
@simple_layout('layouts/submitted-together-per-branch.yaml')
def test_submitted_together_per_branch(self):
self.fake_gerrit._fake_submit_whole_topic = True

View File

@ -948,8 +948,6 @@ class GerritConnection(ZKChangeCacheMixin, ZKBranchCacheMixin, BaseConnection):
def _updateChangeDependencies(self, log, change, data, event, history):
if history is None:
history = []
else:
history = history[:]
history.append((change.number, change.patchset))
needs_changes = set()