blob: 2eb7a2bb41429448f62dec786bb766b5bd9b0645 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""Tests for the project_svc module."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import time
12import unittest
13
14import mox
15import mock
16
17from google.appengine.ext import testbed
18
19from framework import framework_constants
20from framework import sql
21from proto import project_pb2
22from proto import user_pb2
23from services import config_svc
24from services import project_svc
25from testing import fake
26
27NOW = 12345678
28
29
30def MakeProjectService(cache_manager, my_mox):
31 project_service = project_svc.ProjectService(cache_manager)
32 project_service.project_tbl = my_mox.CreateMock(sql.SQLTableManager)
33 project_service.user2project_tbl = my_mox.CreateMock(sql.SQLTableManager)
34 project_service.extraperm_tbl = my_mox.CreateMock(sql.SQLTableManager)
35 project_service.membernotes_tbl = my_mox.CreateMock(sql.SQLTableManager)
36 project_service.usergroupprojects_tbl = my_mox.CreateMock(
37 sql.SQLTableManager)
38 project_service.acexclusion_tbl = my_mox.CreateMock(
39 sql.SQLTableManager)
40 return project_service
41
42
43class ProjectTwoLevelCacheTest(unittest.TestCase):
44
45 def setUp(self):
46 self.testbed = testbed.Testbed()
47 self.testbed.activate()
48 self.testbed.init_memcache_stub()
49
50 self.mox = mox.Mox()
51 self.cnxn = self.mox.CreateMock(sql.MonorailConnection)
52 self.cache_manager = fake.CacheManager()
53 self.project_service = MakeProjectService(self.cache_manager, self.mox)
54
55 def tearDown(self):
56 self.testbed.deactivate()
57
58 def testDeserializeProjects(self):
59 project_rows = [
60 (
61 123, 'proj1', 'test proj 1', 'test project', 'live', 'anyone', '',
62 '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
63 False, None, None, None, None, None, None, False),
64 (
65 234, 'proj2', 'test proj 2', 'test project', 'live', 'anyone', '',
66 '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
67 False, None, None, None, None, None, None, True)
68 ]
69 role_rows = [
70 (123, 111, 'owner'), (123, 444, 'owner'),
71 (123, 222, 'committer'),
72 (123, 333, 'contributor'),
73 (234, 111, 'owner')]
74 extraperm_rows = []
75
76 project_dict = self.project_service.project_2lc._DeserializeProjects(
77 project_rows, role_rows, extraperm_rows)
78
79 self.assertItemsEqual([123, 234], list(project_dict.keys()))
80 self.assertEqual(123, project_dict[123].project_id)
81 self.assertEqual('proj1', project_dict[123].project_name)
82 self.assertEqual(NOW, project_dict[123].recent_activity)
83 self.assertItemsEqual([111, 444], project_dict[123].owner_ids)
84 self.assertItemsEqual([222], project_dict[123].committer_ids)
85 self.assertItemsEqual([333], project_dict[123].contributor_ids)
86 self.assertEqual(234, project_dict[234].project_id)
87 self.assertItemsEqual([111], project_dict[234].owner_ids)
88 self.assertEqual(False, project_dict[123].issue_notify_always_detailed)
89 self.assertEqual(True, project_dict[234].issue_notify_always_detailed)
90
91
92class UserToProjectIdTwoLevelCacheTest(unittest.TestCase):
93
94 def setUp(self):
95 self.testbed = testbed.Testbed()
96 self.testbed.activate()
97 self.testbed.init_memcache_stub()
98
99 self.cnxn = fake.MonorailConnection()
100 self.cache_manager = fake.CacheManager()
101 self.mox = mox.Mox()
102 self.project_service = MakeProjectService(self.cache_manager, self.mox)
103 self.user_to_project_2lc = self.project_service.user_to_project_2lc
104
105 # Set up DB query mocks.
106 self.cached_user_ids = [100, 101]
107 self.from_db_user_ids = [102, 103]
108 test_table = [
109 (900, self.cached_user_ids[0]), # Project 900, User 100
110 (900, self.cached_user_ids[1]), # Project 900, User 101
111 (901, self.cached_user_ids[0]), # Project 901, User 101
112 (902, self.from_db_user_ids[0]), # Project 902, User 102
113 (902, self.from_db_user_ids[1]), # Project 902, User 103
114 (903, self.from_db_user_ids[0]), # Project 903, User 102
115 ]
116 self.project_service.user2project_tbl.Select = mock.Mock(
117 return_value=test_table)
118
119 def tearDown(self):
120 # memcache.flush_all()
121 self.testbed.deactivate()
122 self.mox.UnsetStubs()
123 self.mox.ResetAll()
124
125 def testGetAll(self):
126 # Cache user 100 and 101.
127 self.user_to_project_2lc.CacheItem(self.cached_user_ids[0], set([900, 901]))
128 self.user_to_project_2lc.CacheItem(self.cached_user_ids[1], set([900]))
129 # Test that other project_ids and user_ids get returned by DB queries.
130 first_hit, first_misses = self.user_to_project_2lc.GetAll(
131 self.cnxn, self.cached_user_ids + self.from_db_user_ids)
132
133 self.project_service.user2project_tbl.Select.assert_called_once_with(
134 self.cnxn, cols=['project_id', 'user_id'])
135
136 self.assertEqual(
137 first_hit, {
138 100: set([900, 901]),
139 101: set([900]),
140 102: set([902, 903]),
141 103: set([902]),
142 })
143 self.assertEqual([], first_misses)
144
145 def testGetAllRateLimit(self):
146 test_now = time.time()
147 # Initial request that queries table.
148 self.user_to_project_2lc._GetCurrentTime = mock.Mock(
149 return_value=test_now + 60)
150 self.user_to_project_2lc.GetAll(
151 self.cnxn, self.cached_user_ids + self.from_db_user_ids)
152
153 # Request a user with no projects right after the last request.
154 self.user_to_project_2lc._GetCurrentTime = mock.Mock(
155 return_value=test_now + 61)
156 second_hit, second_misses = self.user_to_project_2lc.GetAll(
157 self.cnxn, [104])
158
159 # Request one more user without project that should make a DB request
160 # because the required rate limit time has passed.
161 self.user_to_project_2lc._GetCurrentTime = mock.Mock(
162 return_value=test_now + 121)
163 third_hit, third_misses = self.user_to_project_2lc.GetAll(self.cnxn, [105])
164
165 # Queried only twice because the second request was rate limited.
166 self.assertEqual(self.project_service.user2project_tbl.Select.call_count, 2)
167
168 # Rate limited response will not return the full table.
169 self.assertEqual(second_hit, {
170 104: set([]),
171 })
172 self.assertEqual([], second_misses)
173 self.assertEqual(
174 third_hit, {
175 100: set([900, 901]),
176 101: set([900]),
177 102: set([902, 903]),
178 103: set([902]),
179 105: set([]),
180 })
181 self.assertEqual([], third_misses)
182
183
184class ProjectServiceTest(unittest.TestCase):
185
186 def setUp(self):
187 self.testbed = testbed.Testbed()
188 self.testbed.activate()
189 self.testbed.init_memcache_stub()
190
191 self.mox = mox.Mox()
192 self.cnxn = self.mox.CreateMock(sql.MonorailConnection)
193 self.cache_manager = fake.CacheManager()
194 self.config_service = self.mox.CreateMock(config_svc.ConfigService)
195 self.project_service = MakeProjectService(self.cache_manager, self.mox)
196
197 self.proj1 = fake.Project(project_name='proj1', project_id=123)
198 self.proj2 = fake.Project(project_name='proj2', project_id=234)
199
200 def tearDown(self):
201 self.testbed.deactivate()
202 self.mox.UnsetStubs()
203 self.mox.ResetAll()
204
205 def SetUpCreateProject(self):
206 # Check for existing project: there should be none.
207 self.project_service.project_tbl.Select(
208 self.cnxn, cols=['project_name', 'project_id'],
209 project_name=['proj1']).AndReturn([])
210
211 # Inserting the project gives the project ID.
212 self.project_service.project_tbl.InsertRow(
213 self.cnxn, project_name='proj1',
214 summary='Test project summary', description='Test project description',
215 home_page=None, docs_url=None, source_url=None,
216 logo_file_name=None, logo_gcs_id=None,
217 state='LIVE', access='ANYONE').AndReturn(123)
218
219 # Insert the users. There are none.
220 self.project_service.user2project_tbl.InsertRows(
221 self.cnxn, ['project_id', 'user_id', 'role_name'], [])
222
223 def testCreateProject(self):
224 self.SetUpCreateProject()
225 self.mox.ReplayAll()
226 self.project_service.CreateProject(
227 self.cnxn, 'proj1', owner_ids=[], committer_ids=[], contributor_ids=[],
228 summary='Test project summary', description='Test project description')
229 self.mox.VerifyAll()
230
231 def SetUpLookupProjectIDs(self):
232 self.project_service.project_tbl.Select(
233 self.cnxn, cols=['project_name', 'project_id'],
234 project_name=['proj2']).AndReturn([('proj2', 234)])
235
236 def testLookupProjectIDs(self):
237 self.SetUpLookupProjectIDs()
238 self.project_service.project_names_to_ids.CacheItem('proj1', 123)
239 self.mox.ReplayAll()
240 id_dict = self.project_service.LookupProjectIDs(
241 self.cnxn, ['proj1', 'proj2'])
242 self.mox.VerifyAll()
243 self.assertEqual({'proj1': 123, 'proj2': 234}, id_dict)
244
245 def testLookupProjectNames(self):
246 self.SetUpGetProjects() # Same as testGetProjects()
247 self.project_service.project_2lc.CacheItem(123, self.proj1)
248 self.mox.ReplayAll()
249 name_dict = self.project_service.LookupProjectNames(
250 self.cnxn, [123, 234])
251 self.mox.VerifyAll()
252 self.assertEqual({123: 'proj1', 234: 'proj2'}, name_dict)
253
254 def SetUpGetProjects(self, roles=None, extra_perms=None):
255 project_rows = [
256 (
257 234, 'proj2', 'test proj 2', 'test project', 'live', 'anyone', '',
258 '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
259 False, None, None, None, None, None, None, False)
260 ]
261 self.project_service.project_tbl.Select(
262 self.cnxn, cols=project_svc.PROJECT_COLS,
263 project_id=[234]).AndReturn(project_rows)
264 self.project_service.user2project_tbl.Select(
265 self.cnxn, cols=['project_id', 'user_id', 'role_name'],
266 project_id=[234]).AndReturn(roles or [])
267 self.project_service.extraperm_tbl.Select(
268 self.cnxn, cols=project_svc.EXTRAPERM_COLS,
269 project_id=[234]).AndReturn(extra_perms or [])
270
271 def testGetProjects(self):
272 self.project_service.project_2lc.CacheItem(123, self.proj1)
273 self.SetUpGetProjects()
274 self.mox.ReplayAll()
275 project_dict = self.project_service.GetProjects(
276 self.cnxn, [123, 234])
277 self.mox.VerifyAll()
278 self.assertItemsEqual([123, 234], list(project_dict.keys()))
279 self.assertEqual('proj1', project_dict[123].project_name)
280 self.assertEqual('proj2', project_dict[234].project_name)
281
282 def testGetProjects_ExtraPerms(self):
283 self.SetUpGetProjects(extra_perms=[(234, 222, 'BarPerm'),
284 (234, 111, 'FooPerm')])
285 self.mox.ReplayAll()
286 project_dict = self.project_service.GetProjects(self.cnxn, [234])
287 self.mox.VerifyAll()
288 self.assertItemsEqual([234], list(project_dict.keys()))
289 self.assertEqual(
290 [project_pb2.Project.ExtraPerms(
291 member_id=111, perms=['FooPerm']),
292 project_pb2.Project.ExtraPerms(
293 member_id=222, perms=['BarPerm'])],
294 project_dict[234].extra_perms)
295
296
297 def testGetVisibleLiveProjects_AnyoneAccessWithUser(self):
298 project_rows = [
299 (
300 234, 'proj2', 'test proj 2', 'test project', 'live', 'anyone', '',
301 '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
302 False, None, None, None, False)
303 ]
304
305 self.project_service.project_tbl.Select(
306 self.cnxn, cols=['project_id'],
307 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
308 self.SetUpGetProjects()
309 self.mox.ReplayAll()
310 user_a = user_pb2.User(email='a@example.com')
311 project_ids = self.project_service.GetVisibleLiveProjects(
312 self.cnxn, user_a, set([111]))
313
314 self.mox.VerifyAll()
315 self.assertItemsEqual([234], project_ids)
316
317 def testGetVisibleLiveProjects_AnyoneAccessWithAnon(self):
318 project_rows = [
319 (
320 234, 'proj2', 'test proj 2', 'test project', 'live', 'anyone', '',
321 '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
322 False, None, None, None, None, None, None, False)
323 ]
324
325 self.project_service.project_tbl.Select(
326 self.cnxn, cols=['project_id'],
327 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
328 self.SetUpGetProjects()
329 self.mox.ReplayAll()
330 project_ids = self.project_service.GetVisibleLiveProjects(
331 self.cnxn, None, None)
332
333 self.mox.VerifyAll()
334 self.assertItemsEqual([234], project_ids)
335
336 def testGetVisibleLiveProjects_RestrictedAccessWithMember(self):
337 project_rows = [
338 (
339 234, 'proj2', 'test proj 2', 'test project', 'live', 'members_only',
340 '', '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
341 False, False, None, None, None, None, None, None, False)
342 ]
343 self.proj2.access = project_pb2.ProjectAccess.MEMBERS_ONLY
344 self.proj2.contributor_ids.append(111)
345 self.project_service.project_2lc.CacheItem(234, self.proj2)
346
347 self.project_service.project_tbl.Select(
348 self.cnxn, cols=['project_id'],
349 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
350 self.mox.ReplayAll()
351 user_a = user_pb2.User(email='a@example.com')
352 project_ids = self.project_service.GetVisibleLiveProjects(
353 self.cnxn, user_a, set([111]))
354
355 self.mox.VerifyAll()
356 self.assertItemsEqual([234], project_ids)
357
358 def testGetVisibleLiveProjects_RestrictedAccessWithNonMember(self):
359 project_rows = [
360 (
361 234, 'proj2', 'test proj 2', 'test project', 'live', 'members_only',
362 '', '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
363 False, None, None, None, None, None, None, False)
364 ]
365 self.proj2.access = project_pb2.ProjectAccess.MEMBERS_ONLY
366 self.project_service.project_2lc.CacheItem(234, self.proj2)
367
368 self.project_service.project_tbl.Select(
369 self.cnxn, cols=['project_id'],
370 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
371 self.mox.ReplayAll()
372 user_a = user_pb2.User(email='a@example.com')
373 project_ids = self.project_service.GetVisibleLiveProjects(
374 self.cnxn, user_a, set([111]))
375
376 self.mox.VerifyAll()
377 self.assertItemsEqual([], project_ids)
378
379 def testGetVisibleLiveProjects_RestrictedAccessWithAnon(self):
380 project_rows = [
381 (
382 234, 'proj2', 'test proj 2', 'test project', 'live', 'members_only',
383 '', '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
384 False, None, None, None, None, None, None, False)
385 ]
386 self.proj2.access = project_pb2.ProjectAccess.MEMBERS_ONLY
387 self.project_service.project_2lc.CacheItem(234, self.proj2)
388
389 self.project_service.project_tbl.Select(
390 self.cnxn, cols=['project_id'],
391 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
392 self.mox.ReplayAll()
393 project_ids = self.project_service.GetVisibleLiveProjects(
394 self.cnxn, None, None)
395
396 self.mox.VerifyAll()
397 self.assertItemsEqual([], project_ids)
398
399 def testGetVisibleLiveProjects_RestrictedAccessWithSiteAdmin(self):
400 project_rows = [
401 (
402 234, 'proj2', 'test proj 2', 'test project', 'live', 'members_only',
403 '', '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
404 False, None, None, None, None, None, None, False)
405 ]
406 self.proj2.access = project_pb2.ProjectAccess.MEMBERS_ONLY
407 self.project_service.project_2lc.CacheItem(234, self.proj2)
408
409 self.project_service.project_tbl.Select(
410 self.cnxn, cols=['project_id'],
411 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
412 self.mox.ReplayAll()
413 user_a = user_pb2.User(email='a@example.com')
414 user_a.is_site_admin = True
415 project_ids = self.project_service.GetVisibleLiveProjects(
416 self.cnxn, user_a, set([111]))
417
418 self.mox.VerifyAll()
419 self.assertItemsEqual([234], project_ids)
420
421 def testGetVisibleLiveProjects_ArchivedProject(self):
422 project_rows = [
423 (
424 234, 'proj2', 'test proj 2', 'test project', 'archived', 'anyone',
425 '', '', None, '', 0, 50 * 1024 * 1024, NOW, NOW, None, True, False,
426 False, None, None, None, None, None, None, False)
427 ]
428 self.proj2.state = project_pb2.ProjectState.ARCHIVED
429 self.project_service.project_2lc.CacheItem(234, self.proj2)
430
431 self.project_service.project_tbl.Select(
432 self.cnxn, cols=['project_id'],
433 state=project_pb2.ProjectState.LIVE).AndReturn(project_rows)
434 self.mox.ReplayAll()
435 user_a = user_pb2.User(email='a@example.com')
436 project_ids = self.project_service.GetVisibleLiveProjects(
437 self.cnxn, user_a, set([111]))
438
439 self.mox.VerifyAll()
440 self.assertItemsEqual([], project_ids)
441
442 def testGetProjectsByName(self):
443 self.project_service.project_names_to_ids.CacheItem('proj1', 123)
444 self.project_service.project_2lc.CacheItem(123, self.proj1)
445 self.SetUpLookupProjectIDs()
446 self.SetUpGetProjects()
447 self.mox.ReplayAll()
448 project_dict = self.project_service.GetProjectsByName(
449 self.cnxn, ['proj1', 'proj2'])
450 self.mox.VerifyAll()
451 self.assertItemsEqual(['proj1', 'proj2'], list(project_dict.keys()))
452 self.assertEqual(123, project_dict['proj1'].project_id)
453 self.assertEqual(234, project_dict['proj2'].project_id)
454
455 def SetUpExpungeProject(self):
456 self.project_service.user2project_tbl.Delete(
457 self.cnxn, project_id=234)
458 self.project_service.usergroupprojects_tbl.Delete(
459 self.cnxn, project_id=234)
460 self.project_service.extraperm_tbl.Delete(
461 self.cnxn, project_id=234)
462 self.project_service.membernotes_tbl.Delete(
463 self.cnxn, project_id=234)
464 self.project_service.acexclusion_tbl.Delete(
465 self.cnxn, project_id=234)
466 self.project_service.project_tbl.Delete(
467 self.cnxn, project_id=234)
468
469 def testExpungeProject(self):
470 self.SetUpExpungeProject()
471 self.mox.ReplayAll()
472 self.project_service.ExpungeProject(self.cnxn, 234)
473 self.mox.VerifyAll()
474
475 def SetUpUpdateProject(self, project_id, delta):
476 self.project_service.project_tbl.SelectValue(
477 self.cnxn, 'project_name', project_id=project_id).AndReturn('projN')
478 self.project_service.project_tbl.Update(
479 self.cnxn, delta, project_id=project_id, commit=False)
480 self.cnxn.Commit()
481
482 def testUpdateProject(self):
483 delta = {'summary': 'An even better one-line summary'}
484 self.SetUpUpdateProject(234, delta)
485 self.mox.ReplayAll()
486 self.project_service.UpdateProject(
487 self.cnxn, 234, summary='An even better one-line summary')
488 self.mox.VerifyAll()
489
490 def testUpdateProject_NotifyAlwaysDetailed(self):
491 delta = {'issue_notify_always_detailed': True}
492 self.SetUpUpdateProject(234, delta)
493 self.mox.ReplayAll()
494 self.project_service.UpdateProject(
495 self.cnxn, 234, issue_notify_always_detailed=True)
496 self.mox.VerifyAll()
497
498 def SetUpUpdateProjectRoles(
499 self, project_id, owner_ids, committer_ids, contributor_ids):
500 self.project_service.project_tbl.SelectValue(
501 self.cnxn, 'project_name', project_id=project_id).AndReturn('projN')
502 self.project_service.project_tbl.Update(
503 self.cnxn, {'cached_content_timestamp': NOW}, project_id=project_id,
504 commit=False)
505
506 self.project_service.user2project_tbl.Delete(
507 self.cnxn, project_id=project_id, role_name='owner', commit=False)
508 self.project_service.user2project_tbl.Delete(
509 self.cnxn, project_id=project_id, role_name='committer', commit=False)
510 self.project_service.user2project_tbl.Delete(
511 self.cnxn, project_id=project_id, role_name='contributor',
512 commit=False)
513
514 self.project_service.user2project_tbl.InsertRows(
515 self.cnxn, ['project_id', 'user_id', 'role_name'],
516 [(project_id, user_id, 'owner') for user_id in owner_ids],
517 commit=False)
518 self.project_service.user2project_tbl.InsertRows(
519 self.cnxn, ['project_id', 'user_id', 'role_name'],
520 [(project_id, user_id, 'committer') for user_id in committer_ids],
521 commit=False)
522 self.project_service.user2project_tbl.InsertRows(
523 self.cnxn, ['project_id', 'user_id', 'role_name'],
524 [(project_id, user_id, 'contributor') for user_id in contributor_ids],
525 commit=False)
526
527 self.cnxn.Commit()
528
529 def testUpdateProjectRoles(self):
530 self.SetUpUpdateProjectRoles(234, [111, 222], [333], [])
531 self.mox.ReplayAll()
532 self.project_service.UpdateProjectRoles(
533 self.cnxn, 234, [111, 222], [333], [], now=NOW)
534 self.mox.VerifyAll()
535
536 def SetUpMarkProjectDeletable(self):
537 delta = {
538 'project_name': 'DELETABLE_123',
539 'state': 'deletable',
540 }
541 self.project_service.project_tbl.Update(self.cnxn, delta, project_id=123)
542 self.config_service.InvalidateMemcacheForEntireProject(123)
543
544 def testMarkProjectDeletable(self):
545 self.SetUpMarkProjectDeletable()
546 self.mox.ReplayAll()
547 self.project_service.MarkProjectDeletable(
548 self.cnxn, 123, self.config_service)
549 self.mox.VerifyAll()
550
551 def testUpdateRecentActivity_SignificantlyLaterActivity(self):
552 activity_time = NOW + framework_constants.SECS_PER_HOUR * 3
553 delta = {'recent_activity_timestamp': activity_time}
554 self.SetUpGetProjects()
555 self.SetUpUpdateProject(234, delta)
556 self.mox.ReplayAll()
557 self.project_service.UpdateRecentActivity(self.cnxn, 234, now=activity_time)
558 self.mox.VerifyAll()
559
560 def testUpdateRecentActivity_NotSignificant(self):
561 activity_time = NOW + 123
562 self.SetUpGetProjects()
563 # ProjectUpdate is not called.
564 self.mox.ReplayAll()
565 self.project_service.UpdateRecentActivity(self.cnxn, 234, now=activity_time)
566 self.mox.VerifyAll()
567
568 def SetUpGetUserRolesInAllProjects(self):
569 rows = [
570 (123, 'committer'),
571 (234, 'owner'),
572 ]
573 self.project_service.user2project_tbl.Select(
574 self.cnxn, cols=['project_id', 'role_name'],
575 user_id={111, 888}).AndReturn(rows)
576
577 def testGetUserRolesInAllProjects(self):
578 self.SetUpGetUserRolesInAllProjects()
579 self.mox.ReplayAll()
580 actual = self.project_service.GetUserRolesInAllProjects(
581 self.cnxn, {111, 888})
582 owned_project_ids, membered_project_ids, contrib_project_ids = actual
583 self.mox.VerifyAll()
584 self.assertItemsEqual([234], owned_project_ids)
585 self.assertItemsEqual([123], membered_project_ids)
586 self.assertItemsEqual([], contrib_project_ids)
587
588 def testGetUserRolesInAllProjectsWithoutEffectiveIds(self):
589 self.mox.ReplayAll()
590 actual = self.project_service.GetUserRolesInAllProjects(self.cnxn, {})
591 owned_project_ids, membered_project_ids, contrib_project_ids = actual
592 self.mox.VerifyAll()
593 self.assertItemsEqual([], owned_project_ids)
594 self.assertItemsEqual([], membered_project_ids)
595 self.assertItemsEqual([], contrib_project_ids)
596
597 def SetUpUpdateExtraPerms(self):
598 self.project_service.extraperm_tbl.Delete(
599 self.cnxn, project_id=234, user_id=111, commit=False)
600 self.project_service.extraperm_tbl.InsertRows(
601 self.cnxn, project_svc.EXTRAPERM_COLS,
602 [(234, 111, 'SecurityTeam')], commit=False)
603 self.project_service.project_tbl.Update(
604 self.cnxn, {'cached_content_timestamp': NOW},
605 project_id=234, commit=False)
606 self.cnxn.Commit()
607
608 def testUpdateExtraPerms(self):
609 self.SetUpGetProjects(roles=[(234, 111, 'owner')])
610 self.SetUpUpdateExtraPerms()
611 self.mox.ReplayAll()
612 self.project_service.UpdateExtraPerms(
613 self.cnxn, 234, 111, ['SecurityTeam'], now=NOW)
614 self.mox.VerifyAll()
615
616 def testExpungeUsersInProjects(self):
617 self.project_service.extraperm_tbl.Delete = mock.Mock()
618 self.project_service.acexclusion_tbl.Delete = mock.Mock()
619 self.project_service.membernotes_tbl.Delete = mock.Mock()
620 self.project_service.user2project_tbl.Delete = mock.Mock()
621
622 user_ids = [111, 222]
623 limit= 16
624 self.project_service.ExpungeUsersInProjects(
625 self.cnxn, user_ids, limit=limit)
626
627 call = [mock.call(self.cnxn, user_id=user_ids, limit=limit, commit=False)]
628 self.project_service.extraperm_tbl.Delete.assert_has_calls(call)
629 self.project_service.acexclusion_tbl.Delete.assert_has_calls(call)
630 self.project_service.membernotes_tbl.Delete.assert_has_calls(call)
631 self.project_service.user2project_tbl.Delete.assert_has_calls(call)