VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py@ 61250

Last change on this file since 61250 was 61250, checked in by vboxsync, 9 years ago

testmanager: Some failure reason improvments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.3 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuihlpform.py 61250 2016-05-27 18:00:16Z vboxsync $
3
4"""
5Test Manager Web-UI - Form Helpers.
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.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: 61250 $"
30
31# Standard python imports.
32import copy;
33
34# Validation Kit imports.
35from common import utils;
36from common.webutils import escapeAttr, escapeElem;
37from testmanager import config;
38from testmanager.core.schedgroup import SchedGroupMemberData, SchedGroupDataEx;
39from testmanager.core.testcaseargs import TestCaseArgsData;
40from testmanager.core.testgroup import TestGroupMemberData, TestGroupDataEx;
41
42
43class WuiHlpForm(object):
44 """
45 Helper for constructing a form.
46 """
47
48 ksItemsList = 'ksItemsList'
49
50 ksOnSubmit_AddReturnToFieldWithCurrentUrl = '+AddReturnToFieldWithCurrentUrl+';
51
52 def __init__(self, sId, sAction, dErrors = None, fReadOnly = False, sOnSubmit = None):
53 self._fFinalized = False;
54 self._fReadOnly = fReadOnly;
55 self._dErrors = dErrors if dErrors is not None else dict();
56
57 if sOnSubmit == self.ksOnSubmit_AddReturnToFieldWithCurrentUrl:
58 sOnSubmit = u'return addRedirectToInputFieldWithCurrentUrl(this)';
59 if sOnSubmit is None: sOnSubmit = u'';
60 else: sOnSubmit = u' onsubmit=\"%s\"' % (escapeAttr(sOnSubmit),);
61
62 self._sBody = u'\n' \
63 u'<div id="%s" class="tmform">\n' \
64 u' <form action="%s" method="post"%s>\n' \
65 u' <ul>\n' \
66 % (sId, sAction, sOnSubmit);
67
68 def _add(self, sText):
69 """Internal worker for appending text to the body."""
70 assert not self._fFinalized;
71 if not self._fFinalized:
72 self._sBody += unicode(sText, errors='ignore') if isinstance(sText, str) else sText;
73 return True;
74 return False;
75
76 def _escapeErrorText(self, sText):
77 """Escapes error text, preserving some predefined HTML tags."""
78 if sText.find('<br>') >= 0:
79 asParts = sText.split('<br>');
80 for i, _ in enumerate(asParts):
81 asParts[i] = escapeElem(asParts[i].strip());
82 sText = '<br>\n'.join(asParts);
83 else:
84 sText = escapeElem(sText);
85 return sText;
86
87 def _addLabel(self, sName, sLabel, sDivSubClass = 'normal'):
88 """Internal worker for adding a label."""
89 if sName in self._dErrors:
90 sError = self._dErrors[sName];
91 if utils.isString(sError): # List error trick (it's an associative array).
92 return self._add(u' <li>\n'
93 u' <div class="tmform-field"><div class="tmform-field-%s">\n'
94 u' <label for="%s" class="tmform-error-label">%s\n'
95 u' <span class="tmform-error-desc">%s</span>\n'
96 u' </label>\n'
97 % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel),
98 self._escapeErrorText(sError), ) );
99 return self._add(u' <li>\n'
100 u' <div class="tmform-field"><div class="tmform-field-%s">\n'
101 u' <label for="%s">%s</label>\n'
102 % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel)) );
103
104
105 def finalize(self):
106 """
107 Finalizes the form and returns the body.
108 """
109 if not self._fFinalized:
110 self._add(u' </ul>\n'
111 u' </form>\n'
112 u'</div>\n'
113 u'<div class="clear"></div>\n' );
114 return self._sBody;
115
116 def addTextHidden(self, sName, sValue, sExtraAttribs = ''):
117 """Adds a hidden text input."""
118 return self._add(u' <div class="tmform-field-hidden">\n'
119 u' <input name="%s" id="%s" type="text" hidden%s value="%s" class="tmform-hidden">\n'
120 u' </div>\n'
121 u' </li>\n'
122 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(str(sValue)) ));
123 #
124 # Non-input stuff.
125 #
126 def addNonText(self, sValue, sLabel, sName = 'non-text', sPostHtml = ''):
127 """Adds a read-only text input."""
128 self._addLabel(sName, sLabel, 'string');
129 if sValue is None: sValue = '';
130 return self._add(u' <p>%s%s</p>\n'
131 u' </div></div>\n'
132 u' </li>\n'
133 % (escapeElem(unicode(sValue)), sPostHtml ));
134
135 def addRawHtml(self, sRawHtml, sLabel, sName = 'raw-html'):
136 """Adds a read-only text input."""
137 self._addLabel(sName, sLabel, 'string');
138 self._add(sRawHtml);
139 return self._add(u' </div></div>\n'
140 u' </li>\n');
141
142
143 #
144 # Text input fields.
145 #
146 def addText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''):
147 """Adds a text input."""
148 if self._fReadOnly:
149 return self.addTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs);
150 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
151 self._addLabel(sName, sLabel, sSubClass);
152 if sValue is None: sValue = '';
153 return self._add(u' <input name="%s" id="%s" type="text"%s value="%s">%s\n'
154 u' </div></div>\n'
155 u' </li>\n'
156 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(sValue), sPostHtml ));
157
158 def addTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''):
159 """Adds a read-only text input."""
160 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
161 self._addLabel(sName, sLabel, sSubClass);
162 if sValue is None: sValue = '';
163 return self._add(u' <input name="%s" id="%s" type="text" readonly%s value="%s" class="tmform-input-readonly">'
164 u'%s\n'
165 u' </div></div>\n'
166 u' </li>\n'
167 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(unicode(sValue)), sPostHtml ));
168
169 def addWideText(self, sName, sValue, sLabel, sExtraAttribs = ''):
170 """Adds a wide text input."""
171 return self.addText(sName, sValue, sLabel, 'wide', sExtraAttribs);
172
173 def addWideTextRO(self, sName, sValue, sLabel, sExtraAttribs = ''):
174 """Adds a wide read-only text input."""
175 return self.addTextRO(sName, sValue, sLabel, 'wide', sExtraAttribs);
176
177 def _adjustMultilineTextAttribs(self, sExtraAttribs, sValue):
178 """ Internal helper for setting good default sizes for textarea based on content."""
179 if sExtraAttribs.find('cols') < 0 and sExtraAttribs.find('width') < 0:
180 sExtraAttribs = 'cols="96%" ' + sExtraAttribs;
181
182 if sExtraAttribs.find('rows') < 0 and sExtraAttribs.find('width') < 0:
183 if sValue is None: sValue = '';
184 else: sValue = sValue.strip();
185
186 cRows = sValue.count('\n') + (not sValue.endswith('\n'));
187 if cRows * 80 < len(sValue):
188 cRows += 2;
189 cRows = max(min(cRows, 16), 2);
190 sExtraAttribs = ('rows="%s" ' % (cRows,)) + sExtraAttribs;
191
192 return sExtraAttribs;
193
194 def addMultilineText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''):
195 """Adds a multiline text input."""
196 if self._fReadOnly:
197 return self.addMultilineTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs);
198 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
199 self._addLabel(sName, sLabel, sSubClass)
200 if sValue is None: sValue = '';
201 sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
202 return self._add(u' <textarea name="%s" id="%s" %s>%s</textarea>\n'
203 u' </div></div>\n'
204 u' </li>\n'
205 % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue),
206 escapeElem(sNewValue)))
207
208 def addMultilineTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''):
209 """Adds a multiline read-only text input."""
210 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
211 self._addLabel(sName, sLabel, sSubClass)
212 if sValue is None: sValue = '';
213 sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
214 return self._add(u' <textarea name="%s" id="%s" readonly %s>%s</textarea>\n'
215 u' </div></div>\n'
216 u' </li>\n'
217 % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue),
218 escapeElem(sNewValue)))
219
220 def addInt(self, sName, iValue, sLabel, sExtraAttribs = ''):
221 """Adds an integer input."""
222 return self.addText(sName, unicode(iValue), sLabel, 'int', sExtraAttribs);
223
224 def addIntRO(self, sName, iValue, sLabel, sExtraAttribs = ''):
225 """Adds an integer input."""
226 return self.addTextRO(sName, unicode(iValue), sLabel, 'int', sExtraAttribs);
227
228 def addLong(self, sName, lValue, sLabel, sExtraAttribs = ''):
229 """Adds a long input."""
230 return self.addText(sName, unicode(lValue), sLabel, 'long', sExtraAttribs);
231
232 def addLongRO(self, sName, lValue, sLabel, sExtraAttribs = ''):
233 """Adds a long input."""
234 return self.addTextRO(sName, unicode(lValue), sLabel, 'long', sExtraAttribs);
235
236 def addUuid(self, sName, uuidValue, sLabel, sExtraAttribs = ''):
237 """Adds an UUID input."""
238 return self.addText(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs);
239
240 def addUuidRO(self, sName, uuidValue, sLabel, sExtraAttribs = ''):
241 """Adds a read-only UUID input."""
242 return self.addTextRO(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs);
243
244 def addTimestampRO(self, sName, sTimestamp, sLabel, sExtraAttribs = ''):
245 """Adds a read-only database string timstamp input."""
246 return self.addTextRO(sName, sTimestamp, sLabel, 'timestamp', sExtraAttribs);
247
248
249 #
250 # Text areas.
251 #
252
253
254 #
255 # Combo boxes.
256 #
257 def addComboBox(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''):
258 """Adds a combo box."""
259 if self._fReadOnly:
260 return self.addComboBoxRO(sName, sSelected, sLabel, aoOptions, sExtraAttribs, sPostHtml);
261 self._addLabel(sName, sLabel, 'combobox');
262 self._add(' <select name="%s" id="%s" class="tmform-combobox"%s>\n'
263 % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
264 sSelected = unicode(sSelected);
265 for iValue, sText, _ in aoOptions:
266 sValue = unicode(iValue);
267 self._add(' <option value="%s"%s>%s</option>\n'
268 % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
269 escapeElem(sText)));
270 return self._add(u' </select>' + sPostHtml + '\n'
271 u' </div></div>\n'
272 u' </li>\n');
273
274 def addComboBoxRO(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''):
275 """Adds a read-only combo box."""
276 self.addTextHidden(sName, sSelected);
277 self._addLabel(sName, sLabel, 'combobox-readonly');
278 self._add(u' <select name="%s" id="%s" disabled class="tmform-combobox"%s>\n'
279 % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
280 sSelected = unicode(sSelected);
281 for iValue, sText, _ in aoOptions:
282 sValue = unicode(iValue);
283 self._add(' <option value="%s"%s>%s</option>\n'
284 % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
285 escapeElem(sText)));
286 return self._add(u' </select>' + sPostHtml + '\n'
287 u' </div></div>\n'
288 u' </li>\n');
289
290 #
291 # Check boxes.
292 #
293 @staticmethod
294 def _reinterpretBool(fValue):
295 """Reinterprets a value as a boolean type."""
296 if fValue is not type(True):
297 if fValue is None:
298 fValue = False;
299 elif str(fValue) in ('True', 'true', '1'):
300 fValue = True;
301 else:
302 fValue = False;
303 return fValue;
304
305 def addCheckBox(self, sName, fChecked, sLabel, sExtraAttribs = ''):
306 """Adds an check box."""
307 if self._fReadOnly:
308 return self.addCheckBoxRO(sName, fChecked, sLabel, sExtraAttribs);
309 self._addLabel(sName, sLabel, 'checkbox');
310 fChecked = self._reinterpretBool(fChecked);
311 return self._add(u' <input name="%s" id="%s" type="checkbox"%s%s value="1" class="tmform-checkbox">\n'
312 u' </div></div>\n'
313 u' </li>\n'
314 % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs));
315
316 def addCheckBoxRO(self, sName, fChecked, sLabel, sExtraAttribs = ''):
317 """Adds an readonly check box."""
318 self._addLabel(sName, sLabel, 'checkbox');
319 fChecked = self._reinterpretBool(fChecked);
320 # Hack Alert! The onclick and onkeydown are for preventing editing and fake readonly/disabled.
321 return self._add(u' <input name="%s" id="%s" type="checkbox"%s readonly%s value="1" class="readonly"\n'
322 u' onclick="return false" onkeydown="return false">\n'
323 u' </div></div>\n'
324 u' </li>\n'
325 % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs));
326
327 #
328 # List of items to check
329 #
330 def _addList(self, sName, aoRows, sLabel, fUseTable = False, sId = 'dummy', sExtraAttribs = ''):
331 """
332 Adds a list of items to check.
333
334 @param sName Name of HTML form element
335 @param aoRows List of [sValue, fChecked, sName] sub-arrays.
336 @param sLabel Label of HTML form element
337 """
338 fReadOnly = self._fReadOnly; ## @todo add this as a parameter.
339 if fReadOnly:
340 sExtraAttribs += ' readonly onclick="return false" onkeydown="return false"';
341
342 self._addLabel(sName, sLabel, 'list');
343 if len(aoRows) == 0:
344 return self._add('No items</div></div></li>')
345 sNameEscaped = escapeAttr(sName);
346
347 self._add(' <div class="tmform-checkboxes-container" id="%s">\n' % (escapeAttr(sId),));
348 if fUseTable:
349 self._add(' <table>\n');
350 for asRow in aoRows:
351 assert len(asRow) == 3; # Don't allow sloppy input data!
352 fChecked = self._reinterpretBool(asRow[1])
353 self._add(u' <tr>\n'
354 u' <td><input type="checkbox" name="%s" value="%s"%s%s></td>\n'
355 u' <td>%s</td>\n'
356 u' </tr>\n'
357 % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs,
358 escapeElem(unicode(asRow[2])), ));
359 self._add(u' </table>\n');
360 else:
361 for asRow in aoRows:
362 assert len(asRow) == 3; # Don't allow sloppy input data!
363 fChecked = self._reinterpretBool(asRow[1])
364 self._add(u' <div class="tmform-checkbox-holder">'
365 u'<input type="checkbox" name="%s" value="%s"%s%s> %s</input></div>\n'
366 % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs,
367 escapeElem(unicode(asRow[2])),));
368 return self._add(u' </div></div></div>\n'
369 u' </li>\n');
370
371
372 def addListOfOsArches(self, sName, aoOsArches, sLabel, sExtraAttribs = ''):
373 """
374 List of checkboxes for OS/ARCH selection.
375 asOsArches is a list of [sValue, fChecked, sName] sub-arrays.
376 """
377 return self._addList(sName, aoOsArches, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-os-arches',
378 sExtraAttribs = sExtraAttribs);
379
380 def addListOfTypes(self, sName, aoTypes, sLabel, sExtraAttribs = ''):
381 """
382 List of checkboxes for build type selection.
383 aoTypes is a list of [sValue, fChecked, sName] sub-arrays.
384 """
385 return self._addList(sName, aoTypes, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-build-types',
386 sExtraAttribs = sExtraAttribs);
387
388 def addListOfTestCases(self, sName, aoTestCases, sLabel, sExtraAttribs = ''):
389 """
390 List of checkboxes for test box (dependency) selection.
391 aoTestCases is a list of [sValue, fChecked, sName] sub-arrays.
392 """
393 return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testcases',
394 sExtraAttribs = sExtraAttribs);
395
396 def addListOfResources(self, sName, aoTestCases, sLabel, sExtraAttribs = ''):
397 """
398 List of checkboxes for resource selection.
399 aoTestCases is a list of [sValue, fChecked, sName] sub-arrays.
400 """
401 return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-resources',
402 sExtraAttribs = sExtraAttribs);
403
404 def addListOfTestGroups(self, sName, aoTestGroups, sLabel, sExtraAttribs = ''):
405 """
406 List of checkboxes for test group selection.
407 aoTestGroups is a list of [sValue, fChecked, sName] sub-arrays.
408 """
409 return self._addList(sName, aoTestGroups, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testgroups',
410 sExtraAttribs = sExtraAttribs);
411
412 def addListOfTestCaseArgs(self, sName, aoVariations, sLabel): # pylint: disable=R0915
413 """
414 Adds a list of test case argument variations to the form.
415
416 @param sName Name of HTML form element
417 @param aoVariations List of TestCaseArgsData instances.
418 @param sLabel Label of HTML form element
419 """
420 self._addLabel(sName, sLabel);
421
422 sTableId = u'TestArgsExtendingListRoot';
423 fReadOnly = self._fReadOnly; ## @todo argument?
424 sReadOnlyAttr = u' readonly class="tmform-input-readonly"' if fReadOnly else '';
425
426 sHtml = u'<li>\n'
427
428 #
429 # Define javascript function for extending the list of test case
430 # variations. Doing it here so we can use the python constants. This
431 # also permits multiple argument lists on one page should that ever be
432 # required...
433 #
434 if not fReadOnly:
435 sHtml += u'<script type="text/javascript">\n'
436 sHtml += u'\n';
437 sHtml += u'g_%s_aItems = { %s };\n' % (sName, ', '.join(('%s: 1' % (i,)) for i in range(len(aoVariations))),);
438 sHtml += u'g_%s_cItems = %s;\n' % (sName, len(aoVariations),);
439 sHtml += u'g_%s_iIdMod = %s;\n' % (sName, len(aoVariations) + 32);
440 sHtml += u'\n';
441 sHtml += u'function %s_removeEntry(sId)\n' % (sName,);
442 sHtml += u'{\n';
443 sHtml += u' if (g_%s_cItems > 1)\n' % (sName,);
444 sHtml += u' {\n';
445 sHtml += u' g_%s_cItems--;\n' % (sName,);
446 sHtml += u' delete g_%s_aItems[sId];\n' % (sName,);
447 sHtml += u' setElementValueToKeyList(\'%s\', g_%s_aItems);\n' % (sName, sName);
448 sHtml += u'\n';
449 for iInput in range(8):
450 sHtml += u' removeHtmlNode(\'%s[\' + sId + \'][%s]\');\n' % (sName, iInput,);
451 sHtml += u' }\n';
452 sHtml += u'}\n';
453 sHtml += u'\n';
454 sHtml += u'function %s_extendListEx(cGangMembers, cSecTimeout, sArgs, sTestBoxReqExpr, sBuildReqExpr)\n' % (sName,);
455 sHtml += u'{\n';
456 sHtml += u' var oElement = document.getElementById(\'%s\');\n' % (sTableId,);
457 sHtml += u' var oTBody = document.createElement(\'tbody\');\n';
458 sHtml += u' var sHtml = \'\';\n';
459 sHtml += u' var sId;\n';
460 sHtml += u'\n';
461 sHtml += u' g_%s_iIdMod += 1;\n' % (sName,);
462 sHtml += u' sId = g_%s_iIdMod.toString();\n' % (sName,);
463
464 oVarDefaults = TestCaseArgsData();
465 oVarDefaults.convertToParamNull();
466 sHtml += u'\n';
467 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-first-row">\';\n';
468 sHtml += u' sHtml += \' <td>Gang Members:</td>\';\n';
469 sHtml += u' sHtml += \' <td class="tmform-field-tiny-int">' \
470 '<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][0]" value="\' + cGangMembers + \'"></td>\';\n' \
471 % (sName, TestCaseArgsData.ksParam_cGangMembers, sName,);
472 sHtml += u' sHtml += \' <td>Timeout:</td>\';\n';
473 sHtml += u' sHtml += \' <td class="tmform-field-int">' \
474 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][1]" value="\'+ cSecTimeout + \'"></td>\';\n' \
475 % (sName, TestCaseArgsData.ksParam_cSecTimeout, sName,);
476 sHtml += u' sHtml += \' <td><a href="#" onclick="%s_removeEntry(\\\'\' + sId + \'\\\');"> Remove</a></td>\';\n' \
477 % (sName, );
478 sHtml += u' sHtml += \' <td></td>\';\n';
479 sHtml += u' sHtml += \'</tr>\';\n'
480 sHtml += u'\n';
481 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-inner-row">\';\n';
482 sHtml += u' sHtml += \' <td>Arguments:</td>\';\n';
483 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="4">' \
484 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sArgs + \'"></td>\';\n' \
485 % (sName, TestCaseArgsData.ksParam_sArgs, sName,);
486 sHtml += u' sHtml += \' <td></td>\';\n';
487 sHtml += u' sHtml += \'</tr>\';\n'
488 sHtml += u'\n';
489 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-inner-row">\';\n';
490 sHtml += u' sHtml += \' <td>TestBox Reqs:</td>\';\n';
491 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="4">' \
492 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sTestBoxReqExpr' \
493 u' + \'"></td>\';\n' \
494 % (sName, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName,);
495 sHtml += u' sHtml += \' <td></td>\';\n';
496 sHtml += u' sHtml += \'</tr>\';\n'
497 sHtml += u'\n';
498 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-final-row">\';\n';
499 sHtml += u' sHtml += \' <td>Build Reqs:</td>\';\n';
500 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="4">' \
501 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sBuildReqExpr + \'"></td>\';\n' \
502 % (sName, TestCaseArgsData.ksParam_sBuildReqExpr, sName,);
503 sHtml += u' sHtml += \' <td></td>\';\n';
504 sHtml += u' sHtml += \'</tr>\';\n'
505 sHtml += u'\n';
506 sHtml += u' oTBody.id = \'%s[\' + sId + \'][6]\';\n' % (sName,);
507 sHtml += u' oTBody.innerHTML = sHtml;\n';
508 sHtml += u'\n';
509 sHtml += u' oElement.appendChild(oTBody);\n';
510 sHtml += u'\n';
511 sHtml += u' g_%s_aItems[sId] = 1;\n' % (sName,);
512 sHtml += u' g_%s_cItems++;\n' % (sName,);
513 sHtml += u' setElementValueToKeyList(\'%s\', g_%s_aItems);\n' % (sName, sName);
514 sHtml += u'}\n';
515 sHtml += u'function %s_extendList()\n' % (sName,);
516 sHtml += u'{\n';
517 sHtml += u' %s_extendListEx("%s", "%s", "%s", "%s", "%s");\n' % (sName,
518 escapeAttr(unicode(oVarDefaults.cGangMembers)), escapeAttr(unicode(oVarDefaults.cSecTimeout)),
519 escapeAttr(oVarDefaults.sArgs), escapeAttr(oVarDefaults.sTestBoxReqExpr),
520 escapeAttr(oVarDefaults.sBuildReqExpr), );
521 sHtml += u'}\n';
522 if config.g_kfVBoxSpecific:
523 sSecTimeoutDef = escapeAttr(unicode(oVarDefaults.cSecTimeout));
524 sHtml += u'function vbox_%s_add_uni()\n' % (sName,);
525 sHtml += u'{\n';
526 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 1 --virt-modes raw", ' \
527 u' "", "");\n' % (sName, sSecTimeoutDef);
528 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 1 --virt-modes hwvirt", ' \
529 u' "fCpuHwVirt is True", "");\n' % (sName, sSecTimeoutDef);
530 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 1 --virt-modes hwvirt-np", ' \
531 u' "fCpuNestedPaging is True", "");\n' % (sName, sSecTimeoutDef);
532 sHtml += u'}\n';
533 sHtml += u'function vbox_%s_add_uni_amd64()\n' % (sName,);
534 sHtml += u'{\n';
535 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 1 --virt-modes hwvirt", ' \
536 u' "fCpuHwVirt is True", "");\n' % (sName, sSecTimeoutDef);
537 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 1 --virt-modes hwvirt-np", ' \
538 u' "fCpuNestedPaging is True", "");\n' % (sName, sSecTimeoutDef);
539 sHtml += u'}\n';
540 sHtml += u'function vbox_%s_add_smp()\n' % (sName,);
541 sHtml += u'{\n';
542 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 2 --virt-modes hwvirt",' \
543 u' "fCpuHwVirt is True and cCpus >= 2", "");\n' % (sName, sSecTimeoutDef);
544 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 2 --virt-modes hwvirt-np",' \
545 u' "fCpuNestedPaging is True and cCpus >= 2", "");\n' % (sName, sSecTimeoutDef);
546 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 3 --virt-modes hwvirt",' \
547 u' "fCpuHwVirt is True and cCpus >= 3", "");\n' % (sName, sSecTimeoutDef);
548 sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 4 --virt-modes hwvirt-np ",' \
549 u' "fCpuNestedPaging is True and cCpus >= 4", "");\n' % (sName, sSecTimeoutDef);
550 #sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 6 --virt-modes hwvirt",' \
551 # u' "fCpuHwVirt is True and cCpus >= 6", "");\n' % (sName, sSecTimeoutDef);
552 #sHtml += u' %s_extendListEx("1", "%s", "--cpu-counts 8 --virt-modes hwvirt-np",' \
553 # u' "fCpuNestedPaging is True and cCpus >= 8", "");\n' % (sName, sSecTimeoutDef);
554 sHtml += u'}\n';
555 sHtml += u'</script>\n';
556
557
558 #
559 # List current entries.
560 #
561 sHtml += u'<input type="hidden" name="%s" id="%s" value="%s">\n' \
562 % (sName, sName, ','.join(unicode(i) for i in range(len(aoVariations))), );
563 sHtml += u' <table id="%s" class="tmform-testcasevars">\n' % (sTableId,)
564 if not fReadOnly:
565 sHtml += u' <caption>\n' \
566 u' <a href="#" onClick="%s_extendList()">Add</a>\n' % (sName,);
567 if config.g_kfVBoxSpecific:
568 sHtml += u' [<a href="#" onClick="vbox_%s_add_uni()">Single CPU Variations</a>\n' % (sName,);
569 sHtml += u' <a href="#" onClick="vbox_%s_add_uni_amd64()">amd64</a>]\n' % (sName,);
570 sHtml += u' [<a href="#" onClick="vbox_%s_add_smp()">SMP Variations</a>]\n' % (sName,);
571 sHtml += u' </caption>\n';
572
573 dSubErrors = {};
574 if sName in self._dErrors and isinstance(self._dErrors[sName], dict):
575 dSubErrors = self._dErrors[sName];
576
577 for iVar, _ in enumerate(aoVariations):
578 oVar = copy.copy(aoVariations[iVar]);
579 oVar.convertToParamNull();
580
581 sHtml += u'<tbody id="%s[%s][6]">\n' % (sName, iVar,)
582 sHtml += u' <tr class="tmform-testcasevars-first-row">\n' \
583 u' <td>Gang Members:</td>' \
584 u' <td class="tmform-field-tiny-int"><input name="%s[%s][%s]" id="%s[%s][1]" value="%s"%s></td>\n' \
585 u' <td>Timeout:</td>' \
586 u' <td class="tmform-field-int"><input name="%s[%s][%s]" id="%s[%s][2]" value="%s"%s></td>\n' \
587 % ( sName, iVar, TestCaseArgsData.ksParam_cGangMembers, sName, iVar, oVar.cGangMembers, sReadOnlyAttr,
588 sName, iVar, TestCaseArgsData.ksParam_cSecTimeout, sName, iVar,
589 utils.formatIntervalSeconds2(oVar.cSecTimeout), sReadOnlyAttr, );
590 if not fReadOnly:
591 sHtml += u' <td><a href="#" onclick="%s_removeEntry(\'%s\');">Remove</a></td>\n' \
592 % (sName, iVar);
593 else:
594 sHtml += u' <td></td>\n';
595 sHtml += u' <td class="tmform-testcasevars-stupid-border-column"></td>\n' \
596 u' </tr>\n';
597
598 sHtml += u' <tr class="tmform-testcasevars-inner-row">\n' \
599 u' <td>Arguments:</td>' \
600 u' <td class="tmform-field-wide100" colspan="4">' \
601 u'<input name="%s[%s][%s]" id="%s[%s][3]" value="%s"%s></td>\n' \
602 u' <td></td>\n' \
603 u' </tr>\n' \
604 % ( sName, iVar, TestCaseArgsData.ksParam_sArgs, sName, iVar, escapeAttr(oVar.sArgs), sReadOnlyAttr)
605
606 sHtml += u' <tr class="tmform-testcasevars-inner-row">\n' \
607 u' <td>TestBox Reqs:</td>' \
608 u' <td class="tmform-field-wide100" colspan="4">' \
609 u'<input name="%s[%s][%s]" id="%s[%s][4]" value="%s"%s></td>\n' \
610 u' <td></td>\n' \
611 u' </tr>\n' \
612 % ( sName, iVar, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName, iVar,
613 escapeAttr(oVar.sTestBoxReqExpr), sReadOnlyAttr)
614
615 sHtml += u' <tr class="tmform-testcasevars-final-row">\n' \
616 u' <td>Build Reqs:</td>' \
617 u' <td class="tmform-field-wide100" colspan="4">' \
618 u'<input name="%s[%s][%s]" id="%s[%s][5]" value="%s"%s></td>\n' \
619 u' <td></td>\n' \
620 u' </tr>\n' \
621 % ( sName, iVar, TestCaseArgsData.ksParam_sBuildReqExpr, sName, iVar,
622 escapeAttr(oVar.sBuildReqExpr), sReadOnlyAttr)
623
624
625 if iVar in dSubErrors:
626 sHtml += u' <tr><td colspan="4"><p align="left" class="tmform-error-desc">%s</p></td></tr>\n' \
627 % (self._escapeErrorText(dSubErrors[iVar]),);
628
629 sHtml += u'</tbody>\n';
630 sHtml += u' </table>\n'
631 sHtml += u'</li>\n'
632
633 return self._add(sHtml)
634
635 def addListOfTestGroupMembers(self, sName, aoTestGroupMembers, aoAllTestCases, sLabel, # pylint: disable=R0914
636 fReadOnly = True):
637 """
638 For WuiTestGroup.
639 """
640 assert len(aoTestGroupMembers) <= len(aoAllTestCases);
641 self._addLabel(sName, sLabel);
642 if len(aoAllTestCases) == 0:
643 return self._add('<li>No testcases available.</li>\n')
644
645 self._add(u'<input name="%s" type="hidden" value="%s">\n'
646 % ( TestGroupDataEx.ksParam_aidTestCases,
647 ','.join([unicode(oTestCase.idTestCase) for oTestCase in aoAllTestCases]), ));
648
649 self._add(u'<table class="tmformtbl">\n'
650 u' <thead>\n'
651 u' <tr>\n'
652 u' <th rowspan="2"></th>\n'
653 u' <th rowspan="2">Test Case</th>\n'
654 u' <th rowspan="2">All Vars</th>\n'
655 u' <th rowspan="2">Priority [0..31]</th>\n'
656 u' <th colspan="4" align="center">Variations</th>\n'
657 u' </tr>\n'
658 u' <tr>\n'
659 u' <th>Included</th>\n'
660 u' <th>Gang size</th>\n'
661 u' <th>Timeout</th>\n'
662 u' <th>Arguments</th>\n'
663 u' </tr>\n'
664 u' </thead>\n'
665 u' <tbody>\n'
666 );
667
668 if self._fReadOnly:
669 fReadOnly = True;
670 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
671
672 oDefMember = TestGroupMemberData();
673 aoTestGroupMembers = list(aoTestGroupMembers); # Copy it so we can pop.
674 for iTestCase, _ in enumerate(aoAllTestCases):
675 oTestCase = aoAllTestCases[iTestCase];
676
677 # Is it a member?
678 oMember = None;
679 for i, _ in enumerate(aoTestGroupMembers):
680 if aoTestGroupMembers[i].oTestCase.idTestCase == oTestCase.idTestCase:
681 oMember = aoTestGroupMembers.pop(i);
682 break;
683
684 # Start on the rows...
685 sPrefix = u'%s[%d]' % (sName, oTestCase.idTestCase,);
686 self._add(u' <tr class="%s">\n'
687 u' <td rowspan="%d">\n'
688 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestCase
689 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
690 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
691 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
692 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
693 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
694 u' </td>\n'
695 % ( 'tmodd' if iTestCase & 1 else 'tmeven',
696 len(oTestCase.aoTestCaseArgs),
697 sPrefix, TestGroupMemberData.ksParam_idTestCase, oTestCase.idTestCase,
698 sPrefix, TestGroupMemberData.ksParam_idTestGroup, -1 if oMember is None else oMember.idTestGroup,
699 sPrefix, TestGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
700 sPrefix, TestGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
701 sPrefix, TestGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
702 TestGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
703 oTestCase.idTestCase, oTestCase.idTestCase, escapeElem(oTestCase.sName),
704 ));
705 self._add(u' <td rowspan="%d" align="left">%s</td>\n'
706 % ( len(oTestCase.aoTestCaseArgs), escapeElem(oTestCase.sName), ));
707
708 self._add(u' <td rowspan="%d" title="Include all variations (checked) or choose a set?">\n'
709 u' <input name="%s[%s]" type="checkbox"%s%s value="-1">\n'
710 u' </td>\n'
711 % ( len(oTestCase.aoTestCaseArgs),
712 sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
713 ' checked' if oMember is None or oMember.aidTestCaseArgs is None else '', sCheckBoxAttr, ));
714
715 self._add(u' <td rowspan="%d" align="center">\n'
716 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
717 u' </td>\n'
718 % ( len(oTestCase.aoTestCaseArgs),
719 sPrefix, TestGroupMemberData.ksParam_iSchedPriority,
720 (oMember if oMember is not None else oDefMember).iSchedPriority,
721 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
722
723 # Argument variations.
724 aidTestCaseArgs = [] if oMember is None or oMember.aidTestCaseArgs is None else oMember.aidTestCaseArgs;
725 for iVar in range(len(oTestCase.aoTestCaseArgs)):
726 oVar = oTestCase.aoTestCaseArgs[iVar];
727 if iVar > 0:
728 self._add(' <tr class="%s">\n' % ('tmodd' if iTestCase & 1 else 'tmeven',));
729 self._add(u' <td align="center">\n'
730 u' <input name="%s[%s]" type="checkbox"%s%s value="%d">'
731 u' </td>\n'
732 % ( sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
733 ' checked' if oVar.idTestCaseArgs in aidTestCaseArgs else '', sCheckBoxAttr, oVar.idTestCaseArgs,
734 ));
735 self._add(u' <td align="center">%s</td>\n'
736 u' <td align="center">%s</td>\n'
737 u' <td align="left">%s</td>\n'
738 % ( oVar.cGangMembers,
739 'Default' if oVar.cSecTimeout is None else oVar.cSecTimeout,
740 escapeElem(oVar.sArgs) ));
741
742 self._add(u' </tr>\n');
743
744
745
746 if len(oTestCase.aoTestCaseArgs) == 0:
747 self._add(u' <td></td> <td></td> <td></td> <td></td>\n'
748 u' </tr>\n');
749 return self._add(u' </tbody>\n'
750 u'</table>\n');
751
752 def addListOfSchedGroupMembers(self, sName, aoSchedGroupMembers, aoAllTestGroups, # pylint: disable=R0914
753 sLabel, fReadOnly = True):
754 """
755 For WuiAdminSchedGroup.
756 """
757 if self._fReadOnly:
758 fReadOnly = True;
759 assert len(aoSchedGroupMembers) <= len(aoAllTestGroups);
760 self._addLabel(sName, sLabel);
761 if len(aoAllTestGroups) == 0:
762 return self._add(u'<li>No test groups available.</li>\n')
763
764 self._add(u'<input name="%s" type="hidden" value="%s">\n'
765 % ( SchedGroupDataEx.ksParam_aidTestGroups,
766 ','.join([unicode(oTestGroup.idTestGroup) for oTestGroup in aoAllTestGroups]), ));
767
768 self._add(u'<table class="tmformtbl">\n'
769 u' <thead>\n'
770 u' <tr>\n'
771 u' <th></th>\n'
772 u' <th>Test Group</th>\n'
773 u' <th>Priority [0..31]</th>\n'
774 u' <th>Prerequisite Test Group</th>\n'
775 u' <th>Weekly schedule</th>\n'
776 u' </tr>\n'
777 u' </thead>\n'
778 u' <tbody>\n'
779 );
780
781 sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
782 sComboBoxAttr = u' disabled' if fReadOnly else '';
783
784 oDefMember = SchedGroupMemberData();
785 aoSchedGroupMembers = list(aoSchedGroupMembers); # Copy it so we can pop.
786 for iTestGroup, _ in enumerate(aoAllTestGroups):
787 oTestGroup = aoAllTestGroups[iTestGroup];
788
789 # Is it a member?
790 oMember = None;
791 for i, _ in enumerate(aoSchedGroupMembers):
792 if aoSchedGroupMembers[i].oTestGroup.idTestGroup == oTestGroup.idTestGroup:
793 oMember = aoSchedGroupMembers.pop(i);
794 break;
795
796 # Start on the rows...
797 sPrefix = u'%s[%d]' % (sName, oTestGroup.idTestGroup,);
798 self._add(u' <tr class="%s">\n'
799 u' <td>\n'
800 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
801 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
802 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
803 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
804 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
805 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
806 u' </td>\n'
807 % ( 'tmodd' if iTestGroup & 1 else 'tmeven',
808 sPrefix, SchedGroupMemberData.ksParam_idTestGroup, oTestGroup.idTestGroup,
809 sPrefix, SchedGroupMemberData.ksParam_idSchedGroup, -1 if oMember is None else oMember.idSchedGroup,
810 sPrefix, SchedGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
811 sPrefix, SchedGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
812 sPrefix, SchedGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
813 SchedGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
814 oTestGroup.idTestGroup, oTestGroup.idTestGroup, escapeElem(oTestGroup.sName),
815 ));
816 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oTestGroup.sName), ));
817
818 self._add(u' <td align="center">\n'
819 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
820 u' </td>\n'
821 % ( sPrefix, SchedGroupMemberData.ksParam_iSchedPriority,
822 (oMember if oMember is not None else oDefMember).iSchedPriority,
823 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
824
825 self._add(u' <td align="center">\n'
826 u' <select name="%s[%s]" id="%s[%s]" class="tmform-combobox"%s>\n'
827 u' <option value="-1"%s>None</option>\n'
828 % ( sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
829 sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
830 sComboBoxAttr,
831 ' selected' if oMember is None or oMember.idTestGroupPreReq is None else '',
832 ));
833 for oTestGroup2 in aoAllTestGroups:
834 if oTestGroup2 != oTestGroup:
835 fSelected = oMember is not None and oTestGroup2.idTestGroup == oMember.idTestGroupPreReq;
836 self._add(' <option value="%s"%s>%s</option>\n'
837 % ( oTestGroup2.idTestGroup, ' selected' if fSelected else '', escapeElem(oTestGroup2.sName), ));
838 self._add(u' </select>\n'
839 u' </td>\n');
840
841 self._add(u' <td align="left">\n'
842 u' Todo<input name="%s[%s]" type="hidden" value="%s">\n'
843 u' </td>\n'
844 % ( sPrefix, SchedGroupMemberData.ksParam_bmHourlySchedule,
845 '' if oMember is None else oMember.bmHourlySchedule, ));
846
847 self._add(u' </tr>\n');
848 return self._add(u' </tbody>\n'
849 u'</table>\n');
850
851 #
852 # Buttons.
853 #
854 def addSubmit(self, sLabel = 'Submit'):
855 """Adds the submit button to the form."""
856 if self._fReadOnly:
857 return True;
858 return self._add(u' <li>\n'
859 u' <br>\n'
860 u' <div class="tmform-field"><div class="tmform-field-submit">\n'
861 u' <label>&nbsp;</label>\n'
862 u' <input type="submit" value="%s">\n'
863 u' </div></div>\n'
864 u' </li>\n'
865 % (escapeElem(sLabel),));
866
867 def addReset(self):
868 """Adds a reset button to the form."""
869 if self._fReadOnly:
870 return True;
871 return self._add(u' <li>\n'
872 u' <div class="tmform-button"><div class="tmform-button-reset">\n'
873 u' <input type="reset" value="%s">\n'
874 u' </div></div>\n'
875 u' </li>\n');
876
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