import sys import os def printHelp(): print("{}: OUTFILE.xml MEMSCRIPT.log [MEMSCRIPT.log]*".format(sys.argv[0])) def validLogfile(logfile): f = open(logfile) valid = False for line in f: if "MemoryScape Script Log File" in line or "TotalView Debugger Script Log File" in line: valid = True break f.close() return valid def processHeader(logfile): header = {} f = open(logfile) for line in f: if "* Date:" in line: header["date"] = line.split()[2] elif "* Target:" in line: header["target"] = line.split()[2] f.close() return header def processErrorNotifications(logfile): errorText = "" inErrorText = False f = open(logfile) for line in f: if "! Process Error Notification" in line: errorText = line inErrorText = True continue elif inErrorText and "!!!!!" in line: # We are done with the Error Notification section inErrorText = False break elif inErrorText: errorText = errorText + line f.close() return errorText def getReplayRecordingFile(logfile): # Return the name of the recording file if one was generated recordingFile = "" f = open(logfile) for line in f: if "Saving replay recording file to file" in line: # A recording file was saved, pick it up recordingFile = line.split("Saving replay recording file to file ")[1].strip() break f.close() return recordingFile def processLogfile(f, logfile): # Pick up the header information from the logfile header = processHeader(logfile) # Pick up if an error was detected errorText = processErrorNotifications(logfile) # Pick up there was a recording file generated recordingFile = getReplayRecordingFile(logfile) print("Recording file: {}".format(recordingFile)) # Recording files will be reported as attachments to JUnit using the # JUnit Attachments plugin. This plugin requires use of the # classname attribute for each testcase in order to associate each # attachment. Each attachment must appear in a directory with the # same name as the classname. Recording files can be big so we'll # simply create a link to the original file from the classname directory. recordingsDir = "recordings" # We'll use classname "recordings". Create a directory that matches # the classname. if not os.path.exists(recordingsDir): os.mkdir(recordingsDir) # Link the original file into the recordings directory srcFile = "{}/{}".format(os.getcwd(), recordingFile) destFile = "{}/{}/{}".format(os.getcwd(), recordingsDir, recordingFile) if not os.path.exists(destFile): os.symlink(srcFile, destFile) # Generate an ATTATCHMENT statement that JUnit Attachments plugin will # pick up #print("[[ATTACHMENT|{}/{}]]".format(os.getcwd(), recordingFile)) f.write(" \n" .format(header["target"])) if errorText: f.write(" \n".format(header["target"])) f.write("\n") f.write(" \n") f.write(" \n") print("Generated testcase for logfile {}.".format(logfile)) def analyzeLogfiles(logfiles): invalid = failures = 0 for logfile in logfiles: # Is the log file valid? if not validLogfile(logfile): invalid = invalid + 1 continue # Pick up information from the "MemoryScape Script Log File"/header section header = processHeader(logfile) print("Header[\"date\"]: {}".format(header["date"])) print("Header[\"target\"]: {}".format(header["target"])) # Keep track of the number of files errorText = processErrorNotifications(logfile) if errorText: failures = failures + 1 return invalid, failures def processLogfiles(outfile, logfiles): # Store summary information in a dictionary script_info = {} # Phase 1 - Determine the number of invalid log files and failures script_info["invalid_logfiles"], script_info["failures"] = analyzeLogfiles(logfiles) print "Phase 1: {}".format(script_info) # Write the header for the XML file f = open(outfile, "w") f.write('\n') f.write("\n".format(script_info["failures"], script_info["failures"])) f.write(" \n".format(script_info["failures"], script_info["failures"])) for logfile in logfiles: if not validLogfile(logfile): print("Skipping invalid tvscript log file: {}".format(logfile)) continue print("Processing script log file: {}".format(logfile)) processLogfile(f, logfile) f.write(" \n") f.write("\n") f.close() print("Generated JUnit XML file: {}".format(outfile)) return True def main(): if len(sys.argv) < 3: printHelp() sys.exit("ERROR") outfile = sys.argv[1] logfiles = sys.argv[2:] processLogfiles(outfile, logfiles) if __name__ == '__main__': main()