VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/core/testgroup.py@ 63694

Last change on this file since 63694 was 62484, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.7 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: testgroup.py 62484 2016-07-22 18:35:33Z vboxsync $
3
4"""
5Test Manager - Test groups management.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2016 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 62484 $"
30
31
32# Standard python imports.
33import unittest;
34
35# Validation Kit imports.
36from testmanager.core.base import ModelDataBase, ModelDataBaseTestCase, ModelLogicBase, TMRowInUse, \
37 TMTooManyRows, TMInvalidData, TMRowNotFound, TMRowAlreadyExists;
38from testmanager.core.testcase import TestCaseData, TestCaseDataEx;
39
40
41class TestGroupMemberData(ModelDataBase):
42 """Representation of a test group member database row."""
43
44 ksParam_idTestGroup = 'TestGroupMember_idTestGroup';
45 ksParam_idTestCase = 'TestGroupMember_idTestCase';
46 ksParam_tsEffective = 'TestGroupMember_tsEffective';
47 ksParam_tsExpire = 'TestGroupMember_tsExpire';
48 ksParam_uidAuthor = 'TestGroupMember_uidAuthor';
49 ksParam_iSchedPriority = 'TestGroupMember_iSchedPriority';
50 ksParam_aidTestCaseArgs = 'TestGroupMember_aidTestCaseArgs';
51
52 kasAllowNullAttributes = ['idTestGroup', 'idTestCase', 'tsEffective', 'tsExpire', 'uidAuthor', 'aidTestCaseArgs' ];
53 kiMin_iSchedPriority = 0;
54 kiMax_iSchedPriority = 31;
55
56 kcDbColumns = 7;
57
58 def __init__(self):
59 ModelDataBase.__init__(self)
60
61 #
62 # Initialize with defaults.
63 # See the database for explanations of each of these fields.
64 #
65 self.idTestGroup = None;
66 self.idTestCase = None;
67 self.tsEffective = None;
68 self.tsExpire = None;
69 self.uidAuthor = None;
70 self.iSchedPriority = 16;
71 self.aidTestCaseArgs = None;
72
73 def initFromDbRow(self, aoRow):
74 """
75 Reinitialize from a SELECT * FROM TestCaseGroupMembers.
76 Return self. Raises exception if no row.
77 """
78 if aoRow is None:
79 raise TMRowNotFound('Test group member not found.')
80
81 self.idTestGroup = aoRow[0];
82 self.idTestCase = aoRow[1];
83 self.tsEffective = aoRow[2];
84 self.tsExpire = aoRow[3];
85 self.uidAuthor = aoRow[4];
86 self.iSchedPriority = aoRow[5];
87 self.aidTestCaseArgs = aoRow[6];
88 return self
89
90
91 def getAttributeParamNullValues(self, sAttr):
92 # Arrays default to [] as NULL currently. That doesn't work for us.
93 if sAttr == 'aidTestCaseArgs':
94 aoNilValues = [None, '-1'];
95 else:
96 aoNilValues = ModelDataBase.getAttributeParamNullValues(self, sAttr);
97 return aoNilValues;
98
99 def _validateAndConvertAttribute(self, sAttr, sParam, oValue, aoNilValues, fAllowNull, oDb):
100 if sAttr != 'aidTestCaseArgs':
101 return ModelDataBase._validateAndConvertAttribute(self, sAttr, sParam, oValue, aoNilValues, fAllowNull, oDb);
102
103 # -1 is a special value, which when present make the whole thing NULL (None).
104 (aidVariations, sError) = self.validateListOfInts(oValue, aoNilValues = aoNilValues, fAllowNull = fAllowNull,
105 iMin = -1, iMax = 0x7ffffffe);
106 if sError is None:
107 if aidVariations is None:
108 pass;
109 elif -1 in aidVariations:
110 aidVariations = None;
111 elif 0 in aidVariations:
112 sError = 'Invalid test case varation ID #0.';
113 else:
114 aidVariations = sorted(aidVariations);
115 return (aidVariations, sError);
116
117
118
119class TestGroupMemberDataEx(TestGroupMemberData):
120 """Extended representation of a test group member."""
121
122 def __init__(self):
123 """Extend parent class"""
124 TestGroupMemberData.__init__(self)
125 self.oTestCase = None; # TestCaseDataEx.
126
127 def initFromDbRowEx(self, aoRow, oDb, tsNow = None):
128 """
129 Reinitialize from a SELECT * FROM TestGroupMembers, TestCases row.
130 Will query the necessary additional data from oDb using tsNow.
131
132 Returns self. Raises exception if no row or database error.
133 """
134 TestGroupMemberData.initFromDbRow(self, aoRow);
135 self.oTestCase = TestCaseDataEx();
136 self.oTestCase.initFromDbRowEx(aoRow[TestGroupMemberData.kcDbColumns:], oDb, tsNow);
137 return self;
138
139 def initFromParams(self, oDisp, fStrict = True):
140 self.oTestCase = None;
141 return TestGroupMemberData.initFromParams(self, oDisp, fStrict);
142
143 def getDataAttributes(self):
144 asAttributes = TestGroupMemberData.getDataAttributes(self);
145 asAttributes.remove('oTestCase');
146 return asAttributes;
147
148 def _validateAndConvertWorker(self, asAllowNullAttributes, oDb, enmValidateFor = ModelDataBase.ksValidateFor_Other):
149 dErrors = TestGroupMemberData._validateAndConvertWorker(self, asAllowNullAttributes, oDb, enmValidateFor);
150 if self.ksParam_idTestCase not in dErrors:
151 self.oTestCase = TestCaseDataEx()
152 try:
153 self.oTestCase.initFromDbWithId(oDb, self.idTestCase);
154 except Exception as oXcpt:
155 self.oTestCase = TestCaseDataEx()
156 dErrors[self.ksParam_idTestCase] = str(oXcpt);
157 return dErrors;
158
159
160class TestGroupMemberData2(TestCaseData):
161 """Special representation of a Test Group Member item"""
162
163 def __init__(self):
164 """Extend parent class"""
165 TestCaseData.__init__(self)
166 self.idTestGroup = None
167 self.aidTestCaseArgs = []
168
169 def initFromDbRowEx(self, aoRow):
170 """
171 Reinitialize from this query:
172
173 SELECT TestCases.*,
174 TestGroupMembers.idTestGroup,
175 TestGroupMembers.aidTestCaseArgs
176 FROM TestCases, TestGroupMembers
177 WHERE TestCases.idTestCase = TestGroupMembers.idTestCase
178
179 Represents complete test group member (test case) info.
180 Returns object of type TestGroupMemberData2. Raises exception if no row.
181 """
182 TestCaseData.initFromDbRow(self, aoRow);
183 self.idTestGroup = aoRow[-2]
184 self.aidTestCaseArgs = aoRow[-1]
185 return self;
186
187
188class TestGroupData(ModelDataBase):
189 """
190 Test group data.
191 """
192
193 ksIdAttr = 'idTestGroup';
194
195 ksParam_idTestGroup = 'TestGroup_idTestGroup'
196 ksParam_tsEffective = 'TestGroup_tsEffective'
197 ksParam_tsExpire = 'TestGroup_tsExpire'
198 ksParam_uidAuthor = 'TestGroup_uidAuthor'
199 ksParam_sName = 'TestGroup_sName'
200 ksParam_sDescription = 'TestGroup_sDescription'
201 ksParam_sComment = 'TestGroup_sComment'
202
203 kasAllowNullAttributes = ['idTestGroup', 'tsEffective', 'tsExpire', 'uidAuthor', 'sDescription', 'sComment' ];
204
205 kcDbColumns = 7;
206
207 def __init__(self):
208 ModelDataBase.__init__(self);
209
210 #
211 # Initialize with defaults.
212 # See the database for explanations of each of these fields.
213 #
214 self.idTestGroup = None
215 self.tsEffective = None
216 self.tsExpire = None
217 self.uidAuthor = None
218 self.sName = None
219 self.sDescription = None
220 self.sComment = None
221
222 def initFromDbRow(self, aoRow):
223 """
224 Reinitialize from a SELECT * FROM TestGroups row.
225 Returns object of type TestGroupData. Raises exception if no row.
226 """
227 if aoRow is None:
228 raise TMRowNotFound('Test group not found.')
229
230 self.idTestGroup = aoRow[0]
231 self.tsEffective = aoRow[1]
232 self.tsExpire = aoRow[2]
233 self.uidAuthor = aoRow[3]
234 self.sName = aoRow[4]
235 self.sDescription = aoRow[5]
236 self.sComment = aoRow[6]
237 return self
238
239 def initFromDbWithId(self, oDb, idTestGroup, tsNow = None, sPeriodBack = None):
240 """
241 Initialize the object from the database.
242 """
243 oDb.execute(self.formatSimpleNowAndPeriodQuery(oDb,
244 'SELECT *\n'
245 'FROM TestGroups\n'
246 'WHERE idTestGroup = %s\n'
247 , ( idTestGroup,), tsNow, sPeriodBack));
248 aoRow = oDb.fetchOne()
249 if aoRow is None:
250 raise TMRowNotFound('idTestGroup=%s not found (tsNow=%s sPeriodBack=%s)' % (idTestGroup, tsNow, sPeriodBack,));
251 return self.initFromDbRow(aoRow);
252
253
254class TestGroupDataEx(TestGroupData):
255 """
256 Extended test group data.
257 """
258
259 ksParam_aoMembers = 'TestGroupDataEx_aoMembers';
260 kasAltArrayNull = [ 'aoMembers', ];
261
262 ## Helper parameter containing the comma separated list with the IDs of
263 # potential members found in the parameters.
264 ksParam_aidTestCases = 'TestGroupDataEx_aidTestCases';
265
266
267 def __init__(self):
268 TestGroupData.__init__(self);
269 self.aoMembers = []; # TestGroupMemberDataEx.
270
271 def _initExtraMembersFromDb(self, oDb, tsNow = None, sPeriodBack = None):
272 """
273 Worker shared by the initFromDb* methods.
274 Returns self. Raises exception if no row or database error.
275 """
276 self.aoMembers = [];
277 _ = sPeriodBack; ## @todo sPeriodBack
278
279 if tsNow is None:
280 oDb.execute('SELECT TestGroupMembers.*, TestCases.*\n'
281 'FROM TestGroupMembers\n'
282 'LEFT OUTER JOIN TestCases ON (\n'
283 ' TestGroupMembers.idTestCase = TestCases.idTestCase\n'
284 ' AND TestCases.tsExpire = \'infinity\'::TIMESTAMP)\n'
285 'WHERE TestGroupMembers.idTestGroup = %s\n'
286 ' AND TestGroupMembers.tsExpire = \'infinity\'::TIMESTAMP\n'
287 'ORDER BY TestCases.sName, TestCases.idTestCase\n'
288 , (self.idTestGroup,));
289 else:
290 oDb.execute('SELECT TestGroupMembers.*, TestCases.*\n'
291 'FROM TestGroupMembers\n'
292 'LEFT OUTER JOIN TestCases ON (\n'
293 ' TestGroupMembers.idTestCase = TestCases.idTestCase\n'
294 ' AND TestCases.tsExpire > %s\n'
295 ' AND TestCases.tsEffective <= %s)\n'
296 'WHERE TestGroupMembers.idTestGroup = %s\n'
297 ' AND TestGroupMembers.tsExpire > %s\n'
298 ' AND TestGroupMembers.tsEffective <= %s\n'
299 'ORDER BY TestCases.sName, TestCases.idTestCase\n'
300 , (tsNow, tsNow, self.idTestGroup, tsNow, tsNow));
301
302 for aoRow in oDb.fetchAll():
303 self.aoMembers.append(TestGroupMemberDataEx().initFromDbRowEx(aoRow, oDb, tsNow));
304 return self;
305
306 def initFromDbRowEx(self, aoRow, oDb, tsNow = None, sPeriodBack = None):
307 """
308 Reinitialize from a SELECT * FROM TestGroups row. Will query the
309 necessary additional data from oDb using tsNow.
310 Returns self. Raises exception if no row or database error.
311 """
312 TestGroupData.initFromDbRow(self, aoRow);
313 return self._initExtraMembersFromDb(oDb, tsNow, sPeriodBack);
314
315 def initFromDbWithId(self, oDb, idTestGroup, tsNow = None, sPeriodBack = None):
316 """
317 Initialize the object from the database.
318 """
319 TestGroupData.initFromDbWithId(self, oDb, idTestGroup, tsNow, sPeriodBack);
320 return self._initExtraMembersFromDb(oDb, tsNow, sPeriodBack);
321
322
323 def getAttributeParamNullValues(self, sAttr):
324 if sAttr != 'aoMembers':
325 return TestGroupData.getAttributeParamNullValues(self, sAttr);
326 return ['', [], None];
327
328 def convertParamToAttribute(self, sAttr, sParam, oValue, oDisp, fStrict):
329 if sAttr != 'aoMembers':
330 return TestGroupData.convertParamToAttribute(self, sAttr, sParam, oValue, oDisp, fStrict);
331
332 aoNewValue = [];
333 aidSelected = oDisp.getListOfIntParams(sParam, iMin = 1, iMax = 0x7ffffffe, aiDefaults = [])
334 sIds = oDisp.getStringParam(self.ksParam_aidTestCases, sDefault = '');
335 for idTestCase in sIds.split(','):
336 try: idTestCase = int(idTestCase);
337 except: pass;
338 oDispWrapper = self.DispWrapper(oDisp, '%s[%s][%%s]' % (TestGroupDataEx.ksParam_aoMembers, idTestCase,))
339 oMember = TestGroupMemberDataEx().initFromParams(oDispWrapper, fStrict = False);
340 if idTestCase in aidSelected:
341 aoNewValue.append(oMember);
342 return aoNewValue;
343
344 def _validateAndConvertAttribute(self, sAttr, sParam, oValue, aoNilValues, fAllowNull, oDb):
345 if sAttr != 'aoMembers':
346 return TestGroupData._validateAndConvertAttribute(self, sAttr, sParam, oValue, aoNilValues, fAllowNull, oDb);
347
348 asErrors = [];
349 aoNewMembers = [];
350 for oOldMember in oValue:
351 oNewMember = TestGroupMemberDataEx().initFromOther(oOldMember);
352 aoNewMembers.append(oNewMember);
353
354 dErrors = oNewMember.validateAndConvert(oDb, ModelDataBase.ksValidateFor_Other);
355 if len(dErrors) > 0:
356 asErrors.append(str(dErrors));
357
358 if len(asErrors) == 0:
359 for i, _ in enumerate(aoNewMembers):
360 idTestCase = aoNewMembers[i];
361 for j in range(i + 1, len(aoNewMembers)):
362 if aoNewMembers[j].idTestCase == idTestCase:
363 asErrors.append('Duplicate testcase #%d!' % (idTestCase, ));
364 break;
365
366 return (aoNewMembers, None if len(asErrors) == 0 else '<br>\n'.join(asErrors));
367
368
369class TestGroupLogic(ModelLogicBase):
370 """
371 Test case management logic.
372 """
373
374 #
375 # Standard methods.
376 #
377
378 def fetchForListing(self, iStart, cMaxRows, tsNow):
379 """
380 Fetches test groups.
381
382 Returns an array (list) of TestGroupDataEx items, empty list if none.
383 Raises exception on error.
384 """
385 if tsNow is None:
386 self._oDb.execute('SELECT *\n'
387 'FROM TestGroups\n'
388 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
389 'ORDER BY sName ASC\n'
390 'LIMIT %s OFFSET %s\n'
391 , (cMaxRows, iStart,));
392 else:
393 self._oDb.execute('SELECT *\n'
394 'FROM TestGroups\n'
395 'WHERE tsExpire > %s\n'
396 ' AND tsEffective <= %s\n'
397 'ORDER BY sName ASC\n'
398 'LIMIT %s OFFSET %s\n'
399 , (tsNow, tsNow, cMaxRows, iStart,));
400
401 aoRet = [];
402 for aoRow in self._oDb.fetchAll():
403 aoRet.append(TestGroupDataEx().initFromDbRowEx(aoRow, self._oDb, tsNow));
404 return aoRet;
405
406 def addEntry(self, oData, uidAuthor, fCommit = False):
407 """
408 Adds a testgroup to the database.
409 """
410
411 #
412 # Validate inputs.
413 #
414 assert isinstance(oData, TestGroupDataEx);
415 dErrors = oData.validateAndConvert(self._oDb, oData.ksValidateFor_Add);
416 if len(dErrors) > 0:
417 raise TMInvalidData('addEntry invalid input: %s' % (dErrors,));
418 self._assertUniq(oData, None);
419
420 #
421 # Do the job.
422 #
423 self._oDb.execute('INSERT INTO TestGroups (uidAuthor, sName, sDescription, sComment)\n'
424 'VALUES (%s, %s, %s, %s)\n'
425 'RETURNING idTestGroup\n'
426 , ( uidAuthor,
427 oData.sName,
428 oData.sDescription,
429 oData.sComment ));
430 idTestGroup = self._oDb.fetchOne()[0];
431 oData.idTestGroup = idTestGroup;
432
433 for oMember in oData.aoMembers:
434 oMember.idTestGroup = idTestGroup;
435 self._insertTestGroupMember(uidAuthor, oMember)
436
437 self._oDb.maybeCommit(fCommit);
438 return True;
439
440 def editEntry(self, oData, uidAuthor, fCommit = False):
441 """
442 Modifies a test group.
443 """
444
445 #
446 # Validate inputs and read in the old(/current) data.
447 #
448 assert isinstance(oData, TestGroupDataEx);
449 dErrors = oData.validateAndConvert(self._oDb, oData.ksValidateFor_Edit);
450 if len(dErrors) > 0:
451 raise TMInvalidData('editEntry invalid input: %s' % (dErrors,));
452 self._assertUniq(oData, oData.idTestGroup);
453
454 oOldData = TestGroupDataEx().initFromDbWithId(self._oDb, oData.idTestGroup);
455
456 #
457 # Update the data that needs updating.
458 #
459
460 if not oData.isEqualEx(oOldData, [ 'aoMembers', 'tsEffective', 'tsExpire', 'uidAuthor', ]):
461 self._historizeTestGroup(oData.idTestGroup);
462 self._oDb.execute('INSERT INTO TestGroups\n'
463 ' (uidAuthor, idTestGroup, sName, sDescription, sComment)\n'
464 'VALUES (%s, %s, %s, %s, %s)\n'
465 , ( uidAuthor,
466 oData.idTestGroup,
467 oData.sName,
468 oData.sDescription,
469 oData.sComment ));
470
471 # Create a lookup dictionary for old entries.
472 dOld = {};
473 for oOld in oOldData.aoMembers:
474 dOld[oOld.idTestCase] = oOld;
475 assert len(dOld) == len(oOldData.aoMembers);
476
477 # Add new members, updated existing ones.
478 dNew = {};
479 for oNewMember in oData.aoMembers:
480 oNewMember.idTestGroup = oData.idTestGroup;
481 if oNewMember.idTestCase in dNew:
482 raise TMRowAlreadyExists('Duplicate test group member: idTestCase=%d (%s / %s)'
483 % (oNewMember.idTestCase, oNewMember, dNew[oNewMember.idTestCase],));
484 dNew[oNewMember.idTestCase] = oNewMember;
485
486 oOldMember = dOld.get(oNewMember.idTestCase, None);
487 if oOldMember is not None:
488 if oNewMember.isEqualEx(oOldMember, [ 'uidAuthor', 'tsEffective', 'tsExpire' ]):
489 continue; # Skip, nothing changed.
490 self._historizeTestGroupMember(oData.idTestGroup, oNewMember.idTestCase);
491 self._insertTestGroupMember(uidAuthor, oNewMember);
492
493 # Expire members that have been removed.
494 sQuery = self._oDb.formatBindArgs('UPDATE TestGroupMembers\n'
495 'SET tsExpire = CURRENT_TIMESTAMP\n'
496 'WHERE idTestGroup = %s\n'
497 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
498 , ( oData.idTestGroup, ));
499 if len(dNew) > 0:
500 sQuery += ' AND idTestCase NOT IN (%s)' % (', '.join([str(iKey) for iKey in dNew.keys()]),);
501 self._oDb.execute(sQuery);
502
503 self._oDb.maybeCommit(fCommit);
504 return True;
505
506 def removeEntry(self, uidAuthor, idTestGroup, fCascade = False, fCommit = False):
507 """
508 Deletes a test group.
509 """
510 _ = uidAuthor; ## @todo record uidAuthor.
511
512 #
513 # Cascade.
514 #
515 if fCascade is not True:
516 self._oDb.execute('SELECT SchedGroups.idSchedGroup, SchedGroups.sName\n'
517 'FROM SchedGroupMembers, SchedGroups\n'
518 'WHERE SchedGroupMembers.idTestGroup = %s\n'
519 ' AND SchedGroupMembers.tsExpire = \'infinity\'::TIMESTAMP\n'
520 ' AND SchedGroups.idSchedGroup = SchedGroupMembers.idSchedGroup\n'
521 ' AND SchedGroups.tsExpire = \'infinity\'::TIMESTAMP\n'
522 , ( idTestGroup, ));
523 aoGroups = self._oDb.fetchAll();
524 if len(aoGroups) > 0:
525 asGroups = ['%s (#%d)' % (sName, idSchedGroup) for idSchedGroup, sName in aoGroups];
526 raise TMRowInUse('Test group #%d is member of one or more scheduling groups: %s'
527 % (idTestGroup, ', '.join(asGroups),));
528 else:
529 self._oDb.execute('UPDATE SchedGroupMembers\n'
530 'SET tsExpire = CURRENT_TIMESTAMP\n'
531 'WHERE idTestGroup = %s\n'
532 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
533 , ( idTestGroup, ));
534
535 #
536 # Remove the group.
537 #
538 self._oDb.execute('UPDATE TestGroupMembers\n'
539 'SET tsExpire = CURRENT_TIMESTAMP\n'
540 'WHERE idTestGroup = %s\n'
541 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
542 , (idTestGroup,))
543 self._oDb.execute('UPDATE TestGroups\n'
544 'SET tsExpire = CURRENT_TIMESTAMP\n'
545 'WHERE idTestGroup = %s\n'
546 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
547 , (idTestGroup,))
548
549 self._oDb.maybeCommit(fCommit)
550 return True;
551
552
553 #
554 # Other methods.
555 #
556
557 def fetchOrderedByName(self, tsNow = None):
558 """
559 Return list of objects of type TestGroupData ordered by name.
560 May raise exception on database error.
561 """
562 if tsNow is None:
563 self._oDb.execute('SELECT *\n'
564 'FROM TestGroups\n'
565 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
566 'ORDER BY sName ASC\n');
567 else:
568 self._oDb.execute('SELECT *\n'
569 'FROM TestGroups\n'
570 'WHERE tsExpire > %s\n'
571 ' AND tsEffective <= %s\n'
572 'ORDER BY sName ASC\n'
573 , (tsNow, tsNow,));
574 aoRet = []
575 for _ in range(self._oDb.getRowCount()):
576 aoRet.append(TestGroupData().initFromDbRow(self._oDb.fetchOne()));
577 return aoRet;
578
579 def getMembers(self, idTestGroup):
580 """
581 Fetches all test case records from DB which are
582 belong to current Test Group.
583 Returns list of objects of type TestGroupMemberData2 (!).
584 """
585 self._oDb.execute('SELECT TestCases.*,\n'
586 ' TestGroupMembers.idTestGroup,\n'
587 ' TestGroupMembers.aidTestCaseArgs\n'
588 'FROM TestCases, TestGroupMembers\n'
589 'WHERE TestCases.tsExpire = \'infinity\'::TIMESTAMP\n'
590 ' AND TestGroupMembers.tsExpire = \'infinity\'::TIMESTAMP\n'
591 ' AND TestGroupMembers.idTestCase = TestCases.idTestCase\n'
592 ' AND TestGroupMembers.idTestGroup = %s\n'
593 'ORDER BY TestCases.idTestCase ASC;',
594 (idTestGroup,))
595
596 aaoRows = self._oDb.fetchAll()
597 aoRet = []
598 for aoRow in aaoRows:
599 aoRet.append(TestGroupMemberData2().initFromDbRowEx(aoRow))
600
601 return aoRet
602
603 def getAll(self, tsNow=None):
604 """Return list of objects of type TestGroupData"""
605
606 if tsNow is None:
607 self._oDb.execute('SELECT *\n'
608 'FROM TestGroups\n'
609 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
610 'ORDER BY idTestGroup ASC;')
611 else:
612 self._oDb.execute('SELECT *\n'
613 'FROM TestGroups\n'
614 'WHERE tsExpire > %s\n'
615 ' AND tsEffective <= %s\n'
616 'ORDER BY idTestGroup ASC;',
617 (tsNow, tsNow))
618
619 aaoRows = self._oDb.fetchAll()
620 aoRet = []
621 for aoRow in aaoRows:
622 aoRet.append(TestGroupData().initFromDbRow(aoRow))
623
624 return aoRet
625
626 def getById(self, idTestGroup, tsNow=None):
627 """Get Test Group data by its ID"""
628
629 if tsNow is None:
630 self._oDb.execute('SELECT *\n'
631 'FROM TestGroups\n'
632 'WHERE tsExpire = \'infinity\'::timestamp\n'
633 ' AND idTestGroup = %s\n'
634 'ORDER BY idTestGroup ASC;'
635 , (idTestGroup,))
636 else:
637 self._oDb.execute('SELECT *\n'
638 'FROM TestGroups\n'
639 'WHERE tsExpire > %s\n'
640 ' AND tsEffective <= %s\n'
641 ' AND idTestGroup = %s\n'
642 'ORDER BY idTestGroup ASC;'
643 , (tsNow, tsNow, idTestGroup))
644
645 aRows = self._oDb.fetchAll()
646 if len(aRows) not in (0, 1):
647 raise TMTooManyRows('Found more than one test groups with the same credentials. Database structure is corrupted.')
648 try:
649 return TestGroupData().initFromDbRow(aRows[0])
650 except IndexError:
651 return None
652
653 #
654 # Helpers.
655 #
656
657 def _assertUniq(self, oData, idTestGroupIgnore):
658 """ Checks that the test group name is unique, raises exception if it isn't. """
659 self._oDb.execute('SELECT idTestGroup\n'
660 'FROM TestGroups\n'
661 'WHERE sName = %s\n'
662 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
663 + ('' if idTestGroupIgnore is None else ' AND idTestGroup <> %d\n' % (idTestGroupIgnore,))
664 , ( oData.sName, ))
665 if self._oDb.getRowCount() > 0:
666 raise TMRowAlreadyExists('A Test group with name "%s" already exist.' % (oData.sName,));
667 return True;
668
669 def _historizeTestGroup(self, idTestGroup):
670 """ Historize Test Group record. """
671 self._oDb.execute('UPDATE TestGroups\n'
672 'SET tsExpire = CURRENT_TIMESTAMP\n'
673 'WHERE idTestGroup = %s\n'
674 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
675 , ( idTestGroup, ));
676 return True;
677
678 def _historizeTestGroupMember(self, idTestGroup, idTestCase):
679 """ Historize Test Group Member record. """
680 self._oDb.execute('UPDATE TestGroupMembers\n'
681 'SET tsExpire = CURRENT_TIMESTAMP\n'
682 'WHERE idTestGroup = %s\n'
683 ' AND idTestCase = %s\n'
684 ' AND tsExpire = \'infinity\'::timestamp\n'
685 , (idTestGroup, idTestCase,));
686 return True;
687
688 def _insertTestGroupMember(self, uidAuthor, oMember):
689 """ Inserts a test group member. """
690 self._oDb.execute('INSERT INTO TestGroupMembers\n'
691 ' (uidAuthor, idTestGroup, idTestCase, iSchedPriority, aidTestCaseArgs)\n'
692 'VALUES (%s, %s, %s, %s, %s)\n'
693 , ( uidAuthor,
694 oMember.idTestGroup,
695 oMember.idTestCase,
696 oMember.iSchedPriority,
697 oMember.aidTestCaseArgs, ));
698 return True;
699
700
701
702#
703# Unit testing.
704#
705
706# pylint: disable=C0111
707class TestGroupMemberDataTestCase(ModelDataBaseTestCase):
708 def setUp(self):
709 self.aoSamples = [TestGroupMemberData(),];
710
711class TestGroupDataTestCase(ModelDataBaseTestCase):
712 def setUp(self):
713 self.aoSamples = [TestGroupData(),];
714
715if __name__ == '__main__':
716 unittest.main();
717 # not reached.
718
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette