blob: 964722d464f2e1909425b4832c40de54167d59fd [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"""Unit tests for services.template_svc module."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import mock
12import unittest
13
14from mock import Mock, patch
15
16from proto import tracker_pb2
17from services import template_svc
18from testing import fake
19from testing import testing_helpers
20from tracker import tracker_bizobj
21from tracker import tracker_constants
22
23
24class TemplateSetTwoLevelCacheTest(unittest.TestCase):
25
26 def setUp(self):
27 self.ts2lc = template_svc.TemplateSetTwoLevelCache(
28 cache_manager=fake.CacheManager(),
29 template_service=Mock(spec=template_svc.TemplateService))
30 self.ts2lc.template_service.template_tbl = Mock()
31
32 def testFetchItems_Empty(self):
33 self.ts2lc.template_service.template_tbl.Select .return_value = []
34 actual = self.ts2lc.FetchItems(cnxn=None, keys=[1, 2])
35 self.assertEqual({1: [], 2: []}, actual)
36
37 def testFetchItems_Normal(self):
38 # pylint: disable=unused-argument
39 def mockSelect(cnxn, cols, project_id, order_by):
40 assert project_id in (1, 2)
41 if project_id == 1:
42 return [
43 (8, 1, 'template-8', 'content', 'summary', False, 111, 'status',
44 False, False, False),
45 (9, 1, 'template-9', 'content', 'summary', False, 111, 'status',
46 True, False, False)]
47 else:
48 return [
49 (7, 2, 'template-7', 'content', 'summary', False, 111, 'status',
50 False, False, False)]
51
52 self.ts2lc.template_service.template_tbl.Select.side_effect = mockSelect
53 actual = self.ts2lc.FetchItems(cnxn=None, keys=[1, 2])
54 expected = {
55 1: [(8, 'template-8', False), (9, 'template-9', True)],
56 2: [(7, 'template-7', False)],
57 }
58 self.assertEqual(expected, actual)
59
60
61class TemplateDefTwoLevelCacheTest(unittest.TestCase):
62
63 def setUp(self):
64 self.template_def_2lc = template_svc.TemplateDefTwoLevelCache(
65 cache_manager=fake.CacheManager(),
66 template_service=Mock(spec=template_svc.TemplateService))
67 self.template_def_2lc.template_service.template_tbl = Mock()
68 self.template_def_2lc.template_service.template2label_tbl = Mock()
69 self.template_def_2lc.template_service.template2component_tbl = Mock()
70 self.template_def_2lc.template_service.template2admin_tbl = Mock()
71 self.template_def_2lc.template_service.template2fieldvalue_tbl = Mock()
72 self.template_def_2lc.template_service.issuephasedef_tbl = Mock()
73 self.template_def_2lc.template_service.template2approvalvalue_tbl = Mock()
74
75 def testFetchItems_Empty(self):
76 self.template_def_2lc.template_service.template_tbl.Select\
77 .return_value = []
78 self.template_def_2lc.template_service.template2label_tbl.Select\
79 .return_value = []
80 self.template_def_2lc.template_service.template2component_tbl.Select\
81 .return_value = []
82 self.template_def_2lc.template_service.template2admin_tbl.Select\
83 .return_value = []
84 self.template_def_2lc.template_service.template2fieldvalue_tbl.Select\
85 .return_value = []
86 self.template_def_2lc.template_service.template2approvalvalue_tbl.Select\
87 .return_value = []
88
89 actual = self.template_def_2lc.FetchItems(cnxn=None, keys=[1, 2])
90 self.assertEqual({}, actual)
91
92 def testFetchItems_Normal(self):
93 template_9_row = (9, 1, 'template-9', 'content', 'summary',
94 False, 111, 'status',
95 False, False, False)
96 template_8_row = (8, 1, 'template-8', 'content', 'summary',
97 False, 111, 'status',
98 False, False, False)
99 template_7_row = (7, 2, 'template-7', 'content', 'summary',
100 False, 111, 'status',
101 False, False, False)
102
103 self.template_def_2lc.template_service.template_tbl.Select\
104 .return_value = [template_7_row, template_8_row,
105 template_9_row]
106 self.template_def_2lc.template_service.template2label_tbl.Select\
107 .return_value = [(9, 'label-1'), (7, 'label-2')]
108 self.template_def_2lc.template_service.template2component_tbl.Select\
109 .return_value = [(9, 13), (7, 14)]
110 self.template_def_2lc.template_service.template2admin_tbl.Select\
111 .return_value = [(9, 111), (7, 222)]
112
113 fv1_row = (15, None, 'fv-1', None, None, None, False)
114 fv2_row = (16, None, 'fv-2', None, None, None, False)
115 fv1 = tracker_bizobj.MakeFieldValue(*fv1_row)
116 fv2 = tracker_bizobj.MakeFieldValue(*fv2_row)
117 self.template_def_2lc.template_service.template2fieldvalue_tbl.Select\
118 .return_value = [((9,) + fv1_row[:-1]), ((7,) + fv2_row[:-1])]
119
120 av1_row = (17, 9, 19, 'na')
121 av2_row = (18, 7, 20, 'not_set')
122 av1 = tracker_pb2.ApprovalValue(approval_id=17, phase_id=19,
123 status=tracker_pb2.ApprovalStatus('NA'))
124 av2 = tracker_pb2.ApprovalValue(approval_id=18, phase_id=20,
125 status=tracker_pb2.ApprovalStatus(
126 'NOT_SET'))
127 phase1_row = (19, 'phase-1', 1)
128 phase2_row = (20, 'phase-2', 2)
129 phase1 = tracker_pb2.Phase(phase_id=19, name='phase-1', rank=1)
130 phase2 = tracker_pb2.Phase(phase_id=20, name='phase-2', rank=2)
131
132 self.template_def_2lc.template_service.template2approvalvalue_tbl.Select\
133 .return_value = [av1_row, av2_row]
134 self.template_def_2lc.template_service.issuephasedef_tbl.Select\
135 .return_value = [phase1_row, phase2_row]
136
137 actual = self.template_def_2lc.FetchItems(cnxn=None, keys=[7, 8, 9])
138 self.assertEqual(3, len(list(actual.keys())))
139 self.assertTrue(isinstance(actual[7], tracker_pb2.TemplateDef))
140 self.assertTrue(isinstance(actual[8], tracker_pb2.TemplateDef))
141 self.assertTrue(isinstance(actual[9], tracker_pb2.TemplateDef))
142
143 self.assertEqual(7, actual[7].template_id)
144 self.assertEqual(8, actual[8].template_id)
145 self.assertEqual(9, actual[9].template_id)
146
147 self.assertEqual(['label-2'], actual[7].labels)
148 self.assertEqual([], actual[8].labels)
149 self.assertEqual(['label-1'], actual[9].labels)
150
151 self.assertEqual([14], actual[7].component_ids)
152 self.assertEqual([], actual[8].component_ids)
153 self.assertEqual([13], actual[9].component_ids)
154
155 self.assertEqual([222], actual[7].admin_ids)
156 self.assertEqual([], actual[8].admin_ids)
157 self.assertEqual([111], actual[9].admin_ids)
158
159 self.assertEqual([fv2], actual[7].field_values)
160 self.assertEqual([], actual[8].field_values)
161 self.assertEqual([fv1], actual[9].field_values)
162
163 self.assertEqual([phase2], actual[7].phases)
164 self.assertEqual([], actual[8].phases)
165 self.assertEqual([phase1], actual[9].phases)
166
167 self.assertEqual([av2], actual[7].approval_values)
168 self.assertEqual([], actual[8].approval_values)
169 self.assertEqual([av1], actual[9].approval_values)
170
171
172class TemplateServiceTest(unittest.TestCase):
173
174 def setUp(self):
175 self.cnxn = Mock()
176 self.template_service = template_svc.TemplateService(fake.CacheManager())
177 self.template_service.template_set_2lc = Mock()
178 self.template_service.template_def_2lc = Mock()
179
180 def testCreateDefaultProjectTemplates_Normal(self):
181 self.template_service.CreateIssueTemplateDef = Mock()
182 self.template_service.CreateDefaultProjectTemplates(self.cnxn, 789)
183
184 expected_calls = [
185 mock.call(self.cnxn, 789, tpl['name'], tpl['content'], tpl['summary'],
186 tpl['summary_must_be_edited'], tpl['status'],
187 tpl.get('members_only', False), True, False, None, tpl['labels'],
188 [], [], [], [])
189 for tpl in tracker_constants.DEFAULT_TEMPLATES]
190 self.template_service.CreateIssueTemplateDef.assert_has_calls(
191 expected_calls, any_order=True)
192
193 def testGetTemplateByName_Normal(self):
194 """GetTemplateByName returns a template that exists."""
195 result_dict = {789: [(1, 'one', 0)]}
196 template = tracker_pb2.TemplateDef(name='one')
197 self.template_service.template_set_2lc.GetAll.return_value = (
198 result_dict, None)
199 self.template_service.template_def_2lc.GetAll.return_value = (
200 {1: template}, None)
201 actual = self.template_service.GetTemplateByName(self.cnxn, 'one', 789)
202 self.assertEqual(actual.template_id, template.template_id)
203
204 def testGetTemplateByName_NotFound(self):
205 """When GetTemplateByName is given the name of a template that does not
206 exist."""
207 result_dict = {789: [(1, 'one', 0)]}
208 template = tracker_pb2.TemplateDef(name='one')
209 self.template_service.template_set_2lc.GetAll.return_value = (
210 result_dict, None)
211 self.template_service.template_def_2lc.GetAll.return_value = (
212 {1: template}, None)
213 actual = self.template_service.GetTemplateByName(self.cnxn, 'two', 789)
214 self.assertEqual(actual, None)
215
216 def testGetTemplateById_Normal(self):
217 """GetTemplateById_Normal returns a template that exists."""
218 template = tracker_pb2.TemplateDef(template_id=1, name='one')
219 self.template_service.template_def_2lc.GetAll.return_value = (
220 {1: template}, None)
221 actual = self.template_service.GetTemplateById(self.cnxn, 1)
222 self.assertEqual(actual.template_id, template.template_id)
223
224 def testGetTemplateById_NotFound(self):
225 """When GetTemplateById is given the ID of a template that does not
226 exist."""
227 self.template_service.template_def_2lc.GetAll.return_value = (
228 {}, None)
229 actual = self.template_service.GetTemplateById(self.cnxn, 1)
230 self.assertEqual(actual, None)
231
232 def testGetTemplatesById_Normal(self):
233 """GetTemplatesById_Normal returns a template that exists."""
234 template = tracker_pb2.TemplateDef(template_id=1, name='one')
235 self.template_service.template_def_2lc.GetAll.return_value = (
236 {1: template}, None)
237 actual = self.template_service.GetTemplatesById(self.cnxn, 1)
238 self.assertEqual(actual[0].template_id, template.template_id)
239
240 def testGetTemplatesById_NotFound(self):
241 """When GetTemplatesById is given the ID of a template that does not
242 exist."""
243 self.template_service.template_def_2lc.GetAll.return_value = (
244 {}, None)
245 actual = self.template_service.GetTemplatesById(self.cnxn, 1)
246 self.assertEqual(actual, [])
247
248 def testGetProjectTemplates_Normal(self):
249 template_set = [(1, 'one', 0), (2, 'two', 1)]
250 result_dict = {789: template_set}
251 self.template_service.template_set_2lc.GetAll.return_value = (
252 result_dict, None)
253 self.template_service.template_def_2lc.GetAll.return_value = (
254 {1: tracker_pb2.TemplateDef()}, None)
255
256 self.assertEqual([tracker_pb2.TemplateDef()],
257 self.template_service.GetProjectTemplates(self.cnxn, 789))
258 self.template_service.template_set_2lc.GetAll.assert_called_once_with(
259 self.cnxn, [789])
260
261 def testExpungeProjectTemplates(self):
262 template_id_rows = [(1,), (2,)]
263 self.template_service.template_tbl.Select = Mock(
264 return_value=template_id_rows)
265 self.template_service.template2label_tbl.Delete = Mock()
266 self.template_service.template2component_tbl.Delete = Mock()
267 self.template_service.template_tbl.Delete = Mock()
268
269 self.template_service.ExpungeProjectTemplates(self.cnxn, 789)
270
271 self.template_service.template_tbl.Select\
272 .assert_called_once_with(self.cnxn, project_id=789, cols=['id'])
273 self.template_service.template2label_tbl.Delete\
274 .assert_called_once_with(self.cnxn, template_id=[1, 2])
275 self.template_service.template2component_tbl.Delete\
276 .assert_called_once_with(self.cnxn, template_id=[1, 2])
277 self.template_service.template_tbl.Delete\
278 .assert_called_once_with(self.cnxn, project_id=789)
279
280
281class CreateIssueTemplateDefTest(TemplateServiceTest):
282
283 def setUp(self):
284 super(CreateIssueTemplateDefTest, self).setUp()
285
286 self.template_service.template_tbl.InsertRow = Mock(return_value=1)
287 self.template_service.template2label_tbl.InsertRows = Mock()
288 self.template_service.template2component_tbl.InsertRows = Mock()
289 self.template_service.template2admin_tbl.InsertRows = Mock()
290 self.template_service.template2fieldvalue_tbl.InsertRows = Mock()
291 self.template_service.issuephasedef_tbl.InsertRow = Mock(return_value=81)
292 self.template_service.template2approvalvalue_tbl.InsertRows = Mock()
293 self.template_service.template_set_2lc._StrToKey = Mock(return_value=789)
294
295 def testCreateIssueTemplateDef(self):
296 fv = tracker_bizobj.MakeFieldValue(
297 1, None, 'somestring', None, None, None, False)
298 av_23 = tracker_pb2.ApprovalValue(
299 approval_id=23, phase_id=11,
300 status=tracker_pb2.ApprovalStatus.NEEDS_REVIEW)
301 av_24 = tracker_pb2.ApprovalValue(approval_id=24, phase_id=11)
302 approval_values = [av_23, av_24]
303 phases = [tracker_pb2.Phase(
304 name='Canary', rank=11, phase_id=11)]
305
306 actual_template_id = self.template_service.CreateIssueTemplateDef(
307 self.cnxn, 789, 'template', 'content', 'summary', True, 'Available',
308 True, True, True, owner_id=111, labels=['label'], component_ids=[3],
309 admin_ids=[222], field_values=[fv], phases=phases,
310 approval_values=approval_values)
311
312 self.assertEqual(1, actual_template_id)
313
314 self.template_service.template_tbl.InsertRow\
315 .assert_called_once_with(self.cnxn, project_id=789, name='template',
316 content='content', summary='summary', summary_must_be_edited=True,
317 owner_id=111, status='Available', members_only=True,
318 owner_defaults_to_member=True, component_required=True,
319 commit=False)
320 self.template_service.template2label_tbl.InsertRows\
321 .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2LABEL_COLS,
322 [(1, 'label')], commit=False)
323 self.template_service.template2component_tbl.InsertRows\
324 .assert_called_once_with(self.cnxn,
325 template_svc.TEMPLATE2COMPONENT_COLS,
326 [(1, 3)], commit=False)
327 self.template_service.template2admin_tbl.InsertRows\
328 .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2ADMIN_COLS,
329 [(1, 222)], commit=False)
330 self.template_service.template2fieldvalue_tbl.InsertRows\
331 .assert_called_once_with(self.cnxn,
332 template_svc.TEMPLATE2FIELDVALUE_COLS,
333 [(1, 1, None, 'somestring', None, None, None)], commit=False)
334 self.template_service.issuephasedef_tbl.InsertRow\
335 .assert_called_once_with(self.cnxn, name='Canary',
336 rank=11, commit=False)
337 self.template_service.template2approvalvalue_tbl.InsertRows\
338 .assert_called_once_with(self.cnxn,
339 template_svc.TEMPLATE2APPROVALVALUE_COLS,
340 [(23, 1, 81, 'needs_review'), (24, 1, 81, 'not_set')], commit=False)
341 self.cnxn.Commit.assert_called_once_with()
342 self.template_service.template_set_2lc.InvalidateKeys\
343 .assert_called_once_with(self.cnxn, [789])
344
345
346class UpdateIssueTemplateDefTest(TemplateServiceTest):
347
348 def setUp(self):
349 super(UpdateIssueTemplateDefTest, self).setUp()
350
351 self.template_service.template_tbl.Update = Mock()
352 self.template_service.template2label_tbl.Delete = Mock()
353 self.template_service.template2label_tbl.InsertRows = Mock()
354 self.template_service.template2admin_tbl.Delete = Mock()
355 self.template_service.template2admin_tbl.InsertRows = Mock()
356 self.template_service.template2approvalvalue_tbl.Delete = Mock()
357 self.template_service.issuephasedef_tbl.InsertRow = Mock(return_value=1)
358 self.template_service.template2approvalvalue_tbl.InsertRows = Mock()
359 self.template_service.template_set_2lc._StrToKey = Mock(return_value=789)
360
361 def testUpdateIssueTemplateDef(self):
362 av_20 = tracker_pb2.ApprovalValue(approval_id=20, phase_id=11)
363 av_21 = tracker_pb2.ApprovalValue(approval_id=21, phase_id=11)
364 approval_values = [av_20, av_21]
365 phases = [tracker_pb2.Phase(
366 name='Canary', phase_id=11, rank=11)]
367 self.template_service.UpdateIssueTemplateDef(
368 self.cnxn, 789, 1, content='content', summary='summary',
369 component_required=True, labels=[], admin_ids=[111],
370 phases=phases, approval_values=approval_values)
371
372 new_values = dict(
373 content='content', summary='summary', component_required=True)
374 self.template_service.template_tbl.Update\
375 .assert_called_once_with(self.cnxn, new_values, id=1, commit=False)
376 self.template_service.template2label_tbl.Delete\
377 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
378 self.template_service.template2label_tbl.InsertRows\
379 .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2LABEL_COLS,
380 [], commit=False)
381 self.template_service.template2admin_tbl.Delete\
382 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
383 self.template_service.template2admin_tbl.InsertRows\
384 .assert_called_once_with(self.cnxn, template_svc.TEMPLATE2ADMIN_COLS,
385 [(1, 111)], commit=False)
386 self.template_service.template2approvalvalue_tbl.Delete\
387 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
388 self.template_service.issuephasedef_tbl.InsertRow\
389 .assert_called_once_with(self.cnxn, name='Canary',
390 rank=11, commit=False)
391 self.template_service.template2approvalvalue_tbl.InsertRows\
392 .assert_called_once_with(self.cnxn,
393 template_svc.TEMPLATE2APPROVALVALUE_COLS,
394 [(20, 1, 1, 'not_set'), (21, 1, 1, 'not_set')], commit=False)
395 self.cnxn.Commit.assert_called_once_with()
396 self.template_service.template_set_2lc.InvalidateKeys\
397 .assert_called_once_with(self.cnxn, [789])
398 self.template_service.template_def_2lc.InvalidateKeys\
399 .assert_called_once_with(self.cnxn, [1])
400
401
402class DeleteTemplateTest(TemplateServiceTest):
403
404 def testDeleteIssueTemplateDef(self):
405 self.template_service.template2label_tbl.Delete = Mock()
406 self.template_service.template2component_tbl.Delete = Mock()
407 self.template_service.template2admin_tbl.Delete = Mock()
408 self.template_service.template2fieldvalue_tbl.Delete = Mock()
409 self.template_service.template2approvalvalue_tbl.Delete = Mock()
410 self.template_service.template_tbl.Delete = Mock()
411 self.template_service.template_set_2lc._StrToKey = Mock(return_value=789)
412
413 self.template_service.DeleteIssueTemplateDef(self.cnxn, 789, 1)
414
415 self.template_service.template2label_tbl.Delete\
416 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
417 self.template_service.template2component_tbl.Delete\
418 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
419 self.template_service.template2admin_tbl.Delete\
420 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
421 self.template_service.template2fieldvalue_tbl.Delete\
422 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
423 self.template_service.template2approvalvalue_tbl.Delete\
424 .assert_called_once_with(self.cnxn, template_id=1, commit=False)
425 self.template_service.template_tbl.Delete\
426 .assert_called_once_with(self.cnxn, id=1, commit=False)
427 self.cnxn.Commit.assert_called_once_with()
428 self.template_service.template_set_2lc.InvalidateKeys\
429 .assert_called_once_with(self.cnxn, [789])
430 self.template_service.template_def_2lc.InvalidateKeys\
431 .assert_called_once_with(self.cnxn, [1])
432
433
434class ExpungeUsersInTemplatesTest(TemplateServiceTest):
435
436 def setUp(self):
437 super(ExpungeUsersInTemplatesTest, self).setUp()
438
439 self.template_service.template2admin_tbl.Delete = Mock()
440 self.template_service.template2fieldvalue_tbl.Delete = Mock()
441 self.template_service.template_tbl.Update = Mock()
442
443 def testExpungeUsersInTemplates(self):
444 user_ids = [111, 222]
445 self.template_service.ExpungeUsersInTemplates(self.cnxn, user_ids, limit=60)
446
447 self.template_service.template2admin_tbl.Delete.assert_called_once_with(
448 self.cnxn, admin_id=user_ids, commit=False, limit=60)
449 self.template_service.template2fieldvalue_tbl\
450 .Delete.assert_called_once_with(
451 self.cnxn, user_id=user_ids, commit=False, limit=60)
452 self.template_service.template_tbl.Update.assert_called_once_with(
453 self.cnxn, {'owner_id': None}, owner_id=user_ids, commit=False)
454
455
456class UnpackTemplateTest(unittest.TestCase):
457
458 def testEmpty(self):
459 with self.assertRaises(ValueError):
460 template_svc.UnpackTemplate(())
461
462 def testNormal(self):
463 row = (1, 2, 'name', 'content', 'summary', False, 3, 'status', False,
464 False, False)
465 self.assertEqual(
466 tracker_pb2.TemplateDef(template_id=1, name='name',
467 content='content', summary='summary', summary_must_be_edited=False,
468 owner_id=3, status='status', members_only=False,
469 owner_defaults_to_member=False,
470 component_required=False),
471 template_svc.UnpackTemplate(row))