blob: 131ebb545254a83147d7d6a06ef1b6b29f15e0a3 [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 monorail.framework.framework_bizobj."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import unittest
12import mock
13
14import settings
15from framework import authdata
16from framework import framework_bizobj
17from framework import framework_constants
18from proto import project_pb2
19from proto import tracker_pb2
20from proto import user_pb2
21from services import service_manager
22from services import client_config_svc
23from testing import fake
24from testing import testing_helpers
25from tracker import tracker_bizobj
26
27
28class CreateUserDisplayNamesAndEmailsTest(unittest.TestCase):
29
30 def setUp(self):
31 self.cnxn = fake.MonorailConnection()
32 self.services = service_manager.Services(
33 project=fake.ProjectService(),
34 user=fake.UserService(),
35 usergroup=fake.UserGroupService())
36
37 self.user_1 = self.services.user.TestAddUser(
38 'user_1@test.com', 111, obscure_email=True)
39 self.user_2 = self.services.user.TestAddUser(
40 'user_2@test.com', 222, obscure_email=False)
41 self.user_3 = self.services.user.TestAddUser(
42 'user_3@test.com', 333, obscure_email=True)
43 self.user_4 = self.services.user.TestAddUser(
44 'user_4@test.com', 444, obscure_email=False)
45 self.service_account = self.services.user.TestAddUser(
46 'service@account.com', 999, obscure_email=True)
47 self.user_deleted = self.services.user.TestAddUser(
48 '', framework_constants.DELETED_USER_ID)
49 self.requester = self.services.user.TestAddUser('user_5@test.com', 555)
50 self.user_auth = authdata.AuthData(
51 user_id=self.requester.user_id, email=self.requester.email)
52 self.project = self.services.project.TestAddProject(
53 'proj',
54 project_id=789,
55 owner_ids=[self.user_1.user_id],
56 committer_ids=[self.user_2.user_id, self.service_account.user_id])
57
58 @mock.patch('services.client_config_svc.GetServiceAccountMap')
59 def testUserCreateDisplayNamesAndEmails_NonProjectMembers(
60 self, fake_account_map):
61 fake_account_map.return_value = {'service@account.com': 'Service'}
62 users = [self.user_1, self.user_2, self.user_3, self.user_4,
63 self.service_account, self.user_deleted]
64 (display_names_by_id,
65 display_emails_by_id) = framework_bizobj.CreateUserDisplayNamesAndEmails(
66 self.cnxn, self.services, self.user_auth, users)
67 expected_display_names = {
68 self.user_1.user_id: testing_helpers.ObscuredEmail(self.user_1.email),
69 self.user_2.user_id: self.user_2.email,
70 self.user_3.user_id: testing_helpers.ObscuredEmail(self.user_3.email),
71 self.user_4.user_id: self.user_4.email,
72 self.service_account.user_id: 'Service',
73 self.user_deleted.user_id: framework_constants.DELETED_USER_NAME}
74 expected_display_emails = {
75 self.user_1.user_id:
76 testing_helpers.ObscuredEmail(self.user_1.email),
77 self.user_2.user_id:
78 self.user_2.email,
79 self.user_3.user_id:
80 testing_helpers.ObscuredEmail(self.user_3.email),
81 self.user_4.user_id:
82 self.user_4.email,
83 self.service_account.user_id:
84 testing_helpers.ObscuredEmail(self.service_account.email),
85 self.user_deleted.user_id: '',
86 }
87 self.assertEqual(display_names_by_id, expected_display_names)
88 self.assertEqual(display_emails_by_id, expected_display_emails)
89
90 @mock.patch('services.client_config_svc.GetServiceAccountMap')
91 def testUserCreateDisplayNamesAndEmails_ProjectMember(self, fake_account_map):
92 fake_account_map.return_value = {'service@account.com': 'Service'}
93 users = [self.user_1, self.user_2, self.user_3, self.user_4,
94 self.service_account, self.user_deleted]
95 self.project.committer_ids.append(self.requester.user_id)
96 (display_names_by_id,
97 display_emails_by_id) = framework_bizobj.CreateUserDisplayNamesAndEmails(
98 self.cnxn, self.services, self.user_auth, users)
99 expected_display_names = {
100 self.user_1.user_id: self.user_1.email, # Project member
101 self.user_2.user_id: self.user_2.email, # Project member and unobscured
102 self.user_3.user_id: testing_helpers.ObscuredEmail(self.user_3.email),
103 self.user_4.user_id: self.user_4.email, # Unobscured email
104 self.service_account.user_id: 'Service',
105 self.user_deleted.user_id: framework_constants.DELETED_USER_NAME
106 }
107 expected_display_emails = {
108 self.user_1.user_id: self.user_1.email, # Project member
109 self.user_2.user_id: self.user_2.email, # Project member and unobscured
110 self.user_3.user_id: testing_helpers.ObscuredEmail(self.user_3.email),
111 self.user_4.user_id: self.user_4.email, # Unobscured email
112 self.service_account.user_id: self.service_account.email,
113 self.user_deleted.user_id: ''
114 }
115 self.assertEqual(display_names_by_id, expected_display_names)
116 self.assertEqual(display_emails_by_id, expected_display_emails)
117
118 @mock.patch('services.client_config_svc.GetServiceAccountMap')
119 def testUserCreateDisplayNamesAndEmails_Admin(self, fake_account_map):
120 fake_account_map.return_value = {'service@account.com': 'Service'}
121 users = [self.user_1, self.user_2, self.user_3, self.user_4,
122 self.service_account, self.user_deleted]
123 self.user_auth.user_pb.is_site_admin = True
124 (display_names_by_id,
125 display_emails_by_id) = framework_bizobj.CreateUserDisplayNamesAndEmails(
126 self.cnxn, self.services, self.user_auth, users)
127 expected_display_names = {
128 self.user_1.user_id: self.user_1.email,
129 self.user_2.user_id: self.user_2.email,
130 self.user_3.user_id: self.user_3.email,
131 self.user_4.user_id: self.user_4.email,
132 self.service_account.user_id: 'Service',
133 self.user_deleted.user_id: framework_constants.DELETED_USER_NAME}
134 expected_display_emails = {
135 self.user_1.user_id: self.user_1.email,
136 self.user_2.user_id: self.user_2.email,
137 self.user_3.user_id: self.user_3.email,
138 self.user_4.user_id: self.user_4.email,
139 self.service_account.user_id: self.service_account.email,
140 self.user_deleted.user_id: ''
141 }
142
143 self.assertEqual(display_names_by_id, expected_display_names)
144 self.assertEqual(display_emails_by_id, expected_display_emails)
145
146
147class ParseAndObscureAddressTest(unittest.TestCase):
148
149 def testParseAndObscureAddress(self):
150 email = 'sir.chicken@farm.test'
151 (username, user_domain, obscured_username,
152 obscured_email) = framework_bizobj.ParseAndObscureAddress(email)
153
154 self.assertEqual(username, 'sir.chicken')
155 self.assertEqual(user_domain, 'farm.test')
156 self.assertEqual(obscured_username, 'sir.c')
157 self.assertEqual(obscured_email, 'sir.c...@farm.test')
158
159
160class FilterViewableEmailsTest(unittest.TestCase):
161
162 def setUp(self):
163 self.cnxn = fake.MonorailConnection()
164 self.services = service_manager.Services(
165 project=fake.ProjectService(),
166 user=fake.UserService(),
167 usergroup=fake.UserGroupService())
168 self.user_1 = self.services.user.TestAddUser(
169 'user_1@test.com', 111, obscure_email=True)
170 self.user_2 = self.services.user.TestAddUser(
171 'user_2@test.com', 222, obscure_email=False)
172 self.requester = self.services.user.TestAddUser(
173 'user_5@test.com', 555, obscure_email=True)
174 self.user_auth = authdata.AuthData(
175 user_id=self.requester.user_id, email=self.requester.email)
176 self.user_auth.user_pb.email = self.user_auth.email
177 self.project = self.services.project.TestAddProject(
178 'proj', project_id=789, owner_ids=[111], committer_ids=[222])
179
180 def testFilterViewableEmail_Anon(self):
181 anon = authdata.AuthData()
182 other_users = [self.user_1, self.user_2]
183 filtered_users = framework_bizobj.FilterViewableEmails(
184 self.cnxn, self.services, anon, other_users)
185 self.assertEqual(filtered_users, [])
186
187 def testFilterViewableEmail_Self(self):
188 filtered_users = framework_bizobj.FilterViewableEmails(
189 self.cnxn, self.services, self.user_auth, [self.user_auth.user_pb])
190 self.assertEqual(filtered_users, [self.user_auth.user_pb])
191
192 def testFilterViewableEmail_SiteAdmin(self):
193 self.user_auth.user_pb.is_site_admin = True
194 other_users = [self.user_1, self.user_2]
195 filtered_users = framework_bizobj.FilterViewableEmails(
196 self.cnxn, self.services, self.user_auth, other_users)
197 self.assertEqual(filtered_users, other_users)
198
199 def testFilterViewableEmail_InDisplayNameGroup(self):
200 display_name_group_id = 666
201 self.services.usergroup.TestAddGroupSettings(
202 display_name_group_id, 'display-perm-perm@email.com')
203 settings.full_emails_perm_groups = ['display-perm-perm@email.com']
204 self.user_auth.effective_ids.add(display_name_group_id)
205
206 other_users = [self.user_1, self.user_2]
207 filtered_users = framework_bizobj.FilterViewableEmails(
208 self.cnxn, self.services, self.user_auth, other_users)
209 self.assertEqual(filtered_users, other_users)
210
211 def testFilterViewableEmail_NonMember(self):
212 other_users = [self.user_1, self.user_2]
213 filtered_users = framework_bizobj.FilterViewableEmails(
214 self.cnxn, self.services, self.user_auth, other_users)
215 self.assertEqual(filtered_users, [])
216
217 def testFilterViewableEmail_ProjectMember(self):
218 self.project.committer_ids.append(self.requester.user_id)
219 other_users = [self.user_1, self.user_2]
220 filtered_users = framework_bizobj.FilterViewableEmails(
221 self.cnxn, self.services, self.user_auth, other_users)
222 self.assertEqual(filtered_users, other_users)
223
224
225# TODO(https://crbug.com/monorail/8192): Remove deprecated tests.
226class DeprecatedShouldRevealEmailTest(unittest.TestCase):
227
228 def setUp(self):
229 self.cnxn = fake.MonorailConnection()
230 self.services = service_manager.Services(
231 project=fake.ProjectService(),
232 user=fake.UserService(),
233 usergroup=fake.UserGroupService())
234 self.user_1 = self.services.user.TestAddUser(
235 'user_1@test.com', 111, obscure_email=True)
236 self.user_2 = self.services.user.TestAddUser(
237 'user_2@test.com', 222, obscure_email=False)
238 self.requester = self.services.user.TestAddUser(
239 'user_5@test.com', 555, obscure_email=True)
240 self.user_auth = authdata.AuthData(
241 user_id=self.requester.user_id, email=self.requester.email)
242 self.user_auth.user_pb.email = self.user_auth.email
243 self.project = self.services.project.TestAddProject(
244 'proj', project_id=789, owner_ids=[111], committer_ids=[222])
245
246 def testDeprecatedShouldRevealEmail_Anon(self):
247 anon = authdata.AuthData()
248 self.assertFalse(
249 framework_bizobj.DeprecatedShouldRevealEmail(
250 anon, self.project, self.user_1.email))
251 self.assertFalse(
252 framework_bizobj.DeprecatedShouldRevealEmail(
253 anon, self.project, self.user_2.email))
254
255 def testDeprecatedShouldRevealEmail_Self(self):
256 self.assertTrue(
257 framework_bizobj.DeprecatedShouldRevealEmail(
258 self.user_auth, self.project, self.user_auth.user_pb.email))
259
260 def testDeprecatedShouldRevealEmail_SiteAdmin(self):
261 self.user_auth.user_pb.is_site_admin = True
262 self.assertTrue(
263 framework_bizobj.DeprecatedShouldRevealEmail(
264 self.user_auth, self.project, self.user_1.email))
265 self.assertTrue(
266 framework_bizobj.DeprecatedShouldRevealEmail(
267 self.user_auth, self.project, self.user_2.email))
268
269 def testDeprecatedShouldRevealEmail_ProjectMember(self):
270 self.project.committer_ids.append(self.requester.user_id)
271 self.assertTrue(
272 framework_bizobj.DeprecatedShouldRevealEmail(
273 self.user_auth, self.project, self.user_1.email))
274 self.assertTrue(
275 framework_bizobj.DeprecatedShouldRevealEmail(
276 self.user_auth, self.project, self.user_2.email))
277
278 def testDeprecatedShouldRevealEmail_NonMember(self):
279 self.assertFalse(
280 framework_bizobj.DeprecatedShouldRevealEmail(
281 self.user_auth, self.project, self.user_1.email))
282 self.assertFalse(
283 framework_bizobj.DeprecatedShouldRevealEmail(
284 self.user_auth, self.project, self.user_2.email))
285
286
287class ArtifactTest(unittest.TestCase):
288
289 def setUp(self):
290 # No custom fields. Exclusive prefixes: Type, Priority, Milestone.
291 self.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
292
293 def testMergeLabels_Labels(self):
294 # Empty case.
295 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
296 [], [], [], self.config)
297 self.assertEqual(merged_labels, [])
298 self.assertEqual(update_add, [])
299 self.assertEqual(update_remove, [])
300
301 # No-op case.
302 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
303 ['a', 'b'], [], [], self.config)
304 self.assertEqual(merged_labels, ['a', 'b'])
305 self.assertEqual(update_add, [])
306 self.assertEqual(update_remove, [])
307
308 # Adding and removing at the same time.
309 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
310 ['a', 'b', 'd'], ['c'], ['d'], self.config)
311 self.assertEqual(merged_labels, ['a', 'b', 'c'])
312 self.assertEqual(update_add, ['c'])
313 self.assertEqual(update_remove, ['d'])
314
315 # Removing a non-matching label has no effect.
316 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
317 ['a', 'b', 'd'], ['d'], ['e'], self.config)
318 self.assertEqual(merged_labels, ['a', 'b', 'd'])
319 self.assertEqual(update_add, []) # d was already there.
320 self.assertEqual(update_remove, []) # there was no e.
321
322 # We can add and remove at the same time.
323 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
324 ['Priority-Medium', 'OpSys-OSX'], ['Hot'], ['OpSys-OSX'], self.config)
325 self.assertEqual(merged_labels, ['Priority-Medium', 'Hot'])
326 self.assertEqual(update_add, ['Hot'])
327 self.assertEqual(update_remove, ['OpSys-OSX'])
328
329 # Adding Priority-High replaces Priority-Medium.
330 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
331 ['Priority-Medium', 'OpSys-OSX'], ['Priority-High', 'OpSys-Win'], [],
332 self.config)
333 self.assertEqual(merged_labels, ['OpSys-OSX', 'Priority-High', 'OpSys-Win'])
334 self.assertEqual(update_add, ['Priority-High', 'OpSys-Win'])
335 self.assertEqual(update_remove, [])
336
337 # Adding Priority-High and Priority-Low replaces with High only.
338 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
339 ['Priority-Medium', 'OpSys-OSX'],
340 ['Priority-High', 'Priority-Low'], [], self.config)
341 self.assertEqual(merged_labels, ['OpSys-OSX', 'Priority-High'])
342 self.assertEqual(update_add, ['Priority-High'])
343 self.assertEqual(update_remove, [])
344
345 # Removing a mix of matching and non-matching labels only does matching.
346 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
347 ['Priority-Medium', 'OpSys-OSX'], [], ['Priority-Medium', 'OpSys-Win'],
348 self.config)
349 self.assertEqual(merged_labels, ['OpSys-OSX'])
350 self.assertEqual(update_add, [])
351 self.assertEqual(update_remove, ['Priority-Medium'])
352
353 # Multi-part labels work as expected.
354 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
355 ['Priority-Medium', 'OpSys-OSX-11'],
356 ['Priority-Medium-Rare', 'OpSys-OSX-13'], [], self.config)
357 self.assertEqual(
358 merged_labels, ['OpSys-OSX-11', 'Priority-Medium-Rare', 'OpSys-OSX-13'])
359 self.assertEqual(update_add, ['Priority-Medium-Rare', 'OpSys-OSX-13'])
360 self.assertEqual(update_remove, [])
361
362 # Multi-part exclusive prefixes only filter labels that match whole prefix.
363 self.config.exclusive_label_prefixes.append('Branch-Name')
364 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
365 ['Branch-Name-xyz'],
366 ['Branch-Prediction', 'Branch-Name-Beta'], [], self.config)
367 self.assertEqual(merged_labels, ['Branch-Prediction', 'Branch-Name-Beta'])
368 self.assertEqual(update_add, ['Branch-Prediction', 'Branch-Name-Beta'])
369 self.assertEqual(update_remove, [])
370
371 def testMergeLabels_SingleValuedEnums(self):
372 self.config.field_defs.append(tracker_pb2.FieldDef(
373 field_id=1, field_name='Size',
374 field_type=tracker_pb2.FieldTypes.ENUM_TYPE,
375 is_multivalued=False))
376 self.config.field_defs.append(tracker_pb2.FieldDef(
377 field_id=1, field_name='Branch-Name',
378 field_type=tracker_pb2.FieldTypes.ENUM_TYPE,
379 is_multivalued=False))
380
381 # We can add a label for a single-valued enum.
382 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
383 ['Priority-Medium', 'OpSys-OSX'], ['Size-L'], [], self.config)
384 self.assertEqual(merged_labels, ['Priority-Medium', 'OpSys-OSX', 'Size-L'])
385 self.assertEqual(update_add, ['Size-L'])
386 self.assertEqual(update_remove, [])
387
388 # Adding and removing the same label adds it.
389 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
390 ['Priority-Medium'], ['Size-M'], ['Size-M'], self.config)
391 self.assertEqual(merged_labels, ['Priority-Medium', 'Size-M'])
392 self.assertEqual(update_add, ['Size-M'])
393 self.assertEqual(update_remove, [])
394
395 # Adding Size-L replaces Size-M.
396 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
397 ['Priority-Medium', 'Size-M'], ['Size-L', 'OpSys-Win'], [],
398 self.config)
399 self.assertEqual(merged_labels, ['Priority-Medium', 'Size-L', 'OpSys-Win'])
400 self.assertEqual(update_add, ['Size-L', 'OpSys-Win'])
401 self.assertEqual(update_remove, [])
402
403 # Adding Size-L and Size-XL replaces with L only.
404 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
405 ['Size-M', 'OpSys-OSX'], ['Size-L', 'Size-XL'], [], self.config)
406 self.assertEqual(merged_labels, ['OpSys-OSX', 'Size-L'])
407 self.assertEqual(update_add, ['Size-L'])
408 self.assertEqual(update_remove, [])
409
410 # Multi-part labels work as expected.
411 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
412 ['Size-M', 'OpSys-OSX'], ['Size-M-USA'], [], self.config)
413 self.assertEqual(merged_labels, ['OpSys-OSX', 'Size-M-USA'])
414 self.assertEqual(update_add, ['Size-M-USA'])
415 self.assertEqual(update_remove, [])
416
417 # Multi-part enum names only filter labels that match whole name.
418 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
419 ['Branch-Name-xyz'],
420 ['Branch-Prediction', 'Branch-Name-Beta'], [], self.config)
421 self.assertEqual(merged_labels, ['Branch-Prediction', 'Branch-Name-Beta'])
422 self.assertEqual(update_add, ['Branch-Prediction', 'Branch-Name-Beta'])
423 self.assertEqual(update_remove, [])
424
425 def testMergeLabels_MultiValuedEnums(self):
426 self.config.field_defs.append(tracker_pb2.FieldDef(
427 field_id=1, field_name='OpSys',
428 field_type=tracker_pb2.FieldTypes.ENUM_TYPE,
429 is_multivalued=True))
430 self.config.field_defs.append(tracker_pb2.FieldDef(
431 field_id=1, field_name='Branch-Name',
432 field_type=tracker_pb2.FieldTypes.ENUM_TYPE,
433 is_multivalued=True))
434
435 # We can add a label for a multi-valued enum.
436 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
437 ['Priority-Medium'], ['OpSys-Win'], [], self.config)
438 self.assertEqual(merged_labels, ['Priority-Medium', 'OpSys-Win'])
439 self.assertEqual(update_add, ['OpSys-Win'])
440 self.assertEqual(update_remove, [])
441
442 # We can remove a matching label for a multi-valued enum.
443 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
444 ['Priority-Medium', 'OpSys-Win'], [], ['OpSys-Win'], self.config)
445 self.assertEqual(merged_labels, ['Priority-Medium'])
446 self.assertEqual(update_add, [])
447 self.assertEqual(update_remove, ['OpSys-Win'])
448
449 # We can remove a non-matching label and it is a no-op.
450 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
451 ['Priority-Medium', 'OpSys-OSX'], [], ['OpSys-Win'], self.config)
452 self.assertEqual(merged_labels, ['Priority-Medium', 'OpSys-OSX'])
453 self.assertEqual(update_add, [])
454 self.assertEqual(update_remove, [])
455
456 # Adding and removing the same label adds it.
457 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
458 ['Priority-Medium'], ['OpSys-Win'], ['OpSys-Win'], self.config)
459 self.assertEqual(merged_labels, ['Priority-Medium', 'OpSys-Win'])
460 self.assertEqual(update_add, ['OpSys-Win'])
461 self.assertEqual(update_remove, [])
462
463 # We can add a label for a multi-valued enum, even if matching exists.
464 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
465 ['Priority-Medium', 'OpSys-OSX'], ['OpSys-Win'], [], self.config)
466 self.assertEqual(
467 merged_labels, ['Priority-Medium', 'OpSys-OSX', 'OpSys-Win'])
468 self.assertEqual(update_add, ['OpSys-Win'])
469 self.assertEqual(update_remove, [])
470
471 # Adding two at the same time is fine.
472 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
473 ['Size-M', 'OpSys-OSX'], ['OpSys-Win', 'OpSys-Vax'], [], self.config)
474 self.assertEqual(
475 merged_labels, ['Size-M', 'OpSys-OSX', 'OpSys-Win', 'OpSys-Vax'])
476 self.assertEqual(update_add, ['OpSys-Win', 'OpSys-Vax'])
477 self.assertEqual(update_remove, [])
478
479 # Multi-part labels work as expected.
480 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
481 ['Size-M', 'OpSys-OSX'], ['OpSys-Win-10'], [], self.config)
482 self.assertEqual(merged_labels, ['Size-M', 'OpSys-OSX', 'OpSys-Win-10'])
483 self.assertEqual(update_add, ['OpSys-Win-10'])
484 self.assertEqual(update_remove, [])
485
486 # Multi-part enum names don't mess up anything.
487 (merged_labels, update_add, update_remove) = framework_bizobj.MergeLabels(
488 ['Branch-Name-xyz'],
489 ['Branch-Prediction', 'Branch-Name-Beta'], [], self.config)
490 self.assertEqual(
491 merged_labels,
492 ['Branch-Name-xyz', 'Branch-Prediction', 'Branch-Name-Beta'])
493 self.assertEqual(update_add, ['Branch-Prediction', 'Branch-Name-Beta'])
494 self.assertEqual(update_remove, [])
495
496
497class CanonicalizeLabelTest(unittest.TestCase):
498
499 def testCanonicalizeLabel(self):
500 self.assertEqual(None, framework_bizobj.CanonicalizeLabel(None))
501 self.assertEqual('FooBar', framework_bizobj.CanonicalizeLabel('Foo Bar '))
502 self.assertEqual('Foo.Bar',
503 framework_bizobj.CanonicalizeLabel('Foo . Bar '))
504 self.assertEqual('Foo-Bar',
505 framework_bizobj.CanonicalizeLabel('Foo - Bar '))
506
507
508class UserIsInProjectTest(unittest.TestCase):
509
510 def testUserIsInProject(self):
511 p = project_pb2.Project()
512 self.assertFalse(framework_bizobj.UserIsInProject(p, {10}))
513 self.assertFalse(framework_bizobj.UserIsInProject(p, set()))
514
515 p.owner_ids.extend([1, 2, 3])
516 p.committer_ids.extend([4, 5, 6])
517 p.contributor_ids.extend([7, 8, 9])
518 self.assertTrue(framework_bizobj.UserIsInProject(p, {1}))
519 self.assertTrue(framework_bizobj.UserIsInProject(p, {4}))
520 self.assertTrue(framework_bizobj.UserIsInProject(p, {7}))
521 self.assertFalse(framework_bizobj.UserIsInProject(p, {10}))
522
523 # Membership via group membership
524 self.assertTrue(framework_bizobj.UserIsInProject(p, {10, 4}))
525
526 # Membership via several group memberships
527 self.assertTrue(framework_bizobj.UserIsInProject(p, {1, 4}))
528
529 # Several irrelevant group memberships
530 self.assertFalse(framework_bizobj.UserIsInProject(p, {10, 11, 12}))
531
532
533class IsValidColumnSpecTest(unittest.TestCase):
534
535 def testIsValidColumnSpec(self):
536 self.assertTrue(
537 framework_bizobj.IsValidColumnSpec('some columns hey-honk hay.honk'))
538
539 self.assertTrue(framework_bizobj.IsValidColumnSpec('some'))
540
541 self.assertTrue(framework_bizobj.IsValidColumnSpec(''))
542
543 def testIsValidColumnSpec_NotValid(self):
544 self.assertFalse(
545 framework_bizobj.IsValidColumnSpec('some columns hey-honk hay.'))
546
547 self.assertFalse(framework_bizobj.IsValidColumnSpec('some columns hey-'))
548
549 self.assertFalse(framework_bizobj.IsValidColumnSpec('-some columns hey'))
550
551 self.assertFalse(framework_bizobj.IsValidColumnSpec('some .columns hey'))
552
553
554class ValidatePrefTest(unittest.TestCase):
555
556 def testUnknown(self):
557 msg = framework_bizobj.ValidatePref('shoe_size', 'true')
558 self.assertIn('shoe_size', msg)
559 self.assertIn('Unknown', msg)
560
561 msg = framework_bizobj.ValidatePref('', 'true')
562 self.assertIn('Unknown', msg)
563
564 def testTooLong(self):
565 msg = framework_bizobj.ValidatePref('code_font', 'x' * 100)
566 self.assertIn('code_font', msg)
567 self.assertIn('too long', msg)
568
569 def testKnownValid(self):
570 self.assertIsNone(framework_bizobj.ValidatePref('code_font', 'true'))
571 self.assertIsNone(framework_bizobj.ValidatePref('code_font', 'false'))
572
573 def testKnownInvalid(self):
574 msg = framework_bizobj.ValidatePref('code_font', '')
575 self.assertIn('Invalid', msg)
576
577 msg = framework_bizobj.ValidatePref('code_font', 'sometimes')
578 self.assertIn('Invalid', msg)
579
580
581class IsRestrictNewIssuesUserTest(unittest.TestCase):
582
583 def setUp(self):
584 self.cnxn = fake.MonorailConnection()
585 self.services = service_manager.Services(
586 user=fake.UserService(),
587 usergroup=fake.UserGroupService())
588 self.services.user.TestAddUser('corp_user@example.com', 111)
589 self.services.user.TestAddUser('corp_group@example.com', 888)
590 self.services.usergroup.TestAddGroupSettings(888, 'corp_group@example.com')
591
592 @mock.patch(
593 'settings.restrict_new_issues_user_groups', ['corp_group@example.com'])
594 def testNonRestrictNewIssuesUser(self):
595 """We detect when a user is not part of a corp user group."""
596 self.assertFalse(
597 framework_bizobj.IsRestrictNewIssuesUser(self.cnxn, self.services, 111))
598
599 @mock.patch(
600 'settings.restrict_new_issues_user_groups', ['corp_group@example.com'])
601 def testRestrictNewIssuesUser(self):
602 """We detect when a user is a member of such a group."""
603 self.services.usergroup.TestAddMembers(888, [111, 222])
604 self.assertTrue(
605 framework_bizobj.IsRestrictNewIssuesUser(self.cnxn, self.services, 111))
606
607
608class IsPublicIssueNoticeUserTest(unittest.TestCase):
609
610 def setUp(self):
611 self.cnxn = fake.MonorailConnection()
612 self.services = service_manager.Services(
613 user=fake.UserService(), usergroup=fake.UserGroupService())
614 self.services.user.TestAddUser('corp_user@example.com', 111)
615 self.services.user.TestAddUser('corp_group@example.com', 888)
616 self.services.usergroup.TestAddGroupSettings(888, 'corp_group@example.com')
617
618 @mock.patch(
619 'settings.public_issue_notice_user_groups', ['corp_group@example.com'])
620 def testNonPublicIssueNoticeUser(self):
621 """We detect when a user is not part of a corp user group."""
622 self.assertFalse(
623 framework_bizobj.IsPublicIssueNoticeUser(self.cnxn, self.services, 111))
624
625 @mock.patch(
626 'settings.public_issue_notice_user_groups', ['corp_group@example.com'])
627 def testPublicIssueNoticeUser(self):
628 """We detect when a user is a member of such a group."""
629 self.services.usergroup.TestAddMembers(888, [111, 222])
630 self.assertTrue(
631 framework_bizobj.IsPublicIssueNoticeUser(self.cnxn, self.services, 111))
632
633
634class GetEffectiveIdsTest(unittest.TestCase):
635
636 def setUp(self):
637 self.cnxn = fake.MonorailConnection()
638 self.services = service_manager.Services(
639 user=fake.UserService(), usergroup=fake.UserGroupService())
640 self.services.user.TestAddUser('test@example.com', 111)
641
642 def testNoMemberships(self):
643 """No user groups means effective_ids == {user_id}."""
644 effective_ids = framework_bizobj.GetEffectiveIds(
645 self.cnxn, self.services, [111])
646 self.assertEqual(effective_ids, {111: {111}})
647
648 def testNormalMemberships(self):
649 """effective_ids should be {user_id, group_id...}."""
650 self.services.usergroup.TestAddMembers(888, [111])
651 self.services.usergroup.TestAddMembers(999, [111])
652 effective_ids = framework_bizobj.GetEffectiveIds(
653 self.cnxn, self.services, [111])
654 self.assertEqual(effective_ids, {111: {111, 888, 999}})
655
656 def testComputedUserGroup(self):
657 """effective_ids should be {user_id, group_id...}."""
658 self.services.usergroup.TestAddGroupSettings(888, 'everyone@example.com')
659 effective_ids = framework_bizobj.GetEffectiveIds(
660 self.cnxn, self.services, [111])
661 self.assertEqual(effective_ids, {111: {111, 888}})
662
663 def testAccountHasParent(self):
664 """The parent's effective_ids are added to child's."""
665 child = self.services.user.TestAddUser('child@example.com', 111)
666 child.linked_parent_id = 222
667 parent = self.services.user.TestAddUser('parent@example.com', 222)
668 parent.linked_child_ids = [111]
669 effective_ids = framework_bizobj.GetEffectiveIds(
670 self.cnxn, self.services, [111])
671 self.assertEqual(effective_ids, {111: {111, 222}})
672
673 self.services.usergroup.TestAddMembers(888, [111])
674 self.services.usergroup.TestAddMembers(999, [222])
675 effective_ids = framework_bizobj.GetEffectiveIds(
676 self.cnxn, self.services, [111])
677 self.assertEqual(effective_ids, {111: {111, 222, 888, 999}})
678
679 def testAccountHasChildren(self):
680 """All linked child effective_ids are added to parent's."""
681 child1 = self.services.user.TestAddUser('child1@example.com', 111)
682 child1.linked_parent_id = 333
683 child2 = self.services.user.TestAddUser('child3@example.com', 222)
684 child2.linked_parent_id = 333
685 parent = self.services.user.TestAddUser('parent@example.com', 333)
686 parent.linked_child_ids = [111, 222]
687
688 effective_ids = framework_bizobj.GetEffectiveIds(
689 self.cnxn, self.services, [333])
690 self.assertEqual(effective_ids, {333: {111, 222, 333}})
691
692 self.services.usergroup.TestAddMembers(888, [111])
693 self.services.usergroup.TestAddMembers(999, [222])
694 effective_ids = framework_bizobj.GetEffectiveIds(
695 self.cnxn, self.services, [333])
696 self.assertEqual(effective_ids, {333: {111, 222, 333, 888, 999}})