12481.1.5
by Curtis Hovey
Updated sendExpirationWarningEmail documentation. Do not assert that the expiration date has past; silently return instead. |
1 |
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
|
8687.15.17
by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
3 |
|
4 |
__metaclass__ = type |
|
5 |
||
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
6 |
import bz2 |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
7 |
from datetime import ( |
8 |
datetime, |
|
9 |
timedelta, |
|
10 |
)
|
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
11 |
import os |
12 |
import pickle |
|
6010.1.1
by Guilherme Salgado
Change the check-teamparticipation.py script to check for people/teams which are not members of themselves. |
13 |
import re |
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
14 |
import subprocess |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
15 |
from unittest import TestLoader |
16 |
||
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
17 |
from fixtures import TempDir |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
18 |
import pytz |
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
19 |
from testtools.content import text_content |
13841.3.1
by Ian Booth
Reduce queries used to find out team affiliation |
20 |
from testtools.matchers import Equals |
13130.1.12
by Curtis Hovey
Sorted imports. |
21 |
import transaction |
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
22 |
from zope.component import getUtility |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
23 |
from zope.security.proxy import removeSecurityProxy |
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
24 |
|
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
25 |
from canonical.config import config |
4868.1.5
by Guilherme Salgado
Add an explicit test for ITeamMembershipSet.handleMembershipsExpiringToday() |
26 |
from canonical.database.sqlbase import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
27 |
cursor, |
28 |
flush_database_caches, |
|
29 |
flush_database_updates, |
|
30 |
sqlvalues, |
|
31 |
)
|
|
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
32 |
from canonical.testing.layers import ( |
33 |
DatabaseFunctionalLayer, |
|
34 |
LaunchpadZopelessLayer, |
|
35 |
)
|
|
13130.1.12
by Curtis Hovey
Sorted imports. |
36 |
from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
7675.110.3
by Curtis Hovey
Ran the migration script to move registry code to lp.registry. |
37 |
from lp.registry.interfaces.person import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
38 |
IPersonSet, |
12481.1.5
by Curtis Hovey
Updated sendExpirationWarningEmail documentation. Do not assert that the expiration date has past; silently return instead. |
39 |
TeamMembershipRenewalPolicy, |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
40 |
TeamSubscriptionPolicy, |
41 |
)
|
|
7675.110.3
by Curtis Hovey
Ran the migration script to move registry code to lp.registry. |
42 |
from lp.registry.interfaces.teammembership import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
43 |
CyclicalTeamMembershipError, |
44 |
ITeamMembershipSet, |
|
45 |
TeamMembershipStatus, |
|
46 |
)
|
|
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
47 |
from lp.registry.model.teammembership import ( |
13841.3.1
by Ian Booth
Reduce queries used to find out team affiliation |
48 |
find_team_participations, |
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
49 |
TeamMembership, |
50 |
TeamParticipation, |
|
51 |
)
|
|
14213.4.19
by Gavin Panella
Check that the only participant of a person is the person. |
52 |
from lp.registry.scripts.teamparticipation import ( |
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
53 |
check_teamparticipation_circular, |
14213.4.19
by Gavin Panella
Check that the only participant of a person is the person. |
54 |
check_teamparticipation_consistency, |
55 |
ConsistencyError, |
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
56 |
fetch_team_participation_info, |
14464.1.2
by Gavin Panella
Test for new function fix_teamparticipation_consistency(). |
57 |
fix_teamparticipation_consistency, |
14213.4.19
by Gavin Panella
Check that the only participant of a person is the person. |
58 |
)
|
14578.4.4
by William Grant
format-imports. |
59 |
from lp.services.database.lpstorm import IStore |
14213.4.3
by Gavin Panella
New test case TestCheckTeamParticipationScriptPerformance that runs check_teamparticipation() in-process, so we can monitor database activity more closely. |
60 |
from lp.services.log.logger import BufferLogger |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
61 |
from lp.testing import ( |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
62 |
login, |
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
63 |
login_celebrity, |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
64 |
login_person, |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
65 |
person_logged_in, |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
66 |
StormStatementRecorder, |
14213.4.3
by Gavin Panella
New test case TestCheckTeamParticipationScriptPerformance that runs check_teamparticipation() in-process, so we can monitor database activity more closely. |
67 |
TestCase, |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
68 |
TestCaseWithFactory, |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
69 |
)
|
14342.1.7
by William Grant
Kill a use of switchDbUser/reload_object. |
70 |
from lp.testing.dbuser import dbuser |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
71 |
from lp.testing.mail_helpers import pop_notifications |
13841.3.1
by Ian Booth
Reduce queries used to find out team affiliation |
72 |
from lp.testing.matchers import HasQueryCount |
14578.4.4
by William Grant
format-imports. |
73 |
from lp.testing.systemdocs import ( |
74 |
default_optionflags, |
|
75 |
LayeredDocFileSuite, |
|
76 |
setUp, |
|
77 |
tearDown, |
|
78 |
)
|
|
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
79 |
|
80 |
||
81 |
class TestTeamMembershipSetScripts(TestCaseWithFactory): |
|
82 |
"""Separate Testcase to separate out examples required dbuser switches.
|
|
83 |
||
84 |
This uses the LaunchpadZoplelessLayer to provide layer.switchDbUser
|
|
85 |
"""
|
|
86 |
||
87 |
layer = LaunchpadZopelessLayer |
|
88 |
||
89 |
def test_handleMembershipsExpiringToday_permissions(self): |
|
90 |
# Create two teams, a control team and and a team to be the control's
|
|
91 |
# administrator.
|
|
92 |
adminteam = self.factory.makeTeam() |
|
93 |
adminteam.setContactAddress(None) |
|
94 |
team = self.factory.makeTeam(owner=adminteam) |
|
13074.2.5
by j.c.sackett
Changes from review. |
95 |
with person_logged_in(team.teamowner): |
96 |
team.renewal_policy = TeamMembershipRenewalPolicy.AUTOMATIC |
|
97 |
team.defaultrenewalperiod = 10 |
|
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
98 |
|
99 |
# Create a person to be in the control team.
|
|
100 |
person = self.factory.makePerson() |
|
101 |
team.addMember(person, team.teamowner) |
|
102 |
membershipset = getUtility(ITeamMembershipSet) |
|
13074.2.4
by j.c.sackett
Lint fixes |
103 |
teammembership = membershipset.getByPersonAndTeam(person, team) |
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
104 |
|
105 |
# Set expiration time to now
|
|
106 |
now = datetime.now(pytz.UTC) |
|
107 |
removeSecurityProxy(teammembership).dateexpires = now |
|
108 |
||
109 |
janitor = getUtility(ILaunchpadCelebrities).janitor |
|
14342.1.7
by William Grant
Kill a use of switchDbUser/reload_object. |
110 |
with dbuser(config.expiredmembershipsflagger.dbuser): |
111 |
membershipset.handleMembershipsExpiringToday(janitor) |
|
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
112 |
self.assertEqual( |
113 |
teammembership.status, TeamMembershipStatus.APPROVED) |
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
114 |
|
13074.2.4
by j.c.sackett
Lint fixes |
115 |
|
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
116 |
class TestTeamMembershipSet(TestCaseWithFactory): |
13074.2.1
by j.c.sackett
Tests to produce the account relation error. |
117 |
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
118 |
layer = DatabaseFunctionalLayer |
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
119 |
|
120 |
def setUp(self): |
|
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
121 |
super(TestTeamMembershipSet, self).setUp() |
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
122 |
login('test@canonical.com') |
123 |
self.membershipset = getUtility(ITeamMembershipSet) |
|
124 |
self.personset = getUtility(IPersonSet) |
|
125 |
||
126 |
def test_membership_creation(self): |
|
127 |
marilize = self.personset.getByName('marilize') |
|
128 |
ubuntu_team = self.personset.getByName('ubuntu-team') |
|
129 |
membership = self.membershipset.new( |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
130 |
marilize, ubuntu_team, TeamMembershipStatus.APPROVED, marilize) |
4868.1.1
by Guilherme Salgado
Make TeamMembership.setStatus call flush_db_updates() and add a script to fix the db corruption caused by the lack of flush_db_updates() on setStatus when it's called from the flag-expired-memberships script |
131 |
self.assertEqual( |
132 |
membership, |
|
133 |
self.membershipset.getByPersonAndTeam(marilize, ubuntu_team)) |
|
134 |
self.assertEqual(membership.status, TeamMembershipStatus.APPROVED) |
|
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
135 |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
136 |
def test_active_membership_creation_stores_proponent_and_reviewer(self): |
5898.2.1
by Guilherme Salgado
Fix TeamMembershipSet.new() to store the datejoined when a membership is created in any active state. |
137 |
"""Memberships created in any active state have the reviewer stored.
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
138 |
|
5898.2.1
by Guilherme Salgado
Fix TeamMembershipSet.new() to store the datejoined when a membership is created in any active state. |
139 |
The date_joined, reviewer_comment, date_reviewed and attributes
|
140 |
related to the proponent are also stored, but everything related to
|
|
141 |
acknowledger will be left empty.
|
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
142 |
"""
|
143 |
marilize = self.personset.getByName('marilize') |
|
144 |
ubuntu_team = self.personset.getByName('ubuntu-team') |
|
145 |
membership = self.membershipset.new( |
|
146 |
marilize, ubuntu_team, TeamMembershipStatus.APPROVED, |
|
147 |
ubuntu_team.teamowner, comment="I like her") |
|
148 |
self.assertEqual(ubuntu_team.teamowner, membership.proposed_by) |
|
149 |
self.assertEqual(membership.proponent_comment, "I like her") |
|
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
150 |
now = datetime.now(pytz.UTC) |
5898.2.1
by Guilherme Salgado
Fix TeamMembershipSet.new() to store the datejoined when a membership is created in any active state. |
151 |
self.failUnless(membership.date_proposed <= now) |
152 |
self.failUnless(membership.datejoined <= now) |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
153 |
self.assertEqual(ubuntu_team.teamowner, membership.reviewed_by) |
154 |
self.assertEqual(membership.reviewer_comment, "I like her") |
|
5898.2.1
by Guilherme Salgado
Fix TeamMembershipSet.new() to store the datejoined when a membership is created in any active state. |
155 |
self.failUnless(membership.date_reviewed <= now) |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
156 |
self.assertEqual(membership.acknowledged_by, None) |
157 |
||
158 |
def test_membership_creation_stores_proponent(self): |
|
159 |
"""Memberships created in the proposed state have proponent stored.
|
|
160 |
||
161 |
The proponent_comment and date_proposed are also stored, but
|
|
162 |
everything related to reviewer and acknowledger will be left empty.
|
|
163 |
"""
|
|
164 |
marilize = self.personset.getByName('marilize') |
|
165 |
ubuntu_team = self.personset.getByName('ubuntu-team') |
|
166 |
membership = self.membershipset.new( |
|
167 |
marilize, ubuntu_team, TeamMembershipStatus.PROPOSED, marilize, |
|
168 |
comment="I'd like to join") |
|
169 |
self.assertEqual(marilize, membership.proposed_by) |
|
170 |
self.assertEqual(membership.proponent_comment, "I'd like to join") |
|
171 |
self.failUnless( |
|
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
172 |
membership.date_proposed <= datetime.now(pytz.UTC)) |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
173 |
self.assertEqual(membership.reviewed_by, None) |
174 |
self.assertEqual(membership.acknowledged_by, None) |
|
175 |
||
3691.272.18
by Guilherme Salgado
some final changes suggested by Bjorn |
176 |
def test_admin_membership_creation(self): |
177 |
ubuntu_team = self.personset.getByName('ubuntu-team') |
|
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
178 |
no_priv = self.personset.getByName('no-priv') |
179 |
membership = self.membershipset.new( |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
180 |
no_priv, ubuntu_team, TeamMembershipStatus.ADMIN, no_priv) |
4868.1.1
by Guilherme Salgado
Make TeamMembership.setStatus call flush_db_updates() and add a script to fix the db corruption caused by the lack of flush_db_updates() on setStatus when it's called from the flag-expired-memberships script |
181 |
self.assertEqual( |
182 |
membership, |
|
183 |
self.membershipset.getByPersonAndTeam(no_priv, ubuntu_team)) |
|
184 |
self.assertEqual(membership.status, TeamMembershipStatus.ADMIN) |
|
185 |
||
4868.1.5
by Guilherme Salgado
Add an explicit test for ITeamMembershipSet.handleMembershipsExpiringToday() |
186 |
def test_handleMembershipsExpiringToday(self): |
187 |
# Create a couple new teams, with one being a member of the other and
|
|
188 |
# make Sample Person an approved member of both teams.
|
|
5126.3.16
by Edwin Grubbs
Fixed launchpad.Edit permission problem in a unit test |
189 |
login('foo.bar@canonical.com') |
4868.1.5
by Guilherme Salgado
Add an explicit test for ITeamMembershipSet.handleMembershipsExpiringToday() |
190 |
foobar = self.personset.getByName('name16') |
191 |
sample_person = self.personset.getByName('name12') |
|
192 |
ubuntu_dev = self.personset.newTeam( |
|
193 |
foobar, 'ubuntu-dev', 'Ubuntu Developers') |
|
194 |
motu = self.personset.newTeam(foobar, 'motu', 'Ubuntu MOTU') |
|
195 |
ubuntu_dev.addMember(motu, foobar, force_team_add=True) |
|
196 |
ubuntu_dev.addMember(sample_person, foobar) |
|
197 |
motu.addMember(sample_person, foobar) |
|
198 |
||
199 |
# Now we need to cheat and set the expiration date of both memberships
|
|
200 |
# manually because otherwise we would only be allowed to set an
|
|
201 |
# expiration date in the future.
|
|
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
202 |
now = datetime.now(pytz.UTC) |
4868.1.5
by Guilherme Salgado
Add an explicit test for ITeamMembershipSet.handleMembershipsExpiringToday() |
203 |
sample_person_on_motu = removeSecurityProxy( |
204 |
self.membershipset.getByPersonAndTeam(sample_person, motu)) |
|
205 |
sample_person_on_motu.dateexpires = now |
|
206 |
sample_person_on_ubuntu_dev = removeSecurityProxy( |
|
207 |
self.membershipset.getByPersonAndTeam(sample_person, ubuntu_dev)) |
|
208 |
sample_person_on_ubuntu_dev.dateexpires = now |
|
209 |
flush_database_updates() |
|
210 |
self.assertEqual( |
|
211 |
sample_person_on_ubuntu_dev.status, TeamMembershipStatus.APPROVED) |
|
212 |
self.assertEqual( |
|
213 |
sample_person_on_motu.status, TeamMembershipStatus.APPROVED) |
|
214 |
self.membershipset.handleMembershipsExpiringToday(foobar) |
|
215 |
flush_database_caches() |
|
216 |
||
217 |
# Now Sample Person is not direct nor indirect member of ubuntu-dev
|
|
218 |
# or motu.
|
|
219 |
self.assertEqual( |
|
220 |
sample_person_on_ubuntu_dev.status, TeamMembershipStatus.EXPIRED) |
|
221 |
self.failIf(sample_person.inTeam(ubuntu_dev)) |
|
222 |
self.assertEqual( |
|
223 |
sample_person_on_motu.status, TeamMembershipStatus.EXPIRED) |
|
224 |
self.failIf(sample_person.inTeam(motu)) |
|
225 |
||
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
226 |
def test_deactivateActiveMemberships(self): |
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
227 |
superteam = self.factory.makeTeam(name='super') |
228 |
targetteam = self.factory.makeTeam(name='target') |
|
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
229 |
member = self.factory.makePerson() |
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
230 |
login_celebrity('admin') |
231 |
targetteam.join(superteam, targetteam.teamowner) |
|
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
232 |
targetteam.addMember(member, targetteam.teamowner) |
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
233 |
targetteam.teamowner.join(superteam, targetteam.teamowner) |
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
234 |
self.membershipset.deactivateActiveMemberships( |
235 |
targetteam, comment='test', reviewer=targetteam.teamowner) |
|
236 |
membership = self.membershipset.getByPersonAndTeam(member, targetteam) |
|
237 |
self.assertEqual('test', membership.last_change_comment) |
|
238 |
self.assertEqual(targetteam.teamowner, membership.last_changed_by) |
|
239 |
self.assertEqual([], list(targetteam.allmembers)) |
|
240 |
self.assertEqual( |
|
241 |
[superteam], list(targetteam.teamowner.teams_participated_in)) |
|
242 |
self.assertEqual([], list(member.teams_participated_in)) |
|
12617.1.6
by Curtis Hovey
Moved deactivateAllMembers tests to TestTeamMembershipSet. |
243 |
|
4868.1.1
by Guilherme Salgado
Make TeamMembership.setStatus call flush_db_updates() and add a script to fix the db corruption caused by the lack of flush_db_updates() on setStatus when it's called from the flag-expired-memberships script |
244 |
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
245 |
class TeamParticipationTestCase(TestCaseWithFactory): |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
246 |
"""Tests for team participation using 5 teams."""
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
247 |
layer = DatabaseFunctionalLayer |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
248 |
|
249 |
def setUp(self): |
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
250 |
super(TeamParticipationTestCase, self).setUp() |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
251 |
login('foo.bar@canonical.com') |
252 |
person_set = getUtility(IPersonSet) |
|
253 |
self.foo_bar = person_set.getByEmail('foo.bar@canonical.com') |
|
254 |
self.no_priv = person_set.getByName('no-priv') |
|
255 |
self.team1 = person_set.newTeam(self.foo_bar, 'team1', 'team1') |
|
256 |
self.team2 = person_set.newTeam(self.foo_bar, 'team2', 'team2') |
|
257 |
self.team3 = person_set.newTeam(self.foo_bar, 'team3', 'team3') |
|
258 |
self.team4 = person_set.newTeam(self.foo_bar, 'team4', 'team4') |
|
259 |
self.team5 = person_set.newTeam(self.foo_bar, 'team5', 'team5') |
|
260 |
||
261 |
def assertParticipantsEquals(self, participant_names, team): |
|
262 |
"""Assert that the participants names in team are the expected ones.
|
|
263 |
"""
|
|
264 |
self.assertEquals( |
|
265 |
sorted(participant_names), |
|
266 |
sorted([participant.name for participant in team.allmembers])) |
|
267 |
||
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
268 |
def getTeamParticipationCount(self): |
269 |
return IStore(TeamParticipation).find(TeamParticipation).count() |
|
270 |
||
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
271 |
|
13841.3.1
by Ian Booth
Reduce queries used to find out team affiliation |
272 |
class TestTeamParticipationQuery(TeamParticipationTestCase): |
273 |
"""A test case for teammembership.test_find_team_participations."""
|
|
274 |
||
275 |
def test_find_team_participations(self): |
|
276 |
# The correct team participations are found and the query count is 1.
|
|
277 |
self.team1.addMember(self.no_priv, self.foo_bar) |
|
278 |
self.team2.addMember(self.no_priv, self.foo_bar) |
|
279 |
self.team1.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
280 |
||
281 |
people = [self.team1, self.team2] |
|
282 |
with StormStatementRecorder() as recorder: |
|
283 |
people_teams = find_team_participations(people) |
|
284 |
self.assertThat(recorder, HasQueryCount(Equals(1))) |
|
285 |
self.assertContentEqual([self.team1, self.team2], people_teams.keys()) |
|
286 |
self.assertContentEqual([self.team1], people_teams[self.team1]) |
|
287 |
self.assertContentEqual( |
|
288 |
[self.team1, self.team2], people_teams[self.team2]) |
|
289 |
||
290 |
def test_find_team_participations_limited_teams(self): |
|
291 |
# The correct team participations are found and the query count is 1.
|
|
292 |
self.team1.addMember(self.no_priv, self.foo_bar) |
|
293 |
self.team2.addMember(self.no_priv, self.foo_bar) |
|
294 |
self.team1.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
295 |
||
296 |
people = [self.foo_bar, self.team2] |
|
297 |
teams = [self.team1, self.team2] |
|
298 |
with StormStatementRecorder() as recorder: |
|
299 |
people_teams = find_team_participations(people, teams) |
|
300 |
self.assertThat(recorder, HasQueryCount(Equals(1))) |
|
301 |
self.assertContentEqual( |
|
302 |
[self.foo_bar, self.team2], people_teams.keys()) |
|
303 |
self.assertContentEqual( |
|
304 |
[self.team1, self.team2], people_teams[self.foo_bar]) |
|
305 |
self.assertContentEqual( |
|
306 |
[self.team1, self.team2], people_teams[self.team2]) |
|
307 |
||
308 |
def test_find_team_participations_no_query(self): |
|
309 |
# Check that no database query is made unless necessary.
|
|
310 |
people = [self.foo_bar, self.team2] |
|
311 |
teams = [self.foo_bar] |
|
312 |
with StormStatementRecorder() as recorder: |
|
313 |
people_teams = find_team_participations(people, teams) |
|
314 |
self.assertThat(recorder, HasQueryCount(Equals(0))) |
|
315 |
self.assertContentEqual([self.foo_bar], people_teams.keys()) |
|
316 |
self.assertContentEqual([self.foo_bar], people_teams[self.foo_bar]) |
|
317 |
||
318 |
||
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
319 |
class TestTeamParticipationHierarchy(TeamParticipationTestCase): |
320 |
"""Participation management tests using 5 nested teams.
|
|
321 |
||
322 |
Create a team hierarchy with 5 teams and one person (no-priv) as
|
|
323 |
member of the last team in the chain.
|
|
324 |
team1
|
|
325 |
team2
|
|
326 |
team3
|
|
327 |
team4
|
|
328 |
team5
|
|
329 |
no-priv
|
|
330 |
"""
|
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
331 |
layer = DatabaseFunctionalLayer |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
332 |
|
333 |
def setUp(self): |
|
334 |
"""Setup the team hierarchy."""
|
|
335 |
super(TestTeamParticipationHierarchy, self).setUp() |
|
336 |
self.team5.addMember(self.no_priv, self.foo_bar) |
|
337 |
self.team1.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
338 |
self.team2.addMember(self.team3, self.foo_bar, force_team_add=True) |
|
339 |
self.team3.addMember(self.team4, self.foo_bar, force_team_add=True) |
|
340 |
self.team4.addMember(self.team5, self.foo_bar, force_team_add=True) |
|
341 |
||
342 |
def testTeamParticipationSetUp(self): |
|
343 |
"""Make sure that the TeamParticipation are sane after setUp."""
|
|
344 |
self.assertParticipantsEquals( |
|
345 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
346 |
self.team1) |
|
347 |
self.assertParticipantsEquals( |
|
348 |
['name16', 'no-priv', 'team3', 'team4', 'team5'], self.team2) |
|
349 |
self.assertParticipantsEquals( |
|
350 |
['name16', 'no-priv', 'team4', 'team5'], self.team3) |
|
351 |
self.assertParticipantsEquals( |
|
352 |
['name16', 'no-priv', 'team5'], self.team4) |
|
353 |
self.assertParticipantsEquals( |
|
354 |
['name16', 'no-priv'], self.team5) |
|
355 |
||
356 |
def testSevereHierarchyByRemovingTeam3FromTeam2(self): |
|
357 |
"""Make sure that the participations is updated correctly when
|
|
358 |
the hierarchy is severed in the two.
|
|
359 |
||
360 |
This is similar to what was experienced in bug 261915.
|
|
361 |
"""
|
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
362 |
previous_count = self.getTeamParticipationCount() |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
363 |
self.team2.setMembershipData( |
364 |
self.team3, TeamMembershipStatus.DEACTIVATED, self.foo_bar) |
|
6914.2.8
by Francis J. Lacoste
Make lint happy. |
365 |
self.assertParticipantsEquals(['name16', 'team2'], self.team1) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
366 |
self.assertParticipantsEquals(['name16'], self.team2) |
367 |
self.assertParticipantsEquals( |
|
368 |
['name16', 'no-priv', 'team4', 'team5'], self.team3) |
|
369 |
self.assertParticipantsEquals( |
|
370 |
['name16', 'no-priv', 'team5'], self.team4) |
|
371 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
372 |
self.assertEqual( |
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
373 |
previous_count - 8, |
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
374 |
self.getTeamParticipationCount()) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
375 |
|
376 |
def testRemovingLeafTeam(self): |
|
377 |
"""Make sure that participations are updated correctly when removing
|
|
378 |
the leaf team.
|
|
379 |
"""
|
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
380 |
previous_count = self.getTeamParticipationCount() |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
381 |
self.team4.setMembershipData( |
382 |
self.team5, TeamMembershipStatus.DEACTIVATED, self.foo_bar) |
|
383 |
self.assertParticipantsEquals( |
|
384 |
['name16', 'team2', 'team3', 'team4'], self.team1) |
|
385 |
self.assertParticipantsEquals( |
|
386 |
['name16', 'team3', 'team4'], self.team2) |
|
387 |
self.assertParticipantsEquals(['name16', 'team4'], self.team3) |
|
388 |
self.assertParticipantsEquals(['name16'], self.team4) |
|
389 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
390 |
self.assertEqual( |
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
391 |
previous_count - 8, |
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
392 |
self.getTeamParticipationCount()) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
393 |
|
394 |
||
395 |
class TestTeamParticipationTree(TeamParticipationTestCase): |
|
396 |
"""Participation management tests using 5 nested teams
|
|
397 |
||
398 |
Create a team hierarchy looking like this:
|
|
399 |
team1
|
|
400 |
team2
|
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
401 |
team5
|
402 |
team3
|
|
403 |
team4
|
|
404 |
team5
|
|
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
405 |
no-priv
|
406 |
"""
|
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
407 |
layer = DatabaseFunctionalLayer |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
408 |
|
409 |
def setUp(self): |
|
410 |
"""Setup the team hierarchy."""
|
|
411 |
super(TestTeamParticipationTree, self).setUp() |
|
412 |
self.team5.addMember(self.no_priv, self.foo_bar) |
|
413 |
self.team1.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
414 |
self.team2.addMember(self.team3, self.foo_bar, force_team_add=True) |
|
415 |
self.team2.addMember(self.team5, self.foo_bar, force_team_add=True) |
|
416 |
self.team3.addMember(self.team4, self.foo_bar, force_team_add=True) |
|
417 |
self.team4.addMember(self.team5, self.foo_bar, force_team_add=True) |
|
418 |
||
12019.11.5
by Brad Crittenden
Borked checkpoint |
419 |
def tearDown(self): |
420 |
super(TestTeamParticipationTree, self).tearDown() |
|
421 |
self.layer.force_dirty_database() |
|
422 |
||
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
423 |
def testTeamParticipationSetUp(self): |
424 |
"""Make sure that the TeamParticipation are sane after setUp."""
|
|
425 |
self.assertParticipantsEquals( |
|
426 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
427 |
self.team1) |
|
428 |
self.assertParticipantsEquals( |
|
429 |
['name16', 'no-priv', 'team3', 'team4', 'team5'], self.team2) |
|
430 |
self.assertParticipantsEquals( |
|
431 |
['name16', 'no-priv', 'team4', 'team5'], self.team3) |
|
432 |
self.assertParticipantsEquals( |
|
433 |
['name16', 'no-priv', 'team5'], self.team4) |
|
434 |
self.assertParticipantsEquals( |
|
435 |
['name16', 'no-priv'], self.team5) |
|
436 |
||
437 |
def testRemoveTeam3FromTeam2(self): |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
438 |
previous_count = self.getTeamParticipationCount() |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
439 |
self.team2.setMembershipData( |
440 |
self.team3, TeamMembershipStatus.DEACTIVATED, self.foo_bar) |
|
441 |
self.assertParticipantsEquals( |
|
442 |
['name16', 'no-priv', 'team2', 'team5'], self.team1) |
|
443 |
self.assertParticipantsEquals( |
|
444 |
['name16', 'no-priv', 'team5'], self.team2) |
|
445 |
self.assertParticipantsEquals( |
|
446 |
['name16', 'no-priv', 'team4', 'team5'], self.team3) |
|
447 |
self.assertParticipantsEquals( |
|
448 |
['name16', 'no-priv', 'team5'], self.team4) |
|
449 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
450 |
self.assertEqual( |
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
451 |
previous_count - 4, |
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
452 |
self.getTeamParticipationCount()) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
453 |
|
454 |
def testRemoveTeam5FromTeam4(self): |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
455 |
previous_count = self.getTeamParticipationCount() |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
456 |
self.team4.setMembershipData( |
457 |
self.team5, TeamMembershipStatus.DEACTIVATED, self.foo_bar) |
|
458 |
self.assertParticipantsEquals( |
|
459 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
460 |
self.team1) |
|
461 |
self.assertParticipantsEquals( |
|
6914.2.5
by Francis J. Lacoste
Use correct expected values |
462 |
['name16', 'no-priv', 'team3', 'team4', 'team5'], self.team2) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
463 |
self.assertParticipantsEquals( |
6914.2.5
by Francis J. Lacoste
Use correct expected values |
464 |
['name16', 'team4'], self.team3) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
465 |
self.assertParticipantsEquals(['name16'], self.team4) |
466 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
467 |
self.assertEqual( |
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
468 |
previous_count - 4, |
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
469 |
self.getTeamParticipationCount()) |
6914.2.3
by Francis J. Lacoste
Refactored tests to use a common setUp and assert, and add more tests on a more complex structure. |
470 |
|
471 |
||
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
472 |
class TestParticipationCleanup(TeamParticipationTestCase): |
473 |
"""Test deletion of a member from a team with many superteams.
|
|
474 |
Create a team hierarchy looking like this:
|
|
475 |
team1
|
|
476 |
team2
|
|
477 |
team3
|
|
478 |
team4
|
|
479 |
team5
|
|
480 |
no-priv
|
|
481 |
"""
|
|
482 |
||
483 |
def setUp(self): |
|
484 |
"""Setup the team hierarchy."""
|
|
485 |
super(TestParticipationCleanup, self).setUp() |
|
486 |
self.team1.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
487 |
self.team2.addMember(self.team3, self.foo_bar, force_team_add=True) |
|
488 |
self.team3.addMember(self.team4, self.foo_bar, force_team_add=True) |
|
489 |
self.team4.addMember(self.team5, self.foo_bar, force_team_add=True) |
|
490 |
self.team5.addMember(self.no_priv, self.foo_bar) |
|
491 |
||
492 |
def testMemberRemoval(self): |
|
493 |
"""Remove the member from the last team.
|
|
494 |
||
495 |
The number of db queries should be constant not O(depth).
|
|
496 |
"""
|
|
497 |
self.assertStatementCount( |
|
12156.7.6
by Edwin Grubbs
Working recursive query. |
498 |
7, |
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
499 |
self.team5.setMembershipData, self.no_priv, |
12156.7.4
by Edwin Grubbs
Mostly working new algorithm. |
500 |
TeamMembershipStatus.DEACTIVATED, self.team5.teamowner) |
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
501 |
|
502 |
||
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
503 |
class TestTeamParticipationMesh(TeamParticipationTestCase): |
504 |
"""Participation management tests using two roots and some duplicated
|
|
505 |
branches.
|
|
506 |
||
507 |
Create a team hierarchy looking like this:
|
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
508 |
team1 team6
|
509 |
\ / |
|
|
510 |
team2 |
|
|
511 |
/ | |
|
|
512 |
team3 | |
|
|
513 |
\ | /
|
|
514 |
team4
|
|
515 |
team5
|
|
516 |
no-priv
|
|
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
517 |
"""
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
518 |
layer = DatabaseFunctionalLayer |
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
519 |
|
520 |
def setUp(self): |
|
521 |
"""Setup the team hierarchy."""
|
|
522 |
super(TestTeamParticipationMesh, self).setUp() |
|
523 |
self.team6 = getUtility(IPersonSet).newTeam( |
|
524 |
self.foo_bar, 'team6', 'team6') |
|
525 |
self.team5.addMember(self.no_priv, self.foo_bar) |
|
526 |
self.team1.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
527 |
self.team2.addMember(self.team3, self.foo_bar, force_team_add=True) |
|
528 |
self.team2.addMember(self.team4, self.foo_bar, force_team_add=True) |
|
529 |
self.team3.addMember(self.team4, self.foo_bar, force_team_add=True) |
|
530 |
self.team4.addMember(self.team5, self.foo_bar, force_team_add=True) |
|
531 |
self.team6.addMember(self.team2, self.foo_bar, force_team_add=True) |
|
532 |
self.team6.addMember(self.team4, self.foo_bar, force_team_add=True) |
|
533 |
||
12019.11.5
by Brad Crittenden
Borked checkpoint |
534 |
def tearDown(self): |
535 |
super(TestTeamParticipationMesh, self).tearDown() |
|
536 |
self.layer.force_dirty_database() |
|
537 |
||
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
538 |
def testTeamParticipationSetUp(self): |
539 |
"""Make sure that the TeamParticipation are sane after setUp."""
|
|
540 |
self.assertParticipantsEquals( |
|
541 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
542 |
self.team1) |
|
543 |
self.assertParticipantsEquals( |
|
544 |
['name16', 'no-priv', 'team3', 'team4', 'team5'], self.team2) |
|
545 |
self.assertParticipantsEquals( |
|
546 |
['name16', 'no-priv', 'team4', 'team5'], self.team3) |
|
547 |
self.assertParticipantsEquals( |
|
548 |
['name16', 'no-priv', 'team5'], self.team4) |
|
549 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
550 |
self.assertParticipantsEquals( |
|
551 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
552 |
self.team6) |
|
553 |
||
554 |
def testRemoveTeam3FromTeam2(self): |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
555 |
previous_count = self.getTeamParticipationCount() |
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
556 |
self.team2.setMembershipData( |
557 |
self.team3, TeamMembershipStatus.DEACTIVATED, self.foo_bar) |
|
558 |
self.assertParticipantsEquals( |
|
559 |
['name16', 'no-priv', 'team2', 'team4', 'team5'], self.team1) |
|
560 |
self.assertParticipantsEquals( |
|
561 |
['name16', 'no-priv', 'team4', 'team5'], self.team2) |
|
562 |
self.assertParticipantsEquals( |
|
563 |
['name16', 'no-priv', 'team4', 'team5'], self.team3) |
|
564 |
self.assertParticipantsEquals( |
|
565 |
['name16', 'no-priv', 'team5'], self.team4) |
|
566 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
567 |
self.assertParticipantsEquals( |
|
568 |
['name16', 'no-priv', 'team2', 'team4', 'team5'], self.team6) |
|
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
569 |
self.assertEqual( |
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
570 |
previous_count - 3, |
12156.7.9
by Edwin Grubbs
Added tests for side-effects. |
571 |
self.getTeamParticipationCount()) |
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
572 |
|
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
573 |
def testRemoveTeam5FromTeam4(self): |
12617.1.1
by Curtis Hovey
Replace bad independent implementation of TeamPartcipation cleaning with a |
574 |
previous_count = self.getTeamParticipationCount() |
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
575 |
self.team4.setMembershipData( |
576 |
self.team5, TeamMembershipStatus.DEACTIVATED, self.foo_bar) |
|
577 |
self.assertParticipantsEquals( |
|
578 |
['name16', 'team2', 'team3', 'team4'], self.team1) |
|
579 |
self.assertParticipantsEquals( |
|
580 |
['name16', 'team3', 'team4'], self.team2) |
|
581 |
self.assertParticipantsEquals(['name16', 'team4'], self.team3) |
|
582 |
self.assertParticipantsEquals(['name16'], self.team4) |
|
12617.1.1
by Curtis Hovey
Replace bad independent implementation of TeamPartcipation cleaning with a |
583 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
584 |
self.assertParticipantsEquals( |
|
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
585 |
['name16', 'team2', 'team3', 'team4'], self.team6) |
586 |
self.assertEqual( |
|
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
587 |
previous_count - 10, |
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
588 |
self.getTeamParticipationCount()) |
12617.1.1
by Curtis Hovey
Replace bad independent implementation of TeamPartcipation cleaning with a |
589 |
|
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
590 |
def testTeam3_deactivateActiveMemberships(self): |
12617.1.1
by Curtis Hovey
Replace bad independent implementation of TeamPartcipation cleaning with a |
591 |
# Removing all the members of team2 will not remove memberships
|
592 |
# to super teams from other paths.
|
|
593 |
non_member = self.factory.makePerson() |
|
594 |
self.team3.addMember(non_member, self.foo_bar, force_team_add=True) |
|
595 |
previous_count = self.getTeamParticipationCount() |
|
12617.1.3
by Curtis Hovey
Moved deactivateAllMembers to ITeamMembershipSet.deactivateActiveMemberships. |
596 |
membershipset = getUtility(ITeamMembershipSet) |
597 |
membershipset.deactivateActiveMemberships( |
|
598 |
self.team3, 'gone', self.foo_bar) |
|
12617.1.7
by Curtis Hovey
Removed duplicate tests. |
599 |
self.assertEqual([], list(self.team3.allmembers)) |
12617.1.1
by Curtis Hovey
Replace bad independent implementation of TeamPartcipation cleaning with a |
600 |
self.assertParticipantsEquals( |
601 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
602 |
self.team1) |
|
603 |
self.assertParticipantsEquals( |
|
604 |
['name16', 'no-priv', 'team3', 'team4', 'team5'], self.team2) |
|
605 |
self.assertParticipantsEquals( |
|
606 |
[], self.team3) |
|
607 |
self.assertParticipantsEquals( |
|
608 |
['name16', 'no-priv', 'team5'], self.team4) |
|
609 |
self.assertParticipantsEquals(['name16', 'no-priv'], self.team5) |
|
610 |
self.assertParticipantsEquals( |
|
611 |
['name16', 'no-priv', 'team2', 'team3', 'team4', 'team5'], |
|
612 |
self.team6) |
|
613 |
self.assertEqual(previous_count - 8, self.getTeamParticipationCount()) |
|
614 |
||
6914.2.4
by Francis J. Lacoste
Add more complex structure for more removeal tests. |
615 |
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
616 |
class TestTeamMembership(TestCaseWithFactory): |
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
617 |
layer = DatabaseFunctionalLayer |
4868.1.1
by Guilherme Salgado
Make TeamMembership.setStatus call flush_db_updates() and add a script to fix the db corruption caused by the lack of flush_db_updates() on setStatus when it's called from the flag-expired-memberships script |
618 |
|
6809.1.1
by Guilherme Salgado
Fix bug 248498 |
619 |
def test_teams_not_kicked_from_themselves_bug_248498(self): |
620 |
"""The self-participation of a team must not be removed.
|
|
621 |
||
622 |
Performing the following steps would cause a team's self-participation
|
|
623 |
to be removed, but it shouldn't.
|
|
624 |
||
625 |
1. propose team A as a member of team B
|
|
626 |
2. propose team B as a member of team A
|
|
627 |
3. approve team A as a member of team B
|
|
628 |
4. decline team B as a member of team A
|
|
629 |
||
630 |
This test will make sure that doesn't happen in the future.
|
|
631 |
"""
|
|
632 |
login('test@canonical.com') |
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
633 |
person = self.factory.makePerson() |
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
634 |
login_person(person) # Now login with the future owner of the teams. |
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
635 |
teamA = self.factory.makeTeam( |
6809.1.1
by Guilherme Salgado
Fix bug 248498 |
636 |
person, subscription_policy=TeamSubscriptionPolicy.MODERATED) |
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
637 |
teamB = self.factory.makeTeam( |
6809.1.1
by Guilherme Salgado
Fix bug 248498 |
638 |
person, subscription_policy=TeamSubscriptionPolicy.MODERATED) |
639 |
self.failUnless( |
|
640 |
teamA.inTeam(teamA), "teamA is not a participant of itself") |
|
641 |
self.failUnless( |
|
642 |
teamB.inTeam(teamB), "teamB is not a participant of itself") |
|
643 |
||
644 |
teamA.join(teamB, requester=person) |
|
645 |
teamB.join(teamA, requester=person) |
|
646 |
teamB.setMembershipData(teamA, TeamMembershipStatus.APPROVED, person) |
|
647 |
teamA.setMembershipData(teamB, TeamMembershipStatus.DECLINED, person) |
|
648 |
||
649 |
self.failUnless(teamA.hasParticipationEntryFor(teamA), |
|
650 |
"teamA is not a participant of itself") |
|
651 |
self.failUnless(teamB.hasParticipationEntryFor(teamB), |
|
652 |
"teamB is not a participant of itself") |
|
653 |
||
4868.1.1
by Guilherme Salgado
Make TeamMembership.setStatus call flush_db_updates() and add a script to fix the db corruption caused by the lack of flush_db_updates() on setStatus when it's called from the flag-expired-memberships script |
654 |
def test_membership_status_changes_are_immediately_flushed_to_db(self): |
655 |
"""Any changes to a membership status must be imediately flushed.
|
|
656 |
||
657 |
Sometimes we may change multiple team memberships in the same
|
|
658 |
transaction (e.g. when expiring memberships). If there are multiple
|
|
659 |
memberships for a given member changed in this way, we need to
|
|
660 |
ensure each change is flushed to the database so that subsequent ones
|
|
661 |
operate on the correct data.
|
|
662 |
"""
|
|
663 |
login('foo.bar@canonical.com') |
|
4868.1.2
by Guilherme Salgado
A couple small changes suggested by kiko |
664 |
tm = TeamMembership.selectFirstBy( |
665 |
status=TeamMembershipStatus.APPROVED, orderBy='id') |
|
666 |
tm.setStatus(TeamMembershipStatus.DEACTIVATED, |
|
667 |
getUtility(IPersonSet).getByName('name16')) |
|
668 |
# Bypass SQLObject to make sure the update was really flushed to the
|
|
669 |
# database.
|
|
670 |
cur = cursor() |
|
671 |
cur.execute("SELECT status FROM teammembership WHERE id = %d" % tm.id) |
|
672 |
[new_status] = cur.fetchone() |
|
673 |
self.assertEqual(new_status, TeamMembershipStatus.DEACTIVATED.value) |
|
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
674 |
|
675 |
||
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
676 |
class TestTeamMembershipSetStatus(TestCaseWithFactory): |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
677 |
"""Test the behaviour of TeamMembership's setStatus()."""
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
678 |
layer = DatabaseFunctionalLayer |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
679 |
|
680 |
def setUp(self): |
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
681 |
super(TestTeamMembershipSetStatus, self).setUp() |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
682 |
login('foo.bar@canonical.com') |
683 |
self.foobar = getUtility(IPersonSet).getByName('name16') |
|
684 |
self.no_priv = getUtility(IPersonSet).getByName('no-priv') |
|
685 |
self.ubuntu_team = getUtility(IPersonSet).getByName('ubuntu-team') |
|
686 |
self.admins = getUtility(IPersonSet).getByName('admins') |
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
687 |
# Create a bunch of arbitrary teams to use in the tests.
|
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
688 |
self.team1 = self.factory.makeTeam(self.foobar) |
689 |
self.team2 = self.factory.makeTeam(self.foobar) |
|
690 |
self.team3 = self.factory.makeTeam(self.foobar) |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
691 |
|
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
692 |
def test_proponent_is_stored(self): |
9538.1.2
by Gary Poster
disable unit test more according to proper process |
693 |
for status in [TeamMembershipStatus.DEACTIVATED, |
694 |
TeamMembershipStatus.EXPIRED, |
|
695 |
TeamMembershipStatus.DECLINED]: |
|
696 |
tm = TeamMembership( |
|
697 |
person=self.no_priv, team=self.ubuntu_team, status=status) |
|
698 |
self.failIf( |
|
699 |
tm.proposed_by, "There can be no proponent at this point.") |
|
700 |
self.failIf( |
|
701 |
tm.date_proposed, "There can be no proposed date this point.") |
|
702 |
self.failIf(tm.proponent_comment, |
|
703 |
"There can be no proponent comment at this point.") |
|
704 |
tm.setStatus( |
|
705 |
TeamMembershipStatus.PROPOSED, self.foobar, |
|
706 |
"Did it 'cause I can") |
|
707 |
self.failUnlessEqual(tm.proposed_by, self.foobar) |
|
708 |
self.failUnlessEqual(tm.proponent_comment, "Did it 'cause I can") |
|
709 |
self.failUnless( |
|
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
710 |
tm.date_proposed <= datetime.now(pytz.UTC)) |
9538.1.2
by Gary Poster
disable unit test more according to proper process |
711 |
# Destroy the membership so that we can create another in a
|
712 |
# different state.
|
|
713 |
tm.destroySelf() |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
714 |
|
715 |
def test_acknowledger_is_stored(self): |
|
716 |
for status in [TeamMembershipStatus.APPROVED, |
|
717 |
TeamMembershipStatus.INVITATION_DECLINED]: |
|
718 |
tm = TeamMembership( |
|
719 |
person=self.admins, team=self.ubuntu_team, |
|
720 |
status=TeamMembershipStatus.INVITED) |
|
721 |
self.failIf( |
|
722 |
tm.acknowledged_by, |
|
723 |
"There can be no acknowledger at this point.") |
|
724 |
self.failIf( |
|
725 |
tm.date_acknowledged, |
|
726 |
"There can be no accepted date this point.") |
|
727 |
self.failIf(tm.acknowledger_comment, |
|
728 |
"There can be no acknowledger comment at this point.") |
|
729 |
tm.setStatus(status, self.foobar, "Did it 'cause I can") |
|
730 |
self.failUnlessEqual(tm.acknowledged_by, self.foobar) |
|
5825.2.8
by Guilherme Salgado
fix a couple things spotted by make lint |
731 |
self.failUnlessEqual( |
732 |
tm.acknowledger_comment, "Did it 'cause I can") |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
733 |
self.failUnless( |
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
734 |
tm.date_acknowledged <= datetime.now(pytz.UTC)) |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
735 |
# Destroy the membership so that we can create another in a
|
736 |
# different state.
|
|
737 |
tm.destroySelf() |
|
738 |
||
739 |
def test_reviewer_is_stored(self): |
|
740 |
transitions_mapping = { |
|
741 |
TeamMembershipStatus.DEACTIVATED: [TeamMembershipStatus.APPROVED], |
|
742 |
TeamMembershipStatus.EXPIRED: [TeamMembershipStatus.APPROVED], |
|
743 |
TeamMembershipStatus.PROPOSED: [ |
|
744 |
TeamMembershipStatus.APPROVED, TeamMembershipStatus.DECLINED], |
|
745 |
TeamMembershipStatus.DECLINED: [TeamMembershipStatus.APPROVED], |
|
746 |
TeamMembershipStatus.INVITATION_DECLINED: [ |
|
747 |
TeamMembershipStatus.APPROVED]} |
|
748 |
for status, new_statuses in transitions_mapping.items(): |
|
749 |
for new_status in new_statuses: |
|
750 |
tm = TeamMembership( |
|
751 |
person=self.no_priv, team=self.ubuntu_team, status=status) |
|
752 |
self.failIf( |
|
753 |
tm.reviewed_by, |
|
754 |
"There can be no approver at this point.") |
|
755 |
self.failIf( |
|
756 |
tm.date_reviewed, |
|
757 |
"There can be no approved date this point.") |
|
758 |
self.failIf( |
|
759 |
tm.reviewer_comment, |
|
760 |
"There can be no approver comment at this point.") |
|
761 |
tm.setStatus(new_status, self.foobar, "Did it 'cause I can") |
|
762 |
self.failUnlessEqual(tm.reviewed_by, self.foobar) |
|
5825.2.8
by Guilherme Salgado
fix a couple things spotted by make lint |
763 |
self.failUnlessEqual( |
764 |
tm.reviewer_comment, "Did it 'cause I can") |
|
5825.2.3
by Guilherme Salgado
Fix the damn thing |
765 |
self.failUnless( |
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
766 |
tm.date_reviewed <= datetime.now(pytz.UTC)) |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
767 |
|
768 |
# Destroy the membership so that we can create another in a
|
|
769 |
# different state.
|
|
770 |
tm.destroySelf() |
|
771 |
||
772 |
def test_datejoined(self): |
|
773 |
"""TeamMembership.datejoined stores the date in which this membership
|
|
774 |
was made active for the first time.
|
|
775 |
"""
|
|
776 |
tm = TeamMembership( |
|
777 |
person=self.no_priv, team=self.ubuntu_team, |
|
778 |
status=TeamMembershipStatus.PROPOSED) |
|
779 |
self.failIf( |
|
780 |
tm.datejoined, "There can be no datejoined at this point.") |
|
781 |
tm.setStatus(TeamMembershipStatus.APPROVED, self.foobar) |
|
9719.1.1
by Brad Crittenden
Re-enable test_proponent_is_stored as the spurious error cannot be reproduced. Also drive-by clean up to use pytz.UTC. |
782 |
now = datetime.now(pytz.UTC) |
5825.2.3
by Guilherme Salgado
Fix the damn thing |
783 |
self.failUnless(tm.datejoined <= now) |
784 |
||
785 |
# We now set the status to deactivated and change datejoined to a
|
|
786 |
# date in the past just so that we can easily show it's not changed
|
|
787 |
# again by setStatus().
|
|
788 |
one_minute_ago = now - timedelta(minutes=1) |
|
789 |
tm.setStatus(TeamMembershipStatus.DEACTIVATED, self.foobar) |
|
790 |
tm.datejoined = one_minute_ago |
|
791 |
tm.setStatus(TeamMembershipStatus.APPROVED, self.foobar) |
|
792 |
self.failUnless(tm.datejoined <= one_minute_ago) |
|
793 |
||
6220.2.1
by Guilherme Salgado
Fix the bug. |
794 |
def test_no_cyclical_membership_allowed(self): |
795 |
"""No status change can create cyclical memberships."""
|
|
796 |
# Invite team2 as member of team1 and team1 as member of team2. This
|
|
797 |
# is not a problem because that won't make any team an active member
|
|
798 |
# of the other.
|
|
10002.2.26
by Edwin Grubbs
Fixed tests and the message from +addmember. |
799 |
self.team1.addMember(self.team2, self.no_priv) |
800 |
self.team2.addMember(self.team1, self.no_priv) |
|
6220.2.1
by Guilherme Salgado
Fix the bug. |
801 |
team1_on_team2 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
802 |
self.team1, self.team2) |
6220.2.1
by Guilherme Salgado
Fix the bug. |
803 |
team2_on_team1 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
804 |
self.team2, self.team1) |
6220.2.1
by Guilherme Salgado
Fix the bug. |
805 |
self.failUnlessEqual( |
806 |
team1_on_team2.status, TeamMembershipStatus.INVITED) |
|
807 |
self.failUnlessEqual( |
|
808 |
team2_on_team1.status, TeamMembershipStatus.INVITED) |
|
809 |
||
810 |
# Now make team1 an active member of team2. From this point onwards,
|
|
811 |
# team2 cannot be made an active member of team1.
|
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
812 |
team1_on_team2.setStatus(TeamMembershipStatus.APPROVED, self.foobar) |
6220.2.1
by Guilherme Salgado
Fix the bug. |
813 |
flush_database_updates() |
814 |
self.failUnlessEqual( |
|
815 |
team1_on_team2.status, TeamMembershipStatus.APPROVED) |
|
816 |
self.assertRaises( |
|
817 |
CyclicalTeamMembershipError, team2_on_team1.setStatus, |
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
818 |
TeamMembershipStatus.APPROVED, self.foobar) |
6220.2.1
by Guilherme Salgado
Fix the bug. |
819 |
self.failUnlessEqual( |
820 |
team2_on_team1.status, TeamMembershipStatus.INVITED) |
|
821 |
||
822 |
# It is possible to change the state of team2's membership on team1
|
|
823 |
# to another inactive state, though.
|
|
824 |
team2_on_team1.setStatus( |
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
825 |
TeamMembershipStatus.INVITATION_DECLINED, self.foobar) |
6220.2.1
by Guilherme Salgado
Fix the bug. |
826 |
self.failUnlessEqual( |
827 |
team2_on_team1.status, TeamMembershipStatus.INVITATION_DECLINED) |
|
828 |
||
6220.2.2
by Guilherme Salgado
Fix to prevent cyclical participation as well. |
829 |
def test_no_cyclical_participation_allowed(self): |
830 |
"""No status change can create cyclical participation."""
|
|
831 |
# Invite team1 as a member of team3 and forcibly add team2 as member
|
|
832 |
# of team1 and team3 as member of team2.
|
|
10002.2.26
by Edwin Grubbs
Fixed tests and the message from +addmember. |
833 |
self.team3.addMember(self.team1, self.no_priv) |
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
834 |
self.team1.addMember(self.team2, self.foobar, force_team_add=True) |
835 |
self.team2.addMember(self.team3, self.foobar, force_team_add=True) |
|
6220.2.2
by Guilherme Salgado
Fix to prevent cyclical participation as well. |
836 |
|
837 |
# Since team2 is a member of team1 and team3 is a member of team2, we
|
|
838 |
# can't make team1 a member of team3.
|
|
839 |
team1_on_team3 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
840 |
self.team1, self.team3) |
6220.2.2
by Guilherme Salgado
Fix to prevent cyclical participation as well. |
841 |
self.assertRaises( |
842 |
CyclicalTeamMembershipError, team1_on_team3.setStatus, |
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
843 |
TeamMembershipStatus.APPROVED, self.foobar) |
844 |
||
845 |
def test_invited_member_can_be_made_admin(self): |
|
10002.2.26
by Edwin Grubbs
Fixed tests and the message from +addmember. |
846 |
self.team2.addMember(self.team1, self.no_priv) |
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
847 |
team1_on_team2 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
848 |
self.team1, self.team2) |
|
849 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.INVITED) |
|
850 |
team1_on_team2.setStatus(TeamMembershipStatus.ADMIN, self.foobar) |
|
851 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.ADMIN) |
|
852 |
||
853 |
def test_deactivated_member_can_be_made_admin(self): |
|
854 |
self.team2.addMember(self.team1, self.foobar, force_team_add=True) |
|
855 |
team1_on_team2 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
856 |
self.team1, self.team2) |
|
857 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.APPROVED) |
|
6809.1.2
by Guilherme Salgado
A couple fixes suggested by Graham. |
858 |
team1_on_team2.setStatus( |
859 |
TeamMembershipStatus.DEACTIVATED, self.foobar) |
|
6592.3.1
by Guilherme Salgado
change TeamMembership.setStatus() to allow all status to be transitioned to admin. |
860 |
self.assertEqual( |
861 |
team1_on_team2.status, TeamMembershipStatus.DEACTIVATED) |
|
862 |
team1_on_team2.setStatus(TeamMembershipStatus.ADMIN, self.foobar) |
|
863 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.ADMIN) |
|
864 |
||
865 |
def test_expired_member_can_be_made_admin(self): |
|
866 |
self.team2.addMember(self.team1, self.foobar, force_team_add=True) |
|
867 |
team1_on_team2 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
868 |
self.team1, self.team2) |
|
869 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.APPROVED) |
|
870 |
team1_on_team2.setStatus(TeamMembershipStatus.EXPIRED, self.foobar) |
|
871 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.EXPIRED) |
|
872 |
team1_on_team2.setStatus(TeamMembershipStatus.ADMIN, self.foobar) |
|
873 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.ADMIN) |
|
874 |
||
875 |
def test_declined_member_can_be_made_admin(self): |
|
876 |
self.team2.subscriptionpolicy = TeamSubscriptionPolicy.MODERATED |
|
877 |
self.team1.join(self.team2, requester=self.foobar) |
|
878 |
team1_on_team2 = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
879 |
self.team1, self.team2) |
|
880 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.PROPOSED) |
|
881 |
team1_on_team2.setStatus(TeamMembershipStatus.DECLINED, self.foobar) |
|
882 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.DECLINED) |
|
883 |
team1_on_team2.setStatus(TeamMembershipStatus.ADMIN, self.foobar) |
|
884 |
self.assertEqual(team1_on_team2.status, TeamMembershipStatus.ADMIN) |
|
6220.2.2
by Guilherme Salgado
Fix to prevent cyclical participation as well. |
885 |
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
886 |
def test_invited_member_can_be_declined(self): |
11818.6.11
by Curtis Hovey
Revised documentation. |
887 |
# A team can decline an invited member.
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
888 |
self.team2.addMember(self.team1, self.no_priv) |
889 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
890 |
self.team1, self.team2) |
|
891 |
tm.setStatus( |
|
892 |
TeamMembershipStatus.INVITATION_DECLINED, self.team2.teamowner) |
|
893 |
self.assertEqual(TeamMembershipStatus.INVITATION_DECLINED, tm.status) |
|
894 |
||
13785.7.1
by Aaron Bentley
Allow inviting previously-declined members. |
895 |
def test_declined_member_can_be_invited(self): |
896 |
# A team can re-invite a declined member.
|
|
897 |
self.team2.addMember( |
|
898 |
self.team1, self.no_priv, status=TeamMembershipStatus.PROPOSED, |
|
899 |
force_team_add=True) |
|
900 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
901 |
self.team1, self.team2) |
|
902 |
tm.setStatus( |
|
903 |
TeamMembershipStatus.DECLINED, self.team1.teamowner) |
|
904 |
tm.setStatus( |
|
905 |
TeamMembershipStatus.INVITED, self.team1.teamowner) |
|
906 |
self.assertEqual(TeamMembershipStatus.INVITED, tm.status) |
|
907 |
||
13785.7.2
by Aaron Bentley
Fix several team membership bugs. |
908 |
def test_add_approved(self): |
909 |
# Adding an approved team is a no-op.
|
|
910 |
member_team = self.factory.makeTeam() |
|
911 |
self.team1.addMember( |
|
912 |
member_team, self.team1.teamowner) |
|
913 |
with person_logged_in(member_team.teamowner): |
|
914 |
member_team.acceptInvitationToBeMemberOf(self.team1, 'alright') |
|
915 |
self.team1.addMember( |
|
916 |
member_team, self.team1.teamowner) |
|
917 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
918 |
member_team, self.team1) |
|
919 |
self.assertEqual(TeamMembershipStatus.APPROVED, tm.status) |
|
920 |
self.team1.addMember( |
|
921 |
member_team, member_team.teamowner) |
|
922 |
self.assertEqual(TeamMembershipStatus.APPROVED, tm.status) |
|
923 |
||
924 |
def test_add_admin(self): |
|
925 |
# Adding an admin team is a no-op.
|
|
926 |
member_team = self.factory.makeTeam() |
|
927 |
self.team1.addMember( |
|
928 |
member_team, self.team1.teamowner, |
|
929 |
status=TeamMembershipStatus.ADMIN, force_team_add=True) |
|
930 |
self.team1.addMember( |
|
931 |
member_team, self.team1.teamowner) |
|
932 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
933 |
member_team, self.team1) |
|
934 |
self.assertEqual(TeamMembershipStatus.ADMIN, tm.status) |
|
935 |
self.team1.addMember( |
|
936 |
member_team, member_team.teamowner) |
|
937 |
self.assertEqual(TeamMembershipStatus.ADMIN, tm.status) |
|
938 |
||
939 |
def test_implicit_approval(self): |
|
940 |
# Inviting a proposed person is an implicit approval.
|
|
941 |
member_team = self.factory.makeTeam() |
|
942 |
self.team1.addMember( |
|
943 |
member_team, self.team1.teamowner, |
|
944 |
status=TeamMembershipStatus.PROPOSED, force_team_add=True) |
|
945 |
self.team1.addMember( |
|
946 |
member_team, self.team1.teamowner) |
|
947 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
948 |
member_team, self.team1) |
|
949 |
self.assertEqual(TeamMembershipStatus.APPROVED, tm.status) |
|
950 |
||
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
951 |
def test_retractTeamMembership_invited(self): |
11818.6.11
by Curtis Hovey
Revised documentation. |
952 |
# A team can retract a membership invitation.
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
953 |
self.team2.addMember(self.team1, self.no_priv) |
954 |
self.team1.retractTeamMembership(self.team2, self.team1.teamowner) |
|
955 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
956 |
self.team1, self.team2) |
|
957 |
self.assertEqual(TeamMembershipStatus.INVITATION_DECLINED, tm.status) |
|
958 |
||
959 |
def test_retractTeamMembership_proposed(self): |
|
11818.6.11
by Curtis Hovey
Revised documentation. |
960 |
# A team can retract the proposed membership in a team.
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
961 |
self.team2.subscriptionpolicy = TeamSubscriptionPolicy.MODERATED |
962 |
self.team1.join(self.team2, self.team1.teamowner) |
|
963 |
self.team1.retractTeamMembership(self.team2, self.team1.teamowner) |
|
964 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
965 |
self.team1, self.team2) |
|
966 |
self.assertEqual(TeamMembershipStatus.DECLINED, tm.status) |
|
967 |
||
968 |
def test_retractTeamMembership_active(self): |
|
11818.6.11
by Curtis Hovey
Revised documentation. |
969 |
# A team can retract the membership in a team.
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
970 |
self.team1.join(self.team2, self.team1.teamowner) |
971 |
self.team1.retractTeamMembership(self.team2, self.team1.teamowner) |
|
972 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
973 |
self.team1, self.team2) |
|
974 |
self.assertEqual(TeamMembershipStatus.DEACTIVATED, tm.status) |
|
975 |
||
976 |
def test_retractTeamMembership_admin(self): |
|
11818.6.11
by Curtis Hovey
Revised documentation. |
977 |
# A team can retract the membership in a team.
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
978 |
self.team1.join(self.team2, self.team1.teamowner) |
979 |
tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
980 |
self.team1, self.team2) |
|
981 |
tm.setStatus(TeamMembershipStatus.ADMIN, self.team2.teamowner) |
|
982 |
self.team1.retractTeamMembership(self.team2, self.team1.teamowner) |
|
11818.6.2
by Curtis Hovey
Added retractTeamMembership so that teams can leave super teams. Allow users to delete teams with user teams. |
983 |
self.assertEqual(TeamMembershipStatus.DEACTIVATED, tm.status) |
984 |
||
5825.2.3
by Guilherme Salgado
Fix the damn thing |
985 |
|
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
986 |
class TestTeamMembershipSendExpirationWarningEmail(TestCaseWithFactory): |
987 |
"""Test the behaviour of sendExpirationWarningEmail()."""
|
|
988 |
layer = DatabaseFunctionalLayer |
|
989 |
||
990 |
def setUp(self): |
|
991 |
super(TestTeamMembershipSendExpirationWarningEmail, self).setUp() |
|
12481.1.3
by Curtis Hovey
Use names for the team and member to simplify tests. |
992 |
self.member = self.factory.makePerson(name='green') |
993 |
self.team = self.factory.makeTeam(name='red') |
|
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
994 |
login_person(self.team.teamowner) |
995 |
self.team.addMember(self.member, self.team.teamowner) |
|
996 |
self.tm = getUtility(ITeamMembershipSet).getByPersonAndTeam( |
|
997 |
self.member, self.team) |
|
998 |
pop_notifications() |
|
999 |
||
12481.1.4
by Curtis Hovey
Added the person and team to the assertion messag. |
1000 |
def test_error_raised_when_no_expiration(self): |
1001 |
# An exception is raised if the membership does not have an
|
|
1002 |
# expiration date.
|
|
1003 |
self.assertEqual(None, self.tm.dateexpires) |
|
12481.1.5
by Curtis Hovey
Updated sendExpirationWarningEmail documentation. Do not assert that the expiration date has past; silently return instead. |
1004 |
message = 'green in team red has no membership expiration date.' |
1005 |
self.assertRaisesWithContent( |
|
1006 |
AssertionError, message, self.tm.sendExpirationWarningEmail) |
|
1007 |
||
1008 |
def test_error_raised_for_team_with_automatic_renewal(self): |
|
1009 |
# An exception is raised if the team's TeamMembershipRenewalPolicy
|
|
1010 |
# is AUTOMATIC.
|
|
1011 |
self.team.renewal_policy = TeamMembershipRenewalPolicy.AUTOMATIC |
|
1012 |
self.team.defaultrenewalperiod = 365 |
|
1013 |
tomorrow = datetime.now(pytz.UTC) + timedelta(days=1) |
|
1014 |
removeSecurityProxy(self.tm).dateexpires = tomorrow |
|
1015 |
message = ( |
|
1016 |
'Team red with automatic renewals should not send '
|
|
1017 |
'expiration warnings.') |
|
12481.1.4
by Curtis Hovey
Added the person and team to the assertion messag. |
1018 |
self.assertRaisesWithContent( |
1019 |
AssertionError, message, self.tm.sendExpirationWarningEmail) |
|
1020 |
||
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
1021 |
def test_message_sent_for_future_expiration(self): |
1022 |
# An email is sent to the user whose membership will expire.
|
|
12481.1.5
by Curtis Hovey
Updated sendExpirationWarningEmail documentation. Do not assert that the expiration date has past; silently return instead. |
1023 |
tomorrow = datetime.now(pytz.UTC) + timedelta(days=1) |
1024 |
removeSecurityProxy(self.tm).dateexpires = tomorrow |
|
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
1025 |
self.tm.sendExpirationWarningEmail() |
1026 |
notifications = pop_notifications() |
|
1027 |
self.assertEqual(1, len(notifications)) |
|
1028 |
message = notifications[0] |
|
1029 |
self.assertEqual( |
|
12481.1.3
by Curtis Hovey
Use names for the team and member to simplify tests. |
1030 |
'Your membership in red is about to expire', message['subject']) |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
1031 |
self.assertEqual( |
12481.1.3
by Curtis Hovey
Use names for the team and member to simplify tests. |
1032 |
self.member.preferredemail.email, message['to']) |
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
1033 |
|
12481.1.5
by Curtis Hovey
Updated sendExpirationWarningEmail documentation. Do not assert that the expiration date has past; silently return instead. |
1034 |
def test_no_message_sent_for_expired_memberships(self): |
1035 |
# Members whose membership has expired do not get a message.
|
|
1036 |
yesterday = datetime.now(pytz.UTC) - timedelta(days=1) |
|
1037 |
removeSecurityProxy(self.tm).dateexpires = yesterday |
|
1038 |
self.tm.sendExpirationWarningEmail() |
|
1039 |
notifications = pop_notifications() |
|
1040 |
self.assertEqual(0, len(notifications)) |
|
1041 |
||
12481.1.1
by Curtis Hovey
Added a simple unittest to verify the behavioursendExpirationWarningEmail(). |
1042 |
def test_no_message_sent_for_non_active_users(self): |
1043 |
# Non-active users do not get an expiration message.
|
|
1044 |
with person_logged_in(self.member): |
|
1045 |
self.member.deactivateAccount('Goodbye.') |
|
1046 |
IStore(self.member).flush() |
|
1047 |
now = datetime.now(pytz.UTC) |
|
1048 |
removeSecurityProxy(self.tm).dateexpires = now + timedelta(days=1) |
|
1049 |
self.tm.sendExpirationWarningEmail() |
|
1050 |
notifications = pop_notifications() |
|
1051 |
self.assertEqual(0, len(notifications)) |
|
1052 |
||
1053 |
||
14213.4.3
by Gavin Panella
New test case TestCheckTeamParticipationScriptPerformance that runs check_teamparticipation() in-process, so we can monitor database activity more closely. |
1054 |
class TestCheckTeamParticipationScript(TestCase): |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
1055 |
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
1056 |
layer = DatabaseFunctionalLayer |
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1057 |
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1058 |
def _runScript(self, *args): |
1059 |
cmd = ["cronscripts/check-teamparticipation.py"] |
|
1060 |
cmd.extend(args) |
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1061 |
process = subprocess.Popen( |
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1062 |
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1063 |
stderr=subprocess.PIPE) |
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
1064 |
out, err = process.communicate() |
14213.4.17
by Gavin Panella
Use inequality instead of len(). |
1065 |
if out != "": |
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
1066 |
self.addDetail("stdout", text_content(out)) |
14213.4.17
by Gavin Panella
Use inequality instead of len(). |
1067 |
if err != "": |
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
1068 |
self.addDetail("stderr", text_content(err)) |
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1069 |
return process.poll(), out, err |
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1070 |
|
1071 |
def test_no_output_if_no_invalid_entries(self): |
|
1072 |
"""No output if there's no invalid teamparticipation entries."""
|
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1073 |
code, out, err = self._runScript() |
1074 |
self.assertEqual(0, code) |
|
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
1075 |
self.assertEqual(0, len(out)) |
1076 |
self.assertEqual(0, len(err)) |
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1077 |
|
1078 |
def test_report_invalid_teamparticipation_entries(self): |
|
7052.1.2
by Guilherme Salgado
Fix the bug. |
1079 |
"""The script reports missing/spurious TeamParticipation entries.
|
6010.1.1
by Guilherme Salgado
Change the check-teamparticipation.py script to check for people/teams which are not members of themselves. |
1080 |
|
1081 |
As well as missing self-participation.
|
|
1082 |
"""
|
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1083 |
cur = cursor() |
7052.1.2
by Guilherme Salgado
Fix the bug. |
1084 |
# Create a new entry in the Person table and change its
|
1085 |
# self-participation entry, making that person a participant in a team
|
|
1086 |
# where it should not be as well as making that person not a member of
|
|
1087 |
# itself (as everybody should be).
|
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1088 |
cur.execute(""" |
6010.1.1
by Guilherme Salgado
Change the check-teamparticipation.py script to check for people/teams which are not members of themselves. |
1089 |
INSERT INTO
|
6198.1.30
by Stuart Bishop
Fix teammembership tests |
1090 |
Person (id, name, displayname, creation_rationale)
|
1091 |
VALUES (9999, 'zzzzz', 'zzzzzz', 1);
|
|
6010.1.2
by Guilherme Salgado
Fix a few stylistic things. |
1092 |
UPDATE TeamParticipation
|
6010.1.1
by Guilherme Salgado
Change the check-teamparticipation.py script to check for people/teams which are not members of themselves. |
1093 |
SET team = (
|
7052.1.2
by Guilherme Salgado
Fix the bug. |
1094 |
SELECT id
|
1095 |
FROM Person
|
|
1096 |
WHERE teamowner IS NOT NULL
|
|
1097 |
ORDER BY name
|
|
1098 |
LIMIT 1)
|
|
6010.1.1
by Guilherme Salgado
Change the check-teamparticipation.py script to check for people/teams which are not members of themselves. |
1099 |
WHERE person = 9999;
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1100 |
""") |
7052.1.2
by Guilherme Salgado
Fix the bug. |
1101 |
# Now add the new person as a member of another team but don't create
|
1102 |
# the relevant TeamParticipation for that person on that team.
|
|
1103 |
cur.execute(""" |
|
1104 |
INSERT INTO
|
|
1105 |
TeamMembership (person, team, status)
|
|
1106 |
VALUES (9999,
|
|
1107 |
(SELECT id
|
|
1108 |
FROM Person
|
|
1109 |
WHERE teamowner IS NOT NULL
|
|
1110 |
ORDER BY name desc
|
|
1111 |
LIMIT 1),
|
|
1112 |
%s); |
|
1113 |
""" % sqlvalues(TeamMembershipStatus.APPROVED)) |
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1114 |
transaction.commit() |
6010.1.1
by Guilherme Salgado
Change the check-teamparticipation.py script to check for people/teams which are not members of themselves. |
1115 |
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1116 |
code, out, err = self._runScript() |
1117 |
self.assertEqual(0, code) |
|
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
1118 |
self.assertEqual(0, len(out)) |
1119 |
self.failUnless( |
|
1120 |
re.search('missing TeamParticipation entries for zzzzz', err)) |
|
1121 |
self.failUnless( |
|
1122 |
re.search('spurious TeamParticipation entries for zzzzz', err)) |
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1123 |
|
7052.1.3
by Guilherme Salgado
Make check-teamparticipation.py detect circular references between teams. |
1124 |
def test_report_circular_team_references(self): |
1125 |
"""The script reports circular references between teams.
|
|
1126 |
||
1127 |
If that happens, though, the script will have to report the circular
|
|
1128 |
references and exit, to avoid an infinite loop when checking for
|
|
1129 |
missing/spurious TeamParticipation entries.
|
|
1130 |
"""
|
|
1131 |
# Create two new teams and make them members of each other.
|
|
1132 |
cursor().execute(""" |
|
1133 |
INSERT INTO
|
|
1134 |
Person (id, name, displayname, teamowner)
|
|
1135 |
VALUES (9998, 'test-team1', 'team1', 1);
|
|
1136 |
INSERT INTO
|
|
1137 |
Person (id, name, displayname, teamowner)
|
|
1138 |
VALUES (9997, 'test-team2', 'team2', 1);
|
|
1139 |
INSERT INTO
|
|
1140 |
TeamMembership (person, team, status)
|
|
1141 |
VALUES (9998, 9997, %(approved)s); |
|
1142 |
INSERT INTO
|
|
1143 |
TeamParticipation (person, team)
|
|
1144 |
VALUES (9998, 9997);
|
|
1145 |
INSERT INTO
|
|
1146 |
TeamMembership (person, team, status)
|
|
1147 |
VALUES (9997, 9998, %(approved)s); |
|
1148 |
INSERT INTO
|
|
1149 |
TeamParticipation (person, team)
|
|
1150 |
VALUES (9997, 9998);
|
|
1151 |
""" % sqlvalues(approved=TeamMembershipStatus.APPROVED)) |
|
1152 |
transaction.commit() |
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1153 |
code, out, err = self._runScript() |
1154 |
self.assertEqual(1, code) |
|
14213.4.5
by Gavin Panella
Improve the tests to add the logs as details. |
1155 |
self.assertEqual(0, len(out)) |
1156 |
self.failUnless(re.search('Circular references found', err)) |
|
7052.1.3
by Guilherme Salgado
Make check-teamparticipation.py detect circular references between teams. |
1157 |
|
14464.1.2
by Gavin Panella
Test for new function fix_teamparticipation_consistency(). |
1158 |
# A script to create two new people, where both participate in the first,
|
1159 |
# and first is missing a self-participation.
|
|
1160 |
script_create_inconsistent_participation = """ |
|
1161 |
INSERT INTO
|
|
1162 |
Person (id, name, displayname, creation_rationale)
|
|
1163 |
VALUES (6969, 'bobby', 'Dazzler', 1);
|
|
1164 |
INSERT INTO
|
|
1165 |
Person (id, name, displayname, creation_rationale)
|
|
1166 |
VALUES (6970, 'nobby', 'Jazzler', 1);
|
|
1167 |
INSERT INTO
|
|
1168 |
TeamParticipation (person, team)
|
|
1169 |
VALUES (6970, 6969);
|
|
1170 |
DELETE FROM
|
|
1171 |
TeamParticipation
|
|
1172 |
WHERE person = 6969
|
|
1173 |
AND team = 6969;
|
|
14464.1.5
by Gavin Panella
Commit changes so that other connections can see them. |
1174 |
"""
|
14464.1.2
by Gavin Panella
Test for new function fix_teamparticipation_consistency(). |
1175 |
|
14464.1.3
by Gavin Panella
Rename test_report_spurious_participants_of_people to test_check_teamparticipation_consistency. |
1176 |
def test_check_teamparticipation_consistency(self): |
14213.4.19
by Gavin Panella
Check that the only participant of a person is the person. |
1177 |
"""The script reports spurious participants of people.
|
1178 |
||
1179 |
Teams can have multiple participants, but only the person should be a
|
|
1180 |
paricipant of him/herself.
|
|
1181 |
"""
|
|
14464.1.2
by Gavin Panella
Test for new function fix_teamparticipation_consistency(). |
1182 |
cursor().execute(self.script_create_inconsistent_participation) |
14464.1.5
by Gavin Panella
Commit changes so that other connections can see them. |
1183 |
transaction.commit() |
14213.4.19
by Gavin Panella
Check that the only participant of a person is the person. |
1184 |
logger = BufferLogger() |
14213.4.31
by Gavin Panella
Use BufferLogger.content in tests. |
1185 |
self.addDetail("log", logger.content) |
14213.4.37
by Gavin Panella
Decouple check_teamparticipation_consistency() from fetch_team_participation_info(). |
1186 |
errors = check_teamparticipation_consistency( |
1187 |
logger, fetch_team_participation_info(logger)) |
|
14464.1.1
by Gavin Panella
Demonstrate check_teamparticipation_consistency() finding a missing TeamParticipation. |
1188 |
errors_expected = [ |
1189 |
ConsistencyError("spurious", 6969, [6970]), |
|
1190 |
ConsistencyError("missing", 6969, [6969]), |
|
1191 |
]
|
|
1192 |
self.assertContentEqual(errors_expected, errors) |
|
14213.4.19
by Gavin Panella
Check that the only participant of a person is the person. |
1193 |
|
14464.1.2
by Gavin Panella
Test for new function fix_teamparticipation_consistency(). |
1194 |
def test_fix_teamparticipation_consistency(self): |
1195 |
"""
|
|
1196 |
`fix_teamparticipation_consistency` takes an iterable of
|
|
1197 |
`ConsistencyError`s and attempts to repair the data.
|
|
1198 |
"""
|
|
1199 |
cursor().execute(self.script_create_inconsistent_participation) |
|
14464.1.5
by Gavin Panella
Commit changes so that other connections can see them. |
1200 |
transaction.commit() |
14464.1.2
by Gavin Panella
Test for new function fix_teamparticipation_consistency(). |
1201 |
logger = BufferLogger() |
1202 |
self.addDetail("log", logger.content) |
|
1203 |
errors = check_teamparticipation_consistency( |
|
1204 |
logger, fetch_team_participation_info(logger)) |
|
1205 |
self.assertNotEqual([], errors) |
|
1206 |
fix_teamparticipation_consistency(logger, errors) |
|
1207 |
errors = check_teamparticipation_consistency( |
|
1208 |
logger, fetch_team_participation_info(logger)) |
|
1209 |
self.assertEqual([], errors) |
|
1210 |
||
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1211 |
def test_load_and_save_team_participation(self): |
14213.4.28
by Gavin Panella
Update docstring. |
1212 |
"""The script can load and save participation info."""
|
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1213 |
logger = BufferLogger() |
14213.4.31
by Gavin Panella
Use BufferLogger.content in tests. |
1214 |
self.addDetail("log", logger.content) |
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1215 |
info = fetch_team_participation_info(logger) |
1216 |
tempdir = self.useFixture(TempDir()).path |
|
1217 |
filename_in = os.path.join(tempdir, "info.in") |
|
1218 |
filename_out = os.path.join(tempdir, "info.out") |
|
1219 |
fout = bz2.BZ2File(filename_in, "w") |
|
1220 |
try: |
|
1221 |
pickle.dump(info, fout, pickle.HIGHEST_PROTOCOL) |
|
1222 |
finally: |
|
1223 |
fout.close() |
|
1224 |
code, out, err = self._runScript( |
|
1225 |
"--load-participation-info", filename_in, |
|
1226 |
"--save-participation-info", filename_out) |
|
1227 |
self.assertEqual(0, code) |
|
1228 |
fin = bz2.BZ2File(filename_out, "r") |
|
1229 |
try: |
|
1230 |
saved_info = pickle.load(fin) |
|
1231 |
finally: |
|
1232 |
fin.close() |
|
1233 |
self.assertEqual(info, saved_info) |
|
1234 |
||
14213.4.3
by Gavin Panella
New test case TestCheckTeamParticipationScriptPerformance that runs check_teamparticipation() in-process, so we can monitor database activity more closely. |
1235 |
|
1236 |
class TestCheckTeamParticipationScriptPerformance(TestCaseWithFactory): |
|
1237 |
||
14213.4.13
by Gavin Panella
Demonstrate that a constant number of queries are issued for the whole check_teamparticipation() run. |
1238 |
layer = DatabaseFunctionalLayer |
14213.4.3
by Gavin Panella
New test case TestCheckTeamParticipationScriptPerformance that runs check_teamparticipation() in-process, so we can monitor database activity more closely. |
1239 |
|
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
1240 |
def test_queries(self): |
14213.4.13
by Gavin Panella
Demonstrate that a constant number of queries are issued for the whole check_teamparticipation() run. |
1241 |
"""The script does not overly tax the database.
|
1242 |
||
1243 |
The whole check_teamparticipation() run executes a constant low number
|
|
1244 |
of queries.
|
|
1245 |
"""
|
|
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
1246 |
# Create a deeply nested team and member structure.
|
1247 |
team = self.factory.makeTeam() |
|
1248 |
for num in xrange(10): |
|
1249 |
another_team = self.factory.makeTeam() |
|
1250 |
another_person = self.factory.makePerson() |
|
1251 |
with person_logged_in(team.teamowner): |
|
1252 |
team.addMember(another_team, team.teamowner) |
|
1253 |
team.addMember(another_person, team.teamowner) |
|
1254 |
team = another_team |
|
14213.4.13
by Gavin Panella
Demonstrate that a constant number of queries are issued for the whole check_teamparticipation() run. |
1255 |
transaction.commit() |
14213.4.31
by Gavin Panella
Use BufferLogger.content in tests. |
1256 |
logger = BufferLogger() |
1257 |
self.addDetail("log", logger.content) |
|
14213.4.13
by Gavin Panella
Demonstrate that a constant number of queries are issued for the whole check_teamparticipation() run. |
1258 |
with StormStatementRecorder() as recorder: |
14213.4.26
by Gavin Panella
Enable loading and saving of team participation info. Work in progress. |
1259 |
check_teamparticipation_circular(logger) |
14213.4.37
by Gavin Panella
Decouple check_teamparticipation_consistency() from fetch_team_participation_info(). |
1260 |
check_teamparticipation_consistency( |
1261 |
logger, fetch_team_participation_info(logger)) |
|
14464.2.1
by Gavin Panella
Remove check_teamparticipation_self() because this is covered by check_teamparticipation_consistency(). |
1262 |
self.assertThat(recorder, HasQueryCount(Equals(5))) |
14213.4.1
by Gavin Panella
Beginnings of performance optimization work for check-teamparticipation.py. |
1263 |
|
4868.1.6
by Guilherme Salgado
Turn the script that was supposed to fix invalid team participation entries into something that just reports the invalid ones, to be run from staging |
1264 |
|
3691.272.16
by Guilherme Salgado
A bunch of fixes and new tests suggested by Bjorn on his review |
1265 |
def test_suite(): |
12019.11.1
by Brad Crittenden
Rework cleanTeamParticipation. Works but is still inefficient. |
1266 |
suite = TestLoader().loadTestsFromName(__name__) |
6702.1.2
by Guilherme Salgado
A couple changes suggested by Francis |
1267 |
bug_249185 = LayeredDocFileSuite( |
1268 |
'bug-249185.txt', optionflags=default_optionflags, |
|
11818.6.7
by Curtis Hovey
Added test to verify corner-cases with managing super teams are handled. |
1269 |
layer=DatabaseFunctionalLayer, setUp=setUp, tearDown=tearDown) |
6702.1.2
by Guilherme Salgado
A couple changes suggested by Francis |
1270 |
suite.addTest(bug_249185) |
1271 |
return suite |