|
| 1 | +""" |
| 2 | +Query-count regression test for pushing a finding group to JIRA. |
| 3 | +
|
| 4 | +Regression: DJANGO-42P8 — push_finding_group_to_jira loaded the group without |
| 5 | +prefetching its findings, so the JIRA helpers it fans out to (jira_description, |
| 6 | +jira_priority, get_sla_deadline, get_labels, get_tags, ...) each re-ran |
| 7 | +finding_group.findings.all(), producing an N+1 on dojo_finding_group_findings. |
| 8 | +""" |
| 9 | +from unittest.mock import patch |
| 10 | + |
| 11 | +from django.test import TestCase |
| 12 | + |
| 13 | +from dojo.jira.helper import push_finding_group_to_jira |
| 14 | +from dojo.models import Dojo_User, Finding, Finding_Group, Test |
| 15 | +from unittests.dojo_test_case import versioned_fixtures |
| 16 | + |
| 17 | + |
| 18 | +@versioned_fixtures |
| 19 | +class JiraFindingGroupPushQueryCountTest(TestCase): |
| 20 | + fixtures = ["dojo_testdata.json"] |
| 21 | + |
| 22 | + def _make_group(self, num_findings: int) -> Finding_Group: |
| 23 | + test = Test.objects.first() |
| 24 | + admin = Dojo_User.objects.get(username="admin") |
| 25 | + group = Finding_Group.objects.create(test=test, name="perf group", creator=admin) |
| 26 | + group.findings.add(*list(Finding.objects.all()[:num_findings])) |
| 27 | + return group |
| 28 | + |
| 29 | + @patch("dojo.jira.helper.add_jira_issue") |
| 30 | + @patch("dojo.jira.helper.update_jira_issue") |
| 31 | + def test_group_findings_prefetched_before_jira_helpers(self, mock_update, mock_add): |
| 32 | + """ |
| 33 | + The group handed to the JIRA helpers must have its findings prefetched. |
| 34 | +
|
| 35 | + The real helpers read finding_group.findings.all() several times; if the |
| 36 | + group is prefetched those reads hit the prefetch (0 queries). Without the |
| 37 | + fix each read is a fresh dojo_finding_group_findings query (N+1). |
| 38 | + """ |
| 39 | + group = self._make_group(5) |
| 40 | + |
| 41 | + def _simulate_jira_helpers(obj, *args, **kwargs): |
| 42 | + with self.assertNumQueries(0): |
| 43 | + for _ in range(5): |
| 44 | + list(obj.findings.all()) |
| 45 | + return "ok", True |
| 46 | + |
| 47 | + mock_add.side_effect = _simulate_jira_helpers |
| 48 | + push_finding_group_to_jira(group.id) |
| 49 | + mock_add.assert_called_once() |
0 commit comments