From 45b14c83a7c6cf0e7930fd5cb5301d942bbbb7f6 Mon Sep 17 00:00:00 2001 From: Russ Housley Date: Sat, 13 Mar 2021 17:30:35 +0000 Subject: [PATCH] Convert generate-draft-aliaes and generate-wg-aliases into management commands: generate_draft_aliases and generate_group_aliases. Also provide tests for the new management commands. - Legacy-Id: 18913 --- ietf/checks.py | 10 +- .../commands/generate_draft_aliases.py | 163 ++++++++++++++++++ ietf/doc/tests.py | 120 ++++++++++++- .../commands/generate_group_aliases.py | 80 +++++++++ ietf/group/tests.py | 117 ++++++++++++- 5 files changed, 479 insertions(+), 11 deletions(-) create mode 100755 ietf/doc/management/commands/generate_draft_aliases.py create mode 100755 ietf/group/management/commands/generate_group_aliases.py diff --git a/ietf/checks.py b/ietf/checks.py index 9f59d36c6..53e695a76 100644 --- a/ietf/checks.py +++ b/ietf/checks.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2015-2020, All Rights Reserved +# Copyright The IETF Trust 2015-2021, All Rights Reserved # -*- coding: utf-8 -*- @@ -62,14 +62,14 @@ def check_group_email_aliases_exists(app_configs, **kwargs): if not ok: errors.append(checks.Error( "Found no aliases in the group email aliases file\n'%s'."%settings.GROUP_ALIASES_PATH, - hint="Please run ietf/bin/generate-wg-aliases to generate them.", + hint="Please run the generate_group_aliases management command to generate them.", obj=None, id="datatracker.E0002", )) except IOError as e: errors.append(checks.Error( "Could not read group email aliases:\n %s" % e, - hint="Please run ietf/bin/generate-wg-aliases to generate them.", + hint="Please run the generate_group_aliases management command to generate them.", obj=None, id="datatracker.E0003", )) @@ -89,14 +89,14 @@ def check_doc_email_aliases_exists(app_configs, **kwargs): if not ok: errors.append(checks.Error( "Found no aliases in the document email aliases file\n'%s'."%settings.DRAFT_VIRTUAL_PATH, - hint="Please run ietf/bin/generate-draft-aliases to generate them.", + hint="Please run the generate_draft_aliases management command to generate them.", obj=None, id="datatracker.E0004", )) except IOError as e: errors.append(checks.Error( "Could not read document email aliases:\n %s" % e, - hint="Please run ietf/bin/generate-draft-aliases to generate them.", + hint="Please run the generate_draft_aliases management command to generate them.", obj=None, id="datatracker.E0005", )) diff --git a/ietf/doc/management/commands/generate_draft_aliases.py b/ietf/doc/management/commands/generate_draft_aliases.py new file mode 100755 index 000000000..a16805ba4 --- /dev/null +++ b/ietf/doc/management/commands/generate_draft_aliases.py @@ -0,0 +1,163 @@ +# Copyright The IETF Trust 2012-2021, All Rights Reserved +# -*- coding: utf-8 -*- + +# This was written as a script by Markus Stenberg . +# It was turned into a management command by Russ Housley . + +import datetime +import io +import os +import re +import time + +from django.conf import settings +from django.core.management.base import BaseCommand + +import debug # pyflakes:ignore + +from ietf.doc.models import Document +from ietf.group.utils import get_group_role_emails, get_group_ad_emails +from ietf.utils.aliases import dump_sublist +from utils.mail import parseaddr + +DEFAULT_YEARS = 2 + + +def get_draft_ad_emails(doc): + """Get AD email addresses for the given draft, if any.""" + ad_emails = set() + # If working group document, return current WG ADs + if doc.group and doc.group.acronym != 'none': + ad_emails.update(get_group_ad_emails(doc.group)) + # Document may have an explicit AD set + if doc.ad: + ad_emails.add(doc.ad.email_address()) + return ad_emails + + +def get_draft_chair_emails(doc): + """Get chair email addresses for the given draft, if any.""" + chair_emails = set() + if doc.group: + chair_emails.update(get_group_role_emails(doc.group, ['chair', 'secr'])) + return chair_emails + + +def get_draft_shepherd_email(doc): + """Get shepherd email addresses for the given draft, if any.""" + shepherd_email = set() + if doc.shepherd: + shepherd_email.add(doc.shepherd.email_address()) + return shepherd_email + + +def get_draft_authors_emails(doc): + """Get list of authors for the given draft.""" + author_emails = set() + for author in doc.documentauthor_set.all(): + if author.email and author.email.email_address(): + author_emails.add(author.email.email_address()) + return author_emails + + +def get_draft_notify_emails(doc): + """Get list of email addresses to notify for the given draft.""" + ad_email_alias_regex = r"^%s.ad@(%s|%s)$" % (doc.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER) + all_email_alias_regex = r"^%s.all@(%s|%s)$" % (doc.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER) + author_email_alias_regex = r"^%s@(%s|%s)$" % (doc.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER) + notify_email_alias_regex = r"^%s.notify@(%s|%s)$" % (doc.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER) + shepherd_email_alias_regex = r"^%s.shepherd@(%s|%s)$" % (doc.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER) + notify_emails = set() + if doc.notify: + for e in doc.notify.split(','): + e = e.strip() + if re.search(ad_email_alias_regex, e): + notify_emails.update(get_draft_ad_emails(doc)) + elif re.search(author_email_alias_regex, e): + notify_emails.update(get_draft_authors_emails(doc)) + elif re.search(shepherd_email_alias_regex, e): + notify_emails.update(get_draft_shepherd_email(doc)) + elif re.search(all_email_alias_regex, e): + notify_emails.update(get_draft_ad_emails(doc)) + notify_emails.update(get_draft_authors_emails(doc)) + notify_emails.update(get_draft_shepherd_email(doc)) + elif re.search(notify_email_alias_regex, e): + pass + else: + (name, email) = parseaddr(e) + notify_emails.add(email) + return notify_emails + + +class Command(BaseCommand): + help = ('Generate the draft-aliases and draft-virtual files for Internet-Draft ' + 'mail aliases, placing them in the files configured in ' + 'settings.DRAFT_ALIASES_PATH and settings.DRAFT_VIRTUAL_PATH, ' + 'respectively. The generation includes aliases for Internet-Drafts ' + 'that have seen activity in the last %s years.' % (DEFAULT_YEARS)) + + def handle(self, *args, **options): + show_since = datetime.datetime.now() - datetime.timedelta(DEFAULT_YEARS*365) + + date = time.strftime("%Y-%m-%d_%H:%M:%S") + signature = '# Generated by %s at %s\n' % (os.path.abspath(__file__), date) + + afile = io.open(settings.DRAFT_ALIASES_PATH, "w") + vfile = io.open(settings.DRAFT_VIRTUAL_PATH, "w") + + afile.write(signature) + vfile.write(signature) + vfile.write("%s anything\n" % settings.DRAFT_VIRTUAL_DOMAIN) + + # Internet-Drafts with active status or expired within DEFAULT_YEARS + drafts = Document.objects.filter(name__startswith='draft-') + active_drafts = drafts.filter(states__slug='active') + inactive_recent_drafts = drafts.exclude(states__slug='active').filter(expires__gte=show_since) + interesting_drafts = active_drafts | inactive_recent_drafts + + alias_domains = ['ietf.org', ] + for draft in interesting_drafts.distinct().iterator(): + # Omit RFCs, unless they were published in the last DEFAULT_YEARS + if draft.docalias.filter(name__startswith='rfc'): + if draft.latest_event(type='published_rfc').time < show_since: + continue + + alias = draft.name + all = set() + + # no suffix and .authors are the same list + emails = get_draft_authors_emails(draft) + all.update(emails) + dump_sublist(afile, vfile, alias, alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) + dump_sublist(afile, vfile, alias+'.authors', alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) + + # .chairs = group chairs + emails = get_draft_chair_emails(draft) + if emails: + all.update(emails) + dump_sublist(afile, vfile, alias+'.chairs', alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) + + # .ad = sponsoring AD / WG AD (WG document) + emails = get_draft_ad_emails(draft) + if emails: + all.update(emails) + dump_sublist(afile, vfile, alias+'.ad', alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) + + # .notify = notify email list from the Document + emails = get_draft_notify_emails(draft) + if emails: + all.update(emails) + dump_sublist(afile, vfile, alias+'.notify', alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) + + # .shepherd = shepherd email from the Document + emails = get_draft_shepherd_email(draft) + if emails: + all.update(emails) + dump_sublist(afile, vfile, alias+'.shepherd', alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) + + # .all = everything from above + dump_sublist(afile, vfile, alias+'.all', alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, all) + + afile.close() + vfile.close() + \ No newline at end of file diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 14c469ad9..138ab2b52 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -10,12 +10,12 @@ import lxml import bibtexparser import mock - from http.cookies import SimpleCookie from pyquery import PyQuery from urllib.parse import urlparse, parse_qs from tempfile import NamedTemporaryFile +from django.core.management import call_command from django.urls import reverse as urlreverse from django.conf import settings @@ -1371,7 +1371,123 @@ class ReferencesTest(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) self.assertContains(r, doc1.name) - + +class GenerateDraftAliasesTests(TestCase): + def setUp(self): + self.doc_aliases_file = NamedTemporaryFile(delete=False, mode='w+') + self.doc_aliases_file.close() + self.doc_virtual_file = NamedTemporaryFile(delete=False, mode='w+') + self.doc_virtual_file.close() + self.saved_draft_aliases_path = settings.DRAFT_ALIASES_PATH + self.saved_draft_virtual_path = settings.DRAFT_VIRTUAL_PATH + settings.DRAFT_ALIASES_PATH = self.doc_aliases_file.name + settings.DRAFT_VIRTUAL_PATH = self.doc_virtual_file.name + + def tearDown(self): + settings.DRAFT_ALIASES_PATH = self.saved_draft_aliases_path + settings.DRAFT_VIRTUAL_PATH = self.saved_draft_virtual_path + os.unlink(self.doc_aliases_file.name) + os.unlink(self.doc_virtual_file.name) + + def testManagementCommand(self): + a_month_ago = datetime.datetime.now() - datetime.timedelta(30) + ad = RoleFactory(name_id='ad', group__type_id='area', group__state_id='active').person + shepherd = PersonFactory() + author1 = PersonFactory() + author2 = PersonFactory() + author3 = PersonFactory() + author4 = PersonFactory() + author5 = PersonFactory() + author6 = PersonFactory() + mars = GroupFactory(type_id='wg', acronym='mars') + marschairman = PersonFactory(user__username='marschairman') + mars.role_set.create(name_id='chair', person=marschairman, email=marschairman.email()) + doc1 = IndividualDraftFactory(authors=[author1], shepherd=shepherd.email(), ad=ad) + doc2 = WgDraftFactory(name='draft-ietf-mars-test', group__acronym='mars', authors=[author2], ad=ad) + doc3 = WgRfcFactory.create(name='draft-ietf-mars-finished', group__acronym='mars', authors=[author3], ad=ad, std_level_id='ps', states=[('draft','rfc'),('draft-iesg','pub')], time=a_month_ago) + DocEventFactory.create(doc=doc3, type='published_rfc', time=a_month_ago.strftime("%Y-%m-%d")) + doc4 = WgRfcFactory.create(authors=[author4,author5], ad=ad, std_level_id='ps', states=[('draft','rfc'),('draft-iesg','pub')], time=datetime.datetime(2010,10,10)) + DocEventFactory.create(doc=doc4, type='published_rfc', time = '2010-10-10') + doc5 = IndividualDraftFactory(authors=[author6]) + + args = [ ] + kwargs = { } + out = io.StringIO() + call_command("generate_draft_aliases", *args, **kwargs, stdout=out, stderr=out) + self.assertFalse(out.getvalue()) + + with open(settings.DRAFT_ALIASES_PATH) as afile: + acontent = afile.read() + self.assertTrue(all([x in acontent for x in [ + 'xfilter-' + doc1.name, + 'xfilter-' + doc1.name + '.ad', + 'xfilter-' + doc1.name + '.authors', + 'xfilter-' + doc1.name + '.shepherd', + 'xfilter-' + doc1.name + '.all', + 'xfilter-' + doc2.name, + 'xfilter-' + doc2.name + '.ad', + 'xfilter-' + doc2.name + '.authors', + 'xfilter-' + doc2.name + '.chairs', + 'xfilter-' + doc2.name + '.all', + 'xfilter-' + doc3.name, + 'xfilter-' + doc3.name + '.ad', + 'xfilter-' + doc3.name + '.authors', + 'xfilter-' + doc3.name + '.chairs', + 'xfilter-' + doc5.name, + 'xfilter-' + doc5.name + '.authors', + 'xfilter-' + doc5.name + '.all', + ]])) + self.assertFalse(all([x in acontent for x in [ + 'xfilter-' + doc1.name + '.chairs', + 'xfilter-' + doc2.name + '.shepherd', + 'xfilter-' + doc3.name + '.shepherd', + 'xfilter-' + doc4.name, + 'xfilter-' + doc5.name + '.shepherd', + 'xfilter-' + doc5.name + '.ad', + ]])) + + with open(settings.DRAFT_VIRTUAL_PATH) as vfile: + vcontent = vfile.read() + self.assertTrue(all([x in vcontent for x in [ + ad.email_address(), + shepherd.email_address(), + marschairman.email_address(), + author1.email_address(), + author2.email_address(), + author3.email_address(), + author6.email_address(), + ]])) + self.assertFalse(all([x in vcontent for x in [ + author4.email_address(), + author5.email_address(), + ]])) + self.assertTrue(all([x in vcontent for x in [ + 'xfilter-' + doc1.name, + 'xfilter-' + doc1.name + '.ad', + 'xfilter-' + doc1.name + '.authors', + 'xfilter-' + doc1.name + '.shepherd', + 'xfilter-' + doc1.name + '.all', + 'xfilter-' + doc2.name, + 'xfilter-' + doc2.name + '.ad', + 'xfilter-' + doc2.name + '.authors', + 'xfilter-' + doc2.name + '.chairs', + 'xfilter-' + doc2.name + '.all', + 'xfilter-' + doc3.name, + 'xfilter-' + doc3.name + '.ad', + 'xfilter-' + doc3.name + '.authors', + 'xfilter-' + doc3.name + '.chairs', + 'xfilter-' + doc5.name, + 'xfilter-' + doc5.name + '.authors', + 'xfilter-' + doc5.name + '.all', + ]])) + self.assertFalse(all([x in vcontent for x in [ + 'xfilter-' + doc1.name + '.chairs', + 'xfilter-' + doc2.name + '.shepherd', + 'xfilter-' + doc3.name + '.shepherd', + 'xfilter-' + doc4.name, + 'xfilter-' + doc5.name + '.shepherd', + 'xfilter-' + doc5.name + '.ad', + ]])) class EmailAliasesTests(TestCase): diff --git a/ietf/group/management/commands/generate_group_aliases.py b/ietf/group/management/commands/generate_group_aliases.py new file mode 100755 index 000000000..7ce4da4b8 --- /dev/null +++ b/ietf/group/management/commands/generate_group_aliases.py @@ -0,0 +1,80 @@ +# Copyright The IETF Trust 2012-2021, All Rights Reserved +# -*- coding: utf-8 -*- + +# This was written as a script by Markus Stenberg . +# It was turned into a management command by Russ Housley . + +import datetime +import io +import os +import time + +from django.conf import settings +from django.core.management.base import BaseCommand + +import debug # pyflakes:ignore + +from ietf.group.models import Group +from ietf.group.utils import get_group_ad_emails, get_group_role_emails, get_child_group_role_emails +from ietf.name.models import GroupTypeName +from ietf.utils.aliases import dump_sublist + +DEFAULT_YEARS = 5 +ACTIVE_STATES=['active', 'bof', 'proposed'] +GROUP_TYPES=['wg','rg','dir','team','review','program'] +NO_AD_GROUP_TYPES=['rg','team','program'] + +class Command(BaseCommand): + help = ('Generate the group-aliases and group-virtual files for Internet-Draft ' + 'mail aliases, placing them in the file configured in ' + 'settings.GROUP_ALIASES_PATH and settings.GROUP_VIRTUAL_PATH, ' + 'respectively. The generation includes aliases for groups that ' + 'have seen activity in the last %s years.' % (DEFAULT_YEARS)) + + def handle(self, *args, **options): + show_since = datetime.datetime.now() - datetime.timedelta(DEFAULT_YEARS*365) + + date = time.strftime("%Y-%m-%d_%H:%M:%S") + signature = '# Generated by %s at %s\n' % (os.path.abspath(__file__), date) + + afile = io.open(settings.GROUP_ALIASES_PATH, "w") + vfile = io.open(settings.GROUP_VIRTUAL_PATH, "w") + + afile.write(signature) + vfile.write(signature) + vfile.write("%s anything\n" % settings.GROUP_VIRTUAL_DOMAIN) + + alias_domains = ['ietf.org', ] + + # Loop through each group type and build -ads and -chairs entries + for g in GROUP_TYPES: + entries = Group.objects.filter(type=g).all() + active_entries = entries.filter(state__in=ACTIVE_STATES) + inactive_recent_entries = entries.exclude(state__in=ACTIVE_STATES).filter(time__gte=show_since) + interesting_entries = active_entries | inactive_recent_entries + + for e in interesting_entries.distinct().iterator(): + name = e.acronym + # Research groups, teams, and programs do not have -ads lists + if not g in NO_AD_GROUP_TYPES: + dump_sublist(afile, vfile, name+'-ads', ['ietf.org', ], settings.GROUP_VIRTUAL_DOMAIN, get_group_ad_emails(e)) + # All group types have -chairs lists + dump_sublist(afile, vfile, name+'-chairs', ['ietf.org', ], settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(e, ['chair', 'secr'])) + + # The area lists include every chair in active working groups in the area + areas = Group.objects.filter(type='area').all() + active_areas = areas.filter(state__in=ACTIVE_STATES) + for area in active_areas: + name = area.acronym + area_ad_emails = get_group_role_emails(area, ['pre-ad', 'ad', 'chair']) + dump_sublist(afile, vfile, name+'-ads', alias_domains, settings.GROUP_VIRTUAL_DOMAIN, area_ad_emails) + dump_sublist(afile, vfile, name+'-chairs', alias_domains, settings.GROUP_VIRTUAL_DOMAIN, (get_child_group_role_emails(area, ['chair', 'secr']) | area_ad_emails)) + + # Other groups with chairs that require Internet-Draft submission approval + gtypes = GroupTypeName.objects.values_list('slug', flat=True) + special_groups = Group.objects.filter(type__features__req_subm_approval=True, acronym__in=gtypes, state='active') + for group in special_groups: + dump_sublist(afile, vfile, group.acronym+'-chairs', alias_domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(group, ['chair', 'delegate'])) + + afile.close() + vfile.close() \ No newline at end of file diff --git a/ietf/group/tests.py b/ietf/group/tests.py index 493a49c09..398969038 100644 --- a/ietf/group/tests.py +++ b/ietf/group/tests.py @@ -1,10 +1,14 @@ # Copyright The IETF Trust 2013-2020, All Rights Reserved # -*- coding: utf-8 -*- - +import io import os -from unittest import skipIf +import datetime +from unittest import skipIf +from tempfile import NamedTemporaryFile + +from django.core.management import call_command from django.conf import settings from django.urls import reverse as urlreverse from django.db.models import Q @@ -18,10 +22,11 @@ from ietf.group.models import Role, Group from ietf.group.utils import get_group_role_emails, get_child_group_role_emails, get_group_ad_emails from ietf.group.factories import GroupFactory, RoleFactory from ietf.utils.test_runner import set_coverage_checking -from ietf.person.factories import EmailFactory +from ietf.person.factories import PersonFactory, EmailFactory from ietf.person.models import Person from ietf.utils.test_utils import login_testing_unauthorized, TestCase + if getattr(settings,'SKIP_DOT_TO_PDF', False): skip_dot_to_pdf = True skip_message = "settings.SKIP_DOT_TO_PDF = %s" % skip_dot_to_pdf @@ -116,6 +121,111 @@ class GroupDocDependencyGraphTests(TestCase): "%s has no content"%group.acronym) +class GenerateGroupAliasesTests(TestCase): + def setUp(self): + self.doc_aliases_file = NamedTemporaryFile(delete=False, mode='w+') + self.doc_aliases_file.close() + self.doc_virtual_file = NamedTemporaryFile(delete=False, mode='w+') + self.doc_virtual_file.close() + self.saved_draft_aliases_path = settings.GROUP_ALIASES_PATH + self.saved_draft_virtual_path = settings.GROUP_VIRTUAL_PATH + settings.GROUP_ALIASES_PATH = self.doc_aliases_file.name + settings.GROUP_VIRTUAL_PATH = self.doc_virtual_file.name + + def tearDown(self): + settings.GROUP_ALIASES_PATH = self.saved_draft_aliases_path + settings.GROUP_VIRTUAL_PATH = self.saved_draft_virtual_path + os.unlink(self.doc_aliases_file.name) + os.unlink(self.doc_virtual_file.name) + + def testManagementCommand(self): + a_month_ago = datetime.datetime.now() - datetime.timedelta(30) + a_decade_ago = datetime.datetime.now() - datetime.timedelta(3650) + role1 = RoleFactory(name_id='ad', group__type_id='area', group__acronym='myth', group__state_id='active') + area = role1.group + ad = role1.person + mars = GroupFactory(type_id='wg', acronym='mars', parent=area) + marschair = PersonFactory(user__username='marschair') + mars.role_set.create(name_id='chair', person=marschair, email=marschair.email()) + marssecr = PersonFactory(user__username='marssecr') + mars.role_set.create(name_id='secr', person=marssecr, email=marssecr.email()) + ames = GroupFactory(type_id='wg', acronym='ames', parent=area) + ameschair = PersonFactory(user__username='ameschair') + ames.role_set.create(name_id='chair', person=ameschair, email=ameschair.email()) + recent = GroupFactory(type_id='wg', acronym='recent', parent=area, state_id='conclude', time=a_month_ago) + recentchair = PersonFactory(user__username='recentchair') + recent.role_set.create(name_id='chair', person=recentchair, email=recentchair.email()) + wayold = GroupFactory(type_id='wg', acronym='recent', parent=area, state_id='conclude', time=a_decade_ago) + wayoldchair = PersonFactory(user__username='wayoldchair') + wayold.role_set.create(name_id='chair', person=wayoldchair, email=wayoldchair.email()) + role2 = RoleFactory(name_id='ad', group__type_id='area', group__acronym='done', group__state_id='conclude') + done = role2.group + done_ad = role2.person + individual = PersonFactory() + + args = [ ] + kwargs = { } + out = io.StringIO() + call_command("generate_group_aliases", *args, **kwargs, stdout=out, stderr=out) + self.assertFalse(out.getvalue()) + + with open(settings.GROUP_ALIASES_PATH) as afile: + acontent = afile.read() + self.assertTrue('xfilter-' + area.acronym + '-ads' in acontent) + self.assertTrue('xfilter-' + area.acronym + '-chairs' in acontent) + self.assertTrue('xfilter-' + mars.acronym + '-ads' in acontent) + self.assertTrue('xfilter-' + mars.acronym + '-chairs' in acontent) + self.assertTrue('xfilter-' + ames.acronym + '-ads' in acontent) + self.assertTrue('xfilter-' + ames.acronym + '-chairs' in acontent) + self.assertTrue(all([x in acontent for x in [ + 'xfilter-' + area.acronym + '-ads', + 'xfilter-' + area.acronym + '-chairs', + 'xfilter-' + mars.acronym + '-ads', + 'xfilter-' + mars.acronym + '-chairs', + 'xfilter-' + ames.acronym + '-ads', + 'xfilter-' + ames.acronym + '-chairs', + 'xfilter-' + recent.acronym + '-ads', + 'xfilter-' + recent.acronym + '-chairs', + ]])) + self.assertFalse(all([x in acontent for x in [ + 'xfilter-' + done.acronym + '-ads', + 'xfilter-' + done.acronym + '-chairs', + 'xfilter-' + wayold.acronym + '-ads', + 'xfilter-' + wayold.acronym + '-chairs', + ]])) + + with open(settings.GROUP_VIRTUAL_PATH) as vfile: + vcontent = vfile.read() + self.assertTrue(all([x in vcontent for x in [ + ad.email_address(), + marschair.email_address(), + marssecr.email_address(), + ameschair.email_address(), + recentchair.email_address(), + ]])) + self.assertFalse(all([x in vcontent for x in [ + done_ad.email_address(), + wayoldchair.email_address(), + individual.email_address(), + ]])) + self.assertTrue(all([x in vcontent for x in [ + 'xfilter-' + area.acronym + '-ads', + 'xfilter-' + area.acronym + '-chairs', + 'xfilter-' + mars.acronym + '-ads', + 'xfilter-' + mars.acronym + '-chairs', + 'xfilter-' + ames.acronym + '-ads', + 'xfilter-' + ames.acronym + '-chairs', + 'xfilter-' + recent.acronym + '-ads', + 'xfilter-' + recent.acronym + '-chairs', + ]])) + self.assertFalse(all([x in vcontent for x in [ + 'xfilter-' + done.acronym + '-ads', + 'xfilter-' + done.acronym + '-chairs', + 'xfilter-' + wayold.acronym + '-ads', + 'xfilter-' + wayold.acronym + '-chairs', + ]])) + + class GroupRoleEmailTests(TestCase): def setUp(self): @@ -152,4 +262,3 @@ class GroupRoleEmailTests(TestCase): self.assertGreater(len(emails), 0) for item in emails: self.assertIn('@', item) -