VirtualBox

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

最後變更 在這個檔案從61220是 61220,由 vboxsync 提交於 9 年 前

testmanager: failiure reason fixes, some exception throwing cleanups, delinting with pylint 1.5.5.

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

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