1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import sys, os, os.path, stat, glob, getopt, re, string, logging
20
21 from pysys import log
22 from pysys import stdoutHandler
23
24 from pysys import __version__
25 from pysys.constants import *
26 from pysys.exceptions import *
27 from pysys.launcher import createDescriptors
28 from pysys.xml.descriptor import DESCRIPTOR_TEMPLATE
29 from pysys.basetest import TEST_TEMPLATE
30
31 EXPR1 = re.compile("^[\w\.]*=.*$")
32 EXPR2 = re.compile("^[\w\.]*$")
33 EXPR3 = re.compile("^[\w]*_([0-9]+)$")
34
35
37 - def __init__(self, workingDir, name=""):
38 self.workingDir = workingDir
39 self.arguments = []
40 self.outsubdir = PLATFORM
41 self.all = False
42 self.name = name
43 self.optionString = 'hav:o:'
44 self.optionList = ["help","all", "verbosity=","outdir="]
45
46
48 print "\nPySys System Test Framework (version %s): Console clean test helper" % __version__
49 print "\nUsage: %s %s [option]* [tests]*" % (os.path.basename(sys.argv[0]), self.name)
50 print " where [option] includes;"
51 print " -h | --help print this message"
52 print " -a | --all clean all compiled testclass files"
53 print " -v | --verbosity STRING set the verbosity level (CRIT, WARN, INFO, DEBUG)"
54 print " -o | --outdir STRING set the name of the test output subdirectories to clean"
55 sys.exit()
56
57
58 - def parseArgs(self, args, printXOptions=None):
59 try:
60 optlist, self.arguments = getopt.getopt(args, self.optionString, self.optionList)
61 except:
62 log.warn("Error parsing command line arguments: %s" % (sys.exc_info()[1]))
63 sys.exit(1)
64
65 for option, value in optlist:
66 if option in ("-h", "--help"):
67 self.printUsage(printXOptions)
68
69 elif option in ("-a", "--all"):
70 self.all = True
71
72 elif option in ("-v", "--verbosity"):
73 if value.upper() == "DEBUG":
74 stdoutHandler.setLevel(logging.DEBUG)
75 elif value.upper() == "INFO":
76 stdoutHandler.setLevel(logging.INFO)
77 elif value.upper() == "WARN":
78 stdoutHandler.setLevel(logging.WARN)
79 elif value.upper() == "CRIT":
80 stdoutHandler.setLevel(logging.CRITICAL)
81
82 elif option in ("-o", "--outdir"):
83 self.outsubdir = value
84
85
87 try:
88 descriptors = createDescriptors(self.arguments, None, [], [], None, self.workingDir)
89 except Exception, (strerror):
90 log.info(strerror)
91 else:
92 for descriptor in descriptors:
93 if self.all:
94 if sys.version_info >= (3,):
95 cache=os.path.join(os.path.dirname(descriptor.module),"__pycache__")
96 if os.path.exists(cache):
97 log.info("Deleting pycache: " + cache)
98 self.purgeDirectory(cache, True)
99 else:
100 path = descriptor.module + ".pyc"
101 try:
102 mode = os.stat(path)[stat.ST_MODE]
103 if stat.S_ISLNK(mode):
104 os.unlink(path)
105 if stat.S_ISREG(mode):
106 os.remove(path)
107 log.info("Deleting compiled module: " + path)
108 except:
109 log.debug("Error deleting compiled module: " + path)
110
111 pathToDelete = os.path.join(descriptor.output, self.outsubdir)
112 if os.path.exists(pathToDelete):
113 log.info("Deleting output directory: " + pathToDelete)
114 self.purgeDirectory(pathToDelete, True)
115 else:
116 log.debug("Output directory does not exist: " + pathToDelete)
117
118
120 for file in os.listdir(dir):
121 path = os.path.join(dir, file)
122 if PLATFORM in ['sunos', 'linux']:
123 mode = os.lstat(path)[stat.ST_MODE]
124 else:
125 mode = os.stat(path)[stat.ST_MODE]
126
127 if stat.S_ISLNK(mode):
128 os.unlink(path)
129 if stat.S_ISREG(mode):
130 os.remove(path)
131 elif stat.S_ISDIR(mode):
132 self.purgeDirectory(path, delTop=True)
133
134 if delTop: os.rmdir(dir)
135
136
138 - def __init__(self, workingDir, name=""):
139 self.workingDir = workingDir
140 self.arguments = []
141 self.full = False
142 self.groups = False
143 self.modes = False
144 self.requirements = False
145 self.mode = None
146 self.type = None
147 self.trace = None
148 self.includes = []
149 self.excludes = []
150 self.tests = None
151 self.name = name
152 self.optionString = 'hfgdrm:a:t:i:e:'
153 self.optionList = ["help","full","groups","modes","requirements","mode=","type=","trace=","include=","exclude="]
154
155
157 print "\nPySys System Test Framework (version %s): Console print test helper" % __version__
158 print "\nUsage: %s %s [option]* [tests]*" % (os.path.basename(sys.argv[0]), self.name)
159 print " where options include;"
160 print " -h | --help print this message"
161 print " -f | --full print full information"
162 print " -g | --groups print test groups defined"
163 print " -d | --modes print test modes defined"
164 print " -r | --requirements print test requirements covered"
165 print " -m | --mode STRING print tests that run in user defined mode "
166 print " -a | --type STRING print tests of supplied type (auto or manual, default all)"
167 print " -t | --trace STRING print tests which cover requirement id "
168 print " -i | --include STRING print tests in included group (can be specified multiple times)"
169 print " -e | --exclude STRING do not print tests in excluded group (can be specified multiple times)"
170 print ""
171 print " and where [tests] describes a set of tests to be printed to the console. Note that multiple test "
172 print " sets can be specified, and where none are given all available tests will be run. If an include "
173 print " group is given, only tests that belong to that group will be printed. If an exclude group is given, "
174 print " tests in the group will not be run. The following syntax is used to select a test set;"
175 print ""
176 print " test1 - a single testcase with id test1"
177 print " :test2 - upto testcase with id test2"
178 print " test1: - from testcase with id test1 onwards"
179 print " id1:id2 - all tests between tests with ids test1 and test2"
180 print ""
181 print " e.g. "
182 print " %s -i group1 -e group2 --full test1:test3" % os.path.basename(sys.argv[0])
183 print ""
184 sys.exit()
185
186
188 try:
189 optlist, self.arguments = getopt.getopt(args, self.optionString, self.optionList)
190 except:
191 log.warn("Error parsing command line arguments: %s" % (sys.exc_info()[1]))
192 sys.exit(1)
193
194 for option, value in optlist:
195 if option in ("-h", "--help"):
196 self.printUsage()
197
198 elif option in ("-f", "--full"):
199 self.full = True
200
201 if option in ("-g", "--groups"):
202 self.groups = True
203
204 if option in ("-d", "--modes"):
205 self.modes = True
206
207 if option in ("-r", "--requirements"):
208 self.requirements = True
209
210 elif option in ("-m", "--mode"):
211 self.mode = value
212
213 elif option in ("-a", "--type"):
214 self.type = value
215 if self.type not in ["auto", "manual"]:
216 log.warn("Unsupported test type - valid types are auto and manual")
217 sys.exit(1)
218
219 elif option in ("-t", "--trace"):
220 self.trace = value
221
222 elif option in ("-i", "--include"):
223 self.includes.append(value)
224
225 elif option in ("-e", "--exclude"):
226 self.excludes.append(value)
227
228
230 try:
231 descriptors = createDescriptors(self.arguments, self.type, self.includes, self.excludes, self.trace, self.workingDir)
232 except Exception, (strerror):
233 log.info(strerror)
234 else:
235 exit = 0
236 if self.groups == True:
237 groups = []
238 for descriptor in descriptors:
239 for group in descriptor.groups:
240 if group not in groups:
241 groups.append(group)
242 print "\nGroups defined: "
243 for group in groups:
244 print " %s" % (group)
245 exit = 1
246
247 if self.modes == True:
248 modes = []
249 for descriptor in descriptors:
250 for mode in descriptor.modes:
251 if mode not in modes:
252 modes.append(mode)
253 print "\nModes defined: "
254 for mode in modes:
255 print " %s" % (mode)
256 exit = 1
257
258 if self.requirements == True:
259 requirements = []
260 for descriptor in descriptors:
261 for requirement in descriptor.traceability:
262 if requirement not in requirements:
263 requirements.append(requirement)
264 print "\nRequirements covered: "
265 for requirement in requirements:
266 print " %s" % (requirement)
267 exit = 1
268
269 if exit: return
270
271 maxsize = 0
272 for descriptor in descriptors:
273 if len(descriptor.id) > maxsize: maxsize = len(descriptor.id)
274 maxsize = maxsize + 2
275
276 for descriptor in descriptors:
277 if self.mode and not self.mode in descriptor.modes: continue
278 padding = " " * (maxsize - len(descriptor.id))
279 if not self.full:
280 print "%s:%s%s" % (descriptor.id, padding, descriptor.title)
281 else:
282 print "=========================================="
283 print " " + descriptor.id
284 print "=========================================="
285 print descriptor
286
287
288
291 self.name = name
292 self.testId = None
293 self.type = "auto"
294 self.testdir = os.getcwd()
295
296
298 print "\nPySys System Test Framework (version %s): Console make test helper" % __version__
299 print "\nUsage: %s %s [option]+ [testid]" % (os.path.basename(sys.argv[0]), self.name)
300 print " where [option] includes;"
301 print " -h | --help print this message"
302 print " -a | --type STRING set the test type (auto or manual, default is auto)"
303 print " -d | --dir STRING base path to testcase (default is current working dir)"
304 print ""
305 print " and where [testid] is the mandatory test identifier."
306 sys.exit()
307
308
310 try:
311 optlist, arguments = getopt.getopt(args, 'ht:d:', ["help","type=","dir="] )
312 except:
313 print "Error parsing command line arguments: %s" % (sys.exc_info()[1])
314 self.printUsage()
315
316 for option, value in optlist:
317 if option in ("-h", "--help"):
318 self.printUsage()
319
320 elif option in ("-a", "--type"):
321 self.type = value
322 if self.type not in ["auto", "manual"]:
323 log.warn("Unsupported test type - valid types are auto and manual")
324 sys.exit(1)
325
326 elif option in ("-d", "--dir"):
327 self.testdir = value
328
329 if arguments == []:
330 print "A valid string test id must be supplied"
331 self.printUsage()
332 else:
333 self.testId = arguments[0]
334
335 return self.testId
336
337
338 - def makeTest(self, input=None, output=None, reference=None, descriptor=None, testclass=None, module=None,
339 group="", constantsImport=None, basetestImport=None, basetest=None, teststring=None):
340 if input==None: input = DEFAULT_INPUT
341 if output==None: output = DEFAULT_OUTPUT
342 if reference==None: reference = DEFAULT_REFERENCE
343 if descriptor==None: descriptor = DEFAULT_DESCRIPTOR[0]
344 if testclass==None: testclass = DEFAULT_TESTCLASS
345 if module==None: module = DEFAULT_MODULE
346 if constantsImport ==None: constantsImport = "from pysys.constants import *"
347 if basetestImport == None: basetestImport = "from pysys.basetest import BaseTest"
348 if basetest == None: basetest = "BaseTest"
349
350 log.info("Creating testcase %s ..." % self.testId)
351 try:
352 os.makedirs(os.path.join(self.testdir, self.testId))
353 log.info("Created directory %s" % os.path.join(self.testdir, self.testId))
354 except OSError:
355 log.info("Error creating testcase " + os.path.join(self.testdir, self.testId) + " - directory already exists")
356 return
357 else:
358 os.makedirs(os.path.join(self.testdir, self.testId, input))
359 log.info("Created directory %s " % os.path.join(self.testdir, self.testId, input))
360 os.makedirs(os.path.join(self.testdir, self.testId, output))
361 log.info("Created directory %s " % os.path.join(self.testdir, self.testId, output))
362 os.makedirs(os.path.join(self.testdir, self.testId, reference))
363 log.info("Created directory %s " % os.path.join(self.testdir, self.testId, reference))
364 descriptor_fp = open(os.path.join(self.testdir, self.testId, descriptor), "w")
365 descriptor_fp.write(DESCRIPTOR_TEMPLATE %(self.type, group, testclass, module))
366 descriptor_fp.close()
367 log.info("Created descriptor %s " % os.path.join(self.testdir, self.testId, descriptor))
368 testclass_fp = open(os.path.join(self.testdir, self.testId, "%s.py" % module), "w")
369 if teststring == None:
370 testclass_fp.write(TEST_TEMPLATE % (constantsImport, basetestImport, testclass, basetest))
371 else:
372 testclass_fp.write(teststring)
373 testclass_fp.close()
374 log.info("Created test class module %s " % os.path.join(self.testdir, self.testId, "%s.py" % module))
375
376
377
379 - def __init__(self, workingDir, name=""):
380 self.workingDir = workingDir
381 self.arguments = []
382 self.record = False
383 self.purge = False
384 self.type = None
385 self.trace = None
386 self.includes = []
387 self.excludes = []
388 self.cycle = 1
389 self.outsubdir = PLATFORM
390 self.mode = None
391 self.threads = 1
392 self.name=name
393 self.userOptions = {}
394 self.descriptors = []
395 self.optionString = 'hrpyv:a:t:i:e:c:o:m:n:b:X:'
396 self.optionList = ["help","record","purge","verbosity=","type=","trace=","include=","exclude=","cycle=","outdir=","mode=","threads=", "abort=", 'validateOnly']
397
398
400 print "\nPySys System Test Framework (version %s): Console run test helper" % __version__
401 print "\nUsage: %s %s [option]* [tests]*" % (os.path.basename(sys.argv[0]), self.name)
402 print " where [option] includes;"
403 print " -h | --help print this message"
404 print " -r | --record record the test results in the working directory"
405 print " -p | --purge purge the output subdirectory on test pass"
406 print " -v | --verbosity STRING set the verbosity level (CRIT, WARN, INFO, DEBUG)"
407 print " -a | --type STRING set the test type to run (auto or manual, default is both)"
408 print " -t | --trace STRING set the requirement id for the test run"
409 print " -i | --include STRING set the test groups to include (can be specified multiple times)"
410 print " -e | --exclude STRING set the test groups to exclude (can be specified multiple times)"
411 print " -c | --cycle INT set the the number of cycles to run the tests"
412 print " -o | --outdir STRING set the name of the test output subdirectory"
413 print " -m | --mode STRING set the user defined mode to run the tests"
414 print " -n | --threads INT set the number of worker threads to run the tests (defaults to 1). "
415 print " A value of 0 sets to the number of available CPUs"
416 print " -b | --abort STRING set the default abort on error property (true|false, overrides "
417 print " that specified in the project properties)"
418 print " -y | --validateOnly test the validate() method without re-running execute()"
419 print " -X KEY=VALUE set user defined options to be passed through to the test and "
420 print " runner classes. The left hand side string is the data attribute "
421 print " to set, the right hand side string the value (True of not specified) "
422 if printXOptions: printXOptions()
423 print ""
424 print " and where [tests] describes a set of tests to be run. Note that multiple test sets can be specified, "
425 print " where none are given all available tests will be run. If an include group is given, only tests that "
426 print " belong to that group will be run. If an exclude group is given, tests in the group will not be run. "
427 print " Tests should contain only alphanumeric and the underscore characters. The following syntax is used "
428 print " to select a test set;"
429 print ""
430 print " test1 - a single testcase with id test1"
431 print " :test2 - up to testcase with id test2"
432 print " test1: - from testcase with id test1 onwards"
433 print " test1:test2 - all tests between tests with ids test1 and test2"
434 print " test1 test 2 test5:test9 - test1, test2 and all tests between test5 and test9"
435 print " ^test* - all tests matching the regex ^test*"
436 print ""
437 print " e.g. "
438 print " %s -vDEBUG --include MYTESTS test1:test4 test7" % os.path.basename(sys.argv[0])
439 print " %s -c2 -Xhost=localhost test1:" % os.path.basename(sys.argv[0])
440 print ""
441 sys.exit()
442
443
444 - def parseArgs(self, args, printXOptions=None):
445 try:
446 optlist, self.arguments = getopt.getopt(args, self.optionString, self.optionList)
447 except:
448 log.warn("Error parsing command line arguments: %s" % (sys.exc_info()[1]))
449 sys.exit(1)
450
451 for option, value in optlist:
452 if option in ("-h", "--help"):
453 self.printUsage(printXOptions)
454
455 elif option in ("-r", "--record"):
456 self.record = True
457
458 elif option in ("-p", "--purge"):
459 self.purge = True
460
461 elif option in ("-v", "--verbosity"):
462 self.verbosity = value
463 if self.verbosity.upper() == "DEBUG":
464 stdoutHandler.setLevel(logging.DEBUG)
465 elif self.verbosity.upper() == "INFO":
466 stdoutHandler.setLevel(logging.INFO)
467 elif self.verbosity.upper() == "WARN":
468 stdoutHandler.setLevel(logging.WARN)
469 elif self.verbosity.upper() == "CRIT":
470 stdoutHandler.setLevel(logging.CRITICAL)
471
472 elif option in ("-a", "--type"):
473 self.type = value
474 if self.type not in ["auto", "manual"]:
475 log.warn("Unsupported test type - valid types are auto and manual")
476 sys.exit(1)
477
478 elif option in ("-t", "--trace"):
479 self.trace = value
480
481 elif option in ("-i", "--include"):
482 self.includes.append(value)
483
484 elif option in ("-e", "--exclude"):
485 self.excludes.append(value)
486
487 elif option in ("-c", "--cycle"):
488 try:
489 self.cycle = int(value)
490 except:
491 print "Error parsing command line arguments: A valid integer for the number of cycles must be supplied"
492 self.printUsage(printXOptions)
493
494 elif option in ("-o", "--outdir"):
495 self.outsubdir = value
496
497 elif option in ("-m", "--mode"):
498 self.mode = value
499
500 elif option in ("-n", "--threads"):
501 try:
502 self.threads = int(value)
503 except:
504 print "Error parsing command line arguments: A valid integer for the number of threads must be supplied"
505 self.printUsage(printXOptions)
506
507 elif option in ("-b", "--abort"):
508 setattr(PROJECT, 'defaultAbortOnError', str(value.lower()=='true'))
509
510 elif option in ["-X"]:
511 if EXPR1.search(value) is not None:
512 self.userOptions[value.split('=')[0]] = value.split('=')[1]
513 if EXPR2.search(value) is not None:
514 self.userOptions[value] = True
515
516 elif option in ("-y", "--validateOnly"):
517 self.userOptions['validateOnly'] = True
518 try:
519 descriptors = createDescriptors(self.arguments, self.type, self.includes, self.excludes, self.trace, self.workingDir)
520 except Exception, (strerror):
521 log.info(strerror)
522 descriptors = []
523 return self.record, self.purge, self.cycle, self.mode, self.threads, self.outsubdir, descriptors, self.userOptions
524