[analyzer] Add support for testing with individual preprocessed files.

llvm-svn: 143786
This commit is contained in:
Anna Zaks 2011-11-05 05:20:48 +00:00
parent dc66efeb10
commit 4720a730f6
2 changed files with 133 additions and 34 deletions

16
clang/utils/analyzer/SATestAdd.py Normal file → Executable file
View File

@ -26,7 +26,7 @@ import sys
# Params:
# Dir is the directory where the sources are.
# ID is a short string used to identify a project.
def addNewProject(ID) :
def addNewProject(ID, IsScanBuild) :
CurDir = os.path.abspath(os.curdir)
Dir = SATestBuild.getProjectDir(ID)
if not os.path.exists(Dir):
@ -34,7 +34,7 @@ def addNewProject(ID) :
sys.exit(-1)
# Build the project.
SATestBuild.testProject(ID, True, Dir)
SATestBuild.testProject(ID, True, IsScanBuild, Dir)
# Add the project ID to the project map.
ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile)
@ -53,7 +53,7 @@ def addNewProject(ID) :
sys.exit(-1)
PMapWriter = csv.writer(PMapFile)
PMapWriter.writerow( (ID, Dir) );
PMapWriter.writerow( (ID, int(IsScanBuild)) );
finally:
PMapFile.close()
@ -65,7 +65,13 @@ def addNewProject(ID) :
if __name__ == '__main__':
if len(sys.argv) < 2:
print >> sys.stderr, 'Usage: ', sys.argv[0],\
'[project ID]'
'project_ID <mode>' \
'mode - 0 for single file project; 1 for scan_build'
sys.exit(-1)
IsScanBuild = 1
if (len(sys.argv) >= 3):
IsScanBuild = int(sys.argv[2])
assert((IsScanBuild == 0) | (IsScanBuild == 1))
addNewProject(sys.argv[1])
addNewProject(sys.argv[1], IsScanBuild)

151
clang/utils/analyzer/SATestBuild.py Normal file → Executable file
View File

@ -45,7 +45,7 @@ import glob
import shutil
import time
import plistlib
from subprocess import check_call
from subprocess import check_call, CalledProcessError
# Project map stores info about all the "registered" projects.
ProjectMapFile = "projectMap.csv"
@ -57,6 +57,7 @@ CleanupScript = "cleanup_run_static_analyzer.sh"
BuildScript = "run_static_analyzer.cmd"
# The log file name.
LogFolderName = "Logs"
BuildLogName = "run_static_analyzer.log"
# Summary file - contains the summary of the failures. Ex: This info can be be
# displayed when buildbot detects a build failure.
@ -71,6 +72,8 @@ SBOutputDirReferencePrefix = "Ref"
Verbose = 1
IsReferenceBuild = False
def getProjectMapPath():
ProjectMapPath = os.path.join(os.path.abspath(os.curdir),
ProjectMapFile)
@ -83,6 +86,12 @@ def getProjectMapPath():
def getProjectDir(ID):
return os.path.join(os.path.abspath(os.curdir), ID)
def getSBOutputDirName() :
if IsReferenceBuild == True :
return SBOutputDirReferencePrefix + SBOutputDirName
else :
return SBOutputDirName
# Run pre-processing script if any.
def runCleanupScript(Dir, PBuildLogFile):
ScriptPath = os.path.join(Dir, CleanupScript)
@ -124,36 +133,105 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
except:
print "Error: scan-build failed. See ",PBuildLogFile.name,\
" for details."
sys.exit(-1)
raise
def buildProject(Dir, SBOutputDir, ClenupAfterBuild):
def hasNoExtension(FileName):
(Root, Ext) = os.path.splitext(FileName)
if ((Ext == "")) :
return True
return False
def isValidSingleInputFile(FileName):
(Root, Ext) = os.path.splitext(FileName)
if ((Ext == ".i") | (Ext == ".ii") |
(Ext == ".c") | (Ext == ".cpp") |
(Ext == ".m") | (Ext == "")) :
return True
return False
# Run analysis on a set of preprocessed files.
def runAnalyzePreprocessed(Dir, SBOutputDir):
if os.path.exists(os.path.join(Dir, BuildScript)):
print "Error: The preprocessed files project should not contain %s" % \
BuildScript
raise Exception()
CmdPrefix = "clang -cc1 -analyze -analyzer-output=plist -w "
CmdPrefix += "-analyzer-checker=core "
PlistPath = os.path.join(Dir, SBOutputDir, "date")
FailPath = os.path.join(PlistPath, "failures");
os.makedirs(FailPath);
for FullFileName in glob.glob(Dir + "/*"):
FileName = os.path.basename(FullFileName)
Failed = False
# Only run the analyzes on supported files.
if (hasNoExtension(FileName)):
continue
if (isValidSingleInputFile(FileName) == False):
print "Error: Invalid single input file %s." % (FullFileName,)
raise Exception()
# Build and call the analyzer command.
OutputOption = "-o " + os.path.join(PlistPath, FileName) + ".plist "
Command = CmdPrefix + OutputOption + os.path.join(Dir, FileName)
LogFile = open(os.path.join(FailPath, FileName + ".stderr.txt"), "w+b")
try:
if Verbose == 1:
print " Executing: %s" % (Command,)
check_call(Command, cwd = Dir, stderr=LogFile,
stdout=LogFile,
shell=True)
except CalledProcessError, e:
print "Error: Analyzes of %s failed. See %s for details." \
"Error code %d." % \
(FullFileName, LogFile.name, e.returncode)
Failed = True
finally:
LogFile.close()
# If command did not fail, erase the log file.
if Failed == False:
os.remove(LogFile.name);
def buildProject(Dir, SBOutputDir, IsScanBuild):
TBegin = time.time()
BuildLogPath = os.path.join(Dir, BuildLogName)
BuildLogPath = os.path.join(SBOutputDir, LogFolderName, BuildLogName)
print "Log file: %s" % (BuildLogPath,)
print "Output directory: %s" %(SBOutputDir, )
# Clean up the log file.
if (os.path.exists(BuildLogPath)) :
RmCommand = "rm " + BuildLogPath
if Verbose == 1:
print " Executing: %s" % (RmCommand,)
check_call(RmCommand, shell=True)
# Clean up scan build results.
if (os.path.exists(SBOutputDir)) :
RmCommand = "rm -r " + SBOutputDir
if Verbose == 1:
print " Executing: %s" % (RmCommand,)
check_call(RmCommand, shell=True)
assert(not os.path.exists(SBOutputDir))
os.makedirs(os.path.join(SBOutputDir, LogFolderName))
# Open the log file.
PBuildLogFile = open(BuildLogPath, "wb+")
try:
# Clean up scan build results.
if (os.path.exists(SBOutputDir)) :
RmCommand = "rm -r " + SBOutputDir
if Verbose == 1:
print " Executing: %s" % (RmCommand,)
check_call(RmCommand, stderr=PBuildLogFile,
stdout=PBuildLogFile, shell=True)
# Build and analyze the project.
try:
runCleanupScript(Dir, PBuildLogFile)
runScanBuild(Dir, SBOutputDir, PBuildLogFile)
if ClenupAfterBuild :
if IsScanBuild:
runScanBuild(Dir, SBOutputDir, PBuildLogFile)
else:
runAnalyzePreprocessed(Dir, SBOutputDir)
if IsReferenceBuild :
runCleanupScript(Dir, PBuildLogFile)
finally:
@ -189,9 +267,9 @@ def checkBuild(SBOutputDir):
return;
# Create summary file to display when the build fails.
SummaryPath = os.path.join(SBOutputDir, FailuresSummaryFileName);
SummaryPath = os.path.join(SBOutputDir, LogFolderName, FailuresSummaryFileName)
if (Verbose > 0):
print " Creating the failures summary file %s." % (SummaryPath,)
print " Creating the failures summary file %s" % (SummaryPath,)
SummaryLog = open(SummaryPath, "w+")
try:
@ -216,7 +294,7 @@ def checkBuild(SBOutputDir):
finally:
SummaryLog.close()
print "Error: Scan-build failed. See ", \
print "Error: analysis failed. See ", \
os.path.join(SBOutputDir, FailuresSummaryFileName)
sys.exit(-1)
@ -235,6 +313,11 @@ def runCmpResults(Dir):
# We have to go one level down the directory tree.
RefList = glob.glob(RefDir + "/*")
NewList = glob.glob(NewDir + "/*")
# Log folders are also located in the results dir, so ignore them.
RefList.remove(os.path.join(RefDir, LogFolderName))
NewList.remove(os.path.join(NewDir, LogFolderName))
if len(RefList) == 0 or len(NewList) == 0:
return False
assert(len(RefList) == len(NewList))
@ -271,8 +354,13 @@ def runCmpResults(Dir):
print "Diagnostic comparison complete (time: %.2f)." % (time.time()-TBegin)
return HaveDiffs
def testProject(ID, InIsReferenceBuild, IsScanBuild , Dir=None):
global IsReferenceBuild
IsReferenceBuild = InIsReferenceBuild
print " \n\n--- Building project %s" % (ID,)
def testProject(ID, IsReferenceBuild, Dir=None):
TBegin = time.time()
if Dir is None :
@ -281,13 +369,9 @@ def testProject(ID, IsReferenceBuild, Dir=None):
print " Build directory: %s." % (Dir,)
# Set the build results directory.
if IsReferenceBuild == True :
SBOutputDir = os.path.join(Dir, SBOutputDirReferencePrefix + \
SBOutputDirName)
else :
SBOutputDir = os.path.join(Dir, SBOutputDirName)
buildProject(Dir, SBOutputDir, IsReferenceBuild)
SBOutputDir = os.path.join(Dir, getSBOutputDirName())
buildProject(Dir, SBOutputDir, IsScanBuild)
checkBuild(SBOutputDir)
@ -297,13 +381,22 @@ def testProject(ID, IsReferenceBuild, Dir=None):
print "Completed tests for project %s (time: %.2f)." % \
(ID, (time.time()-TBegin))
def testAll(IsReferenceBuild=False):
def testAll(InIsReferenceBuild = False):
PMapFile = open(getProjectMapPath(), "rb")
try:
PMapReader = csv.reader(PMapFile)
for I in PMapReader:
print " --- Building project %s" % (I[0],)
testProject(I[0], IsReferenceBuild)
if (len(I) != 2) :
print "Error: Rows in the ProjectMapFile should have 3 entries."
raise Exception()
if (not ((I[1] == "1") | (I[1] == "0"))):
print "Error: Second entry in the ProjectMapFile should be 0 or 1."
raise Exception()
testProject(I[0], InIsReferenceBuild, int(I[1]))
except:
print "Error occurred. Premature termination."
raise
finally:
PMapFile.close()