class CoderRunner(object): def __init__(self, configuration, testFiles): self.logger = Logger() self._configuration = configuration self._icoder = CoderUtil(configuration) self._testFiles = testFiles self._unittestRunner = unittest.TextTestRunner() self._testlist = unittest.TestSuite() self._switches = "" self._version = self._icoder.getVersion() def extractRelatedStories(self, line): # find string that starts with "#" and follows by numbers and characters # furthermore, see the link: https://docs.python.org/2/library/re.html return re.findall("#\d\w+", line) def extractTestProjectAndStartMethod(self, line): # find string that does not starts with "'%sys%'" rs = re.findall("(?<='%sys%' )[a-zA-Z0-9_]+", line) if len(rs) > 0: projectName = rs[0] tmp = re.findall("(?<={0} )[a-zA-Z0-9_]+".format(projectName), line) startMethod = tmp[0] if len(tmp) > 0 else projectName return (projectName, startMethod) else: self.logger.error("Cannot extract project and method from %s" % line) return (None, None) def run(self): try: self.logger.info(self._testFiles) for testFile in self._testFiles: with open(testFile) as tests: coderTestSuite = CoderTestSuites(testFile) for line in tests.readlines(): if line.startswith(";") or not line.strip(): continue if "switches=" in line: self._switches = re.search("(?<=switches=).*", line).group() continue projectName, startMethod = self.extractTestProjectAndStartMethod(line) relatedStories = self.extractRelatedStories(line) if projectName is not None and startMethod is not None: self._testlist.addTest(CoderTestCase(self._icoder, projectName, startMethod, relatedStories, switches=self._switches, cmpSrc=("CompareSrc" in line), coderTestSuite=coderTestSuite)) self._icoder.stopAndUnlockASCETServer("C:\ETAS\ASCET7.1_SERVER6.3") self._unittestRunner.run(self._testlist) ReportUtil(self._configuration, coderTestSuite, self._version).sendMail() except IOError as err: self.logger.error(str(err))
class ProjectUtil(object): def __init__(self): self._logger = Logger() def generateCCode(self, genBatFile , projectPath, *args): """ Generate C code for ESDL project by running the bat file code-generation-cli.bat e.g. 1. With no argument C:/Program Files (x86)/ETAS/ISOLAR-CODER1.2.0/code-generation-cli.bat -w <workspace> -p <project name> 2. With another argument C:/Program Files (x86)/ETAS/ISOLAR-CODER1.2.0/code-generation-cli.bat -w <workspace> -p <project name> -d truncate """ self._logger.info("Generate C Code: %s" % projectPath) if (exists(projectPath)): wp, prjName = projectPath.rsplit(os.sep, 1); cmd = [genBatFile, "-w", wp, "-p", prjName] for arg in args: cmd += arg.split(" ") output, err, code = runWindowCommand(cmd) if "ERROR" in err: self._logger.info("Generate C Code: %s - FAIL" % projectPath) code = 0 else: self._logger.info("Generate C Code: %s - SUCCEED" % projectPath) code = 1 return (output, err, code) else: self._logger.error("Project %s cannot be found in workspace" % projectPath) raise IOError def compileAndLink(self, mingwMake, cgenPrjPath): """ TODO: description """ if(exists(cgenPrjPath)): cmd = [mingwMake, "-C", cgenPrjPath] self._logger.info("Compile and link: %s" % cgenPrjPath) outMsg, errMsg, code = runWindowCommand(cmd); self._logger.info("Compile and link: %s - %s" % (cgenPrjPath,"SUCCEED" if code == 0 else "FAIL")) return (outMsg, errMsg, not code) else: self._logger.error("Cannot be found: %s" % cgenPrjPath) raise IOError
class BeyondCompare(object): r""" According to Beyond Compare. Error levels mapping 0 Success 1 Binary same 2 Rules-based same 11 Binary differences 12 Similar 13 Rules-based differences 14 Conflicts detected 100 Unknown error 101 Conflicts detected, merge output not written 102 BComp.exe unable to wait until BCompare.exe finishes 103 BComp.exe cannot find BCompare.exe 104 Trial period expired 105 Error loading script file 106 Script syntax error 107 Script failed to load folders or files """ def __init__(self): self.logger = Logger() self.logger.name = __name__ self.bc = self._getBeyondCompareExePath() def _getBeyondCompareExePath(self): rs = runWindowCommand('reg query "HKLM\SOFTWARE\\Classes\BeyondCompare.Snapshot\shell\open\command" /ve') path = re.search('(?<=REG_SZ).*(?="%1")', rs[0]).group() return path.strip() def compareFile(self, ref, des, qcType=""): self.logger.info("Beyond Comparing file %s" % ref) if not exists(ref): self.logger.error("Missing file %s" % ref) return 105 elif not exists(des): self.logger.error("Missing file %s" % ref) return 105 if type in ("size", "crc", "binary"): self.logger.info("Using Beyond Compare with /qc=" + type) cmd = self.bc + " " + ref + " " + des + " /qc=" + type else: self.logger.info("Using Beyond Compare with default rules") cmd = self.bc + " " + ref + " " + des + " /qc" rs = runWindowCommand(cmd) self.logger.info("Beyond Compare Result: " + self._translateBCReturnCode(rs[2])) return rs[2] def quickCompareFile(self, ref, des): rs = self.compareFile(ref, des) return rs in [0, 1, 2, 12] def quickCompareFilesInFolder(self, refFolder, desFolder, fileNames): rs = True for f in fileNames: refFile = refFolder + "/" + f desFile = desFolder + "/" + f if not exists(desFile): self.logger.error("Missing file %s" % desFile) return False elif not exists(refFile): self.logger.error("Missing file %s" % refFile) return False else: rs = self.quickCompareFile(refFile, desFile) and rs return rs def _translateBCReturnCode(self, code): switcher = { 0: "Success", 1: "Binary same", 2: "Rules-based same", 11: "Binary differences", 12: "Similar", 13: "Rules-based differences", 14: "Conflicts detected", 100: "Unknown error", 101: "Conflicts detected, merge output not written", 102: "BComp.exe unable to wait until BCompare.exe finishes", 103: "BComp.exe cannot find BCompare.exe", 104: "Trial period expired", 105: "Error loading script file", 106: "Script syntax error", 107: "Script failed to load folders or files", } return switcher[code]