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