11b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks#!/usr/bin/env python 21b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 31b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks""" 41b41716abf6856af893fd2f13cd0272dffa0e312Anna ZaksStatic Analyzer qualification infrastructure. 51b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 61b41716abf6856af893fd2f13cd0272dffa0e312Anna ZaksThe goal is to test the analyzer against different projects, check for failures, 71b41716abf6856af893fd2f13cd0272dffa0e312Anna Zakscompare results, and measure performance. 81b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarRepository Directory will contain sources of the projects as well as the 1087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarinformation on how to build them and the expected output. 111b41716abf6856af893fd2f13cd0272dffa0e312Anna ZaksRepository Directory structure: 121b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - ProjectMap file 131b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - Historical Performance Data 141b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - Project Dir1 151b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - ReferenceOutput 161b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - Project Dir2 171b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - ReferenceOutput 181b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks .. 1987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarNote that the build tree must be inside the project dir. 201b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 211b41716abf6856af893fd2f13cd0272dffa0e312Anna ZaksTo test the build of the analyzer one would: 2287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar - Copy over a copy of the Repository Directory. (TODO: Prefer to ensure that 231b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks the build directory does not pollute the repository to min network traffic). 241b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks - Build all projects, until error. Produce logs to report errors. 2587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar - Compare results. 261b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 2787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarThe files which should be kept around for failure investigations: 281b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks RepositoryCopy/Project DirI/ScanBuildResults 2987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar RepositoryCopy/Project DirI/run_static_analyzer.log 3087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 3187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarAssumptions (TODO: shouldn't need to assume these.): 321b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks The script is being run from the Repository Directory. 335fa3f1309b27d2f117dfd10a45a8642b7d4baae9Anna Zaks The compiler for scan-build and scan-build are in the PATH. 341b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks export PATH=/Users/zaks/workspace/c2llvm/build/Release+Asserts/bin:$PATH 351b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 361b41716abf6856af893fd2f13cd0272dffa0e312Anna ZaksFor more logging, set the env variables: 371b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks zaks:TI zaks$ export CCC_ANALYZER_LOG=1 381b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks zaks:TI zaks$ export CCC_ANALYZER_VERBOSE=1 3987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarThe list of checkers tested are hardcoded in the Checkers variable. 4187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarFor testing additional checkers, use the SA_ADDITIONAL_CHECKERS environment 4287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarvariable. It should contain a comma separated list. 431b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks""" 441b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport CmpRuns 451b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 461b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport os 471b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport csv 481b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport sys 491b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport glob 5082778af78a7337498e6bcfc81c75cee29d329915Ted Kremenekimport math 511b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport shutil 521b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport time 531b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksimport plistlib 5487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarimport argparse 5587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarfrom subprocess import check_call, check_output, CalledProcessError 561b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 577c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek#------------------------------------------------------------------------------ 587c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Helper functions. 597c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek#------------------------------------------------------------------------------ 601b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 6182778af78a7337498e6bcfc81c75cee29d329915Ted Kremenekdef detectCPUs(): 6282778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek """ 6382778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek Detects the number of CPUs on a system. Cribbed from pp. 6482778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek """ 6582778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek # Linux, Unix and MacOS: 6682778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek if hasattr(os, "sysconf"): 6782778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): 6882778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek # Linux & Unix: 6982778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek ncpus = os.sysconf("SC_NPROCESSORS_ONLN") 7082778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek if isinstance(ncpus, int) and ncpus > 0: 7182778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek return ncpus 7282778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek else: # OSX: 7382778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek return int(capture(['sysctl', '-n', 'hw.ncpu'])) 7482778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek # Windows: 7582778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek if os.environ.has_key("NUMBER_OF_PROCESSORS"): 7682778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]) 7782778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek if ncpus > 0: 7882778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek return ncpus 7982778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek return 1 # Default 8082778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek 815abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenekdef which(command, paths = None): 825abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek """which(command, [paths]) - Look up the given command in the paths string 835abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek (or the PATH environment variable, if unspecified).""" 845abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 855abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek if paths is None: 865abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek paths = os.environ.get('PATH','') 875abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 885abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek # Check for absolute match first. 895abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek if os.path.exists(command): 905abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek return command 915abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 925abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek # Would be nice if Python had a lib function for this. 935abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek if not paths: 945abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek paths = os.defpath 955abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 965abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek # Get suffixes to search. 975abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek # On Cygwin, 'PATHEXT' may exist but it should not be used. 985abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek if os.pathsep == ';': 995abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek pathext = os.environ.get('PATHEXT', '').split(';') 1005abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek else: 1015abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek pathext = [''] 1025abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 1035abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek # Search the paths... 1045abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek for path in paths.split(os.pathsep): 1055abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek for ext in pathext: 1065abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek p = os.path.join(path, command + ext) 1075abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek if os.path.exists(p): 1085abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek return p 1095abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 1105abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek return None 1115abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek 112d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks# Make sure we flush the output after every print statement. 113d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaksclass flushfile(object): 114d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks def __init__(self, f): 115d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks self.f = f 116d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks def write(self, x): 117d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks self.f.write(x) 118d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks self.f.flush() 119d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks 120d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zakssys.stdout = flushfile(sys.stdout) 121d3e29ef3e0c3f2f70ec41c83e68c271f970e1852Anna Zaks 1221b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksdef getProjectMapPath(): 12387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ProjectMapPath = os.path.join(os.path.abspath(os.curdir), 1241b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks ProjectMapFile) 1251b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if not os.path.exists(ProjectMapPath): 1261b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print "Error: Cannot find the Project Map file " + ProjectMapPath +\ 1271b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks "\nRunning script for the wrong directory?" 12887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar sys.exit(-1) 12987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return ProjectMapPath 1301b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 1311b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksdef getProjectDir(ID): 13287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return os.path.join(os.path.abspath(os.curdir), ID) 1331b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 1346d7e3727996cf6c418e9fdccf8521dc3282f9368Jordan Rosedef getSBOutputDirName(IsReferenceBuild) : 13545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if IsReferenceBuild == True : 13645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks return SBOutputDirReferencePrefix + SBOutputDirName 13745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks else : 13845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks return SBOutputDirName 13945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks 1407c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek#------------------------------------------------------------------------------ 1417c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Configuration setup. 1427c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek#------------------------------------------------------------------------------ 1437c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 1447c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Find Clang for static analysis. 1457c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekClang = which("clang", os.environ['PATH']) 1467c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenekif not Clang: 1477c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek print "Error: cannot find 'clang' in PATH" 1487c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek sys.exit(-1) 1497c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 15082778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek# Number of jobs. 15158782bee56bf5e6ab42e6695af9ae5befe1fd479Jordan RoseJobs = int(math.ceil(detectCPUs() * 0.75)) 15282778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek 1537c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Project map stores info about all the "registered" projects. 1547c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekProjectMapFile = "projectMap.csv" 1557c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 1567c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Names of the project specific scripts. 15787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# The script that downloads the project. 15887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarDownloadScript = "download_project.sh" 1597c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# The script that needs to be executed before the build can start. 1607c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekCleanupScript = "cleanup_run_static_analyzer.sh" 16187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# This is a file containing commands for scan-build. 1627c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekBuildScript = "run_static_analyzer.cmd" 1637c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 1647c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# The log file name. 1657c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekLogFolderName = "Logs" 1667c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekBuildLogName = "run_static_analyzer.log" 16787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Summary file - contains the summary of the failures. Ex: This info can be be 1687c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# displayed when buildbot detects a build failure. 1697c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekNumOfFailuresInSummary = 10 1707c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekFailuresSummaryFileName = "failures.txt" 1717c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Summary of the result diffs. 1727c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekDiffsSummaryFileName = "diffs.txt" 1737c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 1747c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# The scan-build result directory. 1757c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekSBOutputDirName = "ScanBuildResults" 1767c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekSBOutputDirReferencePrefix = "Ref" 1777c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 17887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# The name of the directory storing the cached project source. If this directory 17987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# does not exist, the download script will be executed. That script should 18087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# create the "CachedSource" directory and download the project source into it. 18187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarCachedSourceDirName = "CachedSource" 18287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 18387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# The name of the directory containing the source code that will be analyzed. 18487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Each time a project is analyzed, a fresh copy of its CachedSource directory 18587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# will be copied to the PatchedSource directory and then the local patches 18687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# in PatchfileName will be applied (if PatchfileName exists). 18787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarPatchedSourceDirName = "PatchedSource" 18887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 18987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# The name of the patchfile specifying any changes that should be applied 19087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# to the CachedSource before analyzing. 19187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarPatchfileName = "changes_for_analyzer.patch" 19287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 1937c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# The list of checkers used during analyzes. 194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines# Currently, consists of all the non-experimental checkers, plus a few alpha 195e449edc5bdace60f9d754c32abc5459bc7d94a14Jordan Rose# checkers we don't want to regress on. 196176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesCheckers="alpha.unix.SimpleStream,alpha.security.taint,cplusplus.NewDeleteLeaks,core,cplusplus,deadcode,security,unix,osx" 1977c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 1987c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted KremenekVerbose = 1 1997c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 2007c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek#------------------------------------------------------------------------------ 2017c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek# Test harness logic. 2027c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek#------------------------------------------------------------------------------ 2037c14c4456532fbaff17c6ae3e5d259d475bfd7f7Ted Kremenek 2041b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks# Run pre-processing script if any. 2055fa3f1309b27d2f117dfd10a45a8642b7d4baae9Anna Zaksdef runCleanupScript(Dir, PBuildLogFile): 20687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Cwd = os.path.join(Dir, PatchedSourceDirName) 2075fa3f1309b27d2f117dfd10a45a8642b7d4baae9Anna Zaks ScriptPath = os.path.join(Dir, CleanupScript) 20887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar runScript(ScriptPath, PBuildLogFile, Cwd) 20987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 21087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Run the script to download the project, if it exists. 21187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef runDownloadScript(Dir, PBuildLogFile): 21287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ScriptPath = os.path.join(Dir, DownloadScript) 21387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar runScript(ScriptPath, PBuildLogFile, Dir) 21487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 21587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Run the provided script if it exists. 21687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef runScript(ScriptPath, PBuildLogFile, Cwd): 2171b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if os.path.exists(ScriptPath): 2181b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks try: 21987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 2201b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print " Executing: %s" % (ScriptPath,) 2214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar check_call("chmod +x '%s'" % ScriptPath, cwd = Cwd, 2221b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks stderr=PBuildLogFile, 22387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar stdout=PBuildLogFile, 22487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar shell=True) 2254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar check_call("'%s'" % ScriptPath, cwd = Cwd, stderr=PBuildLogFile, 22687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar stdout=PBuildLogFile, 2271b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks shell=True) 2281b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks except: 22987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Error: Running %s failed. See %s for details." % (ScriptPath, 23087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PBuildLogFile.name) 2311b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks sys.exit(-1) 2321b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 23387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Download the project and apply the local patchfile if it exists. 23487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef downloadAndPatch(Dir, PBuildLogFile): 23587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CachedSourceDirPath = os.path.join(Dir, CachedSourceDirName) 23687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 23787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # If the we don't already have the cached source, run the project's 23887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # download script to download it. 23987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if not os.path.exists(CachedSourceDirPath): 24087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar runDownloadScript(Dir, PBuildLogFile) 24187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if not os.path.exists(CachedSourceDirPath): 24287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Error: '%s' not found after download." % (CachedSourceDirPath) 24387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar exit(-1) 24487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 24587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName) 24687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 24787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Remove potentially stale patched source. 24887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if os.path.exists(PatchedSourceDirPath): 24987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar shutil.rmtree(PatchedSourceDirPath) 25087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 25187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Copy the cached source and apply any patches to the copy. 25287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar shutil.copytree(CachedSourceDirPath, PatchedSourceDirPath, symlinks=True) 25387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar applyPatch(Dir, PBuildLogFile) 25487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 25587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef applyPatch(Dir, PBuildLogFile): 25687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PatchfilePath = os.path.join(Dir, PatchfileName) 25787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName) 25887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if not os.path.exists(PatchfilePath): 25987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print " No local patches." 26087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return 26187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 26287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print " Applying patch." 26387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar try: 2644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar check_call("patch -p1 < '%s'" % (PatchfilePath), 26587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar cwd = PatchedSourceDirPath, 26687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar stderr=PBuildLogFile, 26787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar stdout=PBuildLogFile, 26887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar shell=True) 26987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar except: 27087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Error: Patch failed. See %s for details." % (PBuildLogFile.name) 27187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar sys.exit(-1) 27287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 27387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Build the project with scan-build by reading in the commands and 2741b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks# prefixing them with the scan-build options. 2751b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksdef runScanBuild(Dir, SBOutputDir, PBuildLogFile): 2761b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks BuildScriptPath = os.path.join(Dir, BuildScript) 2771b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if not os.path.exists(BuildScriptPath): 2781b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print "Error: build script is not defined: %s" % BuildScriptPath 2795abd3d2ba4c4edb5140de5d65a16e5da4076f0b1Ted Kremenek sys.exit(-1) 28087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 28187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar AllCheckers = Checkers 28287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if os.environ.has_key('SA_ADDITIONAL_CHECKERS'): 28387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar AllCheckers = AllCheckers + ',' + os.environ['SA_ADDITIONAL_CHECKERS'] 28487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 28587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Run scan-build from within the patched source directory. 28687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SBCwd = os.path.join(Dir, PatchedSourceDirName) 28787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 2884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SBOptions = "--use-analyzer '%s' " % Clang 2894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SBOptions += "-plist-html -o '%s' " % SBOutputDir 29087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SBOptions += "-enable-checker " + AllCheckers + " " 29133e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose SBOptions += "--keep-empty " 29287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Always use ccc-analyze to ensure that we can locate the failures 293e3a9baa45c91f5c06801a2d667b5d6d71bcfb355Anna Zaks # directory. 294e3a9baa45c91f5c06801a2d667b5d6d71bcfb355Anna Zaks SBOptions += "--override-compiler " 2951b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks try: 2961b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SBCommandFile = open(BuildScriptPath, "r") 2971b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SBPrefix = "scan-build " + SBOptions + " " 2981b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks for Command in SBCommandFile: 2991c840db980075f56e5747b5b636e319a26722fe3Jordan Rose Command = Command.strip() 30087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if len(Command) == 0: 30187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar continue; 30282778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek # If using 'make', auto imply a -jX argument 30382778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek # to speed up analysis. xcodebuild will 30482778af78a7337498e6bcfc81c75cee29d329915Ted Kremenek # automatically use the maximum number of cores. 3057bd51ea64fd06b9a243faaacb0b15c168afe47a6Jordan Rose if (Command.startswith("make ") or Command == "make") and \ 3067bd51ea64fd06b9a243faaacb0b15c168afe47a6Jordan Rose "-j" not in Command: 30758782bee56bf5e6ab42e6695af9ae5befe1fd479Jordan Rose Command += " -j%d" % Jobs 3081b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SBCommand = SBPrefix + Command 30987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 3101b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print " Executing: %s" % (SBCommand,) 31187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar check_call(SBCommand, cwd = SBCwd, stderr=PBuildLogFile, 31287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar stdout=PBuildLogFile, 31387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar shell=True) 3141b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks except: 3151b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print "Error: scan-build failed. See ",PBuildLogFile.name,\ 3161b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks " for details." 31745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks raise 31845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks 31945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaksdef hasNoExtension(FileName): 32045518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks (Root, Ext) = os.path.splitext(FileName) 32145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if ((Ext == "")) : 32245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks return True 32345518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks return False 3241b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 32545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaksdef isValidSingleInputFile(FileName): 32645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks (Root, Ext) = os.path.splitext(FileName) 32787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if ((Ext == ".i") | (Ext == ".ii") | 32887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar (Ext == ".c") | (Ext == ".cpp") | 32945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks (Ext == ".m") | (Ext == "")) : 33045518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks return True 33145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks return False 33287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 33387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Get the path to the SDK for the given SDK name. Returns None if 33487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# the path cannot be determined. 33587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef getSDKPath(SDKName): 33687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if which("xcrun") is None: 33787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return None 33887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 33987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Cmd = "xcrun --sdk " + SDKName + " --show-sdk-path" 34087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return check_output(Cmd, shell=True).rstrip() 34187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 34245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks# Run analysis on a set of preprocessed files. 343817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaksdef runAnalyzePreprocessed(Dir, SBOutputDir, Mode): 34445518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if os.path.exists(os.path.join(Dir, BuildScript)): 34545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print "Error: The preprocessed files project should not contain %s" % \ 34645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks BuildScript 34787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar raise Exception() 34887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 34987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CmdPrefix = Clang + " -cc1 " 35087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 35187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # For now, we assume the preprocessed files should be analyzed 35287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # with the OS X SDK. 35387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SDKPath = getSDKPath("macosx") 35487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if SDKPath is not None: 35587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CmdPrefix += "-isysroot " + SDKPath + " " 35687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 35787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CmdPrefix += "-analyze -analyzer-output=plist -w " 35887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CmdPrefix += "-analyzer-checker=" + Checkers +" -fcxx-exceptions -fblocks " 35945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks 360817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks if (Mode == 2) : 36187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CmdPrefix += "-std=c++11 " 36287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 36345518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks PlistPath = os.path.join(Dir, SBOutputDir, "date") 36445518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks FailPath = os.path.join(PlistPath, "failures"); 36545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks os.makedirs(FailPath); 36687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 36745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks for FullFileName in glob.glob(Dir + "/*"): 36845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks FileName = os.path.basename(FullFileName) 36945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks Failed = False 37087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 37145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks # Only run the analyzes on supported files. 37245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if (hasNoExtension(FileName)): 37345518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks continue 37445518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if (isValidSingleInputFile(FileName) == False): 37545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print "Error: Invalid single input file %s." % (FullFileName,) 37645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks raise Exception() 37787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 37845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks # Build and call the analyzer command. 3794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar OutputOption = "-o '%s.plist' " % os.path.join(PlistPath, FileName) 3804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Command = CmdPrefix + OutputOption + ("'%s'" % FileName) 38145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks LogFile = open(os.path.join(FailPath, FileName + ".stderr.txt"), "w+b") 38245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks try: 38387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 38445518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print " Executing: %s" % (Command,) 38545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks check_call(Command, cwd = Dir, stderr=LogFile, 38687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar stdout=LogFile, 38745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks shell=True) 38845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks except CalledProcessError, e: 38945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print "Error: Analyzes of %s failed. See %s for details." \ 39045518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks "Error code %d." % \ 39145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks (FullFileName, LogFile.name, e.returncode) 39287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Failed = True 39345518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks finally: 39487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar LogFile.close() 39587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 39645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks # If command did not fail, erase the log file. 39745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if Failed == False: 39845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks os.remove(LogFile.name); 39945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks 4004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainardef getBuildLogPath(SBOutputDir): 4014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return os.path.join(SBOutputDir, LogFolderName, BuildLogName) 4024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 4034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainardef removeLogFile(SBOutputDir): 4044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar BuildLogPath = getBuildLogPath(SBOutputDir) 4054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar # Clean up the log file. 4064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (os.path.exists(BuildLogPath)) : 4074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar RmCommand = "rm '%s'" % BuildLogPath 4084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if Verbose == 1: 4094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar print " Executing: %s" % (RmCommand,) 4104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar check_call(RmCommand, shell=True) 4114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 412817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaksdef buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild): 41387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TBegin = time.time() 4141b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 4154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar BuildLogPath = getBuildLogPath(SBOutputDir) 41687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Log file: %s" % (BuildLogPath,) 41745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print "Output directory: %s" %(SBOutputDir, ) 41887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar removeLogFile(SBOutputDir) 42087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 42145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks # Clean up scan build results. 42245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if (os.path.exists(SBOutputDir)) : 4234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar RmCommand = "rm -r '%s'" % SBOutputDir 42487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 42545518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print " Executing: %s" % (RmCommand,) 42645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks check_call(RmCommand, shell=True) 42745518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks assert(not os.path.exists(SBOutputDir)) 42845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks os.makedirs(os.path.join(SBOutputDir, LogFolderName)) 42987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4301b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Open the log file. 4311b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks PBuildLogFile = open(BuildLogPath, "wb+") 43287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 43345518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks # Build and analyze the project. 43445518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks try: 435817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks if (ProjectBuildMode == 1): 43687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar downloadAndPatch(Dir, PBuildLogFile) 43787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar runCleanupScript(Dir, PBuildLogFile) 43845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks runScanBuild(Dir, SBOutputDir, PBuildLogFile) 43945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks else: 440817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks runAnalyzePreprocessed(Dir, SBOutputDir, ProjectBuildMode) 44187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 44245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if IsReferenceBuild : 4435fa3f1309b27d2f117dfd10a45a8642b7d4baae9Anna Zaks runCleanupScript(Dir, PBuildLogFile) 44487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 44587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Make the absolute paths relative in the reference results. 44687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for (DirPath, Dirnames, Filenames) in os.walk(SBOutputDir): 44787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for F in Filenames: 44887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (not F.endswith('plist')): 44987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar continue 45087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Plist = os.path.join(DirPath, F) 45187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Data = plistlib.readPlist(Plist) 45287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PathPrefix = Dir 45387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ProjectBuildMode == 1): 45487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PathPrefix = os.path.join(Dir, PatchedSourceDirName) 45587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Paths = [SourceFile[len(PathPrefix)+1:]\ 45687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if SourceFile.startswith(PathPrefix)\ 45787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar else SourceFile for SourceFile in Data['files']] 45887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Data['files'] = Paths 45987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar plistlib.writePlist(Data, Plist) 46087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4611b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks finally: 4621b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks PBuildLogFile.close() 46387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4641b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print "Build complete (time: %.2f). See the log for more details: %s" % \ 46587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ((time.time()-TBegin), BuildLogPath) 46687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4671b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks# A plist file is created for each call to the analyzer(each source file). 46887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# We are only interested on the once that have bug reports, so delete the rest. 4691b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksdef CleanUpEmptyPlists(SBOutputDir): 4701b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks for F in glob.glob(SBOutputDir + "/*/*.plist"): 4711b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks P = os.path.join(SBOutputDir, F) 47287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4731b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks Data = plistlib.readPlist(P) 4741b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Delete empty reports. 4751b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if not Data['files']: 4761b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks os.remove(P) 4771b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks continue 4781b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 47987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Given the scan-build output directory, checks if the build failed 48087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# (by searching for the failures directories). If there are failures, it 48187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# creates a summary file in the output directory. 4821b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksdef checkBuild(SBOutputDir): 4831b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Check if there are failures. 4841b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks Failures = glob.glob(SBOutputDir + "/*/failures/*.stderr.txt") 4851b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks TotalFailed = len(Failures); 4861b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if TotalFailed == 0: 487191e2b1d4aad18794bc5612459384f0321ffdf38Jordan Rose CleanUpEmptyPlists(SBOutputDir) 488191e2b1d4aad18794bc5612459384f0321ffdf38Jordan Rose Plists = glob.glob(SBOutputDir + "/*/*.plist") 489651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines print "Number of bug reports (non-empty plist files) produced: %d" %\ 490191e2b1d4aad18794bc5612459384f0321ffdf38Jordan Rose len(Plists) 4911b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks return; 49287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4931b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Create summary file to display when the build fails. 49445518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks SummaryPath = os.path.join(SBOutputDir, LogFolderName, FailuresSummaryFileName) 4951b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if (Verbose > 0): 49645518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print " Creating the failures summary file %s" % (SummaryPath,) 49787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4981b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SummaryLog = open(SummaryPath, "w+") 4991b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks try: 5001b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SummaryLog.write("Total of %d failures discovered.\n" % (TotalFailed,)) 5011b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if TotalFailed > NumOfFailuresInSummary: 50287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SummaryLog.write("See the first %d below.\n" 5031b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks % (NumOfFailuresInSummary,)) 5041b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # TODO: Add a line "See the results folder for more." 50587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5061b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks FailuresCopied = NumOfFailuresInSummary 5071b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks Idx = 0 50804bc014dfddd1298ae984a8632b41e0d77c9f556Jordan Rose for FailLogPathI in Failures: 5091b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if Idx >= NumOfFailuresInSummary: 5101b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks break; 51187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Idx += 1 5121b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SummaryLog.write("\n-- Error #%d -----------\n" % (Idx,)); 5131b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks FailLogI = open(FailLogPathI, "r"); 51487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar try: 5151b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks shutil.copyfileobj(FailLogI, SummaryLog); 5161b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks finally: 5171b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks FailLogI.close() 5181b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks finally: 5191b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks SummaryLog.close() 52087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 521f063a3b783e22effa7972d05830cee942b2499ceAnna Zaks print "Error: analysis failed. See ", SummaryPath 52287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar sys.exit(-1) 5231b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 5241b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks# Auxiliary object to discard stdout. 5251b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksclass Discarder(object): 5261b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks def write(self, text): 5271b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks pass # do nothing 5281b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 5291b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks# Compare the warnings produced by scan-build. 53087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# Strictness defines the success criteria for the test: 53187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# 0 - success if there are no crashes or analyzer failure. 53287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# 1 - success if there are no difference in the number of reported bugs. 53387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar# 2 - success if all the bug reports are identical. 53487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef runCmpResults(Dir, Strictness = 0): 53587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TBegin = time.time() 5361b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 5371b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks RefDir = os.path.join(Dir, SBOutputDirReferencePrefix + SBOutputDirName) 5381b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks NewDir = os.path.join(Dir, SBOutputDirName) 53987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5401b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # We have to go one level down the directory tree. 54187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar RefList = glob.glob(RefDir + "/*") 5421b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks NewList = glob.glob(NewDir + "/*") 54387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 544de5f2ee2aa4afabd325056013becfee1172c8db2Jordan Rose # Log folders are also located in the results dir, so ignore them. 545de5f2ee2aa4afabd325056013becfee1172c8db2Jordan Rose RefLogDir = os.path.join(RefDir, LogFolderName) 546de5f2ee2aa4afabd325056013becfee1172c8db2Jordan Rose if RefLogDir in RefList: 547de5f2ee2aa4afabd325056013becfee1172c8db2Jordan Rose RefList.remove(RefLogDir) 54845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks NewList.remove(os.path.join(NewDir, LogFolderName)) 54987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5501b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if len(RefList) == 0 or len(NewList) == 0: 5511b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks return False 5521b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks assert(len(RefList) == len(NewList)) 5531b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 55487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # There might be more then one folder underneath - one per each scan-build 5551b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # command (Ex: one for configure and one for make). 5561b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if (len(RefList) > 1): 5571b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Assume that the corresponding folders have the same names. 5581b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks RefList.sort() 5591b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks NewList.sort() 56087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5611b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Iterate and find the differences. 562a7a2564ff59a1917c5f27343923635bd231466d6Anna Zaks NumDiffs = 0 56387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PairList = zip(RefList, NewList) 56487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for P in PairList: 56587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar RefDir = P[0] 5661b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks NewDir = P[1] 56787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 56887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar assert(RefDir != NewDir) 56987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 5701b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print " Comparing Results: %s %s" % (RefDir, NewDir) 57187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5721b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks DiffsPath = os.path.join(NewDir, DiffsSummaryFileName) 57387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PatchedSourceDirPath = os.path.join(Dir, PatchedSourceDirName) 57487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Opts = CmpRuns.CmpOptions(DiffsPath, "", PatchedSourceDirPath) 5751b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Discard everything coming out of stdout (CmpRun produces a lot of them). 5761b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks OLD_STDOUT = sys.stdout 5771b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks sys.stdout = Discarder() 5781b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Scan the results, delete empty plist files. 57987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NumDiffs, ReportsInRef, ReportsInNew = \ 58087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CmpRuns.dumpScanBuildResultsDiff(RefDir, NewDir, Opts, False) 5811b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks sys.stdout = OLD_STDOUT 582a7a2564ff59a1917c5f27343923635bd231466d6Anna Zaks if (NumDiffs > 0) : 583a7a2564ff59a1917c5f27343923635bd231466d6Anna Zaks print "Warning: %r differences in diagnostics. See %s" % \ 584a7a2564ff59a1917c5f27343923635bd231466d6Anna Zaks (NumDiffs, DiffsPath,) 58587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Strictness >= 2 and NumDiffs > 0: 58687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Error: Diffs found in strict mode (2)." 58787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar sys.exit(-1) 58887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar elif Strictness >= 1 and ReportsInRef != ReportsInNew: 58987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Error: The number of results are different in strict mode (1)." 59087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar sys.exit(-1) 59187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 59287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar print "Diagnostic comparison complete (time: %.2f)." % (time.time()-TBegin) 593a7a2564ff59a1917c5f27343923635bd231466d6Anna Zaks return (NumDiffs > 0) 59487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainardef cleanupReferenceResults(SBOutputDir): 5964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar # Delete html, css, and js files from reference results. These can 5974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar # include multiple copies of the benchmark source and so get very large. 5984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Extensions = ["html", "css", "js"] 5994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for E in Extensions: 6004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for F in glob.glob("%s/*/*.%s" % (SBOutputDir, E)): 6014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar P = os.path.join(SBOutputDir, F) 6024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar RmCommand = "rm '%s'" % P 6034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar check_call(RmCommand, shell=True) 6044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 6054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar # Remove the log file. It leaks absolute path names. 6064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar removeLogFile(SBOutputDir) 6074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 60809e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaksdef updateSVN(Mode, ProjectsMap): 60909e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks try: 61087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ProjectsMap.seek(0) 61109e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks for I in csv.reader(ProjectsMap): 61287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ProjName = I[0] 6136d7e3727996cf6c418e9fdccf8521dc3282f9368Jordan Rose Path = os.path.join(ProjName, getSBOutputDirName(True)) 61487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 61509e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks if Mode == "delete": 6164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Command = "svn delete '%s'" % (Path,) 61709e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks else: 6184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Command = "svn add '%s'" % (Path,) 61945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks 62087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 62109e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks print " Executing: %s" % (Command,) 62287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar check_call(Command, shell=True) 62387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 62409e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks if Mode == "delete": 62509e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks CommitCommand = "svn commit -m \"[analyzer tests] Remove " \ 62687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar "reference results.\"" 62709e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks else: 62809e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks CommitCommand = "svn commit -m \"[analyzer tests] Add new " \ 62909e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks "reference results.\"" 63087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 63109e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks print " Executing: %s" % (CommitCommand,) 63287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar check_call(CommitCommand, shell=True) 63309e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks except: 63409e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks print "Error: SVN update failed." 63509e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks sys.exit(-1) 63687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 63787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Dir=None, Strictness = 0): 63845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print " \n\n--- Building project %s" % (ID,) 6391b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 64087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TBegin = time.time() 6411b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 6421b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks if Dir is None : 64387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Dir = getProjectDir(ID) 64487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Verbose == 1: 6451b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print " Build directory: %s." % (Dir,) 64687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 6471b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks # Set the build results directory. 6486d7e3727996cf6c418e9fdccf8521dc3282f9368Jordan Rose RelOutputDir = getSBOutputDirName(IsReferenceBuild) 64909e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks SBOutputDir = os.path.join(Dir, RelOutputDir) 65087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 651817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild) 6521b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks 6531b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks checkBuild(SBOutputDir) 65487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 655191e2b1d4aad18794bc5612459384f0321ffdf38Jordan Rose if IsReferenceBuild == False: 65687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar runCmpResults(Dir, Strictness) 6574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar else: 6584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar cleanupReferenceResults(SBOutputDir) 65987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 6601b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks print "Completed tests for project %s (time: %.2f)." % \ 6611b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks (ID, (time.time()-TBegin)) 66287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 66387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainardef testAll(IsReferenceBuild = False, UpdateSVN = False, Strictness = 0): 6641b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks PMapFile = open(getProjectMapPath(), "rb") 66587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar try: 66609e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks # Validate the input. 66709e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks for I in csv.reader(PMapFile): 66845518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks if (len(I) != 2) : 66945518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print "Error: Rows in the ProjectMapFile should have 3 entries." 67045518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks raise Exception() 671817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks if (not ((I[1] == "0") | (I[1] == "1") | (I[1] == "2"))): 672817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks print "Error: Second entry in the ProjectMapFile should be 0" \ 673817ce3dd26590bf3f099fb82d9b6fcc43e8a7ee9Anna Zaks " (single file), 1 (project), or 2(single file c++11)." 67487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar raise Exception() 67509e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks 67687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # When we are regenerating the reference results, we might need to 67709e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks # update svn. Remove reference results from SVN. 67809e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks if UpdateSVN == True: 6796d7e3727996cf6c418e9fdccf8521dc3282f9368Jordan Rose assert(IsReferenceBuild == True); 68009e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks updateSVN("delete", PMapFile); 68187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 68209e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks # Test the projects. 68387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PMapFile.seek(0) 68409e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks for I in csv.reader(PMapFile): 68587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar testProject(I[0], int(I[1]), IsReferenceBuild, None, Strictness) 68609e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks 68709e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks # Add reference results to SVN. 68809e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks if UpdateSVN == True: 68909e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks updateSVN("add", PMapFile); 69009e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks 69145518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks except: 69245518b1f768c302837096d1359b2935cdb8ee08dAnna Zaks print "Error occurred. Premature termination." 69387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar raise 6941b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaks finally: 69587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar PMapFile.close() 69687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 6971b41716abf6856af893fd2f13cd0272dffa0e312Anna Zaksif __name__ == '__main__': 69887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar # Parse command line arguments. 69987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Parser = argparse.ArgumentParser(description='Test the Clang Static Analyzer.') 70087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Parser.add_argument('--strictness', dest='strictness', type=int, default=0, 70187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar help='0 to fail on runtime errors, 1 to fail when the number\ 70287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar of found bugs are different from the reference, 2 to \ 70387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar fail on any difference from the reference. Default is 0.') 70487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Parser.add_argument('-r', dest='regenerate', action='store_true', default=False, 70587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar help='Regenerate reference output.') 70687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Parser.add_argument('-rs', dest='update_reference', action='store_true', 70787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar default=False, help='Regenerate reference output and update svn.') 70887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Args = Parser.parse_args() 70987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 71009e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks IsReference = False 71109e9cf0927641ee64bb0a354b0a6acca604361ccAnna Zaks UpdateSVN = False 71287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Strictness = Args.strictness 71387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if Args.regenerate: 71487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar IsReference = True 71587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar elif Args.update_reference: 71687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar IsReference = True 71787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar UpdateSVN = True 71887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 71987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar testAll(IsReference, UpdateSVN, Strictness) 720