|
19 | 19 |
|
20 | 20 | import debug # pyflakes:ignore |
21 | 21 |
|
22 | | -from ietf.doc.expire import get_expired_drafts, send_expire_notice_for_draft, expire_draft |
23 | | -from ietf.doc.factories import EditorialDraftFactory, IndividualDraftFactory, WgDraftFactory, RgDraftFactory, DocEventFactory |
| 22 | +from ietf.doc.expire import expirable_drafts, get_expired_drafts, repair_dead_on_expire, send_expire_notice_for_draft, expire_draft |
| 23 | +from ietf.doc.factories import EditorialDraftFactory, IndividualDraftFactory, StateDocEventFactory, WgDraftFactory, RgDraftFactory, DocEventFactory |
24 | 24 | from ietf.doc.models import ( Document, DocReminder, DocEvent, |
25 | | - ConsensusDocEvent, LastCallDocEvent, RelatedDocument, State, TelechatDocEvent, |
| 25 | + ConsensusDocEvent, LastCallDocEvent, RelatedDocument, State, StateDocEvent, TelechatDocEvent, |
26 | 26 | WriteupDocEvent, DocRelationshipName, IanaExpertDocEvent ) |
27 | 27 | from ietf.doc.utils import get_tags_for_stream_id, create_ballot_if_not_open |
28 | 28 | from ietf.doc.views_draft import AdoptDraftForm |
|
36 | 36 | from ietf.utils.test_utils import login_testing_unauthorized |
37 | 37 | from ietf.utils.mail import outbox, empty_outbox, get_payload_text |
38 | 38 | from ietf.utils.test_utils import TestCase |
39 | | -from ietf.utils.timezone import date_today, datetime_from_date, DEADLINE_TZINFO |
| 39 | +from ietf.utils.timezone import date_today, datetime_today, datetime_from_date, DEADLINE_TZINFO |
40 | 40 |
|
41 | 41 |
|
42 | 42 | class ChangeStateTests(TestCase): |
@@ -763,13 +763,16 @@ def test_expire_drafts(self): |
763 | 763 | txt = "%s-%s.txt" % (draft.name, draft.rev) |
764 | 764 | self.write_draft_file(txt, 5000) |
765 | 765 |
|
| 766 | + self.assertFalse(expirable_drafts(Document.objects.filter(pk=draft.pk)).exists()) |
| 767 | + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="idexists")) |
| 768 | + self.assertTrue(expirable_drafts(Document.objects.filter(pk=draft.pk)).exists()) |
766 | 769 | expire_draft(draft) |
767 | 770 |
|
768 | 771 | draft = Document.objects.get(name=draft.name) |
769 | 772 | self.assertEqual(draft.get_state_slug(), "expired") |
770 | | - self.assertEqual(draft.get_state_slug("draft-iesg"), "dead") |
| 773 | + self.assertEqual(draft.get_state_slug("draft-iesg"), "idexists") |
771 | 774 | self.assertTrue(draft.latest_event(type="expired_document")) |
772 | | - self.assertCountEqual(draft.action_holders.all(), []) |
| 775 | + self.assertEqual(draft.action_holders.count(), 0) |
773 | 776 | self.assertIn('Removed all action holders', draft.latest_event(type='changed_action_holders').desc) |
774 | 777 | self.assertTrue(not os.path.exists(os.path.join(settings.INTERNET_DRAFT_PATH, txt))) |
775 | 778 | self.assertTrue(os.path.exists(os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, txt))) |
@@ -842,6 +845,77 @@ def test_clean_up_draft_files(self): |
842 | 845 | self.assertTrue(not os.path.exists(os.path.join(settings.INTERNET_DRAFT_PATH, txt))) |
843 | 846 | self.assertTrue(os.path.exists(os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, txt))) |
844 | 847 |
|
| 848 | + @mock.patch("ietf.community.signals.notify_of_event") |
| 849 | + def test_repair_dead_on_expire(self, mock_notify): |
| 850 | + |
| 851 | + # Create a draft in iesg idexists - ensure it doesn't get new docevents. |
| 852 | + # Create a draft in iesg dead with no expires within the window - ensure it doesn't get new docevents and its state doesn't change. |
| 853 | + # Create a draft in iesg dead with an expiry in the window - ensure it gets the right doc events, iesg state changes, draft state doesn't change. |
| 854 | + last_year = datetime_today() - datetime.timedelta(days=365) |
| 855 | + |
| 856 | + not_dead = WgDraftFactory(name="draft-not-dead") |
| 857 | + not_dead_event_count = not_dead.docevent_set.count() |
| 858 | + |
| 859 | + dead_not_from_expires = WgDraftFactory(name="draft-dead-not-from-expiring") |
| 860 | + dead_not_from_expires.set_state( |
| 861 | + State.objects.get(type="draft-iesg", slug="dead") |
| 862 | + ) |
| 863 | + StateDocEventFactory( |
| 864 | + doc=dead_not_from_expires, state=("draft-iesg", "dead"), time=last_year |
| 865 | + ) |
| 866 | + DocEventFactory( |
| 867 | + doc=dead_not_from_expires, |
| 868 | + type="expired_document", |
| 869 | + time=last_year + datetime.timedelta(days=1), |
| 870 | + ) |
| 871 | + dead_not_from_expires_event_count = dead_not_from_expires.docevent_set.count() |
| 872 | + |
| 873 | + dead_from_expires = [] |
| 874 | + dead_from_expires_event_count = dict() |
| 875 | + for delta in [-5, 5]: |
| 876 | + d = WgDraftFactory( |
| 877 | + name=f"draft-dead-from-expiring-just-{'before' if delta<0 else 'after'}" |
| 878 | + ) |
| 879 | + d.set_state(State.objects.get(type="draft-iesg", slug="dead")) |
| 880 | + StateDocEventFactory(doc=d, state=("draft-iesg", "dead"), time=last_year) |
| 881 | + DocEventFactory( |
| 882 | + doc=d, |
| 883 | + type="expired_document", |
| 884 | + time=last_year + datetime.timedelta(seconds=delta), |
| 885 | + ) |
| 886 | + dead_from_expires.append(d) |
| 887 | + dead_from_expires_event_count[d] = d.docevent_set.count() |
| 888 | + |
| 889 | + notified_during_factory_work = mock_notify.call_count |
| 890 | + for call_args in mock_notify.call_args_list: |
| 891 | + e = call_args.args[0] |
| 892 | + self.assertTrue(isinstance(e,DocEvent)) |
| 893 | + self.assertFalse(hasattr(e,"skip_community_list_notification")) |
| 894 | + |
| 895 | + repair_dead_on_expire() |
| 896 | + |
| 897 | + self.assertEqual(not_dead.docevent_set.count(), not_dead_event_count) |
| 898 | + self.assertEqual( |
| 899 | + dead_not_from_expires.docevent_set.count(), |
| 900 | + dead_not_from_expires_event_count, |
| 901 | + ) |
| 902 | + for d in dead_from_expires: |
| 903 | + self.assertEqual( |
| 904 | + d.docevent_set.count(), dead_from_expires_event_count[d] + 2 |
| 905 | + ) |
| 906 | + self.assertIn( |
| 907 | + "due only to document expiry", d.latest_event(type="added_comment").desc |
| 908 | + ) |
| 909 | + self.assertEqual( |
| 910 | + d.latest_event(StateDocEvent).desc, |
| 911 | + "IESG state changed to <b>I-D Exists</b> from Dead", |
| 912 | + ) |
| 913 | + self.assertEqual(mock_notify.call_count, 4+notified_during_factory_work) |
| 914 | + for call_args in mock_notify.call_args_list[-4:]: |
| 915 | + e = call_args.args[0] |
| 916 | + self.assertTrue(isinstance(e,DocEvent)) |
| 917 | + self.assertTrue(hasattr(e,"skip_community_list_notification")) |
| 918 | + self.assertTrue(e.skip_community_list_notification) |
845 | 919 |
|
846 | 920 | class ExpireLastCallTests(TestCase): |
847 | 921 | def test_expire_last_call(self): |
|
0 commit comments