#!/usr/bin/env python2 # import getopt import glob import os import re import sys def Usage(): print """Run standalone oaRawEvent tests either as part of comet-validate or standalone. Caution: Assumes that oaRawEvent CMT setup script has been sourced. Invocation: comet-validate --apply Call via validation framework which will call this script with arguments: owning-package executing-package $OARAWEVENTROOT/validate.d/050RunStandaloneTests.py {options} Call directly where:- owning-package Package root for the package containing the script executing-package Package root for the package executing the script options --debug --help --regenerate Regenerate file reference logs. Will ask for confirmation --extend Add file reference logs to data files that don't have them. Will ask for confirmation --no-tidy Will not delete temporary files. Implies --debug If owning-package and executing-package are not supplied then the script switches to standalone mode and carries out the following additional steps before begining testing:- 1) Switches to the data directory to $OARAWEVENTROOT/$OARAWEVENTCONFIG/validation 2) Runs $OARAWEVENTROOT/validate.d/001DownloadStandaloneData.py to get the input data The script consists of a single class OaRawEventTester and a driver to run it. It performs two types of tests:- 1) Execution of the binary TestOARawEvent.exe 2) File tests performed on every reference file in the data directory SAT__.log e.g. SAT_fgd_v3r14.log where:- SAT Stands for StandAlone Testing A description of the type of file The version of oaRawEvent in which the test was generated or last regenerated For each file the corresponding data file SAT_.mid.gz is passed to oaRawEvent_dump_midas_file.exe and the output to the reference file ignoring cosmetic differences. """ class OaRawEventTester: """Class to test oaRawEvent.""" def __init__(self): """Initialise.""" self.ValidCommand = 0 self.TestsPassed = 0 self.TestsFailed = 0 self.Debug = 0 self.Extend = 0 self.NoTidy = 0 self.Regenerate = 0 self.StandAlone = True self.TemporaryDirectory = "/tmp/OaRawEventTester_%d" % os.getpid() self.OaExeDir = os.path.expandvars("$OARAWEVENTROOT/$OARAWEVENTCONFIG") self.DataSourceDirectory = self.OaExeDir + "/validation" self.DownloaderScript = os.path.expandvars("$OARAWEVENTROOT/validate.d/001DownloadStandaloneData.py") self.version_number = os.path.basename(os.environ["OARAWEVENTROOT"]) self.WebDataDirectory = "http://repo.nd280.org/nd280files/validate/oaRawEvent" self.updated_tests = [] # If --regenerate or --extend will contain a list of ref log names # Check the environment if not os.environ.get("OARAWEVENTROOT") or not os.environ.get("OARAWEVENTCONFIG"): print "Cannot find evironmental variables OARAWEVENTROOT and OARAWEVENTCONFIG" +\ " has the ICEDUST_install/setup script been sourced?" return # Process command options and arguments try: opts, args = getopt.getopt(sys.argv[1:], "dehnr", ["debug","extend","help","no-tidy","regenerate"]) except getopt.GetoptError, err: print str(err) # will print something like "option -a not recognized" return for o, a in opts: if o in ("-d", "--debug"): self.Debug = 1 elif o in ("-e", "--extend"): self.Extend = 1 elif o in ("-h", "--help"): Usage() sys.exit() elif o in ("-n", "--no-tidy"): self.Debug = 1 self.NoTidy =1 elif o in ("-r", "--regenerate"): self.Regenerate = 1 else: print "unhandled option: " + o return # Don't actually need owning-package executing-package args # beyond switching out of standalone mode. if args: self.StandAlone = False os.mkdir(self.TemporaryDirectory) # If running standalone, perform extra preparation if self.StandAlone: print "Running in standalone mode" if not os.path.isdir(self.DataSourceDirectory): print "Cannot find data directory %s" % self.DataSourceDirectory return print "Switching to " + self.DataSourceDirectory os.chdir(self.DataSourceDirectory) log_file = "%s/cmd.log" % self.TemporaryDirectory if self.RunCommand(self.DownloaderScript,log_file): return os.system("cat " + log_file) # Preparations complete. self.ValidCommand = 1 def IsValid(self): """Return True if have valid command.""" return self.ValidCommand def ReportTestResult(self,title,failed): """Report test results.""" print "%-50s" % title, if failed: print "Failed" self.TestsFailed += 1 else: print "Passed" self.TestsPassed += 1 def RunAllTests(self): """Run all tests.""" print "\nRunning SAT (StandAlone Testing) ...\n" self.RunTestOaRawEvent() self.RunFileTests() def RunCommand(self,cmd,log_file=""): """Run command and return exit code.""" if not log_file: log_file = "%s/cmd.log" % self.TemporaryDirectory if self.Debug: print "Executing: " + cmd exit_code = os.system("%s > %s 2>&1" % (cmd,log_file)) if self.Debug and exit_code: print "Failed with exit code %d\n\nLog file contents:-\n" % exit_code os.system("cat " + log_file) return exit_code def RunFileTests(self): """Run file tests on all SAT__.log files.""" # Loop over all SAT__.log in data directory. done_data_base_names = [] for log_ref_raw_file_path in glob.glob("%s/SAT_*.log" % self.DataSourceDirectory): log_ref_raw_file_name = os.path.basename(log_ref_raw_file_path) mo = re.search('(.*)_',log_ref_raw_file_name) if not mo: print "Badly formed reference file name: '%s'" % log_ref_raw_file_name self.ReportTestResult(log_ref_raw_file_name,1) continue data_base_name = mo.group(1) done_data_base_names.append(data_base_name) data_file_name = data_base_name + ".mid.gz" data_file_path = "%s/%s" % (self.DataSourceDirectory,data_file_name) # Make sure there is a data file. if not os.path.isfile(data_file_path): if self.Debug: print "Cannot find data file %s associated with %s" %\ (data_file_path,log_ref_raw_file_name) self.ReportTestResult(data_file_name,1) continue # If regenerating, ask if log file is to be recreated. if self.Regenerate: print "Regenerate log file for %s ? Ans: y [n]" % data_file_name, ans = "" while ( not ans ): ans = raw_input() if not ans: ans = "n" if not re.search("^(y|Y|n|N)",ans): print "Please answer y [n]", ans = "" if re.search("^(y|Y)",ans): cmd = "%s/oaRawEvent_dump_midas_file.exe %s > %s 2>&1" % (self.OaExeDir,data_file_path,log_ref_raw_file_path) exit_code = self.RunCommand(cmd,log_ref_raw_file_path) # Bring version number on the log file up to date. old_name = log_ref_raw_file_path log_ref_raw_file_path = "%s/%s_%s.log" % (self.DataSourceDirectory,data_base_name,self.version_number) os.rename(old_name,log_ref_raw_file_path) self.updated_tests.append(os.path.basename(log_ref_raw_file_path)) # Run oaRawEvent_dump_midas_file.exe log_test_raw_file_path = "%s/%s_test_raw.log" % (self.TemporaryDirectory,data_base_name) cmd = "%s/oaRawEvent_dump_midas_file.exe %s > %s 2>&1" % (self.OaExeDir,data_file_path,log_test_raw_file_path) exit_code = self.RunCommand(cmd,log_test_raw_file_path) if exit_code: self.ReportTestResult(data_file_name,1) continue # Process reference and test log files to remove cosmetic changes and then compare them. log_ref_file_path = "%s/%s_ref.log" % (self.TemporaryDirectory,data_base_name) log_test_file_path = "%s/%s_test.log" % (self.TemporaryDirectory,data_base_name) for log_type in ["ref","test"]: if log_type == "ref": file_in = open(log_ref_raw_file_path) file_out = open(log_ref_file_path,"w") else: file_in = open(log_test_raw_file_path) file_out = open(log_test_file_path,"w") for line in file_in: # Remove directory name for input file path mo = re.search("Dumping MIDAS file",line) if mo: line = "Dumping MIDAS file " + data_file_name # Remove memory addresses (@0x...) mo = re.compile("(@0x\S+)") line = mo.sub("@??",line) file_out.write(line) file_in.close() file_out.close() cmd = "diff %s %s" % (log_ref_file_path, log_test_file_path) self.ReportTestResult(data_file_name,self.RunCommand(cmd)) ## If --extend has been specified, look for data files that ## have not been processed and create reference files for them ## if required. if not self.Extend: return for data_file_path in glob.glob("%s/SAT_*.mid.gz" % self.DataSourceDirectory): data_file_name = os.path.basename(data_file_path) data_base_name = data_file_name[0:-7] if data_base_name in done_data_base_names: continue print "Generate log file for %s ? Ans: y [n]" % data_file_name, ans = "" while ( not ans ): ans = raw_input() if not ans: ans = "n" if not re.search("^(y|Y|n|N)",ans): print "Please answer y [n]", ans = "" if re.search("^(y|Y)",ans): log_ref_raw_file_path = "%s/%s_%s.log" % (self.DataSourceDirectory,data_base_name,self.version_number) cmd = "%s/oaRawEvent_dump_midas_file.exe %s > %s 2>&1" % (self.OaExeDir,data_file_path,log_ref_raw_file_path) exit_code = self.RunCommand(cmd,log_ref_raw_file_path) self.updated_tests.append(os.path.basename(log_ref_raw_file_path)) def RunTestOaRawEvent(self): """Run binary TestOARawEvent.exe .""" cmd = "%s/TestOARawEvent.exe" % self.OaExeDir self.ReportTestResult("TestOARawEvent.exe",self.RunCommand(cmd)) def Terminate(self): """Clean up and terminate, setting exit code.""" if os.path.isdir(self.TemporaryDirectory) and not self.NoTidy: self.RunCommand("rm -r " + self.TemporaryDirectory) print "\nTotals Tests passed: %d Tests failed: %d \n" % (self.TestsPassed,self.TestsFailed) if self.TestsPassed and not self.TestsFailed: print "SAT successful.\n" sys.exit(0) print "SAT failed.\n" print "FAIL" sys.exit(1) def UpdateTests(self): """For the list self.updated_tests give user instructions on how to update the web data directory and the downloader script""" if not self.updated_tests: if self.Debug: print "No tests to update" return script_mods = ""; print "\nTo installed the new/revised tests please carry out the following steps" print "\n1) Upload the following data files\n" for log_ref_name in self.updated_tests: mo = re.search('(.*)_',log_ref_name) data_file_name = mo.group(1) + ".mid.gz" data_file_path = "%s/%s" % (self.DataSourceDirectory,data_file_name) print " %s" % data_file_name print " %s" % log_ref_name # Determine the md5sums of both the data and the log file # and use them to build a new line for the downloader # script. script_mods += ' inputfiles.append(("%s"' % log_ref_name inp = os.popen("md5sum %s/%s %s" % (self.DataSourceDirectory,log_ref_name,data_file_path),"r") for line in inp: script_mods += ',"%s"' % line[0:32] inp.close() script_mods += '))\n' print "\n from:-\n\n %s\n\n to:-\n\n %s" %\ (self.DataSourceDirectory,self.WebDataDirectory) print "\n\n2) Add the following lines:-\n\n%s\n to:-\n\n %s" % (script_mods,self.DownloaderScript) print "\n removing any pre-existing 'inputfiles.append' lines that refer to the same tests" # Driver code to invoke OaRawEventTester tester = OaRawEventTester() if tester.IsValid(): tester.RunAllTests() tester.UpdateTests() else: Usage() tester.Terminate()