Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: appengine/monorail/services/test/config_svc_test.py

Issue 1868553004: Open Source Monorail (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is govered 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 config_svc module."""
7
8 import re
9 import unittest
10
11 import mox
12
13 from google.appengine.api import memcache
14 from google.appengine.ext import testbed
15
16 from framework import sql
17 from services import config_svc
18 from testing import fake
19 from tracker import tracker_bizobj
20 from tracker import tracker_constants
21
22
23 def MakeConfigService(cache_manager, my_mox):
24 config_service = config_svc.ConfigService(cache_manager)
25 for table_var in [
26 'template_tbl', 'template2label_tbl', 'template2admin_tbl',
27 'template2component_tbl', 'template2fieldvalue_tbl',
28 'projectissueconfig_tbl', 'statusdef_tbl', 'labeldef_tbl', 'fielddef_tbl',
29 'fielddef2admin_tbl', 'componentdef_tbl', 'component2admin_tbl',
30 'component2cc_tbl']:
31 setattr(config_service, table_var, my_mox.CreateMock(sql.SQLTableManager))
32
33 return config_service
34
35
36 class LabelRowTwoLevelCacheTest(unittest.TestCase):
37
38 def setUp(self):
39 self.mox = mox.Mox()
40 self.cnxn = 'fake connection'
41 self.cache_manager = fake.CacheManager()
42 self.config_service = MakeConfigService(self.cache_manager, self.mox)
43 self.label_row_2lc = self.config_service.label_row_2lc
44
45 self.rows = [(1, 789, 1, 'A', 'doc', False),
46 (2, 789, 2, 'B', 'doc', False),
47 (3, 678, 1, 'C', 'doc', True),
48 (4, 678, None, 'D', 'doc', False)]
49
50 def tearDown(self):
51 self.mox.UnsetStubs()
52 self.mox.ResetAll()
53
54 def testDeserializeLabelRows_Empty(self):
55 label_row_dict = self.label_row_2lc._DeserializeLabelRows([])
56 self.assertEqual({}, label_row_dict)
57
58 def testDeserializeLabelRows_Normal(self):
59 label_rows_dict = self.label_row_2lc._DeserializeLabelRows(self.rows)
60 expected = {
61 678: [(3, 678, 1, 'C', 'doc', True), (4, 678, None, 'D', 'doc', False)],
62 789: [(1, 789, 1, 'A', 'doc', False), (2, 789, 2, 'B', 'doc', False)],
63 }
64 self.assertEqual(expected, label_rows_dict)
65
66 def SetUpFetchItems(self, keys, rows):
67 self.config_service.labeldef_tbl.Select(
68 self.cnxn, cols=config_svc.LABELDEF_COLS, project_id=keys,
69 order_by=[('rank DESC', []), ('label DESC', [])]).AndReturn(
70 rows)
71
72 def testFetchItems(self):
73 keys = [567, 678, 789]
74 self.SetUpFetchItems(keys, self.rows)
75 self.mox.ReplayAll()
76 label_rows_dict = self.label_row_2lc.FetchItems(self.cnxn, keys)
77 self.mox.VerifyAll()
78 expected = {
79 567: [],
80 678: [(3, 678, 1, 'C', 'doc', True), (4, 678, None, 'D', 'doc', False)],
81 789: [(1, 789, 1, 'A', 'doc', False), (2, 789, 2, 'B', 'doc', False)],
82 }
83 self.assertEqual(expected, label_rows_dict)
84
85
86 class StatusRowTwoLevelCacheTest(unittest.TestCase):
87
88 def setUp(self):
89 self.mox = mox.Mox()
90 self.cnxn = 'fake connection'
91 self.cache_manager = fake.CacheManager()
92 self.config_service = MakeConfigService(self.cache_manager, self.mox)
93 self.status_row_2lc = self.config_service.status_row_2lc
94
95 self.rows = [(1, 789, 1, 'A', True, 'doc', False),
96 (2, 789, 2, 'B', False, 'doc', False),
97 (3, 678, 1, 'C', True, 'doc', True),
98 (4, 678, None, 'D', True, 'doc', False)]
99
100 def tearDown(self):
101 self.mox.UnsetStubs()
102 self.mox.ResetAll()
103
104 def testDeserializeStatusRows_Empty(self):
105 status_row_dict = self.status_row_2lc._DeserializeStatusRows([])
106 self.assertEqual({}, status_row_dict)
107
108 def testDeserializeStatusRows_Normal(self):
109 status_rows_dict = self.status_row_2lc._DeserializeStatusRows(self.rows)
110 expected = {
111 678: [(3, 678, 1, 'C', True, 'doc', True),
112 (4, 678, None, 'D', True, 'doc', False)],
113 789: [(1, 789, 1, 'A', True, 'doc', False),
114 (2, 789, 2, 'B', False, 'doc', False)],
115 }
116 self.assertEqual(expected, status_rows_dict)
117
118 def SetUpFetchItems(self, keys, rows):
119 self.config_service.statusdef_tbl.Select(
120 self.cnxn, cols=config_svc.STATUSDEF_COLS, project_id=keys,
121 order_by=[('rank DESC', []), ('status DESC', [])]).AndReturn(
122 rows)
123
124 def testFetchItems(self):
125 keys = [567, 678, 789]
126 self.SetUpFetchItems(keys, self.rows)
127 self.mox.ReplayAll()
128 status_rows_dict = self.status_row_2lc.FetchItems(self.cnxn, keys)
129 self.mox.VerifyAll()
130 expected = {
131 567: [],
132 678: [(3, 678, 1, 'C', True, 'doc', True),
133 (4, 678, None, 'D', True, 'doc', False)],
134 789: [(1, 789, 1, 'A', True, 'doc', False),
135 (2, 789, 2, 'B', False, 'doc', False)],
136 }
137 self.assertEqual(expected, status_rows_dict)
138
139
140 class ConfigRowTwoLevelCacheTest(unittest.TestCase):
141
142 def setUp(self):
143 self.mox = mox.Mox()
144 self.cnxn = 'fake connection'
145 self.cache_manager = fake.CacheManager()
146 self.config_service = MakeConfigService(self.cache_manager, self.mox)
147 self.config_2lc = self.config_service.config_2lc
148
149 self.config_rows = [(789, 'Duplicate', 'Pri Type', 1, 2, 'Type Pri Summary',
150 '-Pri', 'Mstone', 'Owner', None)]
151 self.template_rows = []
152 self.template2label_rows = []
153 self.template2component_rows = []
154 self.template2admin_rows = []
155 self.template2fieldvalue_rows = []
156 self.statusdef_rows = [(1, 789, 1, 'New', True, 'doc', False),
157 (2, 789, 2, 'Fixed', False, 'doc', False)]
158 self.labeldef_rows = [(1, 789, 1, 'Security', 'doc', False),
159 (2, 789, 2, 'UX', 'doc', False)]
160 self.fielddef_rows = [(1, 789, None, 'Field', 'INT_TYPE',
161 'Defect', '', False, False,
162 1, 99, None, '', '',
163 None, 'NEVER', 'doc', False)]
164 self.fielddef2admin_rows = []
165 self.componentdef_rows = []
166 self.component2admin_rows = []
167 self.component2cc_rows = []
168
169 def tearDown(self):
170 self.mox.UnsetStubs()
171 self.mox.ResetAll()
172
173 def testDeserializeIssueConfigs_Empty(self):
174 config_dict = self.config_2lc._DeserializeIssueConfigs(
175 [], [], [], [], [], [], [], [], [], [], [], [], [])
176 self.assertEqual({}, config_dict)
177
178 def testDeserializeIssueConfigs_Normal(self):
179 config_dict = self.config_2lc._DeserializeIssueConfigs(
180 self.config_rows, self.template_rows, self.template2label_rows,
181 self.template2component_rows, self.template2admin_rows,
182 self.template2fieldvalue_rows, self.statusdef_rows, self.labeldef_rows,
183 self.fielddef_rows, self.fielddef2admin_rows, self.componentdef_rows,
184 self.component2admin_rows, self.component2cc_rows)
185 self.assertItemsEqual([789], config_dict.keys())
186 config = config_dict[789]
187 self.assertEqual(789, config.project_id)
188 self.assertEqual(['Duplicate'], config.statuses_offer_merge)
189 self.assertEqual([], config.templates)
190 self.assertEqual(len(self.labeldef_rows), len(config.well_known_labels))
191 self.assertEqual(len(self.statusdef_rows), len(config.well_known_statuses))
192 self.assertEqual(len(self.fielddef_rows), len(config.field_defs))
193 self.assertEqual(len(self.componentdef_rows), len(config.component_defs))
194
195 def SetUpFetchConfigs(self, project_ids):
196 self.config_service.projectissueconfig_tbl.Select(
197 self.cnxn, cols=config_svc.PROJECTISSUECONFIG_COLS,
198 project_id=project_ids).AndReturn(self.config_rows)
199 self.config_service.template_tbl.Select(
200 self.cnxn, cols=config_svc.TEMPLATE_COLS, project_id=project_ids,
201 order_by=[('name', [])]).AndReturn(self.template_rows)
202 template_ids = [row[0] for row in self.template_rows]
203 self.config_service.template2label_tbl.Select(
204 self.cnxn, cols=config_svc.TEMPLATE2LABEL_COLS,
205 template_id=template_ids).AndReturn(self.template2label_rows)
206 self.config_service.template2component_tbl.Select(
207 self.cnxn, cols=config_svc.TEMPLATE2COMPONENT_COLS,
208 template_id=template_ids).AndReturn(self.template2component_rows)
209 self.config_service.template2admin_tbl.Select(
210 self.cnxn, cols=config_svc.TEMPLATE2ADMIN_COLS,
211 template_id=template_ids).AndReturn(self.template2admin_rows)
212 self.config_service.template2fieldvalue_tbl.Select(
213 self.cnxn, cols=config_svc.TEMPLATE2FIELDVALUE_COLS,
214 template_id=template_ids).AndReturn(self.template2fieldvalue_rows)
215 self.config_service.statusdef_tbl.Select(
216 self.cnxn, cols=config_svc.STATUSDEF_COLS, project_id=project_ids,
217 where=[('rank IS NOT NULL', [])], order_by=[('rank', [])]).AndReturn(
218 self.statusdef_rows)
219 self.config_service.labeldef_tbl.Select(
220 self.cnxn, cols=config_svc.LABELDEF_COLS, project_id=project_ids,
221 where=[('rank IS NOT NULL', [])], order_by=[('rank', [])]).AndReturn(
222 self.labeldef_rows)
223 self.config_service.fielddef_tbl.Select(
224 self.cnxn, cols=config_svc.FIELDDEF_COLS, project_id=project_ids,
225 order_by=[('field_name', [])]).AndReturn(self.fielddef_rows)
226 field_ids = [row[0] for row in self.fielddef_rows]
227 self.config_service.fielddef2admin_tbl.Select(
228 self.cnxn, cols=config_svc.FIELDDEF2ADMIN_COLS,
229 field_id=field_ids).AndReturn(self.fielddef2admin_rows)
230 self.config_service.componentdef_tbl.Select(
231 self.cnxn, cols=config_svc.COMPONENTDEF_COLS, project_id=project_ids,
232 order_by=[('LOWER(path)', [])]).AndReturn(self.componentdef_rows)
233 component_ids = [cd_row[0] for cd_row in self.componentdef_rows]
234 self.config_service.component2admin_tbl.Select(
235 self.cnxn, cols=config_svc.COMPONENT2ADMIN_COLS,
236 component_id=component_ids).AndReturn(self.component2admin_rows)
237 self.config_service.component2cc_tbl.Select(
238 self.cnxn, cols=config_svc.COMPONENT2CC_COLS,
239 component_id=component_ids).AndReturn(self.component2cc_rows)
240
241 def testFetchConfigs(self):
242 keys = [789]
243 self.SetUpFetchConfigs(keys)
244 self.mox.ReplayAll()
245 config_dict = self.config_2lc._FetchConfigs(self.cnxn, keys)
246 self.mox.VerifyAll()
247 self.assertItemsEqual(keys, config_dict.keys())
248
249 def testFetchItems(self):
250 keys = [678, 789]
251 self.SetUpFetchConfigs(keys)
252 self.mox.ReplayAll()
253 config_dict = self.config_2lc.FetchItems(self.cnxn, keys)
254 self.mox.VerifyAll()
255 self.assertItemsEqual(keys, config_dict.keys())
256
257
258 class ConfigServiceTest(unittest.TestCase):
259
260 def setUp(self):
261 self.testbed = testbed.Testbed()
262 self.testbed.activate()
263 self.testbed.init_memcache_stub()
264
265 self.mox = mox.Mox()
266 self.cnxn = self.mox.CreateMock(sql.MonorailConnection)
267 self.cache_manager = fake.CacheManager()
268 self.config_service = MakeConfigService(self.cache_manager, self.mox)
269
270 def tearDown(self):
271 self.testbed.deactivate()
272 self.mox.UnsetStubs()
273 self.mox.ResetAll()
274
275 ### Label lookups
276
277 def testGetLabelDefRows(self):
278 rows = 'foo'
279 self.config_service.label_row_2lc.CacheItem(
280 789, rows)
281 actual = self.config_service.GetLabelDefRows(self.cnxn, 789)
282 self.assertEqual(rows, actual)
283
284 def SetUpGetLabelDefRowsAnyProject(self, rows):
285 self.config_service.labeldef_tbl.Select(
286 self.cnxn, cols=config_svc.LABELDEF_COLS, where=None,
287 order_by=[('rank DESC', []), ('label DESC', [])]).AndReturn(
288 rows)
289
290 def testGetLabelDefRowsAnyProject(self):
291 rows = 'foo'
292 self.SetUpGetLabelDefRowsAnyProject(rows)
293 self.mox.ReplayAll()
294 actual = self.config_service.GetLabelDefRowsAnyProject(self.cnxn)
295 self.mox.VerifyAll()
296 self.assertEqual(rows, actual)
297
298 def testDeserializeLabels(self):
299 labeldef_rows = [(1, 789, 1, 'Security', 'doc', False),
300 (2, 789, 2, 'UX', 'doc', True)]
301 id_to_name, name_to_id = self.config_service._DeserializeLabels(
302 labeldef_rows)
303 self.assertEqual({1: 'Security', 2: 'UX'}, id_to_name)
304 self.assertEqual({'security': 1, 'ux': 2}, name_to_id)
305
306 def testEnsureLabelCacheEntry_Hit(self):
307 label_dicts = 'foo'
308 self.config_service.label_cache.CacheItem(789, label_dicts)
309 # No mock calls set up because none are needed.
310 self.mox.ReplayAll()
311 self.config_service._EnsureLabelCacheEntry(self.cnxn, 789)
312 self.mox.VerifyAll()
313
314 def SetUpEnsureLabelCacheEntry_Miss(self, keys, rows):
315 self.config_service.labeldef_tbl.Select(
316 self.cnxn, cols=config_svc.LABELDEF_COLS, project_id=keys,
317 order_by=[('rank DESC', []), ('label DESC', [])]).AndReturn(
318 rows)
319
320 def testEnsureLabelCacheEntry_Miss(self):
321 labeldef_rows = [(1, 789, 1, 'Security', 'doc', False),
322 (2, 789, 2, 'UX', 'doc', True)]
323 self.SetUpEnsureLabelCacheEntry_Miss([789], labeldef_rows)
324 self.mox.ReplayAll()
325 self.config_service._EnsureLabelCacheEntry(self.cnxn, 789)
326 self.mox.VerifyAll()
327 label_dicts = {1: 'Security', 2: 'UX'}, {'security': 1, 'ux': 2}
328 self.assertEqual(label_dicts, self.config_service.label_cache.GetItem(789))
329
330 def testLookupLabel_Hit(self):
331 label_dicts = {1: 'Security', 2: 'UX'}, {'security': 1, 'ux': 2}
332 self.config_service.label_cache.CacheItem(789, label_dicts)
333 # No mock calls set up because none are needed.
334 self.mox.ReplayAll()
335 self.assertEqual(
336 'Security', self.config_service.LookupLabel(self.cnxn, 789, 1))
337 self.assertEqual(
338 'UX', self.config_service.LookupLabel(self.cnxn, 789, 2))
339 self.mox.VerifyAll()
340
341 def testLookupLabelID_Hit(self):
342 label_dicts = {1: 'Security', 2: 'UX'}, {'security': 1, 'ux': 2}
343 self.config_service.label_cache.CacheItem(789, label_dicts)
344 # No mock calls set up because none are needed.
345 self.mox.ReplayAll()
346 self.assertEqual(
347 1, self.config_service.LookupLabelID(self.cnxn, 789, 'Security'))
348 self.assertEqual(
349 2, self.config_service.LookupLabelID(self.cnxn, 789, 'UX'))
350 self.mox.VerifyAll()
351
352 def testLookupLabelIDs_Hit(self):
353 label_dicts = {1: 'Security', 2: 'UX'}, {'security': 1, 'ux': 2}
354 self.config_service.label_cache.CacheItem(789, label_dicts)
355 # No mock calls set up because none are needed.
356 self.mox.ReplayAll()
357 self.assertEqual(
358 [1, 2],
359 self.config_service.LookupLabelIDs(self.cnxn, 789, ['Security', 'UX']))
360 self.mox.VerifyAll()
361
362 def testLookupIDsOfLabelsMatching_Hit(self):
363 label_dicts = {1: 'Security', 2: 'UX'}, {'security': 1, 'ux': 2}
364 self.config_service.label_cache.CacheItem(789, label_dicts)
365 # No mock calls set up because none are needed.
366 self.mox.ReplayAll()
367 self.assertItemsEqual(
368 [1],
369 self.config_service.LookupIDsOfLabelsMatching(
370 self.cnxn, 789, re.compile('Sec.*')))
371 self.assertItemsEqual(
372 [1, 2],
373 self.config_service.LookupIDsOfLabelsMatching(
374 self.cnxn, 789, re.compile('.*')))
375 self.assertItemsEqual(
376 [],
377 self.config_service.LookupIDsOfLabelsMatching(
378 self.cnxn, 789, re.compile('Zzzzz.*')))
379 self.mox.VerifyAll()
380
381 def SetUpLookupLabelIDsAnyProject(self, label, id_rows):
382 self.config_service.labeldef_tbl.Select(
383 self.cnxn, cols=['id'], label=label).AndReturn(id_rows)
384
385 def testLookupLabelIDsAnyProject(self):
386 self.SetUpLookupLabelIDsAnyProject('Security', [(1,)])
387 self.mox.ReplayAll()
388 actual = self.config_service.LookupLabelIDsAnyProject(
389 self.cnxn, 'Security')
390 self.mox.VerifyAll()
391 self.assertEqual([1], actual)
392
393 def SetUpLookupIDsOfLabelsMatchingAnyProject(self, id_label_rows):
394 self.config_service.labeldef_tbl.Select(
395 self.cnxn, cols=['id', 'label']).AndReturn(id_label_rows)
396
397 def testLookupIDsOfLabelsMatchingAnyProject(self):
398 id_label_rows = [(1, 'Security'), (2, 'UX')]
399 self.SetUpLookupIDsOfLabelsMatchingAnyProject(id_label_rows)
400 self.mox.ReplayAll()
401 actual = self.config_service.LookupIDsOfLabelsMatchingAnyProject(
402 self.cnxn, re.compile('(Sec|Zzz).*'))
403 self.mox.VerifyAll()
404 self.assertEqual([1], actual)
405
406 ### Status lookups
407
408 def testGetStatusDefRows(self):
409 rows = 'foo'
410 self.config_service.status_row_2lc.CacheItem(789, rows)
411 actual = self.config_service.GetStatusDefRows(self.cnxn, 789)
412 self.assertEqual(rows, actual)
413
414 def SetUpGetStatusDefRowsAnyProject(self, rows):
415 self.config_service.statusdef_tbl.Select(
416 self.cnxn, cols=config_svc.STATUSDEF_COLS,
417 order_by=[('rank DESC', []), ('status DESC', [])]).AndReturn(
418 rows)
419
420 def testGetStatusDefRowsAnyProject(self):
421 rows = 'foo'
422 self.SetUpGetStatusDefRowsAnyProject(rows)
423 self.mox.ReplayAll()
424 actual = self.config_service.GetStatusDefRowsAnyProject(self.cnxn)
425 self.mox.VerifyAll()
426 self.assertEqual(rows, actual)
427
428 def testDeserializeStatuses(self):
429 statusdef_rows = [(1, 789, 1, 'New', True, 'doc', False),
430 (2, 789, 2, 'Fixed', False, 'doc', True)]
431 actual = self.config_service._DeserializeStatuses(statusdef_rows)
432 id_to_name, name_to_id, closed_ids = actual
433 self.assertEqual({1: 'New', 2: 'Fixed'}, id_to_name)
434 self.assertEqual({'new': 1, 'fixed': 2}, name_to_id)
435 self.assertEqual([2], closed_ids)
436
437 def testEnsureStatusCacheEntry_Hit(self):
438 status_dicts = 'foo'
439 self.config_service.status_cache.CacheItem(789, status_dicts)
440 # No mock calls set up because none are needed.
441 self.mox.ReplayAll()
442 self.config_service._EnsureStatusCacheEntry(self.cnxn, 789)
443 self.mox.VerifyAll()
444
445 def SetUpEnsureStatusCacheEntry_Miss(self, keys, rows):
446 self.config_service.statusdef_tbl.Select(
447 self.cnxn, cols=config_svc.STATUSDEF_COLS, project_id=keys,
448 order_by=[('rank DESC', []), ('status DESC', [])]).AndReturn(
449 rows)
450
451 def testEnsureStatusCacheEntry_Miss(self):
452 statusdef_rows = [(1, 789, 1, 'New', True, 'doc', False),
453 (2, 789, 2, 'Fixed', False, 'doc', True)]
454 self.SetUpEnsureStatusCacheEntry_Miss([789], statusdef_rows)
455 self.mox.ReplayAll()
456 self.config_service._EnsureStatusCacheEntry(self.cnxn, 789)
457 self.mox.VerifyAll()
458 status_dicts = {1: 'New', 2: 'Fixed'}, {'new': 1, 'fixed': 2}, [2]
459 self.assertEqual(
460 status_dicts, self.config_service.status_cache.GetItem(789))
461
462 def testLookupStatus_Hit(self):
463 status_dicts = {1: 'New', 2: 'Fixed'}, {'new': 1, 'fixed': 2}, [2]
464 self.config_service.status_cache.CacheItem(789, status_dicts)
465 # No mock calls set up because none are needed.
466 self.mox.ReplayAll()
467 self.assertEqual(
468 'New', self.config_service.LookupStatus(self.cnxn, 789, 1))
469 self.assertEqual(
470 'Fixed', self.config_service.LookupStatus(self.cnxn, 789, 2))
471 self.mox.VerifyAll()
472
473 def testLookupStatusID_Hit(self):
474 status_dicts = {1: 'New', 2: 'Fixed'}, {'new': 1, 'fixed': 2}, [2]
475 self.config_service.status_cache.CacheItem(789, status_dicts)
476 # No mock calls set up because none are needed.
477 self.mox.ReplayAll()
478 self.assertEqual(
479 1, self.config_service.LookupStatusID(self.cnxn, 789, 'New'))
480 self.assertEqual(
481 2, self.config_service.LookupStatusID(self.cnxn, 789, 'Fixed'))
482 self.mox.VerifyAll()
483
484 def testLookupStatusIDs_Hit(self):
485 status_dicts = {1: 'New', 2: 'Fixed'}, {'new': 1, 'fixed': 2}, [2]
486 self.config_service.status_cache.CacheItem(789, status_dicts)
487 # No mock calls set up because none are needed.
488 self.mox.ReplayAll()
489 self.assertEqual(
490 [1, 2],
491 self.config_service.LookupStatusIDs(self.cnxn, 789, ['New', 'Fixed']))
492 self.mox.VerifyAll()
493
494 def testLookupClosedStatusIDs_Hit(self):
495 status_dicts = {1: 'New', 2: 'Fixed'}, {'new': 1, 'fixed': 2}, [2]
496 self.config_service.status_cache.CacheItem(789, status_dicts)
497 # No mock calls set up because none are needed.
498 self.mox.ReplayAll()
499 self.assertEqual(
500 [2],
501 self.config_service.LookupClosedStatusIDs(self.cnxn, 789))
502 self.mox.VerifyAll()
503
504 def SetUpLookupClosedStatusIDsAnyProject(self, id_rows):
505 self.config_service.statusdef_tbl.Select(
506 self.cnxn, cols=['id'], means_open=False).AndReturn(
507 id_rows)
508
509 def testLookupClosedStatusIDsAnyProject(self):
510 self.SetUpLookupClosedStatusIDsAnyProject([(2,)])
511 self.mox.ReplayAll()
512 actual = self.config_service.LookupClosedStatusIDsAnyProject(self.cnxn)
513 self.mox.VerifyAll()
514 self.assertEqual([2], actual)
515
516 def SetUpLookupStatusIDsAnyProject(self, status, id_rows):
517 self.config_service.statusdef_tbl.Select(
518 self.cnxn, cols=['id'], status=status).AndReturn(id_rows)
519
520 def testLookupStatusIDsAnyProject(self):
521 self.SetUpLookupStatusIDsAnyProject('New', [(1,)])
522 self.mox.ReplayAll()
523 actual = self.config_service.LookupStatusIDsAnyProject(self.cnxn, 'New')
524 self.mox.VerifyAll()
525 self.assertEqual([1], actual)
526
527 ### Issue tracker configuration objects
528
529 def SetUpGetProjectConfigs(self, project_ids):
530 self.config_service.projectissueconfig_tbl.Select(
531 self.cnxn, cols=config_svc.PROJECTISSUECONFIG_COLS,
532 project_id=project_ids).AndReturn([])
533 self.config_service.template_tbl.Select(
534 self.cnxn, cols=config_svc.TEMPLATE_COLS,
535 project_id=project_ids, order_by=[('name', [])]).AndReturn([])
536 self.config_service.template2label_tbl.Select(
537 self.cnxn, cols=config_svc.TEMPLATE2LABEL_COLS,
538 template_id=[]).AndReturn([])
539 self.config_service.template2component_tbl.Select(
540 self.cnxn, cols=config_svc.TEMPLATE2COMPONENT_COLS,
541 template_id=[]).AndReturn([])
542 self.config_service.template2admin_tbl.Select(
543 self.cnxn, cols=config_svc.TEMPLATE2ADMIN_COLS,
544 template_id=[]).AndReturn([])
545 self.config_service.template2fieldvalue_tbl.Select(
546 self.cnxn, cols=config_svc.TEMPLATE2FIELDVALUE_COLS,
547 template_id=[]).AndReturn([])
548 self.config_service.statusdef_tbl.Select(
549 self.cnxn, cols=config_svc.STATUSDEF_COLS,
550 project_id=project_ids, where=[('rank IS NOT NULL', [])],
551 order_by=[('rank', [])]).AndReturn([])
552 self.config_service.labeldef_tbl.Select(
553 self.cnxn, cols=config_svc.LABELDEF_COLS,
554 project_id=project_ids, where=[('rank IS NOT NULL', [])],
555 order_by=[('rank', [])]).AndReturn([])
556 self.config_service.fielddef_tbl.Select(
557 self.cnxn, cols=config_svc.FIELDDEF_COLS,
558 project_id=project_ids, order_by=[('field_name', [])]).AndReturn([])
559 self.config_service.fielddef2admin_tbl.Select(
560 self.cnxn, cols=config_svc.FIELDDEF2ADMIN_COLS,
561 field_id=[]).AndReturn([])
562 self.config_service.componentdef_tbl.Select(
563 self.cnxn, cols=config_svc.COMPONENTDEF_COLS,
564 project_id=project_ids, order_by=[('LOWER(path)', [])]).AndReturn([])
565 self.config_service.component2admin_tbl.Select(
566 self.cnxn, cols=config_svc.COMPONENT2ADMIN_COLS,
567 component_id=[]).AndReturn([])
568 self.config_service.component2cc_tbl.Select(
569 self.cnxn, cols=config_svc.COMPONENT2CC_COLS,
570 component_id=[]).AndReturn([])
571
572 def testGetProjectConfigs(self):
573 project_ids = [789, 679]
574 self.SetUpGetProjectConfigs(project_ids)
575
576 self.mox.ReplayAll()
577 config_dict = self.config_service.GetProjectConfigs(
578 self.cnxn, [789, 679], use_cache=False)
579 self.assertEqual(2, len(config_dict))
580 for pid in project_ids:
581 self.assertEqual(pid, config_dict[pid].project_id)
582 self.mox.VerifyAll()
583
584 def testGetProjectConfig_Hit(self):
585 project_id = 789
586 config = tracker_bizobj.MakeDefaultProjectIssueConfig(project_id)
587 self.config_service.config_2lc.CacheItem(project_id, config)
588
589 self.mox.ReplayAll()
590 actual = self.config_service.GetProjectConfig(self.cnxn, project_id)
591 self.assertEqual(config, actual)
592 self.mox.VerifyAll()
593
594 def testGetProjectConfig_Miss(self):
595 project_id = 789
596 self.SetUpGetProjectConfigs([project_id])
597
598 self.mox.ReplayAll()
599 config = self.config_service.GetProjectConfig(self.cnxn, project_id)
600 self.assertEqual(project_id, config.project_id)
601 self.mox.VerifyAll()
602
603 def SetUpStoreConfig_Default(self, project_id):
604 self.config_service.projectissueconfig_tbl.InsertRow(
605 self.cnxn, replace=True,
606 project_id=project_id,
607 statuses_offer_merge='Duplicate',
608 exclusive_label_prefixes='Type Priority Milestone',
609 default_template_for_developers=0,
610 default_template_for_users=0,
611 default_col_spec=tracker_constants.DEFAULT_COL_SPEC,
612 default_sort_spec='',
613 default_x_attr='',
614 default_y_attr='',
615 custom_issue_entry_url=None,
616 commit=False)
617
618 self.SetUpUpdateTemplates_Default(project_id)
619 self.SetUpUpdateWellKnownLabels_Default(project_id)
620 self.SetUpUpdateWellKnownStatuses_Default(project_id)
621 self.cnxn.Commit()
622
623 def SetUpUpdateTemplates_Default(self, project_id):
624 self.config_service.template_tbl.Select(
625 self.cnxn, cols=['id'], project_id=project_id).AndReturn([])
626 self.config_service.template2label_tbl.Delete(
627 self.cnxn, template_id=[], commit=False)
628 self.config_service.template2component_tbl.Delete(
629 self.cnxn, template_id=[], commit=False)
630 self.config_service.template2admin_tbl.Delete(
631 self.cnxn, template_id=[], commit=False)
632 self.config_service.template2fieldvalue_tbl.Delete(
633 self.cnxn, template_id=[], commit=False)
634 self.config_service.template_tbl.Delete(
635 self.cnxn, project_id=project_id, commit=False)
636
637 template_rows = []
638 for template_dict in tracker_constants.DEFAULT_TEMPLATES:
639 row = (None,
640 project_id,
641 template_dict['name'],
642 template_dict['content'],
643 template_dict['summary'],
644 template_dict.get('summary_must_be_edited'),
645 None,
646 template_dict['status'],
647 template_dict.get('members_only', False),
648 template_dict.get('owner_defaults_to_member', True),
649 template_dict.get('component_required', False))
650 template_rows.append(row)
651
652 self.config_service.template_tbl.InsertRows(
653 self.cnxn, config_svc.TEMPLATE_COLS, template_rows,
654 replace=True, commit=False, return_generated_ids=True).AndReturn(
655 range(1, len(template_rows) + 1))
656
657 template2label_rows = [
658 (2, 'Type-Defect'),
659 (2, 'Priority-Medium'),
660 (1, 'Type-Defect'),
661 (1, 'Priority-Medium'),
662 ]
663 template2component_rows = []
664 template2admin_rows = []
665 template2fieldvalue_rows = []
666
667 self.config_service.template2label_tbl.InsertRows(
668 self.cnxn, config_svc.TEMPLATE2LABEL_COLS, template2label_rows,
669 ignore=True, commit=False)
670 self.config_service.template2component_tbl.InsertRows(
671 self.cnxn, config_svc.TEMPLATE2COMPONENT_COLS, template2component_rows,
672 commit=False)
673 self.config_service.template2admin_tbl.InsertRows(
674 self.cnxn, config_svc.TEMPLATE2ADMIN_COLS, template2admin_rows,
675 commit=False)
676 self.config_service.template2fieldvalue_tbl.InsertRows(
677 self.cnxn, config_svc.TEMPLATE2FIELDVALUE_COLS,
678 template2fieldvalue_rows, commit=False)
679
680 def SetUpUpdateWellKnownLabels_Default(self, project_id):
681 by_id = {
682 idx + 1: label for idx, (label, _, _) in enumerate(
683 tracker_constants.DEFAULT_WELL_KNOWN_LABELS)}
684 by_name = {name.lower(): label_id
685 for label_id, name in by_id.iteritems()}
686 label_dicts = by_id, by_name
687 self.config_service.label_cache.CacheAll({789: label_dicts})
688
689 update_labeldef_rows = [
690 (idx + 1, project_id, idx, label, doc, deprecated)
691 for idx, (label, doc, deprecated) in enumerate(
692 tracker_constants.DEFAULT_WELL_KNOWN_LABELS)]
693 self.config_service.labeldef_tbl.Update(
694 self.cnxn, {'rank': None}, project_id=project_id, commit=False)
695 self.config_service.labeldef_tbl.InsertRows(
696 self.cnxn, config_svc.LABELDEF_COLS, update_labeldef_rows,
697 replace=True, commit=False)
698 self.config_service.labeldef_tbl.InsertRows(
699 self.cnxn, config_svc.LABELDEF_COLS[1:], [], commit=False)
700
701 def SetUpUpdateWellKnownStatuses_Default(self, project_id):
702 by_id = {
703 idx + 1: status for idx, (status, _, _, _) in enumerate(
704 tracker_constants.DEFAULT_WELL_KNOWN_STATUSES)}
705 by_name = {name.lower(): label_id
706 for label_id, name in by_id.iteritems()}
707 closed_ids = [
708 idx + 1 for idx, (_, _, means_open, _) in enumerate(
709 tracker_constants.DEFAULT_WELL_KNOWN_STATUSES)
710 if not means_open]
711 status_dicts = by_id, by_name, closed_ids
712 self.config_service.status_cache.CacheAll({789: status_dicts})
713
714 update_statusdef_rows = [
715 (idx + 1, project_id, idx, status, means_open, doc, deprecated)
716 for idx, (status, doc, means_open, deprecated) in enumerate(
717 tracker_constants.DEFAULT_WELL_KNOWN_STATUSES)]
718 self.config_service.statusdef_tbl.Update(
719 self.cnxn, {'rank': None}, project_id=project_id, commit=False)
720 self.config_service.statusdef_tbl.InsertRows(
721 self.cnxn, config_svc.STATUSDEF_COLS, update_statusdef_rows,
722 replace=True, commit=False)
723 self.config_service.statusdef_tbl.InsertRows(
724 self.cnxn, config_svc.STATUSDEF_COLS[1:], [], commit=False)
725
726 def testStoreConfig(self):
727 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
728 self.SetUpStoreConfig_Default(789)
729
730 self.mox.ReplayAll()
731 self.config_service.StoreConfig(self.cnxn, config)
732 self.mox.VerifyAll()
733
734 def testUpdateTemplates(self):
735 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
736 self.SetUpUpdateTemplates_Default(789)
737
738 self.mox.ReplayAll()
739 self.config_service._UpdateTemplates(self.cnxn, config)
740 self.mox.VerifyAll()
741
742 def testUpdateWellKnownLabels(self):
743 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
744 self.SetUpUpdateWellKnownLabels_Default(789)
745
746 self.mox.ReplayAll()
747 self.config_service._UpdateWellKnownLabels(self.cnxn, config)
748 self.mox.VerifyAll()
749
750 def testUpdateWellKnownStatuses(self):
751 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
752 self.SetUpUpdateWellKnownStatuses_Default(789)
753
754 self.mox.ReplayAll()
755 self.config_service._UpdateWellKnownStatuses(self.cnxn, config)
756 self.mox.VerifyAll()
757
758 def testUpdateConfig(self):
759 pass # TODO(jrobbins): add a test for this
760
761 def SetUpExpungeConfig(self, project_id):
762 self.config_service.template_tbl.Select(
763 self.cnxn, cols=['id'], project_id=project_id).AndReturn([])
764 self.config_service.template2label_tbl.Delete(self.cnxn, template_id=[])
765 self.config_service.template2component_tbl.Delete(self.cnxn, template_id=[])
766 self.config_service.template_tbl.Delete(self.cnxn, project_id=project_id)
767 self.config_service.statusdef_tbl.Delete(self.cnxn, project_id=project_id)
768 self.config_service.labeldef_tbl.Delete(self.cnxn, project_id=project_id)
769 self.config_service.projectissueconfig_tbl.Delete(
770 self.cnxn, project_id=project_id)
771
772 self.config_service.config_2lc.InvalidateKeys(self.cnxn, [project_id])
773
774 def testExpungeConfig(self):
775 self.SetUpExpungeConfig(789)
776
777 self.mox.ReplayAll()
778 self.config_service.ExpungeConfig(self.cnxn, 789)
779 self.mox.VerifyAll()
780
781 ### Custom field definitions
782
783 def SetUpCreateFieldDef(self, project_id):
784 self.config_service.fielddef_tbl.InsertRow(
785 self.cnxn, project_id=project_id,
786 field_name='PercentDone', field_type='int_type',
787 applicable_type='Defect', applicable_predicate='',
788 is_required=False, is_multivalued=False,
789 min_value=1, max_value=100, regex=None,
790 needs_member=None, needs_perm=None,
791 grants_perm=None, notify_on='never',
792 docstring='doc', commit=False).AndReturn(1)
793 self.config_service.fielddef2admin_tbl.InsertRows(
794 self.cnxn, config_svc.FIELDDEF2ADMIN_COLS, [], commit=False)
795 self.cnxn.Commit()
796
797 def testCreateFieldDef(self):
798 self.SetUpCreateFieldDef(789)
799
800 self.mox.ReplayAll()
801 field_id = self.config_service.CreateFieldDef(
802 self.cnxn, 789, 'PercentDone', 'int_type', 'Defect', '', False, False,
803 1, 100, None, None, None, None, 0, 'doc', [])
804 self.mox.VerifyAll()
805 self.assertEqual(1, field_id)
806
807 def SetUpSoftDeleteFieldDef(self, field_id):
808 self.config_service.fielddef_tbl.Update(
809 self.cnxn, {'is_deleted': True}, id=field_id)
810
811 def testSoftDeleteFieldDef(self):
812 self.SetUpSoftDeleteFieldDef(1)
813
814 self.mox.ReplayAll()
815 self.config_service.SoftDeleteFieldDef(self.cnxn, 789, 1)
816 self.mox.VerifyAll()
817
818 def SetUpUpdateFieldDef(self, field_id, new_values):
819 self.config_service.fielddef_tbl.Update(
820 self.cnxn, new_values, id=field_id, commit=False)
821 self.config_service.fielddef2admin_tbl.Delete(
822 self.cnxn, field_id=field_id, commit=False)
823 self.config_service.fielddef2admin_tbl.InsertRows(
824 self.cnxn, config_svc.FIELDDEF2ADMIN_COLS, [], commit=False)
825 self.cnxn.Commit()
826
827 def testUpdateFieldDef_NoOp(self):
828 new_values = {}
829 self.SetUpUpdateFieldDef(1, new_values)
830
831 self.mox.ReplayAll()
832 self.config_service.UpdateFieldDef(self.cnxn, 789, 1, admin_ids=[])
833 self.mox.VerifyAll()
834
835 def testUpdateFieldDef_Normal(self):
836 new_values = dict(
837 field_name='newname', applicable_type='defect',
838 applicable_predicate='pri:1', is_required=True,
839 is_multivalued=True, min_value=32, max_value=212, regex='a.*b',
840 needs_member=True, needs_perm='EditIssue', grants_perm='DeleteIssue',
841 notify_on='any_comment', docstring='new doc')
842 self.SetUpUpdateFieldDef(1, new_values)
843
844 self.mox.ReplayAll()
845 new_values = new_values.copy()
846 new_values['notify_on'] = 1
847 self.config_service.UpdateFieldDef(
848 self.cnxn, 789, 1, admin_ids=[], **new_values)
849 self.mox.VerifyAll()
850
851 ### Component definitions
852
853 def SetUpFindMatchingComponentIDsAnyProject(self, _exact, rows):
854 # TODO(jrobbins): more details here.
855 self.config_service.componentdef_tbl.Select(
856 self.cnxn, cols=['id'], where=mox.IsA(list)).AndReturn(rows)
857
858 def testFindMatchingComponentIDsAnyProject_Rooted(self):
859 self.SetUpFindMatchingComponentIDsAnyProject(True, [(1,), (2,), (3,)])
860
861 self.mox.ReplayAll()
862 comp_ids = self.config_service.FindMatchingComponentIDsAnyProject(
863 self.cnxn, ['WindowManager', 'NetworkLayer'])
864 self.mox.VerifyAll()
865 self.assertItemsEqual([1, 2, 3], comp_ids)
866
867 def testFindMatchingComponentIDsAnyProject_NonRooted(self):
868 self.SetUpFindMatchingComponentIDsAnyProject(False, [(1,), (2,), (3,)])
869
870 self.mox.ReplayAll()
871 comp_ids = self.config_service.FindMatchingComponentIDsAnyProject(
872 self.cnxn, ['WindowManager', 'NetworkLayer'], exact=False)
873 self.mox.VerifyAll()
874 self.assertItemsEqual([1, 2, 3], comp_ids)
875
876 def SetUpCreateComponentDef(self, comp_id):
877 self.config_service.componentdef_tbl.InsertRow(
878 self.cnxn, project_id=789, path='WindowManager',
879 docstring='doc', deprecated=False, commit=False,
880 created=0, creator_id=0).AndReturn(comp_id)
881 self.config_service.component2admin_tbl.InsertRows(
882 self.cnxn, config_svc.COMPONENT2ADMIN_COLS, [], commit=False)
883 self.config_service.component2cc_tbl.InsertRows(
884 self.cnxn, config_svc.COMPONENT2CC_COLS, [], commit=False)
885 self.cnxn.Commit()
886
887 def testCreateComponentDef(self):
888 self.SetUpCreateComponentDef(1)
889
890 self.mox.ReplayAll()
891 comp_id = self.config_service.CreateComponentDef(
892 self.cnxn, 789, 'WindowManager', 'doc', False, [], [], 0, 0)
893 self.mox.VerifyAll()
894 self.assertEqual(1, comp_id)
895
896 def SetUpUpdateComponentDef(self, component_id):
897 self.config_service.component2admin_tbl.Delete(
898 self.cnxn, component_id=component_id, commit=False)
899 self.config_service.component2admin_tbl.InsertRows(
900 self.cnxn, config_svc.COMPONENT2ADMIN_COLS, [], commit=False)
901 self.config_service.component2cc_tbl.Delete(
902 self.cnxn, component_id=component_id, commit=False)
903 self.config_service.component2cc_tbl.InsertRows(
904 self.cnxn, config_svc.COMPONENT2CC_COLS, [], commit=False)
905
906 self.config_service.componentdef_tbl.Update(
907 self.cnxn,
908 {'path': 'DisplayManager', 'docstring': 'doc', 'deprecated': True},
909 id=component_id, commit=False)
910 self.cnxn.Commit()
911
912 def testUpdateComponentDef(self):
913 self.SetUpUpdateComponentDef(1)
914
915 self.mox.ReplayAll()
916 self.config_service.UpdateComponentDef(
917 self.cnxn, 789, 1, path='DisplayManager', docstring='doc',
918 deprecated=True, admin_ids=[], cc_ids=[])
919 self.mox.VerifyAll()
920
921 def SetUpDeleteComponentDef(self, component_id):
922 self.config_service.component2cc_tbl.Delete(
923 self.cnxn, component_id=component_id, commit=False)
924 self.config_service.component2admin_tbl.Delete(
925 self.cnxn, component_id=component_id, commit=False)
926 self.config_service.componentdef_tbl.Delete(
927 self.cnxn, id=component_id, commit=False)
928 self.cnxn.Commit()
929
930 def testDeleteComponentDef(self):
931 self.SetUpDeleteComponentDef(1)
932
933 self.mox.ReplayAll()
934 self.config_service.DeleteComponentDef(self.cnxn, 789, 1)
935 self.mox.VerifyAll()
936
937 ### Memcache management
938
939 def testInvalidateMemcache(self):
940 pass # TODO(jrobbins): write this
941
942 def testInvalidateMemcacheShards(self):
943 NOW = 1234567
944 memcache.set('789;1', NOW)
945 memcache.set('789;2', NOW - 1000)
946 memcache.set('789;3', NOW - 2000)
947 memcache.set('all;1', NOW)
948 memcache.set('all;2', NOW - 1000)
949 memcache.set('all;3', NOW - 2000)
950
951 # Delete some of them.
952 self.config_service._InvalidateMemcacheShards(
953 [(789, 1), (789, 2), (789,9)])
954
955 self.assertIsNone(memcache.get('789;1'))
956 self.assertIsNone(memcache.get('789;2'))
957 self.assertEqual(NOW - 2000, memcache.get('789;3'))
958 self.assertIsNone(memcache.get('all;1'))
959 self.assertIsNone(memcache.get('all;2'))
960 self.assertEqual(NOW - 2000, memcache.get('all;3'))
961
962 def testInvalidateMemcacheForEntireProject(self):
963 NOW = 1234567
964 memcache.set('789;1', NOW)
965 memcache.set('config:789', 'serialized config')
966 memcache.set('label_rows:789', 'serialized label rows')
967 memcache.set('status_rows:789', 'serialized status rows')
968 memcache.set('field_rows:789', 'serialized field rows')
969 memcache.set('890;1', NOW) # Other projects will not be affected.
970
971 self.config_service.InvalidateMemcacheForEntireProject(789)
972
973 self.assertIsNone(memcache.get('789;1'))
974 self.assertIsNone(memcache.get('config:789'))
975 self.assertIsNone(memcache.get('status_rows:789'))
976 self.assertIsNone(memcache.get('label_rows:789'))
977 self.assertIsNone(memcache.get('field_rows:789'))
978 self.assertEqual(NOW, memcache.get('890;1'))
979
980
981 if __name__ == '__main__':
982 unittest.main()
OLDNEW
« no previous file with comments | « appengine/monorail/services/test/client_config_svc_test.py ('k') | appengine/monorail/services/test/features_svc_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698