[analyzer] Add support for testing with individual preprocessed files.
llvm-svn: 143786
This commit is contained in:
parent
dc66efeb10
commit
4720a730f6
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
Loading…
Reference in New Issue