From: Stephen Finucane Date: Tue, 18 Oct 2016 20:12:05 +0000 (+0100) Subject: signals: Add callbacks for events X-Git-Tag: v2.0.0-rc1~75 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75e33665bbf571ce747082f24afd9cf87892637d;p=thirdparty%2Fpatchwork.git signals: Add callbacks for events When models are modified, fire signal handlers to create the relevant events. Signed-off-by: Stephen Finucane Tested-by: Daniel Axtens --- diff --git a/patchwork/models.py b/patchwork/models.py index 56a32490..94aaa0f5 100644 --- a/patchwork/models.py +++ b/patchwork/models.py @@ -888,6 +888,9 @@ class Event(models.Model): # TODO(stephenfin): Validate that the correct fields are being set by way # of a 'clean' method + def __repr__(self): + return " +# +# This file is part of the Patchwork package. +# +# Patchwork is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Patchwork is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Patchwork; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from django.test import TestCase + +from patchwork.models import Event +from patchwork.tests import utils + +BASE_FIELDS = ['previous_state', 'current_state', 'previous_delegate', + 'current_delegate'] + + +def _get_events(**filters): + # These are sorted by reverse normally, so reverse it once again + return Event.objects.filter(**filters).order_by('date') + + +class _BaseTestCase(TestCase): + + def assertEventFields(self, event, parent_type='patch', **fields): + for field_name in [x for x in BASE_FIELDS]: + field = getattr(event, field_name) + if field_name in fields: + self.assertEqual(field, fields[field_name]) + else: + self.assertIsNone(field) + + +class PatchCreateTest(_BaseTestCase): + + def test_patch_created(self): + """No series, so patch dependencies implicitly exist.""" + patch = utils.create_patch() + + # This should raise both the CATEGORY_PATCH_CREATED and + # CATEGORY_PATCH_COMPLETED events as there are no specific dependencies + events = _get_events(patch=patch) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) + self.assertEqual(events[0].project, patch.project) + self.assertEventFields(events[0]) + + def test_patch_dependencies_present_series(self): + """Patch dependencies already exist.""" + series_patch = utils.create_series_patch() + + # This should raise both the CATEGORY_PATCH_CREATED and + # CATEGORY_PATCH_COMPLETED events + events = _get_events(patch=series_patch.patch) + self.assertEqual(events.count(), 2) + self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) + self.assertEqual(events[0].project, series_patch.patch.project) + self.assertEqual(events[1].category, Event.CATEGORY_PATCH_COMPLETED) + self.assertEqual(events[1].project, series_patch.patch.project) + self.assertEventFields(events[0]) + self.assertEventFields(events[1]) + + def test_patch_dependencies_out_of_order(self): + series = utils.create_series() + series_patch_3 = utils.create_series_patch(series=series, number=3) + series_patch_2 = utils.create_series_patch(series=series, number=2) + + # This should only raise the CATEGORY_PATCH_CREATED event for + # both patches as they are both missing dependencies + for series_patch in [series_patch_2, series_patch_3]: + events = _get_events(patch=series_patch.patch) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) + self.assertEventFields(events[0]) + + series_patch_1 = utils.create_series_patch(series=series, number=1) + + # We should now see the CATEGORY_PATCH_COMPLETED event for all patches + # as the dependencies for all have been met + for series_patch in [series_patch_1, series_patch_2, series_patch_3]: + events = _get_events(patch=series_patch.patch) + self.assertEqual(events.count(), 2) + self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) + self.assertEqual(events[1].category, + Event.CATEGORY_PATCH_COMPLETED) + self.assertEventFields(events[0]) + self.assertEventFields(events[1]) + + def test_patch_dependencies_missing(self): + series_patch = utils.create_series_patch(number=2) + + # This should only raise the CATEGORY_PATCH_CREATED event as + # there is a missing dependency (patch 1) + events = _get_events(patch=series_patch.patch) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) + self.assertEventFields(events[0]) + + +class PatchChangedTest(_BaseTestCase): + + def test_patch_state_changed(self): + patch = utils.create_patch() + old_state = patch.state + new_state = utils.create_state() + + patch.state = new_state + patch.save() + + events = _get_events(patch=patch) + self.assertEqual(events.count(), 2) + # we don't care about the CATEGORY_PATCH_CREATED event here + self.assertEqual(events[1].category, + Event.CATEGORY_PATCH_STATE_CHANGED) + self.assertEqual(events[1].project, patch.project) + self.assertEventFields(events[1], previous_state=old_state, + current_state=new_state) + + def test_patch_delegated(self): + patch = utils.create_patch() + delegate_a = utils.create_user() + + # None -> Delegate A + + patch.delegate = delegate_a + patch.save() + + events = _get_events(patch=patch) + self.assertEqual(events.count(), 2) + # we don't care about the CATEGORY_PATCH_CREATED event here + self.assertEqual(events[1].category, + Event.CATEGORY_PATCH_DELEGATED) + self.assertEqual(events[1].project, patch.project) + self.assertEventFields(events[1], current_delegate=delegate_a) + + delegate_b = utils.create_user() + + # Delegate A -> Delegate B + + patch.delegate = delegate_b + patch.save() + + events = _get_events(patch=patch) + self.assertEqual(events.count(), 3) + self.assertEqual(events[2].category, + Event.CATEGORY_PATCH_DELEGATED) + self.assertEventFields(events[2], previous_delegate=delegate_a, + current_delegate=delegate_b) + + # Delegate B -> None + + patch.delegate = None + patch.save() + + events = _get_events(patch=patch) + self.assertEqual(events.count(), 4) + self.assertEqual(events[3].category, + Event.CATEGORY_PATCH_DELEGATED) + self.assertEventFields(events[3], previous_delegate=delegate_b) + + +class CheckCreateTest(_BaseTestCase): + + def test_check_created(self): + check = utils.create_check() + events = _get_events(created_check=check) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].category, Event.CATEGORY_CHECK_CREATED) + self.assertEqual(events[0].project, check.patch.project) + self.assertEventFields(events[0]) + + +class CoverCreateTest(_BaseTestCase): + + def test_cover_created(self): + cover = utils.create_cover() + events = _get_events(cover=cover) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].category, Event.CATEGORY_COVER_CREATED) + self.assertEqual(events[0].project, cover.project) + self.assertEventFields(events[0]) + + +class SeriesCreateTest(_BaseTestCase): + + def test_series_created(self): + series = utils.create_series() + events = _get_events(series=series) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].category, Event.CATEGORY_SERIES_CREATED) + self.assertEqual(events[0].project, series.project) + self.assertEventFields(events[0]) diff --git a/patchwork/tests/utils.py b/patchwork/tests/utils.py index 0c6f7634..3d0293ca 100644 --- a/patchwork/tests/utils.py +++ b/patchwork/tests/utils.py @@ -33,6 +33,7 @@ from patchwork.models import Patch from patchwork.models import Person from patchwork.models import Project from patchwork.models import Series +from patchwork.models import SeriesPatch from patchwork.models import SeriesReference from patchwork.models import State from patchwork.tests import TEST_PATCH_DIR @@ -233,6 +234,20 @@ def create_series(**kwargs): return Series.objects.create(**values) +def create_series_patch(**kwargs): + """Create 'SeriesPatch' object.""" + num = 1 if 'series' not in kwargs else kwargs['series'].patches.count() + 1 + + values = { + 'series': create_series() if 'series' not in kwargs else None, + 'number': num, + 'patch': create_patch() if 'patch' not in kwargs else None, + } + values.update(**kwargs) + + return SeriesPatch.objects.create(**values) + + def create_series_reference(**kwargs): """Create 'SeriesReference' object.""" values = {