blob: eed69576fc65988085c85cc5446f1bfa89154875 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2018 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Copybara854996b2021-09-07 19:36:02 +00004
5"""Tests for converting between resource names and external ids."""
6from __future__ import print_function
7from __future__ import division
8from __future__ import absolute_import
9
10from mock import Mock, patch
11import unittest
12import re
13
14from api import resource_name_converters as rnc
15from framework import exceptions
16from testing import fake
17from services import service_manager
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010018from mrproto import tracker_pb2
Copybara854996b2021-09-07 19:36:02 +000019
20class ResourceNameConverterTest(unittest.TestCase):
21
22 def setUp(self):
23 self.services = service_manager.Services(
24 issue=fake.IssueService(),
25 project=fake.ProjectService(),
26 user=fake.UserService(),
27 features=fake.FeaturesService(),
28 template=fake.TemplateService(),
29 config=fake.ConfigService())
30 self.cnxn = fake.MonorailConnection()
31 self.PAST_TIME = 12345
32 self.project_1 = self.services.project.TestAddProject(
33 'proj', project_id=789)
34 self.project_2 = self.services.project.TestAddProject(
35 'goose', project_id=788)
36 self.dne_project_id = 1999
37
38 self.issue_1 = fake.MakeTestIssue(
39 self.project_1.project_id, 1, 'sum', 'New', 111,
40 project_name=self.project_1.project_name)
41 self.issue_2 = fake.MakeTestIssue(
42 self.project_2.project_id, 2, 'sum', 'New', 111,
43 project_name=self.project_2.project_name)
44 self.services.issue.TestAddIssue(self.issue_1)
45 self.services.issue.TestAddIssue(self.issue_2)
46
47 self.user_1 = self.services.user.TestAddUser('user_111@example.com', 111)
48 self.user_2 = self.services.user.TestAddUser('user_222@example.com', 222)
49 self.user_3 = self.services.user.TestAddUser('user_333@example.com', 333)
50
51 hotlist_items = [
52 (self.issue_1.issue_id, 9, self.user_2.user_id, self.PAST_TIME, 'note'),
53 (self.issue_2.issue_id, 1, self.user_1.user_id, self.PAST_TIME, 'note')]
54 self.hotlist_1 = self.services.features.TestAddHotlist(
55 'HotlistName', owner_ids=[], editor_ids=[],
56 hotlist_item_fields=hotlist_items)
57
58 self.template_1 = self.services.template.TestAddIssueTemplateDef(
59 1, self.project_1.project_id, 'template_1_name')
60 self.template_2 = self.services.template.TestAddIssueTemplateDef(
61 2, self.project_2.project_id, 'template_2_name')
62 self.dne_template_id = 3
63
64 self.field_def_1_name = 'test_field'
65 self.field_def_1 = self.services.config.CreateFieldDef(
66 self.cnxn, self.project_1.project_id, self.field_def_1_name, 'STR_TYPE',
67 None, None, None, None, None, None, None, None, None, None, None, None,
68 None, None, [], [])
69 self.approval_def_1_name = 'approval_field_1'
70 self.approval_def_1_id = self.services.config.CreateFieldDef(
71 self.cnxn, self.project_1.project_id, self.approval_def_1_name,
72 'APPROVAL_TYPE', None, None, None, None, None, None, None, None, None,
73 None, None, None, None, None, [], [])
74 self.component_def_1_path = 'Foo'
75 self.component_def_1_id = self.services.config.CreateComponentDef(
76 self.cnxn, self.project_1.project_id, self.component_def_1_path, '',
77 False, [], [], None, 111, [])
78 self.component_def_2_path = 'Foo>Bar>Hey123_I-am-valid'
79 self.component_def_2_id = self.services.config.CreateComponentDef(
80 self.cnxn, self.project_1.project_id, self.component_def_2_path, '',
81 False, [], [], None, 111, [])
82 self.component_def_3_path = 'Fizz'
83 self.component_def_3_id = self.services.config.CreateComponentDef(
84 self.cnxn, self.project_2.project_id, self.component_def_3_path, '',
85 False, [], [], None, 111, [])
86 self.dne_component_def_id = 999
87 self.dne_field_def_id = 999999
88 self.psq_1 = tracker_pb2.SavedQuery(
89 query_id=2, name='psq1 name', base_query_id=1, query='foo=bar')
90 self.psq_2 = tracker_pb2.SavedQuery(
91 query_id=3, name='psq2 name', base_query_id=1, query='fizz=buzz')
92 self.dne_psq_id = 987
93 self.services.features.UpdateCannedQueries(
94 self.cnxn, self.project_1.project_id, [self.psq_1, self.psq_2])
95
96 def testGetResourceNameMatch(self):
97 """We can get a resource name match."""
98 regex = re.compile(r'name\/(?P<group_name>[a-z]+)$')
99 match = rnc._GetResourceNameMatch('name/honque', regex)
100 self.assertEqual(match.group('group_name'), 'honque')
101
102 def testGetResouceNameMatch_InvalidName(self):
103 """An exception is raised if there is not match."""
104 regex = re.compile(r'name\/(?P<group_name>[a-z]+)$')
105 with self.assertRaises(exceptions.InputException):
106 rnc._GetResourceNameMatch('honque/honque', regex)
107
108 def testIngestApprovalDefName(self):
109 approval_id = rnc.IngestApprovalDefName(
110 self.cnxn, 'projects/proj/approvalDefs/123', self.services)
111 self.assertEqual(approval_id, 123)
112
113 def testIngestApprovalDefName_InvalidName(self):
114 with self.assertRaises(exceptions.InputException):
115 rnc.IngestApprovalDefName(
116 self.cnxn, 'projects/proj/approvalDefs/123d', self.services)
117
118 with self.assertRaises(exceptions.NoSuchProjectException):
119 rnc.IngestApprovalDefName(
120 self.cnxn, 'projects/garbage/approvalDefs/123', self.services)
121
122 def testIngestFieldDefName(self):
123 """We can get a FieldDef's resource name match."""
124 self.assertEqual(
125 rnc.IngestFieldDefName(
126 self.cnxn, 'projects/proj/fieldDefs/123', self.services),
127 (789, 123))
128
129 def testIngestFieldDefName_InvalidName(self):
130 """An exception is raised if the FieldDef's resource name is invalid"""
131 with self.assertRaises(exceptions.InputException):
132 rnc.IngestFieldDefName(
133 self.cnxn, 'projects/proj/fieldDefs/7Dog', self.services)
134
135 with self.assertRaises(exceptions.InputException):
136 rnc.IngestFieldDefName(
137 self.cnxn, 'garbage/proj/fieldDefs/123', self.services)
138
139 with self.assertRaises(exceptions.NoSuchProjectException):
140 rnc.IngestFieldDefName(
141 self.cnxn, 'projects/garbage/fieldDefs/123', self.services)
142
143 def testIngestHotlistName(self):
144 """We can get a Hotlist's resource name match."""
145 self.assertEqual(rnc.IngestHotlistName('hotlists/78909'), 78909)
146
147 def testIngestHotlistName_InvalidName(self):
148 """An exception is raised if the Hotlist's resource name is invalid"""
149 with self.assertRaises(exceptions.InputException):
150 rnc.IngestHotlistName('hotlists/789honk789')
151
152 def testIngestHotlistItemNames(self):
153 """We can get Issue IDs from HotlistItems resource names."""
154 names = [
155 'hotlists/78909/items/proj.1',
156 'hotlists/78909/items/goose.2']
157 self.assertEqual(
158 rnc.IngestHotlistItemNames(self.cnxn, names, self.services),
159 [self.issue_1.issue_id, self.issue_2.issue_id])
160
161 def testIngestHotlistItemNames_ProjectNotFound(self):
162 """Exception is raised if a project is not found."""
163 names = [
164 'hotlists/78909/items/proj.1',
165 'hotlists/78909/items/chicken.2']
166 with self.assertRaises(exceptions.NoSuchProjectException):
167 rnc.IngestHotlistItemNames(self.cnxn, names, self.services)
168
169 def testIngestHotlistItemNames_MultipleProjectsNotFound(self):
170 """Aggregated exceptions raised if projects are not found."""
171 names = [
172 'hotlists/78909/items/proj.1', 'hotlists/78909/items/chicken.2',
173 'hotlists/78909/items/cow.3'
174 ]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100175 with self.assertRaisesRegex(exceptions.NoSuchProjectException,
176 'Project chicken not found.\n' +
177 'Project cow not found.'):
Copybara854996b2021-09-07 19:36:02 +0000178 rnc.IngestHotlistItemNames(self.cnxn, names, self.services)
179
180 def testIngestHotlistItems_IssueNotFound(self):
181 """Exception is raised if an Issue is not found."""
182 names = [
183 'hotlists/78909/items/proj.1',
184 'hotlists/78909/items/goose.5']
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100185 with self.assertRaisesRegex(exceptions.NoSuchIssueException, '%r' % names):
Copybara854996b2021-09-07 19:36:02 +0000186 rnc.IngestHotlistItemNames(self.cnxn, names, self.services)
187
188 def testConvertHotlistName(self):
189 """We can get a Hotlist's resource name."""
190 self.assertEqual(rnc.ConvertHotlistName(10), 'hotlists/10')
191
192 def testConvertHotlistItemNames(self):
193 """We can get Hotlist items' resource names."""
194 expected_dict = {
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100195 self.hotlist_1.items[0].issue_id:
196 'hotlists/%d/items/proj.1' % self.hotlist_1.hotlist_id,
197 self.hotlist_1.items[1].issue_id:
198 'hotlists/%d/items/goose.2' % self.hotlist_1.hotlist_id,
Copybara854996b2021-09-07 19:36:02 +0000199 }
200 self.assertEqual(
201 rnc.ConvertHotlistItemNames(
202 self.cnxn, self.hotlist_1.hotlist_id, expected_dict.keys(),
203 self.services), expected_dict)
204
205 def testIngestApprovalValueName(self):
206 project_id, issue_id, approval_def_id = rnc.IngestApprovalValueName(
207 self.cnxn, 'projects/proj/issues/1/approvalValues/404', self.services)
208 self.assertEqual(project_id, self.project_1.project_id)
209 self.assertEqual(issue_id, self.issue_1.issue_id)
210 self.assertEqual(404, approval_def_id) # We don't verify it exists.
211
212 def testIngestApprovalValueName_ProjectDoesNotExist(self):
213 with self.assertRaises(exceptions.NoSuchProjectException):
214 rnc.IngestApprovalValueName(
215 self.cnxn, 'projects/noproj/issues/1/approvalValues/1', self.services)
216
217 def testIngestApprovalValueName_IssueDoesNotExist(self):
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100218 with self.assertRaisesRegex(exceptions.NoSuchIssueException,
219 'projects/proj/issues/404'):
Copybara854996b2021-09-07 19:36:02 +0000220 rnc.IngestApprovalValueName(
221 self.cnxn, 'projects/proj/issues/404/approvalValues/1', self.services)
222
223 def testIngestApprovalValueName_InvalidStart(self):
224 with self.assertRaises(exceptions.InputException):
225 rnc.IngestApprovalValueName(
226 self.cnxn, 'zprojects/proj/issues/1/approvalValues/1', self.services)
227
228 def testIngestApprovalValueName_InvalidEnd(self):
229 with self.assertRaises(exceptions.InputException):
230 rnc.IngestApprovalValueName(
231 self.cnxn, 'projects/proj/issues/1/approvalValues/1z', self.services)
232
233 def testIngestApprovalValueName_InvalidCollection(self):
234 with self.assertRaises(exceptions.InputException):
235 rnc.IngestApprovalValueName(
236 self.cnxn, 'projects/proj/issues/1/approvalValue/1', self.services)
237
238 def testIngestIssueName(self):
239 """We can get an Issue global id from its resource name."""
240 self.assertEqual(
241 rnc.IngestIssueName(self.cnxn, 'projects/proj/issues/1', self.services),
242 self.issue_1.issue_id)
243
244 def testIngestIssueName_ProjectDoesNotExist(self):
245 with self.assertRaises(exceptions.NoSuchProjectException):
246 rnc.IngestIssueName(self.cnxn, 'projects/noproj/issues/1', self.services)
247
248 def testIngestIssueName_IssueDoesNotExist(self):
249 with self.assertRaises(exceptions.NoSuchIssueException):
250 rnc.IngestIssueName(self.cnxn, 'projects/proj/issues/2', self.services)
251
252 def testIngestIssueName_InvalidLocalId(self):
253 """Issue resource name Local IDs are digits."""
254 with self.assertRaises(exceptions.InputException):
255 rnc.IngestIssueName(self.cnxn, 'projects/proj/issues/x', self.services)
256
257 def testIngestIssueName_InvalidProjectId(self):
258 """Project names are more than 1 character."""
259 with self.assertRaises(exceptions.InputException):
260 rnc.IngestIssueName(self.cnxn, 'projects/p/issues/1', self.services)
261
262 def testIngestIssueName_InvalidFormat(self):
263 """Issue resource names must begin with the project resource name."""
264 with self.assertRaises(exceptions.InputException):
265 rnc.IngestIssueName(self.cnxn, 'issues/1', self.services)
266
267 def testIngestIssueName_Moved(self):
268 """We can get a moved issue."""
269 moved_to_project_id = 987
270 self.services.project.TestAddProject(
271 'other', project_id=moved_to_project_id)
272 new_issue_id = 1010
273 issue = fake.MakeTestIssue(
274 moved_to_project_id, 200, 'sum', 'New', 111, issue_id=new_issue_id)
275 self.services.issue.TestAddIssue(issue)
276 self.services.issue.TestAddMovedIssueRef(
277 self.project_1.project_id, 404, moved_to_project_id, 200)
278
279 self.assertEqual(
280 rnc.IngestIssueName(
281 self.cnxn, 'projects/proj/issues/404', self.services), new_issue_id)
282
283 def testIngestIssueNames(self):
284 """We can get an Issue global ids from resource names."""
285 self.assertEqual(
286 rnc.IngestIssueNames(
287 self.cnxn, ['projects/proj/issues/1', 'projects/goose/issues/2'],
288 self.services), [self.issue_1.issue_id, self.issue_2.issue_id])
289
290 def testIngestIssueNames_EmptyList(self):
291 """We get an empty list when providing an empty list of issue names."""
292 self.assertEqual(rnc.IngestIssueNames(self.cnxn, [], self.services), [])
293
294 def testIngestIssueNames_WithBadInputs(self):
295 """We aggregate input exceptions."""
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100296 with self.assertRaisesRegex(
Copybara854996b2021-09-07 19:36:02 +0000297 exceptions.InputException,
298 'Invalid resource name: projects/proj/badformat/1.\n' +
299 'Invalid resource name: badformat/proj/issues/1.'):
300 rnc.IngestIssueNames(
301 self.cnxn, [
302 'projects/proj/badformat/1', 'badformat/proj/issues/1',
303 'projects/proj/issues/1'
304 ], self.services)
305
306 def testIngestIssueNames_OneDoesNotExist(self):
307 """We get an exception if one issue name provided does not exist."""
308 with self.assertRaises(exceptions.NoSuchIssueException):
309 rnc.IngestIssueNames(
310 self.cnxn, ['projects/proj/issues/1', 'projects/proj/issues/2'],
311 self.services)
312
313 def testIngestIssueNames_ManyDoNotExist(self):
314 """We get an exception if one issue name provided does not exist."""
315 dne_issues = ['projects/proj/issues/2', 'projects/proj/issues/3']
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100316 with self.assertRaisesRegex(exceptions.NoSuchIssueException,
317 '%r' % dne_issues):
Copybara854996b2021-09-07 19:36:02 +0000318 rnc.IngestIssueNames(self.cnxn, dne_issues, self.services)
319
320 def testIngestIssueNames_ProjectsNotExist(self):
321 """Aggregated exceptions raised if projects are not found."""
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100322 with self.assertRaisesRegex(exceptions.NoSuchProjectException,
323 'Project chicken not found.\n' +
324 'Project cow not found.'):
Copybara854996b2021-09-07 19:36:02 +0000325 rnc.IngestIssueNames(
326 self.cnxn, [
327 'projects/chicken/issues/2', 'projects/cow/issues/3',
328 'projects/proj/issues/1'
329 ], self.services)
330
331 def testIngestProjectFromIssue(self):
332 self.assertEqual(rnc.IngestProjectFromIssue('projects/xyz/issues/1'), 'xyz')
333
334 def testIngestProjectFromIssue_InvalidName(self):
335 with self.assertRaises(exceptions.InputException):
336 rnc.IngestProjectFromIssue('projects/xyz')
337 with self.assertRaises(exceptions.InputException):
338 rnc.IngestProjectFromIssue('garbage')
339 with self.assertRaises(exceptions.InputException):
340 rnc.IngestProjectFromIssue('projects/xyz/issues/garbage')
341
342 def testIngestCommentName(self):
343 name = 'projects/proj/issues/1/comments/0'
344 actual = rnc.IngestCommentName(self.cnxn, name, self.services)
345 self.assertEqual(
346 actual, (self.project_1.project_id, self.issue_1.issue_id, 0))
347
348 def testIngestCommentName_InputException(self):
349 with self.assertRaises(exceptions.InputException):
350 rnc.IngestCommentName(self.cnxn, 'misspelled name', self.services)
351
352 def testIngestCommentName_NoSuchProject(self):
353 with self.assertRaises(exceptions.NoSuchProjectException):
354 rnc.IngestCommentName(
355 self.cnxn, 'projects/doesnotexist/issues/1/comments/0', self.services)
356
357 def testIngestCommentName_NoSuchIssue(self):
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100358 with self.assertRaisesRegex(exceptions.NoSuchIssueException,
359 "['projects/proj/issues/404']"):
Copybara854996b2021-09-07 19:36:02 +0000360 rnc.IngestCommentName(
361 self.cnxn, 'projects/proj/issues/404/comments/0', self.services)
362
363 def testConvertCommentNames(self):
364 """We can create comment names."""
365 expected = {
366 0: 'projects/proj/issues/1/comments/0',
367 1: 'projects/proj/issues/1/comments/1'
368 }
369 self.assertEqual(rnc.CreateCommentNames(1, 'proj', [0, 1]), expected)
370
371 def testConvertCommentNames_Empty(self):
372 """Converting an empty list of comments returns an empty dict."""
373 self.assertEqual(rnc.CreateCommentNames(1, 'proj', []), {})
374
375 def testConvertIssueName(self):
376 """We can create an Issue resource name from an issue_id."""
377 self.assertEqual(
378 rnc.ConvertIssueName(self.cnxn, self.issue_1.issue_id, self.services),
379 'projects/proj/issues/1')
380
381 def testConvertIssueName_NotFound(self):
382 """Exception is raised if the issue is not found."""
383 with self.assertRaises(exceptions.NoSuchIssueException):
384 rnc.ConvertIssueName(self.cnxn, 3279, self.services)
385
386 def testConvertIssueNames(self):
387 """We can create Issue resource names from issue_ids."""
388 self.assertEqual(
389 rnc.ConvertIssueNames(
390 self.cnxn, [self.issue_1.issue_id, 3279], self.services),
391 {self.issue_1.issue_id: 'projects/proj/issues/1'})
392
393 def testConvertApprovalValueNames(self):
394 """We can create ApprovalValue resource names."""
395 self.issue_1.approval_values = [tracker_pb2.ApprovalValue(
396 approval_id=self.approval_def_1_id)]
397
398 expected_name = (
399 'projects/proj/issues/1/approvalValues/%d' % self.approval_def_1_id)
400 self.assertEqual(
401 {self.approval_def_1_id: expected_name},
402 rnc.ConvertApprovalValueNames(
403 self.cnxn, self.issue_1.issue_id, self.services))
404
405 def testIngestUserName(self):
406 """We can get a User ID from User resource name."""
407 name = 'users/111'
408 self.assertEqual(rnc.IngestUserName(self.cnxn, name, self.services), 111)
409
410 def testIngestUserName_DisplayName(self):
411 """We can get a User ID from User resource name with a display name set."""
412 name = 'users/%s' % self.user_3.email
413 self.assertEqual(rnc.IngestUserName(self.cnxn, name, self.services), 333)
414
415 def testIngestUserName_NoSuchUser(self):
416 """When autocreate=False, we raise an exception if a user is not found."""
417 name = 'users/chicken@test.com'
418 with self.assertRaises(exceptions.NoSuchUserException):
419 rnc.IngestUserName(self.cnxn, name, self.services)
420
421 def testIngestUserName_InvalidEmail(self):
422 """We raise an exception if a given resource name's email is invalid."""
423 name = 'users/chickentest.com'
424 with self.assertRaises(exceptions.InputException):
425 rnc.IngestUserName(self.cnxn, name, self.services)
426
427 def testIngestUserName_Autocreate(self):
428 """When autocreate=True create a new User if they don't already exist."""
429 new_email = 'chicken@test.com'
430 name = 'users/%s' % new_email
431 user_id = rnc.IngestUserName(
432 self.cnxn, name, self.services, autocreate=True)
433
434 new_id = self.services.user.LookupUserID(
435 self.cnxn, new_email, autocreate=False)
436 self.assertEqual(new_id, user_id)
437
438 def testIngestUserNames(self):
439 """We can get User IDs from User resource names."""
440 names = ['users/111', 'users/222', 'users/%s' % self.user_3.email]
441 expected_ids = [111, 222, 333]
442 self.assertEqual(
443 rnc.IngestUserNames(self.cnxn, names, self.services), expected_ids)
444
445 def testIngestUserNames_NoSuchUser(self):
446 """When autocreate=False, we raise an exception if a user is not found."""
447 names = [
448 'users/111', 'users/chicken@test.com',
449 'users/%s' % self.user_3.email
450 ]
451 with self.assertRaises(exceptions.NoSuchUserException):
452 rnc.IngestUserNames(self.cnxn, names, self.services)
453
454 def testIngestUserNames_InvalidEmail(self):
455 """We raise an exception if a given resource name's email is invalid."""
456 names = [
457 'users/111', 'users/chickentest.com',
458 'users/%s' % self.user_3.email
459 ]
460 with self.assertRaises(exceptions.InputException):
461 rnc.IngestUserNames(self.cnxn, names, self.services)
462
463 def testIngestUserNames_Autocreate(self):
464 """When autocreate=True we create new Users if they don't already exist."""
465 new_email = 'user_444@example.com'
466 names = [
467 'users/111',
468 'users/%s' % new_email,
469 'users/%s' % self.user_3.email
470 ]
471 ids = rnc.IngestUserNames(self.cnxn, names, self.services, autocreate=True)
472
473 new_id = self.services.user.LookupUserID(
474 self.cnxn, new_email, autocreate=False)
475 expected_ids = [111, new_id, 333]
476 self.assertEqual(expected_ids, ids)
477
478 def testConvertUserName(self):
479 """We can convert a single User ID to resource name."""
480 self.assertEqual(rnc.ConvertUserName(111), 'users/111')
481
482 def testConvertUserNames(self):
483 """We can get User resource names."""
484 expected_dict = {111: 'users/111', 222: 'users/222', 333: 'users/333'}
485 self.assertEqual(rnc.ConvertUserNames(expected_dict.keys()), expected_dict)
486
487 def testConvertUserNames_Empty(self):
488 """We can process an empty Users list."""
489 self.assertEqual(rnc.ConvertUserNames([]), {})
490
491 def testConvertProjectStarName(self):
492 """We can convert a User ID and Project ID to resource name."""
493 name = rnc.ConvertProjectStarName(
494 self.cnxn, 111, self.project_1.project_id, self.services)
495 expected = 'users/111/projectStars/{}'.format(self.project_1.project_name)
496 self.assertEqual(name, expected)
497
498 def testConvertProjectStarName_NoSuchProjectException(self):
499 """Throws an exception when Project ID is invalid."""
500 with self.assertRaises(exceptions.NoSuchProjectException):
501 rnc.ConvertProjectStarName(self.cnxn, 111, 123455, self.services)
502
503 def testIngestProjectName(self):
504 """We can get project name from Project resource names."""
505 name = 'projects/{}'.format(self.project_1.project_name)
506 expected = self.project_1.project_id
507 self.assertEqual(
508 rnc.IngestProjectName(self.cnxn, name, self.services), expected)
509
510 def testIngestProjectName_InvalidName(self):
511 """An exception is raised if the Hotlist's resource name is invalid"""
512 with self.assertRaises(exceptions.InputException):
513 rnc.IngestProjectName(self.cnxn, 'projects/', self.services)
514
515 def testConvertTemplateNames(self):
516 """We can get IssueTemplate resource names."""
517 expected_resource_name = 'projects/{}/templates/{}'.format(
518 self.project_1.project_name, self.template_1.template_id)
519 expected = {self.template_1.template_id: expected_resource_name}
520
521 self.assertEqual(
522 rnc.ConvertTemplateNames(
523 self.cnxn, self.project_1.project_id, [self.template_1.template_id],
524 self.services), expected)
525
526 def testConvertTemplateNames_NoSuchProjectException(self):
527 """We get an exception if project with id does not exist."""
528 with self.assertRaises(exceptions.NoSuchProjectException):
529 rnc.ConvertTemplateNames(
530 self.cnxn, self.dne_project_id, [self.template_1.template_id],
531 self.services)
532
533 def testConvertTemplateNames_NonExistentTemplate(self):
534 """We only return templates that exist."""
535 self.assertEqual(
536 rnc.ConvertTemplateNames(
537 self.cnxn, self.project_1.project_id, [self.dne_template_id],
538 self.services), {})
539
540 def testConvertTemplateNames_TemplateInProject(self):
541 """We only return templates in the project."""
542 expected_resource_name = 'projects/{}/templates/{}'.format(
543 self.project_2.project_name, self.template_2.template_id)
544 expected = {self.template_2.template_id: expected_resource_name}
545
546 self.assertEqual(
547 rnc.ConvertTemplateNames(
548 self.cnxn, self.project_2.project_id,
549 [self.template_1.template_id, self.template_2.template_id],
550 self.services), expected)
551
552 def testIngestTemplateName(self):
553 name = 'projects/{}/templates/{}'.format(
554 self.project_1.project_name, self.template_1.template_id)
555 actual = rnc.IngestTemplateName(self.cnxn, name, self.services)
556 expected = (self.template_1.template_id, self.project_1.project_id)
557 self.assertEqual(actual, expected)
558
559 def testIngestTemplateName_DoesNotExist(self):
560 """We will ingest templates that don't exist."""
561 name = 'projects/{}/templates/{}'.format(
562 self.project_1.project_name, self.dne_template_id)
563 actual = rnc.IngestTemplateName(self.cnxn, name, self.services)
564 expected = (self.dne_template_id, self.project_1.project_id)
565 self.assertEqual(actual, expected)
566
567 def testIngestTemplateName_InvalidName(self):
568 with self.assertRaises(exceptions.InputException):
569 rnc.IngestTemplateName(
570 self.cnxn, 'projects/asdf/misspelled_template/123', self.services)
571
572 with self.assertRaises(exceptions.NoSuchProjectException):
573 rnc.IngestTemplateName(
574 self.cnxn, 'projects/asdf/templates/123', self.services)
575
576 def testConvertStatusDefNames(self):
577 """We can get Status resource name."""
578 expected_resource_name = 'projects/{}/statusDefs/{}'.format(
579 self.project_1.project_name, self.issue_1.status)
580
581 actual = rnc.ConvertStatusDefNames(
582 self.cnxn, [self.issue_1.status], self.project_1.project_id,
583 self.services)
584 self.assertEqual(actual[self.issue_1.status], expected_resource_name)
585
586 def testConvertStatusDefNames_NoSuchProjectException(self):
587 """We can get an exception if project with id does not exist."""
588 with self.assertRaises(exceptions.NoSuchProjectException):
589 rnc.ConvertStatusDefNames(
590 self.cnxn, [self.issue_1.status], self.dne_project_id, self.services)
591
592 def testConvertLabelDefNames(self):
593 """We can get Label resource names."""
594 expected_label = 'some label'
595 expected_resource_name = 'projects/{}/labelDefs/{}'.format(
596 self.project_1.project_name, expected_label)
597
598 self.assertEqual(
599 rnc.ConvertLabelDefNames(
600 self.cnxn, [expected_label], self.project_1.project_id,
601 self.services), {expected_label: expected_resource_name})
602
603 def testConvertLabelDefNames_NoSuchProjectException(self):
604 """We can get an exception if project with id does not exist."""
605 some_label = 'some label'
606 with self.assertRaises(exceptions.NoSuchProjectException):
607 rnc.ConvertLabelDefNames(
608 self.cnxn, [some_label], self.dne_project_id, self.services)
609
610 def testConvertComponentDefNames(self):
611 """We can get Component resource names."""
612 expected_id = 123456
613 expected_resource_name = 'projects/{}/componentDefs/{}'.format(
614 self.project_1.project_name, expected_id)
615
616 self.assertEqual(
617 rnc.ConvertComponentDefNames(
618 self.cnxn, [expected_id], self.project_1.project_id, self.services),
619 {expected_id: expected_resource_name})
620
621 def testConvertComponentDefNames_NoSuchProjectException(self):
622 """We can get an exception if project with id does not exist."""
623 component_id = 123456
624 with self.assertRaises(exceptions.NoSuchProjectException):
625 rnc.ConvertComponentDefNames(
626 self.cnxn, [component_id], self.dne_project_id, self.services)
627
628 def testIngestComponentDefNames(self):
629 names = [
630 'projects/proj/componentDefs/%d' % self.component_def_1_id,
631 'projects/proj/componentDefs/%s' % self.component_def_2_path
632 ]
633 actual = rnc.IngestComponentDefNames(self.cnxn, names, self.services)
634 self.assertEqual(actual, [
635 (self.project_1.project_id, self.component_def_1_id),
636 (self.project_1.project_id, self.component_def_2_id)])
637
638 def testIngestComponentDefNames_NoSuchProjectException(self):
639 names = ['projects/xyz/componentDefs/%d' % self.component_def_1_id]
640 with self.assertRaises(exceptions.NoSuchProjectException):
641 rnc.IngestComponentDefNames(self.cnxn, names, self.services)
642
643 names = ['projects/xyz/componentDefs/1', 'projects/zyz/componentDefs/1']
644 expected_error = 'Project not found: xyz.\nProject not found: zyz.'
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100645 with self.assertRaisesRegex(exceptions.NoSuchProjectException,
646 expected_error):
Copybara854996b2021-09-07 19:36:02 +0000647 rnc.IngestComponentDefNames(self.cnxn, names, self.services)
648
649 def testIngestComponentDefNames_NoSuchComponentException(self):
650 names = ['projects/proj/componentDefs/%d' % self.dne_component_def_id]
651 with self.assertRaises(exceptions.NoSuchComponentException):
652 rnc.IngestComponentDefNames(self.cnxn, names, self.services)
653
654 names = [
655 'projects/proj/componentDefs/999', 'projects/proj/componentDefs/cow'
656 ]
657 expected_error = 'Component not found: 999.\nComponent not found: \'cow\'.'
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +0100658 with self.assertRaisesRegex(exceptions.NoSuchComponentException,
659 expected_error):
Copybara854996b2021-09-07 19:36:02 +0000660 rnc.IngestComponentDefNames(self.cnxn, names, self.services)
661
662 def testIngestComponentDefNames_InvalidNames(self):
663 with self.assertRaises(exceptions.InputException):
664 rnc.IngestComponentDefNames(
665 self.cnxn, ['projects/proj/componentDefs/not.path.or.id'],
666 self.services)
667
668 with self.assertRaises(exceptions.InputException):
669 rnc.IngestComponentDefNames(
670 self.cnxn, ['projects/proj/componentDefs/Foo>'], self.services)
671
672 with self.assertRaises(exceptions.InputException):
673 rnc.IngestComponentDefNames(
674 self.cnxn, ['projects/proj/componentDefs/>Bar'], self.services)
675
676 with self.assertRaises(exceptions.InputException):
677 rnc.IngestComponentDefNames(
678 self.cnxn, ['projects/proj/componentDefs/Foo>123Bar'], self.services)
679
680 def testIngestComponentDefNames_CrossProject(self):
681 names = [
682 'projects/proj/componentDefs/%d' % self.component_def_1_id,
683 'projects/goose/componentDefs/%s' % self.component_def_3_path
684 ]
685 actual = rnc.IngestComponentDefNames(self.cnxn, names, self.services)
686 self.assertEqual(actual, [
687 (self.project_1.project_id, self.component_def_1_id),
688 (self.project_2.project_id, self.component_def_3_id)])
689
690 def testConvertFieldDefNames(self):
691 """Returns resource names for fields that exist and ignores others."""
692 expected_key = self.field_def_1
693 expected_value = 'projects/{}/fieldDefs/{}'.format(
694 self.project_1.project_name, self.field_def_1)
695
696 field_ids = [self.field_def_1, self.dne_field_def_id]
697 self.assertEqual(
698 rnc.ConvertFieldDefNames(
699 self.cnxn, field_ids, self.project_1.project_id, self.services),
700 {expected_key: expected_value})
701
702 def testConvertFieldDefNames_NoSuchProjectException(self):
703 field_ids = [self.field_def_1, self.dne_field_def_id]
704 with self.assertRaises(exceptions.NoSuchProjectException):
705 rnc.ConvertFieldDefNames(
706 self.cnxn, field_ids, self.dne_project_id, self.services)
707
708 def testConvertApprovalDefNames(self):
709 outcome = rnc.ConvertApprovalDefNames(
710 self.cnxn, [self.approval_def_1_id], self.project_1.project_id,
711 self.services)
712
713 expected_key = self.approval_def_1_id
714 expected_value = 'projects/{}/approvalDefs/{}'.format(
715 self.project_1.project_name, self.approval_def_1_id)
716 self.assertEqual(outcome, {expected_key: expected_value})
717
718 def testConvertApprovalDefNames_NoSuchProjectException(self):
719 approval_ids = [self.approval_def_1_id]
720 with self.assertRaises(exceptions.NoSuchProjectException):
721 rnc.ConvertApprovalDefNames(
722 self.cnxn, approval_ids, self.dne_project_id, self.services)
723
724 def testConvertProjectName(self):
725 self.assertEqual(
726 rnc.ConvertProjectName(
727 self.cnxn, self.project_1.project_id, self.services),
728 'projects/{}'.format(self.project_1.project_name))
729
730 def testConvertProjectName_NoSuchProjectException(self):
731 with self.assertRaises(exceptions.NoSuchProjectException):
732 rnc.ConvertProjectName(self.cnxn, self.dne_project_id, self.services)
733
734 def testConvertProjectConfigName(self):
735 self.assertEqual(
736 rnc.ConvertProjectConfigName(
737 self.cnxn, self.project_1.project_id, self.services),
738 'projects/{}/config'.format(self.project_1.project_name))
739
740 def testConvertProjectConfigName_NoSuchProjectException(self):
741 with self.assertRaises(exceptions.NoSuchProjectException):
742 rnc.ConvertProjectConfigName(
743 self.cnxn, self.dne_project_id, self.services)
744
745 def testConvertProjectMemberName(self):
746 self.assertEqual(
747 rnc.ConvertProjectMemberName(
748 self.cnxn, self.project_1.project_id, 111, self.services),
749 'projects/{}/members/{}'.format(self.project_1.project_name, 111))
750
751 def testConvertProjectMemberName_NoSuchProjectException(self):
752 with self.assertRaises(exceptions.NoSuchProjectException):
753 rnc.ConvertProjectMemberName(
754 self.cnxn, self.dne_project_id, 111, self.services)
755
756 def testConvertProjectSavedQueryNames(self):
757 query_ids = [self.psq_1.query_id, self.psq_2.query_id, self.dne_psq_id]
758 outcome = rnc.ConvertProjectSavedQueryNames(
759 self.cnxn, query_ids, self.project_1.project_id, self.services)
760
761 expected_value_1 = 'projects/{}/savedQueries/{}'.format(
762 self.project_1.project_name, self.psq_1.name)
763 expected_value_2 = 'projects/{}/savedQueries/{}'.format(
764 self.project_1.project_name, self.psq_2.name)
765 self.assertEqual(
766 outcome, {
767 self.psq_1.query_id: expected_value_1,
768 self.psq_2.query_id: expected_value_2
769 })
770
771 def testConvertProjectSavedQueryNames_NoSuchProjectException(self):
772 with self.assertRaises(exceptions.NoSuchProjectException):
773 rnc.ConvertProjectSavedQueryNames(
774 self.cnxn, [self.psq_1.query_id], self.dne_project_id, self.services)