Add parsing of warnings and errors
This commit is contained in:
parent
350eeeab4e
commit
8f63293056
261
Source/ctest.cxx
261
Source/ctest.cxx
@ -18,6 +18,8 @@
|
|||||||
#include "cmRegularExpression.h"
|
#include "cmRegularExpression.h"
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
|
|
||||||
|
#include <strstream>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -42,6 +44,70 @@ static std::string CurrentTime()
|
|||||||
return ::CleanString(ctime(¤ttime));
|
return ::CleanString(ctime(¤ttime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* cmCTestErrorMatches[] = {
|
||||||
|
"^[Bb]us [Ee]rror",
|
||||||
|
"^[Ss]egmentation [Vv]iolation",
|
||||||
|
"^[Ss]egmentation [Ff]ault",
|
||||||
|
"([^ :]+):([0-9]+): ([^ \\t])",
|
||||||
|
"([^:]+): error[ \\t]*[0-9]+[ \\t]*:",
|
||||||
|
"^Error ([0-9]+):",
|
||||||
|
"^Error ",
|
||||||
|
"^\"[^\"]+\", line [0-9]+: [^Ww]",
|
||||||
|
"^cc[^C]*CC: ERROR File = ([^,]+), Line = ([0-9]+)",
|
||||||
|
"^ld([^:])*:([ \\t])*ERROR([^:])*:",
|
||||||
|
"^ild:([ \\t])*\\(undefined symbol\\)",
|
||||||
|
"([^ :]+) : (error|fatal error|catastrophic error)",
|
||||||
|
"([^:]+): (Error:|error|undefined reference|multiply defined)",
|
||||||
|
"([^:]+)\\(([^\\)]+)\\) : (error|fatal error|catastrophic error)",
|
||||||
|
"^fatal error C[0-9]+:",
|
||||||
|
": syntax error ",
|
||||||
|
"^collect2: ld returned 1 exit status",
|
||||||
|
"Unsatisfied symbols:",
|
||||||
|
"Undefined symbols:",
|
||||||
|
"^Undefined[ \\t]+first referenced",
|
||||||
|
"^CMake Error:",
|
||||||
|
":[ \\t]cannot find",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* cmCTestErrorExceptions[] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* cmCTestWarningMatches[] = {
|
||||||
|
"([^ :]+):([0-9]+): warning:",
|
||||||
|
"^cc[^C]*CC: WARNING File = ([^,]+), Line = ([0-9]+)",
|
||||||
|
"^ld([^:])*:([ \\t])*WARNING([^:])*:",
|
||||||
|
"([^:]+): warning ([0-9]+):",
|
||||||
|
"^\"[^\"]+\", line [0-9]+: [Ww]arning",
|
||||||
|
"([^:]+): warning[ \\t]*[0-9]+[ \\t]*:",
|
||||||
|
"^Warning ([0-9]+):",
|
||||||
|
"^Warning ",
|
||||||
|
"([^ :]+) : warning",
|
||||||
|
"([^:]+): warning",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* cmCTestWarningExceptions[] = {
|
||||||
|
"/usr/openwin/include/X11/Xlib\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration",
|
||||||
|
"/usr/openwin/include/X11/Xutil\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration",
|
||||||
|
"/usr/openwin/include/X11/XResource\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration",
|
||||||
|
"WARNING 84 :",
|
||||||
|
"WARNING 47 :",
|
||||||
|
"makefile:",
|
||||||
|
"Makefile:",
|
||||||
|
"warning: Clock skew detected. Your build may be incomplete.",
|
||||||
|
"/usr/openwin/include/GL/[^:]+:",
|
||||||
|
"bind_at_load",
|
||||||
|
"XrmQGetResource",
|
||||||
|
"IceFlush",
|
||||||
|
"warning LNK4089: all references to .GDI32.dll. discarded by .OPT:REF",
|
||||||
|
"warning LNK4089: all references to .USER32.dll. discarded by .OPT:REF",
|
||||||
|
"ld32: WARNING 85: definition of dataKey in",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
bool TryExecutable(const char *dir, const char *file,
|
bool TryExecutable(const char *dir, const char *file,
|
||||||
std::string *fullPath, const char *subdir)
|
std::string *fullPath, const char *subdir)
|
||||||
{
|
{
|
||||||
@ -357,8 +423,200 @@ void ctest::BuildDirectory()
|
|||||||
}
|
}
|
||||||
// To do:
|
// To do:
|
||||||
// Add parsing of output for errors and warnings.
|
// Add parsing of output for errors and warnings.
|
||||||
|
|
||||||
|
cmCTestBuildErrorWarning cerw;
|
||||||
|
char* coutput = new char[ output.size() + 1];
|
||||||
|
memcpy(coutput, output.c_str(), output.size());
|
||||||
|
int cc;
|
||||||
|
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
|
||||||
|
// Lines are marked:
|
||||||
|
// 0 - nothing
|
||||||
|
// 1 - error
|
||||||
|
// > 1 - warning
|
||||||
|
std::vector<int> markedLines;
|
||||||
|
std::istrstream istr(coutput);
|
||||||
|
while(istr)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
std::string line;
|
||||||
|
while ( istr )
|
||||||
|
{
|
||||||
|
buffer[0] = 0;
|
||||||
|
istr.getline(buffer, 1023);
|
||||||
|
buffer[1023] = 0;
|
||||||
|
line += buffer;
|
||||||
|
if ( strlen(buffer) < 1023 )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lines.push_back(line);
|
||||||
|
markedLines.push_back(0);
|
||||||
|
//std::cout << "Line [" << line << "]" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
for ( cc = 0; cmCTestErrorMatches[cc]; cc ++ )
|
||||||
|
{
|
||||||
|
cmRegularExpression re(cmCTestErrorMatches[cc]);
|
||||||
|
std::vector<std::string>::size_type kk;
|
||||||
|
for ( kk = 0; kk < lines.size(); kk ++ )
|
||||||
|
{
|
||||||
|
if ( re.find(lines[kk]) )
|
||||||
|
{
|
||||||
|
markedLines[kk] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Warnings
|
||||||
|
for ( cc = 0; cmCTestWarningMatches[cc]; cc ++ )
|
||||||
|
{
|
||||||
|
cmRegularExpression re(cmCTestWarningMatches[cc]);
|
||||||
|
std::vector<std::string>::size_type kk;
|
||||||
|
for ( kk = 0; kk < lines.size(); kk ++ )
|
||||||
|
{
|
||||||
|
if ( re.find(lines[kk]) )
|
||||||
|
{
|
||||||
|
markedLines[kk] += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( cc = 0; cmCTestErrorExceptions[cc]; cc ++ )
|
||||||
|
{
|
||||||
|
cmRegularExpression re(cmCTestErrorExceptions[cc]);
|
||||||
|
std::vector<int>::size_type kk;
|
||||||
|
for ( kk =0; kk < markedLines.size(); kk ++ )
|
||||||
|
{
|
||||||
|
if ( markedLines[cc] == 1 )
|
||||||
|
{
|
||||||
|
if ( re.find(lines[kk]) )
|
||||||
|
{
|
||||||
|
markedLines[cc] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( cc = 0; cmCTestWarningExceptions[cc]; cc ++ )
|
||||||
|
{
|
||||||
|
cmRegularExpression re(cmCTestWarningExceptions[cc]);
|
||||||
|
std::vector<int>::size_type kk;
|
||||||
|
for ( kk =0; kk < markedLines.size(); kk ++ )
|
||||||
|
{
|
||||||
|
if ( markedLines[cc] > 1 )
|
||||||
|
{
|
||||||
|
if ( re.find(lines[kk]) )
|
||||||
|
{
|
||||||
|
markedLines[cc] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<cmCTestBuildErrorWarning> errorsWarnings;
|
||||||
|
|
||||||
|
std::vector<int>::size_type kk;
|
||||||
|
cmCTestBuildErrorWarning errorwarning;
|
||||||
|
for ( kk =0; kk < markedLines.size(); kk ++ )
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
if ( markedLines[kk] == 1 )
|
||||||
|
{
|
||||||
|
std::cout << "Error: " << lines[kk] << std::endl;
|
||||||
|
errorwarning.m_Error = true;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else if ( markedLines[kk] > 1 )
|
||||||
|
{
|
||||||
|
std::cout << "Warning: " << lines[kk] << std::endl;
|
||||||
|
errorwarning.m_Error = false;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if ( found )
|
||||||
|
{
|
||||||
|
errorwarning.m_LogLine = kk;
|
||||||
|
errorwarning.m_Text = lines[kk];
|
||||||
|
errorwarning.m_PreContext = "";
|
||||||
|
errorwarning.m_PostContext = "";
|
||||||
|
std::vector<int>::size_type jj;
|
||||||
|
for ( jj = kk;
|
||||||
|
jj > 0 && jj > kk - 6 /* && markedLines[jj] == 0 */;
|
||||||
|
jj -- );
|
||||||
|
for (; jj < kk; jj ++ )
|
||||||
|
{
|
||||||
|
errorwarning.m_PreContext += lines[jj] + "\n";
|
||||||
|
}
|
||||||
|
for ( jj = kk+1;
|
||||||
|
jj < lines.size() && jj < kk + 6 /* && markedLines[jj] == 0*/;
|
||||||
|
jj ++ )
|
||||||
|
{
|
||||||
|
errorwarning.m_PostContext += lines[jj] + "\n";
|
||||||
|
}
|
||||||
|
errorsWarnings.push_back(errorwarning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
this->GenerateDartBuildOutput(std::cout,
|
||||||
|
errorsWarnings);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ctest::GenerateDartBuildOutput(std::ostream& os,
|
||||||
|
std::vector<cmCTestBuildErrorWarning> ew)
|
||||||
|
{
|
||||||
|
time_t tctime = time(0);
|
||||||
|
struct tm *lctime = gmtime(&tctime);
|
||||||
|
char datestring[100];
|
||||||
|
sprintf(datestring, "%4d%02d%02d-%d%d",
|
||||||
|
lctime->tm_year + 1900,
|
||||||
|
lctime->tm_mon,
|
||||||
|
lctime->tm_mday,
|
||||||
|
lctime->tm_hour,
|
||||||
|
lctime->tm_min);
|
||||||
|
|
||||||
|
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
<< "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
|
||||||
|
<< "\" BuildStamp=\"" << datestring << "-Experimental\" Name=\""
|
||||||
|
<< m_DartConfiguration["Site"] << "\">\n"
|
||||||
|
<< "<Build>\n"
|
||||||
|
<< " <StartDateTime>" << ::CurrentTime() << "</StartDateTime>\n"
|
||||||
|
<< " <BuildCommand>" << m_DartConfiguration["MakeCommand"]
|
||||||
|
<< "</BuildCommand>" << std::endl;
|
||||||
|
|
||||||
|
std::vector<cmCTestBuildErrorWarning>::iterator it;
|
||||||
|
for ( it = ew.begin(); it != ew.end(); it++ )
|
||||||
|
{
|
||||||
|
cmCTestBuildErrorWarning *cm = &(*it);
|
||||||
|
os << " <" << (cm->m_Error ? "Error" : "Warning") << ">\n"
|
||||||
|
<< " <BuildLogLine>" << cm->m_LogLine << "</BuildLogLine>\n"
|
||||||
|
<< " <Text>" << cm->m_Text << "</Text>" << std::endl;
|
||||||
|
if ( cm->m_SourceFile.size() > 0 )
|
||||||
|
{
|
||||||
|
os << " <SourceFile>" << cm->m_SourceFile << "</SourceFile>"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
if ( cm->m_SourceFileTail.size() > 0 )
|
||||||
|
{
|
||||||
|
os << " <SourceFileTail>" << cm->m_SourceFileTail
|
||||||
|
<< "</SourceFileTail>" << std::endl;
|
||||||
|
}
|
||||||
|
if ( cm->m_LineNumber >= 0 )
|
||||||
|
{
|
||||||
|
os << " <SourceLineNumber>" << cm->m_LineNumber
|
||||||
|
<< "</SourceLineNumber>" << std::endl;
|
||||||
|
}
|
||||||
|
os << " <PreContext>" << cm->m_PreContext << "</PreContext>\n"
|
||||||
|
<< " <PostContext>" << cm->m_PostContext << "</PostContext>\n"
|
||||||
|
<< " </" << (cm->m_Error ? "Error" : "Warning") << ">"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
os << " <Log Encoding=\"base64\" Compression=\"/bin/gzip\">\n </Log>\n"
|
||||||
|
<< " <EndDateTime>" << ::CurrentTime() << "</EndDateTime>\n"
|
||||||
|
<< "</Build>\n"
|
||||||
|
<< "</Site>" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void ctest::ProcessDirectory(std::vector<std::string> &passed,
|
void ctest::ProcessDirectory(std::vector<std::string> &passed,
|
||||||
std::vector<std::string> &failed)
|
std::vector<std::string> &failed)
|
||||||
{
|
{
|
||||||
@ -547,13 +805,12 @@ void ctest::GenerateDartOutput(std::ostream& os)
|
|||||||
lctime->tm_hour,
|
lctime->tm_hour,
|
||||||
lctime->tm_min);
|
lctime->tm_min);
|
||||||
|
|
||||||
os << "Try to create dart output file" << std::endl;
|
|
||||||
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
<< "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
|
<< "<Site BuildName=\"" << m_DartConfiguration["BuildName"]
|
||||||
<< "\" BuildStamp=\"" << datestring << "-Experimental\" Name=\""
|
<< "\" BuildStamp=\"" << datestring << "-Experimental\" Name=\""
|
||||||
<< m_DartConfiguration["Site"] << "\">\n"
|
<< m_DartConfiguration["Site"] << "\">\n"
|
||||||
<< "<Testing>\n"
|
<< "<Testing>\n"
|
||||||
<< " <StartDateTime>" << ::CurrentTime() << " </StartDateTime>\n"
|
<< " <StartDateTime>" << ::CurrentTime() << "</StartDateTime>\n"
|
||||||
<< " <TestList>\n";
|
<< " <TestList>\n";
|
||||||
tm_TestResultsVector::size_type cc;
|
tm_TestResultsVector::size_type cc;
|
||||||
for ( cc = 0; cc < m_TestResults.size(); cc ++ )
|
for ( cc = 0; cc < m_TestResults.size(); cc ++ )
|
||||||
|
@ -60,11 +60,6 @@ public:
|
|||||||
void ProcessDirectory(std::vector<std::string> &passed,
|
void ProcessDirectory(std::vector<std::string> &passed,
|
||||||
std::vector<std::string> &failed);
|
std::vector<std::string> &failed);
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the Dart compatible output
|
|
||||||
*/
|
|
||||||
void GenerateDartOutput(std::ostream& os);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the executable for a test
|
* Find the executable for a test
|
||||||
*/
|
*/
|
||||||
@ -115,6 +110,18 @@ private:
|
|||||||
std::string m_Output;
|
std::string m_Output;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cmCTestBuildErrorWarning
|
||||||
|
{
|
||||||
|
bool m_Error;
|
||||||
|
int m_LogLine;
|
||||||
|
std::string m_Text;
|
||||||
|
std::string m_SourceFile;
|
||||||
|
std::string m_SourceFileTail;
|
||||||
|
int m_LineNumber;
|
||||||
|
std::string m_PreContext;
|
||||||
|
std::string m_PostContext;
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::vector<cmCTestTestResult> tm_TestResultsVector;
|
typedef std::vector<cmCTestTestResult> tm_TestResultsVector;
|
||||||
typedef std::map<std::string, std::string> tm_DartConfigurationMap;
|
typedef std::map<std::string, std::string> tm_DartConfigurationMap;
|
||||||
|
|
||||||
@ -122,5 +129,14 @@ private:
|
|||||||
std::string m_ToplevelPath;
|
std::string m_ToplevelPath;
|
||||||
tm_DartConfigurationMap m_DartConfiguration;
|
tm_DartConfigurationMap m_DartConfiguration;
|
||||||
int m_Tests[LAST_TEST];
|
int m_Tests[LAST_TEST];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the Dart compatible output
|
||||||
|
*/
|
||||||
|
void GenerateDartOutput(std::ostream& os);
|
||||||
|
void GenerateDartBuildOutput(std::ostream& os,
|
||||||
|
std::vector<cmCTestBuildErrorWarning>);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user