VirtualBox

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

Last change on this file since 53346 was 52776, checked in by vboxsync, 10 years ago

fix OSE

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

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