Пример #1
0
    def parseArgs(self, args, printXOptions=None):
        try:
            optlist, self.arguments = getopt.getopt(args, self.optionString,
                                                    self.optionList)
        except Exception:
            log.warn("Error parsing command line arguments: %s" %
                     (sys.exc_info()[1]))
            sys.exit(1)

        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage(printXOptions)

            elif option in ("-a", "--all"):
                self.all = True

            elif option in ("-v", "--verbosity"):
                if value.upper() == "DEBUG":
                    stdoutHandler.setLevel(logging.DEBUG)
                elif value.upper() == "INFO":
                    stdoutHandler.setLevel(logging.INFO)
                elif value.upper() == "WARN":
                    stdoutHandler.setLevel(logging.WARN)
                elif value.upper() == "CRIT":
                    stdoutHandler.setLevel(logging.CRITICAL)

            elif option in ("-o", "--outdir"):
                self.outsubdir = value
Пример #2
0
    def parseArgs(self, args):
        try:
            optlist, arguments = getopt.getopt(args, 'ha:d:',
                                               ["help", "type=", "dir="])
        except Exception:
            print("Error parsing command line arguments: %s" %
                  (sys.exc_info()[1]))
            self.printUsage()

        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage()

            elif option in ("-a", "--type"):
                self.type = value
                if self.type not in ["auto", "manual"]:
                    log.warn(
                        "Unsupported test type - valid types are auto and manual"
                    )
                    sys.exit(1)

            elif option in ("-d", "--dir"):
                self.testdir = value

        if arguments == []:
            print("A valid string test id must be supplied")
            self.printUsage()
        else:
            self.testId = arguments[0]

        return self.testId
Пример #3
0
    def parseArgs(self, args):
        try:
            optlist, self.arguments = getopt.gnu_getopt(
                args, self.optionString, self.optionList)
        except Exception:
            log.warn("Error parsing command line arguments: %s" %
                     (sys.exc_info()[1]))
            sys.exit(1)

        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage()

            elif option in ("-f", "--full"):
                self.full = True

            elif option in ("-g", "--groups"):
                self.groups = True

            elif option in ("-d", "--modes"):
                self.modes = True

            elif option in ("-r", "--requirements"):
                self.requirements = True

            elif option in ("-m", "--mode"):
                self.modefilter = value
                if ',' in value or '!' in value:
                    raise UserError(
                        'Only one mode can be specified when printing tests')

            elif option in ("-a", "--type"):
                self.type = value
                if self.type not in ["auto", "manual"]:
                    log.warn(
                        "Unsupported test type - valid types are auto and manual"
                    )
                    sys.exit(1)

            elif option in ("-t", "--trace"):
                self.trace = value

            elif option in ("-i", "--include"):
                self.includes.append(value)

            elif option in ("-e", "--exclude"):
                self.excludes.append(value)

            elif option in ("-s", "--sort"):
                self.sort = value

            elif option in ("-G", "--grep"):
                self.grep = value

            elif option == '--json':
                self.json = True

            else:
                print("Unknown option: %s" % option)
                sys.exit(1)
Пример #4
0
	def assertLineCount(self, file, filedir=None, expr='', condition=">=1", ignores=None, encoding=None, **xargs):
		"""Perform a validation assert on the number of lines in a text file matching a specific regular expression.
		
		This method will add a C{PASSED} outcome to the outcome list if the number of lines in the 
		input file matching the specified regular expression evaluate to true when evaluated against 
		the supplied condition.
		
		@param file: The basename of the file used in the line count
		@param filedir: The dirname of the file (defaults to the testcase output subdirectory)
		@param expr: The regular expression string used to match a line of the input file
		@param condition: The condition to be met for the number of lines matching the regular expression
		@param ignores: A list of regular expressions that will cause lines to be excluded from the count
		@param encoding: The encoding to use to open the file. 
		The default value is None which indicates that the decision will be delegated 
		to the L{getDefaultFileEncoding()} method. 
		@param xargs: Variable argument list (see class description for supported parameters)
				
		"""	
		if filedir is None: filedir = self.output
		f = os.path.join(filedir, file)

		try:
			numberLines = linecount(f, expr, ignores=ignores, encoding=encoding or self.getDefaultFileEncoding(f))
			log.debug("Number of matching lines is %d"%numberLines)
		except Exception:
			log.warn("caught %s: %s", sys.exc_info()[0], sys.exc_info()[1], exc_info=1)
			msg = self.__assertMsg(xargs, 'Line count on %s for %s%s '%(file, quotestring(expr), condition))
			self.addOutcome(BLOCKED, '%s failed due to %s: %s'%(msg, sys.exc_info()[0], sys.exc_info()[1]), abortOnError=self.__abortOnError(xargs))
		else:
			if (eval("%d %s" % (numberLines, condition))):
				msg = self.__assertMsg(xargs, 'Line count on input file %s' % file)
				self.addOutcome(PASSED, msg, abortOnError=self.__abortOnError(xargs))
			else:
				msg = self.__assertMsg(xargs, 'Line count on %s for %s%s (actual =%d) '%(file, quotestring(expr), condition, numberLines))
				self.addOutcome(FAILED, msg, abortOnError=self.__abortOnError(xargs))
Пример #5
0
	def assertDiff(self, file1, file2, filedir1=None, filedir2=None, ignores=[], sort=False, replace=[], includes=[], encoding=None, **xargs):
		"""Perform a validation assert on the comparison of two input text files.
		
		This method performs a file comparison on two input files. The files are pre-processed prior to the 
		comparison to either ignore particular lines, sort their constituent lines, replace matches to regular 
		expressions in a line with an alternate value, or to only include particular lines. Should the files 
		after pre-processing be equivalent a C{PASSED} outcome is added to the test outcome list, otherwise
		a C{FAILED} outcome is added.
		
		@param file1: The basename of the first file used in the file comparison
		@param file2: The basename of the second file used in the file comparison (often a reference file)
		@param filedir1: The dirname of the first file (defaults to the testcase output subdirectory)
		@param filedir2: The dirname of the second file (defaults to the testcase reference directory)
		@param ignores: A list of regular expressions used to denote lines in the files which should be ignored
		@param sort: Boolean flag to indicate if the lines in the files should be sorted prior to the comparison
		@param replace: List of tuples of the form ('regexpr', 'replacement'). For each regular expression in the 
			list, any occurences in the files is replaced with the replacement value prior to the comparison being 
			carried out. This is often useful to replace timestamps in logfiles etc.
		@param includes: A list of regular expressions used to denote lines in the files which should be used in the 
			comparison. Only lines which match an expression in the list are used for the comparison
		@param encoding: The encoding to use to open the file. 
		The default value is None which indicates that the decision will be delegated 
		to the L{getDefaultFileEncoding()} method. 
		@param xargs: Variable argument list (see class description for supported parameters)
				
		"""
		if filedir1 is None: filedir1 = self.output
		if filedir2 is None: filedir2 = self.reference
		f1 = os.path.join(filedir1, file1)
		f2 = os.path.join(filedir2, file2)

		log.debug("Performing file comparison:")
		log.debug("  file1:       %s" % file1)
		log.debug("  filedir1:    %s" % filedir1)
		log.debug("  file2:       %s" % file2)
		log.debug("  filedir2:    %s" % filedir2)
		
		msg = self.__assertMsg(xargs, 'File comparison between %s and %s'%(file1, file2))
		unifiedDiffOutput=os.path.join(self.output, os.path.basename(f1)+'.diff')
		result = False
		try:
			result = filediff(f1, f2, ignores, sort, replace, includes, unifiedDiffOutput=unifiedDiffOutput, encoding=encoding or self.getDefaultFileEncoding(f1))
		except Exception:
			log.warn("caught %s: %s", sys.exc_info()[0], sys.exc_info()[1], exc_info=1)
			self.addOutcome(BLOCKED, '%s failed due to %s: %s'%(msg, sys.exc_info()[0], sys.exc_info()[1]), abortOnError=self.__abortOnError(xargs))
		else:
			try:
				self.addOutcome(PASSED if result else FAILED, msg, abortOnError=self.__abortOnError(xargs))
			finally:
				if not result:
					self.logFileContents(unifiedDiffOutput, encoding=encoding or self.getDefaultFileEncoding(f1))
Пример #6
0
	def assertOrderedGrep(self, file, filedir=None, exprList=[], contains=True, encoding=None, **xargs):   
		"""Perform a validation assert on a list of regular expressions occurring in specified order in a text file.
		
		When the C{contains} input argument is set to true, this method will append a C{PASSED} outcome 
		to the test outcome list if the supplied regular expressions in the C{exprList} are seen in the file
		in the order they appear in the list; otherwise a C{FAILED} outcome is added. Should C{contains} be set 
		to false, a C{PASSED} outcome will only be added should the regular expressions not be seen in the file in 
		the order they appear in the list.
		
		@param file: The basename of the file used in the ordered grep
		@param filedir: The dirname of the file (defaults to the testcase output subdirectory)
		@param exprList: A list of regular expressions which should occur in the file in the order they appear in the list
		@param contains: Boolean flag to denote if the expressions should or should not be seen in the file in the order specified
		@param encoding: The encoding to use to open the file. 
		The default value is None which indicates that the decision will be delegated 
		to the L{getDefaultFileEncoding()} method. 
		@param xargs: Variable argument list (see class description for supported parameters)
				
		"""
		if filedir is None: filedir = self.output
		f = os.path.join(filedir, file)
	
		log.debug("Performing ordered grep on file:")
		log.debug("  file:       %s" % file)
		log.debug("  filedir:    %s" % filedir)
		for expr in exprList: log.debug("  exprList:   %s" % expr)
		log.debug("  contains:   %s" % LOOKUP[contains])
		
		msg = self.__assertMsg(xargs, 'Ordered grep on input file %s' % file)
		expr = None
		try:
			expr = orderedgrep(f, exprList, encoding=encoding or self.getDefaultFileEncoding(f))
		except Exception:
			log.warn("caught %s: %s", sys.exc_info()[0], sys.exc_info()[1], exc_info=1)
			self.addOutcome(BLOCKED, '%s failed due to %s: %s'%(msg, sys.exc_info()[0], sys.exc_info()[1]), abortOnError=self.__abortOnError(xargs))
		else:
			if expr is None and contains:
				result = PASSED
			elif expr is None and not contains:
				result = FAILED
			elif expr is not None and not contains:
				result = PASSED
			else:
				result = FAILED

			if result == FAILED and expr: 
				msg += ' failed on expression \"%s\"'% expr
			self.addOutcome(result, msg, abortOnError=self.__abortOnError(xargs))
Пример #7
0
    def parseArgs(self, args):
        try:
            optlist, self.arguments = getopt.getopt(args, self.optionString,
                                                    self.optionList)
        except Exception:
            log.warn("Error parsing command line arguments: %s" %
                     (sys.exc_info()[1]))
            sys.exit(1)

        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage()

            elif option in ("-f", "--full"):
                self.full = True

            if option in ("-g", "--groups"):
                self.groups = True

            if option in ("-d", "--modes"):
                self.modes = True

            if option in ("-r", "--requirements"):
                self.requirements = True

            elif option in ("-m", "--mode"):
                self.mode = value

            elif option in ("-a", "--type"):
                self.type = value
                if self.type not in ["auto", "manual"]:
                    log.warn(
                        "Unsupported test type - valid types are auto and manual"
                    )
                    sys.exit(1)

            elif option in ("-t", "--trace"):
                self.trace = value

            elif option in ("-i", "--include"):
                self.includes.append(value)

            elif option in ("-e", "--exclude"):
                self.excludes.append(value)
Пример #8
0
    def parseArgs(self, args, printXOptions=None):
        try:
            optlist, self.arguments = getopt.gnu_getopt(
                args, self.optionString, self.optionList)
        except Exception:
            log.warn("Error parsing command line arguments: %s" %
                     (sys.exc_info()[1]))
            sys.exit(1)

        from pysys.internal.initlogging import pysysLogHandler, stdoutHandler
        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage(printXOptions)

            elif option in ("-a", "--all"):
                self.all = True

            elif option in ("-v", "--verbosity"):
                if value.upper() == "DEBUG":
                    verbosity = logging.DEBUG
                elif value.upper() == "INFO":
                    verbosity = logging.INFO
                elif value.upper() == "WARN":
                    verbosity = logging.WARN
                elif value.upper() == "CRIT":
                    verbosity = logging.CRITICAL
                else:
                    log.warn('Invalid log level "%s"' % value)
                    sys.exit(1)

                log.setLevel(verbosity)
                if verbosity == logging.DEBUG:
                    stdoutHandler.setLevel(verbosity)

                # refresh handler levels
                pysysLogHandler.setLogHandlersForCurrentThread([stdoutHandler])

            elif option in ("-o", "--outdir"):
                self.outsubdir = value

            else:
                print("Unknown option: %s" % option)
                sys.exit(1)
Пример #9
0
	def assertLastGrep(self, file, filedir=None, expr='', contains=True, ignores=[], includes=[], encoding=None, **xargs):
		"""Perform a validation assert on a regular expression occurring in the last line of a text file.
		
		When the C{contains} input argument is set to true, this method will add a C{PASSED} outcome 
		to the test outcome list if the supplied regular expression is seen in the file; otherwise a 
		C{FAILED} outcome is added. Should C{contains} be set to false, a C{PASSED} outcome will only 
		be added should the regular expression not be seen in the file.
		
		@param file: The basename of the file used in the grep
		@param filedir: The dirname of the file (defaults to the testcase output subdirectory)
		@param expr: The regular expression to check for in the last line of the file
		@param contains: Boolean flag to denote if the expression should or should not be seen in the file
		@param ignores: A list of regular expressions used to denote lines in the file which should be ignored
		@param includes: A list of regular expressions used to denote lines in the file which should be used in the assertion.#
		@param encoding: The encoding to use to open the file. 
		The default value is None which indicates that the decision will be delegated 
		to the L{getDefaultFileEncoding()} method. 
		@param xargs: Variable argument list (see class description for supported parameters)
				
		"""
		if filedir is None: filedir = self.output
		f = os.path.join(filedir, file)

		log.debug("Performing grep on file:")
		log.debug("  file:       %s" % file)
		log.debug("  filedir:    %s" % filedir)
		log.debug("  expr:       %s" % expr)
		log.debug("  contains:   %s" % LOOKUP[contains])

		msg = self.__assertMsg(xargs, 'Grep on last line of %s %s %s'%(file, 'contains' if contains else 'not contains', quotestring(expr)))
		try:
			result = lastgrep(f, expr, ignores, includes, encoding=encoding or self.getDefaultFileEncoding(f)) == contains
		except Exception:
			log.warn("caught %s: %s", sys.exc_info()[0], sys.exc_info()[1], exc_info=1)
			self.addOutcome(BLOCKED, '%s failed due to %s: %s'%(msg, sys.exc_info()[0], sys.exc_info()[1]), abortOnError=self.__abortOnError(xargs))
		else:
			if result: msg = self.__assertMsg(xargs, 'Grep on input file %s' % file)
			self.addOutcome(PASSED if result else FAILED, msg, abortOnError=self.__abortOnError(xargs))
Пример #10
0
    def parseArgs(self, args, printXOptions=None):
        try:
            optlist, self.arguments = getopt.getopt(args, self.optionString,
                                                    self.optionList)
        except Exception:
            log.warn("Error parsing command line arguments: %s" %
                     (sys.exc_info()[1]))
            sys.exit(1)

        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage(printXOptions)

            elif option in ("-r", "--record"):
                self.record = True

            elif option in ("-p", "--purge"):
                self.purge = True

            elif option in ("-v", "--verbosity"):
                self.verbosity = value
                if self.verbosity.upper() == "DEBUG":
                    stdoutHandler.setLevel(logging.DEBUG)
                elif self.verbosity.upper() == "INFO":
                    stdoutHandler.setLevel(logging.INFO)
                elif self.verbosity.upper() == "WARN":
                    stdoutHandler.setLevel(logging.WARN)
                elif self.verbosity.upper() == "CRIT":
                    stdoutHandler.setLevel(logging.CRITICAL)

            elif option in ("-a", "--type"):
                self.type = value
                if self.type not in ["auto", "manual"]:
                    log.warn(
                        "Unsupported test type - valid types are auto and manual"
                    )
                    sys.exit(1)

            elif option in ("-t", "--trace"):
                self.trace = value

            elif option in ("-i", "--include"):
                self.includes.append(value)

            elif option in ("-e", "--exclude"):
                self.excludes.append(value)

            elif option in ("-c", "--cycle"):
                try:
                    self.cycle = int(value)
                except Exception:
                    print(
                        "Error parsing command line arguments: A valid integer for the number of cycles must be supplied"
                    )
                    self.printUsage(printXOptions)

            elif option in ("-o", "--outdir"):
                self.outsubdir = value

            elif option in ("-m", "--mode"):
                self.mode = value

            elif option in ("-n", "--threads"):
                try:
                    self.threads = int(value)
                except Exception:
                    print(
                        "Error parsing command line arguments: A valid integer for the number of threads must be supplied"
                    )
                    self.printUsage(printXOptions)

            elif option in ("-b", "--abort"):
                setattr(PROJECT, 'defaultAbortOnError',
                        str(value.lower() == 'true'))

            elif option in ["-g", "--progress"]:
                self.progress = True

            elif option in ["-X"]:
                if EXPR1.search(value) is not None:
                    self.userOptions[value.split('=')[0]] = value.split('=')[1]
                if EXPR2.search(value) is not None:
                    self.userOptions[value] = True

            elif option in ("-y", "--validateOnly"):
                self.userOptions['validateOnly'] = True

        if os.getenv('PYSYS_PROGRESS', '').lower() == 'true':
            self.progress = True
        self.userOptions['__progressWritersEnabled'] = self.progress

        descriptors = createDescriptors(self.arguments, self.type,
                                        self.includes, self.excludes,
                                        self.trace, self.workingDir)
        # No exception handler above, as any createDescriptors failure is really a fatal problem that should cause us to
        # terminate with a non-zero exit code; we don't want to run no tests without realizing it and return success

        return self.record, self.purge, self.cycle, self.mode, self.threads, self.outsubdir, descriptors, self.userOptions
Пример #11
0
def filediff(file1,
             file2,
             ignore=[],
             sort=True,
             replacementList=[],
             include=[],
             unifiedDiffOutput=None,
             encoding=None):
    """Perform a file comparison between two (preprocessed) input files, returning true if the files are equivalent.
	
	The method reads in the files and loads the contents of each as a list of strings. The two files are 
	said to be equal if the two lists are equal. The method allows for preprocessing of the string lists 
	to trim down their contents prior to the comparison being performed. Preprocessing is either to remove 
	entries from the lists which match any entry in a set of regular expressions, include only lines which 
	match any entry in a set of regular expressions, replace certain keywords in the string values of each list
	with a set value (e.g. to replace time stamps etc), or to sort the lists before the comparison (e.g. where 
	determinism may not exist). Verbose logging of the method occurs at DEBUG level showing the contents of the 
	processed lists prior to the comparison being performed.  
	
	@param file1: The full path to the first file to use in the comparison
	@param file2: The full path to the second file to use in the comparison, typically a reference file
	@param ignore: A list of regular expressions which remove entries in the input file contents before making the comparison
	@param sort: Boolean to sort the input file contents before making the comparison
	@param replacementList: A list of tuples (key, value) where matches to key are replaced with value in the input file contents before making the comparison
	@param include: A list of regular expressions used to select lines from the input file contents to use in the comparison 
	@param unifiedDiffOutput: If specified, indicates the full path of a file to which unified diff output will be written, 
		if the diff fails. 
	@param encoding: Specifies the encoding to be used for opening the file, or None for default. 
	
	@return: success (True / False)
	@rtype: boolean
	@raises FileNotFoundException: Raised if either of the files do not exist

	"""
    for file in file1, file2:
        if not os.path.exists(file):
            raise FileNotFoundException("unable to find file %s" %
                                        (os.path.basename(file)))
    else:
        list1 = []
        list2 = []

        with openfile(file1, 'r', encoding=encoding) as f:
            for i in f:
                list1.append(i.strip())

        with openfile(file2, 'r', encoding=encoding) as f:
            for i in f:
                list2.append(i.strip())

        list1 = trimContents(list1, ignore, exclude=True)
        list2 = trimContents(list2, ignore, exclude=True)
        list1 = trimContents(list1, include, exclude=False)
        list2 = trimContents(list2, include, exclude=False)
        list1 = replace(list1, replacementList)
        list2 = replace(list2, replacementList)
        if sort:
            list1.sort()
            list2.sort()

        logContents(
            "Contents of %s after pre-processing;" % os.path.basename(file1),
            list1)
        logContents(
            "Contents of %s after pre-processing;" % os.path.basename(file2),
            list2)
        if not list1 and not list2:
            # maybe this should be an exception... it's probably not what was intended
            log.warn(
                'File comparison pre-processing has filtered out all lines from the files to be diffed, please check if this is intended: %s, %s',
                os.path.basename(file1), os.path.basename(file2))

        if list1 != list2:
            log.debug("Unified diff between pre-processed input files;")
            l1 = []
            l2 = []
            for i in list1:
                l1.append("%s\n" % i)
            for i in list2:
                l2.append("%s\n" % i)

            # nb: have to switch 1 and 2 around to get the right diff for a typical output,ref file pair
            diff = ''.join(
                difflib.unified_diff(
                    l2,
                    l1,
                    fromfile='%s (%d lines)' %
                    (os.path.basename(file2), len(l2)),
                    tofile='%s (%d lines)' %
                    (os.path.basename(file1), len(l1)),
                ))
            if unifiedDiffOutput:
                with openfile(unifiedDiffOutput, 'w', encoding=encoding) as f:
                    f.write(diff)
            for line in diff.split('\n'):
                log.debug("  %s", line)

        if list1 == list2: return True
        return False
Пример #12
0
    def parseArgs(self, args, printXOptions=None):
        # add any default args first; shlex.split does a great job of providing consistent parsing from str->list,
        # but need to avoid mangling \'s on windows; since this env var will be different for each OS no need for consistent win+unix behaviour
        if os.getenv('PYSYS_DEFAULT_ARGS', ''):
            log.info('Using PYSYS_DEFAULT_ARGS = %s' %
                     os.environ['PYSYS_DEFAULT_ARGS'])
            args = shlex.split(os.environ['PYSYS_DEFAULT_ARGS'].replace(
                os.sep, os.sep * 2 if os.sep == '\\' else os.sep)) + args

        printLogsDefault = PrintLogs.ALL
        if '--ci' in args:
            # to ensure identical behaviour, set these as if on the command line
            # (printLogs we don't set here since we use the printLogsDefault mechanism to allow it to be overridden
            # by CI writers and/or the command line; note that setting --mode=ALL would be incorrect if
            # supportMultipleModesPerRun=false but that's a legacy options so we raise an exception later if this happened)
            args = [
                '--purge', '--record', '-j0', '--type=auto', '--mode=ALL',
                '-XcodeCoverage'
            ] + args
            printLogsDefault = PrintLogs.FAILURES

        try:
            optlist, self.arguments = getopt.gnu_getopt(
                args, self.optionString, self.optionList)
        except Exception:
            log.warn("Error parsing command line arguments: %s" %
                     (sys.exc_info()[1]))
            sys.exit(1)

        log.debug('PySys arguments: tests=%s options=%s', self.arguments,
                  optlist)

        EXPR1 = re.compile("^[\w\.]*=.*$")
        EXPR2 = re.compile("^[\w\.]*$")

        printLogs = None
        ci = False
        defaultAbortOnError = None

        logging.getLogger('pysys').setLevel(logging.INFO)

        # as a special case, set a non-DEBUG log level for the implementation of assertions
        # so that it doesn't get enabled with -vDEBUG only -vassertions=DEBUG
        # as it is incredibly verbose and slow and not often useful
        logging.getLogger('pysys.assertions').setLevel(logging.INFO)

        for option, value in optlist:
            if option in ("-h", "--help"):
                self.printUsage(printXOptions)

            elif option in ['--ci']:
                continue  # handled above

            elif option in ("-r", "--record"):
                self.record = True

            elif option in ("-p", "--purge"):
                self.purge = True

            elif option in ("-v", "--verbosity"):
                verbosity = value
                if '=' in verbosity:
                    loggername, verbosity = value.split('=')
                    assert not loggername.startswith(
                        'pysys.'
                    ), 'The "pysys." prefix is assumed and should not be explicitly specified'
                    if loggername.startswith('python:'):
                        loggername = loggername[len('python:'):]
                        assert not loggername.startswith(
                            'pysys'
                        ), 'Cannot use python: with pysys.*'  # would produce a duplicate log handler
                        # in the interests of performance and simplicity we normally only add the pysys.* category
                        logging.getLogger(loggername).addHandler(
                            pysys.internal.initlogging.pysysLogHandler)
                    else:
                        loggername = 'pysys.' + loggername
                else:
                    loggername = None

                if verbosity.upper() == "DEBUG":
                    verbosity = logging.DEBUG
                elif verbosity.upper() == "INFO":
                    verbosity = logging.INFO
                elif verbosity.upper() == "WARN":
                    verbosity = logging.WARN
                elif verbosity.upper() == "CRIT":
                    verbosity = logging.CRITICAL
                else:
                    log.warn('Invalid log level "%s"' % verbosity)
                    sys.exit(1)

                if loggername is None:
                    # when setting global log level to a higher level like WARN etc we want to affect stdout but
                    # not necessarily downgrade the root level (would make run.log less useful and break
                    # some PrintLogs behaviour)
                    stdoutHandler.setLevel(verbosity)
                    if verbosity == logging.DEBUG:
                        logging.getLogger('pysys').setLevel(logging.DEBUG)
                else:
                    # for specific level setting we need the opposite - only change stdoutHandler if we're
                    # turning up the logging (since otherwise it wouldn't be seen) but also change the specified level
                    logging.getLogger(loggername).setLevel(verbosity)

            elif option in ("-a", "--type"):
                self.type = value
                if self.type not in ["auto", "manual"]:
                    log.warn(
                        "Unsupported test type - valid types are auto and manual"
                    )
                    sys.exit(1)

            elif option in ("-t", "--trace"):
                self.trace = value

            elif option in ("-i", "--include"):
                self.includes.append(value)

            elif option in ("-e", "--exclude"):
                self.excludes.append(value)

            elif option in ("-c", "--cycle"):
                try:
                    self.cycle = int(value)
                except Exception:
                    print(
                        "Error parsing command line arguments: A valid integer for the number of cycles must be supplied"
                    )
                    sys.exit(1)

            elif option in ("-o", "--outdir"):
                value = os.path.normpath(value)
                if os.path.isabs(value) and not value.startswith('\\\\?\\'):
                    value = fromLongPathSafe(toLongPathSafe(value))
                self.outsubdir = value

            elif option in ("-m", "--mode", "--modeinclude"):
                self.modeinclude = self.modeinclude + [
                    x.strip() for x in value.split(',')
                ]

            elif option in ["--modeexclude"]:
                self.modeexclude = self.modeexclude + [
                    x.strip() for x in value.split(',')
                ]

            elif option in ["-n", "-j", "--threads"]:
                N_CPUS = multiprocessing.cpu_count()
                if value.lower() == 'auto': value = '0'
                if value.lower().startswith('x'):
                    self.threads = max(1, int(float(value[1:]) * N_CPUS))
                else:
                    self.threads = int(value)
                    if self.threads <= 0:
                        self.threads = int(
                            os.getenv('PYSYS_DEFAULT_THREADS', N_CPUS))

            elif option in ("-b", "--abort"):
                defaultAbortOnError = str(value.lower() == 'true')

            elif option in ["-g", "--progress"]:
                self.progress = True

            elif option in ["--printLogs"]:
                printLogs = getattr(PrintLogs, value.upper(), None)
                if printLogs is None:
                    print(
                        "Error parsing command line arguments: Unsupported --printLogs value '%s'"
                        % value)
                    sys.exit(1)

            elif option in ["-X"]:
                if '=' in value:
                    key, value = value.split('=', 1)
                else:
                    key, value = value, 'true'

                # best not to risk unintended consequences with matching of other types, but for boolean
                # it's worth it to resolve the inconsistent behaviour of -Xkey=true and -Xkey that existed until 1.6.0,
                # and because getting a bool where you expected a string is a bit more likely to give an exception
                # and be noticed that getting a string where you expected a boolean (e.g. the danger of if "false":)
                if value.lower() == 'true':
                    value = True
                elif value.lower() == 'false':
                    value = False

                self.userOptions[key] = value

            elif option in ("-y", "--validateOnly"):
                self.userOptions['validateOnly'] = True

            elif option in ("-G", "--grep"):
                self.grep = value

            else:
                print("Unknown option: %s" % option)
                sys.exit(1)

        # log this once we've got the log levels setup
        log.debug('PySys is installed at: %s; python from %s',
                  os.path.dirname(pysys.__file__), sys.executable)

        # retained for compatibility, but PYSYS_DEFAULT_ARGS is a better way to achieve the same thing
        if os.getenv('PYSYS_PROGRESS', '').lower() == 'true':
            self.progress = True

        # special hidden dict of extra values to pass to the runner, since we can't change
        # the public API now
        self.userOptions['__extraRunnerOptions'] = {
            'progressWritersEnabled': self.progress,
            'printLogs': printLogs,
            'printLogsDefault':
            printLogsDefault,  # to use if not provided by a CI writer or cmdline
        }

        # load project AFTER we've parsed the arguments, which opens the possibility of using cmd line config in
        # project properties if needed
        Project.findAndLoadProject(outdir=self.outsubdir)

        if defaultAbortOnError is not None:
            setattr(Project.getInstance(), 'defaultAbortOnError',
                    defaultAbortOnError)
        if '--ci' in args and not Project.getInstance().getProperty(
                'supportMultipleModesPerRun', True):
            raise UserError(
                'Cannot use --ci option with a legacy supportMultipleModesPerRun=false project'
            )

        descriptors = createDescriptors(self.arguments,
                                        self.type,
                                        self.includes,
                                        self.excludes,
                                        self.trace,
                                        self.workingDir,
                                        modeincludes=self.modeinclude,
                                        modeexcludes=self.modeexclude,
                                        expandmodes=True)
        descriptors.sort(
            key=lambda d: [d.executionOrderHint, d._defaultSortKey])

        # No exception handler above, as any createDescriptors failure is really a fatal problem that should cause us to
        # terminate with a non-zero exit code; we don't want to run no tests without realizing it and return success

        if self.grep:
            regex = re.compile(self.grep, flags=re.IGNORECASE)
            descriptors = [
                d for d in descriptors
                if (regex.search(d.id) or regex.search(d.title))
            ]

        runnermode = self.modeinclude[0] if len(
            self.modeinclude
        ) == 1 else None  # used when supportMultipleModesPerRun=False
        return self.record, self.purge, self.cycle, runnermode, self.threads, self.outsubdir, descriptors, self.userOptions
Пример #13
0
def makeProject(args):
    _PYSYS_SCRIPT_NAME = os.path.basename(
        sys.argv[0]) if '__main__' not in sys.argv[0] else 'pysys.py'
    templatelist = ', '.join(sorted(getProjectConfigTemplates().keys()))

    def printUsage():
        print(
            "\nPySys System Test Framework (version %s): Project configuration file maker"
            % __version__)
        print("")
        print("Usage: %s makeproject [option]* [--template=TEMPLATE]" %
              (_PYSYS_SCRIPT_NAME))
        print("")
        print("   where TEMPLATE can be: %s" % templatelist)
        print("")
        print("   and [option] includes:")
        print("       -h | --help                 print this message")
        print(
            "       -d | --dir      STRING      root directory in which to create project configuration file"
        )
        print(
            "                                   (default is current working dir)"
        )
        print("")
        print("Project configuration templates are stored in: %s" %
              os.path.normpath(
                  os.path.dirname(getProjectConfigTemplates()['default'])))
        sys.exit()

    optionString = 'hd:'
    optionList = ['dir=', 'help', 'template=']

    try:
        optlist, arguments = getopt.gnu_getopt(args, optionString, optionList)
    except Exception:
        log.warn("Error parsing command line arguments: %s" %
                 (sys.exc_info()[1]))
        sys.exit(1)

    dir = '.'
    tmpl = 'default'
    for option, value in optlist:
        if option in ["-h", "--help"]:
            printUsage()

        if option in ["--template"]:
            tmpl = value

        elif option in ["-d", "--dir"]:
            dir = value

        else:
            print("Unknown option: %s" % option)
            sys.exit(1)

    if arguments:
        print("Unexpected argument '%s'; maybe you meant to use --template" %
              arguments[0])
        sys.exit(1)

    templates = getProjectConfigTemplates()
    if tmpl not in templates:
        print(
            "Unknown template '%s', please specify one of the following: %s" %
            (tmpl, templatelist))
        sys.exit(1)
    if os.path.exists(dir):
        for f in os.listdir(dir):
            if f in DEFAULT_PROJECTFILE:
                print("Cannot create as project file already exists: %s" %
                      os.path.normpath(dir + '/' + f))
                sys.exit(1)

    createProjectConfig(dir, templates[tmpl])
    print(
        "Successfully created project configuration in root directory '%s'." %
        os.path.normpath(dir))
    print(
        "Now change to that directory and use 'pysys make' to create your first testcase."
    )
Пример #14
0
	def assertGrep(self, file, filedir=None, expr='', contains=True, ignores=None, literal=False, encoding=None, **xargs):
		"""Perform a validation assert on a regular expression occurring in a text file.
		
		When the C{contains} input argument is set to true, this method will add a C{PASSED} outcome 
		to the test outcome list if the supplied regular expression is seen in the file; otherwise a 
		C{FAILED} outcome is added. Should C{contains} be set to false, a C{PASSED} outcome will only 
		be added should the regular expression not be seen in the file.
		
		@param file: The basename of the file used in the grep
		@param filedir: The dirname of the file (defaults to the testcase output subdirectory)
		@param expr: The regular expression to check for in the file (or a string literal if literal=True). 
			If the match fails, the matching regex will be reported as the test outcome
		@param contains: Boolean flag to denote if the expression should or should not be seen in the file
		@param ignores: Optional list of regular expressions that will be 
			ignored when reading the file. 
		@param literal: By default expr is treated as a regex, but set this to True to pass in 
			a string literal instead
		@param encoding: The encoding to use to open the file. 
		The default value is None which indicates that the decision will be delegated 
		to the L{getDefaultFileEncoding()} method. 
		@param xargs: Variable argument list (see class description for supported parameters)
				
		"""
		if filedir is None: filedir = self.output
		f = os.path.join(filedir, file)

		if literal:
			def escapeRegex(expr):
				# use our own escaping as re.escape makes the string unreadable
				regex = expr
				expr = ''
				for c in regex:
					if c in '\\{}[]+?^$':
						expr += '\\'+c
					elif c in '().*/':
						expr += '['+c+']' # more readable
					else:
						expr += c
				return expr
			expr = escapeRegex(expr)

		log.debug("Performing grep on file:")
		log.debug("  file:       %s" % file)
		log.debug("  filedir:    %s" % filedir)
		log.debug("  expr:       %s" % expr)
		log.debug("  contains:   %s" % LOOKUP[contains])
		try:
			result = filegrep(f, expr, ignores=ignores, returnMatch=True, encoding=encoding or self.getDefaultFileEncoding(f))
		except Exception:
			log.warn("caught %s: %s", sys.exc_info()[0], sys.exc_info()[1], exc_info=1)
			msg = self.__assertMsg(xargs, 'Grep on %s %s %s'%(file, 'contains' if contains else 'does not contain', quotestring(expr) ))
			self.addOutcome(BLOCKED, '%s failed due to %s: %s'%(msg, sys.exc_info()[0], sys.exc_info()[1]), abortOnError=self.__abortOnError(xargs))
		else:
			# short message if it succeeded, more verbose one if it failed to help you understand why, 
			# including the expression it found that should not have been there
			outcome = PASSED if (result!=None) == contains else FAILED
			if outcome == PASSED: 
				msg = self.__assertMsg(xargs, 'Grep on input file %s' % file)
			else:
				msg = self.__assertMsg(xargs, 'Grep on %s %s %s'%(file, 'contains' if contains else 'does not contain', 
					quotestring(result.group(0) if result else expr) ))
			self.addOutcome(outcome, msg, abortOnError=self.__abortOnError(xargs))