diff --git a/Modules/Dart.cmake b/Modules/Dart.cmake index cfe6fdb286..b5eb9c74a7 100644 --- a/Modules/Dart.cmake +++ b/Modules/Dart.cmake @@ -69,7 +69,9 @@ IF(BUILD_TESTING) DOC "Path to program used to compress files for transfer to the dart server") FIND_PROGRAM(GUNZIPCOMMAND gunzip DOC "Path to gunzip executable") FIND_PROGRAM(JAVACOMMAND java DOC "Path to java command, used by the Dart server to create html.") - FIND_PROGRAM(PURIFYCOMMAND purify + FIND_PROGRAM(MEMORYCHECK_COMMAND + NAMES purify valgrind boundscheck + PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rational Software\\Purify\\Setup;InstallFolder]" DOC "Path to Rational purify command, used for memory error detection." ) @@ -95,11 +97,25 @@ IF(BUILD_TESTING) ELSE(WIN32) SET(DART_NAME_COMPONENT "NAME") ENDIF(WIN32) + SET(BUILD_NAME_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}") + IF(WIN32) + SET(BUILD_NAME_SYSTEM_NAME "Win32") + ENDIF(WIN32) IF(UNIX OR BORLAND) GET_FILENAME_COMPONENT(DART_CXX_NAME "${CMAKE_CXX_COMPILER}" ${DART_NAME_COMPONENT}) ELSE(UNIX OR BORLAND) GET_FILENAME_COMPONENT(DART_CXX_NAME "${CMAKE_BUILD_TOOL}" ${DART_NAME_COMPONENT}) ENDIF(UNIX OR BORLAND) + IF(DART_CXX_NAME MATCHES "msdev") + SET(DART_CXX_NAME "vs60") + ENDIF(DART_CXX_NAME MATCHES "msdev") + IF(DART_CXX_NAME MATCHES "devenv") + IF(CMAKE_GENERATOR MATCHES "^Visual Studio 7$") + SET(DART_CXX_NAME "vs70") + ELSE(CMAKE_GENERATOR MATCHES "^Visual Studio 7$") + SET(DART_CXX_NAME "vs71") + ENDIF(CMAKE_GENERATOR MATCHES "^Visual Studio 7$") + ENDIF(DART_CXX_NAME MATCHES "devenv") SET(BUILDNAME "${CMAKE_SYSTEM_NAME}-${DART_CXX_NAME}") MESSAGE(STATUS "Using Buildname: ${BUILDNAME}") ENDIF(NOT BUILDNAME) @@ -140,7 +156,7 @@ IF(BUILD_TESTING) # configure files CONFIGURE_FILE( - ${DART_ROOT}/Source/Client/Utility.conf.in + ${DART_ROOT}/Source/Client/Dart.conf.in ${PROJECT_BINARY_DIR}/DartConfiguration.tcl ) # diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in index aaed45a205..25d6f26264 100644 --- a/Modules/DartConfiguration.tcl.in +++ b/Modules/DartConfiguration.tcl.in @@ -40,6 +40,8 @@ ScpCommand: @SCPCOMMAND@ PurifyCommand: @PURIFYCOMMAND@ ValgrindCommand: @VALGRIND_COMMAND@ ValgrindCommandOptions: @VALGRIND_COMMAND_OPTIONS@ +MemoryCheckCommand: @MEMORYCHECK_COMMAND@ +MemoryCheckCommandOptions: @MEMORYCHECK_COMMAND_OPTIONS@ CoverageCommand: @COVERAGE_COMMAND@ # Compression commands GunzipCommand: @GUNZIPCOMMAND@ diff --git a/Source/CTest/cmCTestSubmit.cxx b/Source/CTest/cmCTestSubmit.cxx index 665c1d49ec..81f83b2679 100644 --- a/Source/CTest/cmCTestSubmit.cxx +++ b/Source/CTest/cmCTestSubmit.cxx @@ -37,7 +37,7 @@ cmCTestSubmit::cmCTestSubmit() : m_HTTPProxy(), m_FTPProxy() } if ( getenv("HTTP_PROXY_TYPE") ) { - std::string type = getenv("HTTP_PROXY_TYPE"); + cmStdString type = getenv("HTTP_PROXY_TYPE"); // HTTP/SOCKS4/SOCKS5 if ( type == "HTTP" ) { @@ -66,7 +66,7 @@ cmCTestSubmit::cmCTestSubmit() : m_HTTPProxy(), m_FTPProxy() } if ( getenv("FTP_PROXY_TYPE") ) { - std::string type = getenv("FTP_PROXY_TYPE"); + cmStdString type = getenv("FTP_PROXY_TYPE"); // HTTP/SOCKS4/SOCKS5 if ( type == "HTTP" ) { @@ -92,10 +92,10 @@ cmCTestSubmit::cmCTestSubmit() : m_HTTPProxy(), m_FTPProxy() } } -bool cmCTestSubmit::SubmitUsingFTP(const std::string& localprefix, - const std::vector& files, - const std::string& remoteprefix, - const std::string& url) +bool cmCTestSubmit::SubmitUsingFTP(const cmStdString& localprefix, + const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url) { CURL *curl; CURLcode res; @@ -105,7 +105,7 @@ bool cmCTestSubmit::SubmitUsingFTP(const std::string& localprefix, /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); - std::string::size_type cc; + cmStdString::size_type cc; for ( cc = 0; cc < files.size(); cc ++ ) { /* get a curl handle */ @@ -132,8 +132,8 @@ bool cmCTestSubmit::SubmitUsingFTP(const std::string& localprefix, // enable uploading ::curl_easy_setopt(curl, CURLOPT_UPLOAD, TRUE) ; - std::string local_file = localprefix + "/" + files[cc]; - std::string upload_as = url + "/" + remoteprefix + files[cc]; + cmStdString local_file = localprefix + "/" + files[cc]; + cmStdString upload_as = url + "/" + remoteprefix + files[cc]; struct stat st; if ( ::stat(local_file.c_str(), &st) ) @@ -184,10 +184,10 @@ bool cmCTestSubmit::SubmitUsingFTP(const std::string& localprefix, } // Uploading files is simpler -bool cmCTestSubmit::SubmitUsingHTTP(const std::string& localprefix, - const std::vector& files, - const std::string& remoteprefix, - const std::string& url) +bool cmCTestSubmit::SubmitUsingHTTP(const cmStdString& localprefix, + const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url) { CURL *curl; CURLcode res; @@ -196,7 +196,7 @@ bool cmCTestSubmit::SubmitUsingHTTP(const std::string& localprefix, /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); - std::string::size_type cc, kk; + cmStdString::size_type cc, kk; for ( cc = 0; cc < files.size(); cc ++ ) { /* get a curl handle */ @@ -231,9 +231,9 @@ bool cmCTestSubmit::SubmitUsingHTTP(const std::string& localprefix, ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); } - std::string local_file = localprefix + "/" + files[cc]; - std::string remote_file = remoteprefix + files[cc]; - std::string ofile = ""; + cmStdString local_file = localprefix + "/" + files[cc]; + cmStdString remote_file = remoteprefix + files[cc]; + cmStdString ofile = ""; for ( kk = 0; kk < remote_file.size(); kk ++ ) { char c = remote_file[kk]; @@ -256,7 +256,7 @@ bool cmCTestSubmit::SubmitUsingHTTP(const std::string& localprefix, ofile.append(hex); } } - std::string upload_as = url + "?FileName=" + ofile; + cmStdString upload_as = url + "?FileName=" + ofile; struct stat st; if ( ::stat(local_file.c_str(), &st) ) @@ -301,16 +301,16 @@ bool cmCTestSubmit::SubmitUsingHTTP(const std::string& localprefix, return true; } -bool cmCTestSubmit::TriggerUsingHTTP(const std::vector& files, - const std::string& remoteprefix, - const std::string& url) +bool cmCTestSubmit::TriggerUsingHTTP(const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url) { CURL *curl; /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); - std::string::size_type cc, kk; + cmStdString::size_type cc, kk; for ( cc = 0; cc < files.size(); cc ++ ) { /* get a curl handle */ @@ -339,8 +339,8 @@ bool cmCTestSubmit::TriggerUsingHTTP(const std::vector& files, { ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); } - std::string file = remoteprefix + files[cc]; - std::string ofile = ""; + cmStdString file = remoteprefix + files[cc]; + cmStdString ofile = ""; for ( kk = 0; kk < file.size(); kk ++ ) { char c = file[kk]; @@ -363,7 +363,7 @@ bool cmCTestSubmit::TriggerUsingHTTP(const std::vector& files, ofile.append(hex); } } - std::string turl = url + "?xmlfile=" + ofile; + cmStdString turl = url + "?xmlfile=" + ofile; if ( m_Verbose ) { std::cout << " Trigger url: " << turl.c_str() << std::endl; @@ -386,10 +386,10 @@ bool cmCTestSubmit::TriggerUsingHTTP(const std::vector& files, return true; } -bool cmCTestSubmit::SubmitUsingSCP(const std::string&, - const std::vector&, - const std::string&, - const std::string&) +bool cmCTestSubmit::SubmitUsingSCP(const cmStdString&, + const std::vector&, + const cmStdString&, + const cmStdString&) { std::cout << "SubmitUsingSCP is not yet implemented" << std::endl; return false; diff --git a/Source/CTest/cmCTestSubmit.h b/Source/CTest/cmCTestSubmit.h index c888b67e19..65dcd64ffa 100644 --- a/Source/CTest/cmCTestSubmit.h +++ b/Source/CTest/cmCTestSubmit.h @@ -41,27 +41,27 @@ public: /** * Submit file using various ways */ - bool SubmitUsingFTP(const std::string& localprefix, - const std::vector& files, - const std::string& remoteprefix, - const std::string& url); - bool SubmitUsingHTTP(const std::string& localprefix, - const std::vector& files, - const std::string& remoteprefix, - const std::string& url); - bool SubmitUsingSCP(const std::string& localprefix, - const std::vector& files, - const std::string& remoteprefix, - const std::string& url); + bool SubmitUsingFTP(const cmStdString& localprefix, + const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url); + bool SubmitUsingHTTP(const cmStdString& localprefix, + const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url); + bool SubmitUsingSCP(const cmStdString& localprefix, + const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url); - bool TriggerUsingHTTP(const std::vector& files, - const std::string& remoteprefix, - const std::string& url); + bool TriggerUsingHTTP(const std::vector& files, + const cmStdString& remoteprefix, + const cmStdString& url); private: - std::string m_HTTPProxy; + cmStdString m_HTTPProxy; int m_HTTPProxyType; - std::string m_FTPProxy; + cmStdString m_FTPProxy; int m_FTPProxyType; bool m_Verbose; }; diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx index 391e413e3c..93262b840c 100644 --- a/Source/CursesDialog/cmCursesPathWidget.cxx +++ b/Source/CursesDialog/cmCursesPathWidget.cxx @@ -62,7 +62,7 @@ void cmCursesPathWidget::OnTab(cmCursesMainForm* fm, WINDOW* w) { glob = cstr + "*"; } - std::vector dirs; + std::vector dirs; cmSystemTools::SimpleGlob(glob.c_str(), dirs, (m_Type == cmCacheManager::PATH?-1:0)); if ( m_CurrentIndex < dirs.size() ) diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 2a003dc1fe..da77921b09 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -22,10 +22,8 @@ #include #include "cmListFileCache.h" -#ifdef HAVE_CURL -# include "cmCTestSubmit.h" -# include "curl/curl.h" -#endif +#include "cmCTestSubmit.h" +#include "curl/curl.h" #include #include @@ -38,7 +36,6 @@ #define SAFEDIV(x,y) (((y)!=0)?((x)/(y)):(0)) -#ifdef HAVE_CURL static struct tm* GetNightlyTime(std::string str) { struct tm* lctime; @@ -66,7 +63,6 @@ static struct tm* GetNightlyTime(std::string str) lctime = gmtime(&ntime); return lctime; } -#endif static std::string CleanString(std::string str) { @@ -175,6 +171,32 @@ static const char* cmCTestWarningExceptions[] = { 0 }; +static const char* cmCTestMemCheckResultStrings[] = { + "ABR", + "ABW", + "ABWL", + "COR", + "EXU", + "FFM", + "FIM", + "FMM", + "FMR", + "FMW", + "FUM", + "IPR", + "IPW", + "MAF", + "MLK", + "MPK", + "NPR", + "ODS", + "PAR", + "PLK", + "UMC", + "UMR", + 0 +}; + std::string cmCTest::MakeXMLSafe(const std::string& str) { cmOStringStream ost; @@ -271,6 +293,7 @@ cmCTest::cmCTest() m_RunConfigurationScript = false; m_TestModel = cmCTest::EXPERIMENTAL; m_TimeOut = 0; + m_CompatibilityMode = 1; int cc; for ( cc=0; cc < cmCTest::LAST_TEST; cc ++ ) { @@ -369,14 +392,12 @@ void cmCTest::Initialize() } if ( tag.size() == 0 || m_Tests[cmCTest::START_TEST] || m_Tests[ALL_TEST]) { -#ifdef HAVE_CURL //std::cout << "TestModel: " << this->GetTestModelString() << std::endl; //std::cout << "TestModel: " << m_TestModel << std::endl; if ( m_TestModel == cmCTest::NIGHTLY ) { lctime = ::GetNightlyTime(m_DartConfiguration["NightlyStartTime"]); } -#endif char datestring[100]; sprintf(datestring, "%04d%02d%02d-%02d%02d", lctime->tm_year + 1900, @@ -427,9 +448,9 @@ bool cmCTest::SetTest(const char* ttype) { m_Tests[cmCTest::COVERAGE_TEST] = 1; } - else if ( cmSystemTools::LowerCase(ttype) == "purify" ) + else if ( cmSystemTools::LowerCase(ttype) == "memcheck" ) { - m_Tests[cmCTest::PURIFY_TEST] = 1; + m_Tests[cmCTest::MEMCHECK_TEST] = 1; } else if ( cmSystemTools::LowerCase(ttype) == "submit" ) { @@ -543,7 +564,6 @@ int cmCTest::UpdateDirectory() } std::string extra_update_opts; -#ifdef HAVE_CURL if ( m_TestModel == cmCTest::NIGHTLY ) { struct tm* t = ::GetNightlyTime(m_DartConfiguration["NightlyStartTime"]); @@ -560,7 +580,6 @@ int cmCTest::UpdateDirectory() extra_update_opts += "-D \"" + today_update_date +"\""; //std::cout << "Update: " << extra_update_opts << std::endl; } -#endif std::string command = cvsCommand + " -z3 update " + cvsOptions + " " + extra_update_opts; @@ -597,8 +616,8 @@ int cmCTest::UpdateDirectory() << "\t" << m_DartConfiguration["BuildName"] << "\n" << "\t" << m_CurrentTag << "-" - << this->GetTestModelString() << "\n" - << "\t" << start_time << "\n" + << this->GetTestModelString() << "" << std::endl; + os << "\t" << start_time << "\n" << "\t" << command << "\n" << "\t"; if ( retVal ) @@ -904,12 +923,8 @@ int cmCTest::ConfigureDirectory() if ( os ) { - os << "\n" - << "GetTestModelString() << "\" Name=\"" - << m_DartConfiguration["Site"] << "\">\n" - << "\n" + this->StartXML(os); + os << "\n" << "\t" << start_time << "" << std::endl; if ( res == cmsysProcess_State_Exited && retVal ) { @@ -921,8 +936,8 @@ int cmCTest::ConfigureDirectory() std::string end_time = ::CurrentTime(); os << "\t" << retVal << "\n" << "\t" << end_time << "\n" - << "\n" - << "" << std::endl; + << "" << std::endl; + this->EndXML(os); } } else @@ -999,7 +1014,7 @@ int cmCTest::BuildDirectory() for ( cc = 0; cmCTestErrorMatches[cc]; cc ++ ) { cmsys::RegularExpression re(cmCTestErrorMatches[cc]); - std::vector::size_type kk; + cmCTest::tm_VectorOfStrings::size_type kk; for ( kk = 0; kk < lines.size(); kk ++ ) { if ( re.find(lines[kk]) ) @@ -1012,7 +1027,7 @@ int cmCTest::BuildDirectory() for ( cc = 0; cmCTestWarningMatches[cc]; cc ++ ) { cmsys::RegularExpression re(cmCTestWarningMatches[cc]); - std::vector::size_type kk; + cmCTest::tm_VectorOfStrings::size_type kk; for ( kk = 0; kk < lines.size(); kk ++ ) { if ( re.find(lines[kk]) ) @@ -1128,9 +1143,9 @@ int cmCTest::BuildDirectory() int cmCTest::CoverageDirectory() { std::cout << "Performing coverage" << std::endl; - std::vector files; - std::vector cfiles; - std::vector cdirs; + cmCTest::tm_VectorOfStrings files; + cmCTest::tm_VectorOfStrings cfiles; + cmCTest::tm_VectorOfStrings cdirs; bool done = false; std::string::size_type cc; std::string glob; @@ -1279,7 +1294,7 @@ int cmCTest::CoverageDirectory() std::cout << "Cannot found any coverage files" << std::endl; return 1; } - std::map > sourcefiles; + std::map sourcefiles; for ( cc = 0; cc < cfiles.size(); cc ++ ) { std::string& fname = cfiles[cc]; @@ -1302,7 +1317,7 @@ int cmCTest::CoverageDirectory() if ( allsourcefiles.find(nf) != allsourcefiles.end() || allbinaryfiles.find(nf) != allbinaryfiles.end() ) { - std::vector &cvec = sourcefiles[nf]; + cmCTest::tm_VectorOfStrings &cvec = sourcefiles[nf]; cvec.push_back(fname); } } @@ -1313,15 +1328,11 @@ int cmCTest::CoverageDirectory() // std::cout << "File: " << files[cc] << std::endl; // } - std::map >::iterator it; + std::map::iterator it; cmCTest::tm_CoverageMap coverageresults; - log << "\n" - << "GetTestModelString() << "\" Name=\"" - << m_DartConfiguration["Site"] << "\">\n" - << "\n" + this->StartXML(log); + log << "\n" << "\t" << start_time << "" << std::endl; int total_tested = 0; @@ -1329,8 +1340,9 @@ int cmCTest::CoverageDirectory() for ( it = sourcefiles.begin(); it != sourcefiles.end(); it ++ ) { - // std::cerr << "Source file: " << it->first << std::endl; - std::vector &gfiles = it->second; + //std::cerr << "Source file: " << it->first << std::endl; + cmCTest::tm_VectorOfStrings &gfiles = it->second; + for ( cc = 0; cc < gfiles.size(); cc ++ ) { //std::cout << "\t" << gfiles[cc] << std::endl; @@ -1435,8 +1447,8 @@ int cmCTest::CoverageDirectory() { local_end_time = ::CurrentTime(); cfileoutput << "\t" << local_end_time << "\n" - << "\n" - << "" << std::endl; + << "" << std::endl; + this->EndXML(cfileoutput); cfileoutput.close(); std::cout << "Close file: " << cfileoutputname << std::endl; ccount = 0; @@ -1451,12 +1463,8 @@ int cmCTest::CoverageDirectory() return 1; } local_start_time = ::CurrentTime(); - cfileoutput << "\n" - << "GetTestModelString() << "\" Site=\"" - << m_DartConfiguration["Site"] << "\">\n" - << "\n" + this->StartXML(cfileoutput); + cfileoutput << "\n" << "\t" << local_start_time << "" << std::endl; } @@ -1524,8 +1532,8 @@ int cmCTest::CoverageDirectory() { local_end_time = ::CurrentTime(); cfileoutput << "\t" << local_end_time << "\n" - << "\n" - << "" << std::endl; + << "" << std::endl; + this->EndXML(cfileoutput); cfileoutput.close(); } @@ -1547,8 +1555,8 @@ int cmCTest::CoverageDirectory() log.precision(2); log << (percent_coverage)<< "\n" << "\t" << end_time << "\n" - << "\n" - << "" << std::endl; + << "" << std::endl; + this->EndXML(log); std::cout << "\tCovered LOC: " << total_tested << std::endl << "\tNot covered LOC: " << total_untested << std::endl @@ -1603,12 +1611,8 @@ bool cmCTest::OpenOutputFile(const std::string& path, void cmCTest::GenerateDartBuildOutput(std::ostream& os, std::vector ew) { - os << "\n" - << "GetTestModelString() << "\" Name=\"" - << m_DartConfiguration["Site"] << "\">\n" - << "\n" + this->StartXML(os); + os << "\n" << "\t" << m_StartBuild << "\n" << "" << this->MakeXMLSafe(m_DartConfiguration["MakeCommand"]) @@ -1647,12 +1651,13 @@ void cmCTest::GenerateDartBuildOutput(std::ostream& os, } os << "\t\n\t\n" << "\t" << m_EndBuild << "\n" - << "\n" - << "" << std::endl; + << "" << std::endl; + this->EndXML(os); } -void cmCTest::ProcessDirectory(std::vector &passed, - std::vector &failed) +void cmCTest::ProcessDirectory(cmCTest::tm_VectorOfStrings &passed, + cmCTest::tm_VectorOfStrings &failed, + bool memcheck) { // does the DartTestfile.txt exist ? if(!cmSystemTools::FileExists("DartTestfile.txt")) @@ -1692,7 +1697,7 @@ void cmCTest::ProcessDirectory(std::vector &passed, if (cmSystemTools::FileIsDirectory(nwd.c_str())) { cmSystemTools::ChangeDirectory(nwd.c_str()); - this->ProcessDirectory(passed, failed); + this->ProcessDirectory(passed, failed, memcheck); } } // return to the original directory @@ -1724,7 +1729,10 @@ void cmCTest::ProcessDirectory(std::vector &passed, if (firstTest) { std::string nwd = cmSystemTools::GetCurrentWorkingDirectory(); - std::cerr << "Changing directory into " << nwd.c_str() << "\n"; + if ( m_Verbose ) + { + std::cerr << "Changing directory into " << nwd.c_str() << "\n"; + } firstTest = 0; } cres.m_Name = args[0].Value; @@ -1756,6 +1764,15 @@ void cmCTest::ProcessDirectory(std::vector &passed, ++j; ++j; std::vector arguments; + if ( memcheck ) + { + cmCTest::tm_VectorOfStrings::size_type pp; + arguments.push_back(m_MemoryTester.c_str()); + for ( pp = 0; pp < m_MemoryTesterOptionsParsed.size(); pp ++ ) + { + arguments.push_back(m_MemoryTesterOptionsParsed[pp].c_str()); + } + } arguments.push_back(actualCommand.c_str()); for(;j != args.end(); ++j) { @@ -1867,15 +1884,97 @@ void cmCTest::ProcessDirectory(std::vector &passed, } } -int cmCTest::TestDirectory() +bool cmCTest::InitializeMemoryChecking() { - std::cout << "Test project" << std::endl; - std::vector passed; - std::vector failed; + if ( cmSystemTools::FileExists(m_DartConfiguration["MemoryCheckCommand"].c_str()) ) + { + m_MemoryTester + = cmSystemTools::ConvertToOutputPath(m_DartConfiguration["MemoryCheckCommand"].c_str()); + } + else if ( cmSystemTools::FileExists(m_DartConfiguration["PurifyCommand"].c_str()) ) + { + m_MemoryTester + = cmSystemTools::ConvertToOutputPath(m_DartConfiguration["PurifyCommand"].c_str()); + } + else if ( cmSystemTools::FileExists(m_DartConfiguration["ValgrindCommand"].c_str()) ) + { + m_MemoryTester + = cmSystemTools::ConvertToOutputPath(m_DartConfiguration["ValgrindCommand"].c_str()); + } + else + { + std::cout << "Memory checker (MemoryCheckCommand) not set, or cannot find the specified program." + << std::endl; + return false; + } + + if ( m_DartConfiguration["MemoryCheckCommandOptions"].size() ) + { + m_MemoryTesterOptions = m_DartConfiguration["MemoryCheckCommandOptions"]; + } + else if ( m_DartConfiguration["ValgrindCommandOptions"].size() ) + { + m_MemoryTesterOptions = m_DartConfiguration["ValgrindCommandOptions"]; + } + + m_MemoryTesterOutputFile = m_ToplevelPath + "/Testing/Temporary/MemoryChecker.log"; + m_MemoryTesterOutputFile = cmSystemTools::EscapeSpaces(m_MemoryTesterOutputFile.c_str()); + + if ( m_MemoryTester.find("valgrind") ) + { + m_MemoryTesterStyle = cmCTest::VALGRIND; + if ( !m_MemoryTesterOptions.size() ) + { + m_MemoryTesterOptions = "-q --skin=memcheck --leak-check=yes --show-reachable=yes --workaround-gcc296-bugs=yes --num-callers=100"; + } + } + else if ( m_MemoryTester.find("purify") ) + { + m_MemoryTesterStyle = cmCTest::PURIFY; +#ifdef _WIN32 + m_MemoryTesterOptions += " /SAVETEXTDATA=" + m_MemoryTesterOutputFile; +#else + m_MemoryTesterOptions += " -log-file=" + m_MemoryTesterOutputFile; +#endif + } + else if ( m_MemoryTester.find("boundschecker") ) + { + m_MemoryTesterStyle = cmCTest::BOUNDS_CHECKER; + std::cout << "Bounds checker not yet implemented" << std::endl; + return false; + } + else + { + std::cout << "Do not understand memory checker: " << m_MemoryTester.c_str() << std::endl; + return false; + } + + m_MemoryTesterOptionsParsed = cmSystemTools::ParseArguments(m_MemoryTesterOptions.c_str()); + cmCTest::tm_VectorOfStrings::size_type cc; + for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) + { + m_MemoryTesterGlobalResults[cc] = 0; + } + return true; +} + +int cmCTest::TestDirectory(bool memcheck) +{ + std::cout << (memcheck ? "Memory check" : "Test") << " project" << std::endl; + if ( memcheck ) + { + if ( !this->InitializeMemoryChecking() ) + { + return 1; + } + } + + cmCTest::tm_VectorOfStrings passed; + cmCTest::tm_VectorOfStrings failed; int total; m_StartTest = ::CurrentTime(); - this->ProcessDirectory(passed, failed); + this->ProcessDirectory(passed, failed, memcheck); m_EndTest = ::CurrentTime(); total = int(passed.size()) + int(failed.size()); @@ -1892,7 +1991,7 @@ int cmCTest::TestDirectory() if (passed.size() && (m_UseIncludeRegExp || m_UseExcludeRegExp)) { std::cerr << "\nThe following tests passed:\n"; - for(std::vector::iterator j = passed.begin(); + for(cmCTest::tm_VectorOfStrings::iterator j = passed.begin(); j != passed.end(); ++j) { std::cerr << "\t" << *j << "\n"; @@ -1906,7 +2005,7 @@ int cmCTest::TestDirectory() if (failed.size()) { std::cerr << "\nThe following tests FAILED:\n"; - for(std::vector::iterator j = failed.begin(); + for(cmCTest::tm_VectorOfStrings::iterator j = failed.begin(); j != failed.end(); ++j) { std::cerr << "\t" << *j << "\n"; @@ -1917,12 +2016,21 @@ int cmCTest::TestDirectory() if ( m_DartMode ) { std::ofstream ofs; - if( !this->OpenOutputFile(m_CurrentTag, "Test.xml", ofs) ) + if( !this->OpenOutputFile(m_CurrentTag, + (memcheck ? (m_CompatibilityMode?"Purify.xml":"MemCheck.xml") : "Test.xml"), ofs) ) { - std::cerr << "Cannot create testing XML file" << std::endl; + std::cerr << "Cannot create " << (memcheck ? "memory check" : "testing") + << " XML file" << std::endl; return 1; } - this->GenerateDartTestOutput(ofs); + if ( memcheck ) + { + this->GenerateDartMemCheckOutput(ofs); + } + else + { + this->GenerateDartTestOutput(ofs); + } } return int(failed.size()); @@ -1930,8 +2038,7 @@ int cmCTest::TestDirectory() int cmCTest::SubmitResults() { -#ifdef HAVE_CURL - std::vector files; + cmCTest::tm_VectorOfStrings files; std::string prefix = this->GetSubmitResultsPrefix(); // TODO: // Check if test is enabled @@ -1954,7 +2061,7 @@ int cmCTest::SubmitResults() if ( this->CTestFileExists("Coverage.xml") ) { files.push_back("Coverage.xml"); - std::vector gfiles; + cmCTest::tm_VectorOfStrings gfiles; std::string gpath = m_ToplevelPath + "/Testing/" + m_CurrentTag; std::string::size_type glen = gpath.size() + 1; gpath = gpath + "/CoverageLog*"; @@ -1974,6 +2081,10 @@ int cmCTest::SubmitResults() std::cout << "Problem globbing" << std::endl; } } + if ( this->CTestFileExists("MemCheck.xml") ) + { + files.push_back("MemCheck.xml"); + } if ( this->CTestFileExists("Purify.xml") ) { files.push_back("Purify.xml"); @@ -2035,7 +2146,6 @@ int cmCTest::SubmitResults() std::cout << "SCP submit not yet implemented" << std::endl; } -#endif return 0; } @@ -2055,6 +2165,96 @@ std::string cmCTest::GetSubmitResultsPrefix() return name; } +void cmCTest::GenerateDartMemCheckOutput(std::ostream& os) +{ + if ( !m_DartMode ) + { + return; + } + + this->StartXML(os); + if ( m_CompatibilityMode ) + { + os << "" << std::endl; + } + else + { + os << "" << std::endl; + } + os << "\t" << m_StartTest << "\n" + << "\t\n"; + tm_TestResultsVector::size_type cc; + for ( cc = 0; cc < m_TestResults.size(); cc ++ ) + { + cmCTestTestResult *result = &m_TestResults[cc]; + os << "\t\t" << this->MakeXMLSafe(result->m_Path) + << "/" << this->MakeXMLSafe(result->m_Name) + << "" << std::endl; + } + os << "\t\n"; + for ( cc = 0; cc < m_TestResults.size(); cc ++ ) + { + cmCTestTestResult *result = &m_TestResults[cc]; + std::string memcheckstr; + int memcheckresults[cmCTest::NO_MEMORY_FAULT]; + int kk; + this->ProcessMemCheckOutput(result->m_Output, memcheckstr, memcheckresults); + os << "\tm_Status == cmCTest::COMPLETED ) + { + os << "passed"; + } + else if ( result->m_Status == cmCTest::NOT_RUN ) + { + os << "notrun"; + } + else + { + os << "failed"; + } + os << "\">\n" + << "\t\t" << this->MakeXMLSafe(result->m_Name) << "\n" + << "\t\t" << this->MakeXMLSafe(result->m_Path) << "\n" + << "\t\t" << this->MakeXMLSafe(result->m_Path) + << "/" << this->MakeXMLSafe(result->m_Name) << "\n" + << "\t\t" + << this->MakeXMLSafe(result->m_FullCommandLine) + << "\n" + << "\t\t" << std::endl; + for ( kk = 0; cmCTestMemCheckResultStrings[kk]; kk ++ ) + { + os << "\t\t\t<" << cmCTestMemCheckResultStrings[kk] << ">" + << memcheckresults[kk] + << "" << std::endl; + m_MemoryTesterGlobalResults[kk] += memcheckresults[kk]; + } + os + << "\t\t\n" + << "\t\n" << cmCTest::MakeXMLSafe(memcheckstr) << std::endl + << "\t\n" + << "\t" << std::endl; + } + + os << "\t" << m_EndTest << "" << std::endl; + if ( m_CompatibilityMode ) + { + os << "" << std::endl; + } + else + { + os << "" << std::endl; + } + this->EndXML(os); + + + std::cerr << "Memory checking results:" << std::endl; + for ( cc = 0; cmCTestMemCheckResultStrings[cc]; cc ++ ) + { + std::cerr << "\t\t" << cmCTestMemCheckResultStrings[cc] << " - " + << m_MemoryTesterGlobalResults[cc] << std::endl; + } +} + void cmCTest::GenerateDartTestOutput(std::ostream& os) { if ( !m_DartMode ) @@ -2062,12 +2262,8 @@ void cmCTest::GenerateDartTestOutput(std::ostream& os) return; } - os << "\n" - << "GetTestModelString() << "\" Name=\"" - << m_DartConfiguration["Site"] << "\">\n" - << "\n" + this->StartXML(os); + os << "\n" << "\t" << m_StartTest << "\n" << "\t\n"; tm_TestResultsVector::size_type cc; @@ -2132,8 +2328,8 @@ void cmCTest::GenerateDartTestOutput(std::ostream& os) } os << "\t" << m_EndTest << "\n" - << "\n" - << "" << std::endl; + << "" << std::endl; + this->EndXML(os); } int cmCTest::ProcessTests() @@ -2173,23 +2369,19 @@ int cmCTest::ProcessTests() } if ( m_Tests[TEST_TEST] || m_Tests[ALL_TEST] || notest ) { - res += this->TestDirectory(); + res += this->TestDirectory(false); } if ( m_Tests[COVERAGE_TEST] || m_Tests[ALL_TEST] ) { this->CoverageDirectory(); } - if ( m_Tests[PURIFY_TEST] || m_Tests[ALL_TEST] ) + if ( m_Tests[MEMCHECK_TEST] || m_Tests[ALL_TEST] ) { - std::cerr << "Purify test is not yet implemented" << std::endl; + res += this->TestDirectory(true); } if ( m_Tests[SUBMIT_TEST] || m_Tests[ALL_TEST] ) { -#ifdef HAVE_CURL this->SubmitResults(); -#else - std::cerr << "Submit test is not yet implemented" << std::endl; -#endif } return res; } @@ -2763,3 +2955,100 @@ int cmCTest::RunConfigurationScript() return 0; } + +void cmCTest::StartXML(ostream& ostr) +{ + ostr << "\n" + << "GetTestModelString() << "\" Name=\"" + << m_DartConfiguration["Site"] << "\">" << std::endl; +} + +void cmCTest::EndXML(ostream& ostr) +{ + ostr << "" << std::endl; +} + +bool cmCTest::ProcessMemCheckValgrindOutput(const std::string& str, std::string& log, int* results) +{ + std::vector lines; + cmSystemTools::Split(str.c_str(), lines); + + + std::string::size_type cc; + + cmOStringStream ostr; + log = ""; + + cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*=="); + + cmsys::RegularExpression vgFIM("== .*Invalid free\\(\\) / delete / delete\\[\\]"); + cmsys::RegularExpression vgFMM("== .*Mismatched free\\(\\) / delete / delete \\[\\]"); + cmsys::RegularExpression vgMLK("== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are definitely lost in loss record [0-9][0-9]* of [0-9]"); + cmsys::RegularExpression vgPAR("== .*Syscall param .* contains unaddressable byte\\(s\\)"); + cmsys::RegularExpression vgMPK1("== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are possibly lost in loss record [0-9][0-9]* of [0-9]"); + cmsys::RegularExpression vgMPK2("== .*[0-9][0-9]* bytes in [0-9][0-9]* blocks are still reachable in loss record [0-9][0-9]* of [0-9]"); + cmsys::RegularExpression vgUMC("== .*Conditional jump or move depends on uninitialised value\\(s\\)"); + cmsys::RegularExpression vgUMR1("== .*Use of uninitialised value of size [0-9][0-9]*"); + cmsys::RegularExpression vgUMR2("== .*Invalid read of size [0-9][0-9]*"); + cmsys::RegularExpression vgUMR3("== .*Jump to the invalid address "); + cmsys::RegularExpression vgUMR4("== .*Syscall param .* contains uninitialised or unaddressable byte\\(s\\)"); + cmsys::RegularExpression vgIPW("== .*Invalid write of size [0-9]"); + + for ( cc = 0; cc < lines.size(); cc ++ ) + { + if ( valgrindLine.find(lines[cc]) ) + { + if ( vgFIM.find(lines[cc]) ) { results[cmCTest::FIM] ++; ostr << "FIM"; } + else if ( vgFMM.find(lines[cc]) ) { results[cmCTest::FMM] ++; ostr << "FMM"; } + else if ( vgMLK.find(lines[cc]) ) { results[cmCTest::MLK] ++; ostr << "MLK"; } + else if ( vgPAR.find(lines[cc]) ) { results[cmCTest::PAR] ++; ostr << "PAR"; } + else if ( vgMPK1.find(lines[cc]) ) { results[cmCTest::MPK] ++; ostr << "MPK"; } + else if ( vgMPK2.find(lines[cc]) ) { results[cmCTest::MPK] ++; ostr << "MPK"; } + else if ( vgUMC.find(lines[cc]) ) { results[cmCTest::UMC] ++; ostr << "UMC"; } + else if ( vgUMR1.find(lines[cc]) ) { results[cmCTest::UMR] ++; ostr << "UMR"; } + else if ( vgUMR2.find(lines[cc]) ) { results[cmCTest::UMR] ++; ostr << "UMR"; } + else if ( vgUMR3.find(lines[cc]) ) { results[cmCTest::UMR] ++; ostr << "UMR"; } + else if ( vgUMR4.find(lines[cc]) ) { results[cmCTest::UMR] ++; ostr << "UMR"; } + else if ( vgIPW.find(lines[cc]) ) { results[cmCTest::IPW] ++; ostr << "IPW"; } + + ostr << lines[cc] << std::endl; + } + } + log = ostr.str(); + return true; +} + +bool cmCTest::ProcessMemCheckOutput(const std::string& str, std::string& log, int* results) +{ + std::string::size_type cc; + for ( cc = 0; cc < cmCTest::NO_MEMORY_FAULT; cc ++ ) + { + results[cc] = 0; + } + + if ( m_MemoryTesterStyle == cmCTest::VALGRIND ) + { + return ProcessMemCheckValgrindOutput(str, log, results); + } + else if ( m_MemoryTesterStyle == cmCTest::PURIFY ) + { + log.append("\nMemory checking style used was: "); + log.append("Purify"); + } + else if ( m_MemoryTesterStyle == cmCTest::BOUNDS_CHECKER ) + { + log.append("\nMemory checking style used was: "); + log.append("Bounds Checker"); + } + else + { + log.append("\nMemory checking style used was: "); + log.append("None that I know"); + log = str; + } + + + return true; +} diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 9be9346492..8e5e2fbd16 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -24,6 +24,8 @@ class cmCTest { public: + typedef std::vector tm_VectorOfStrings; + /** * Run a dashboard using a specified confiuration script */ @@ -55,7 +57,7 @@ public: /** * Try to run tests of the project */ - int TestDirectory(); + int TestDirectory(bool memcheck); /** * Try to get coverage of the project @@ -86,8 +88,9 @@ public: /** * Run the test for a directory and any subdirectories */ - void ProcessDirectory(std::vector &passed, - std::vector &failed); + void ProcessDirectory(tm_VectorOfStrings &passed, + tm_VectorOfStrings &failed, + bool memcheck); /** * Find the executable for a test @@ -143,7 +146,7 @@ private: BUILD_TEST = 4, TEST_TEST = 5, COVERAGE_TEST = 6, - PURIFY_TEST = 7, + MEMCHECK_TEST = 7, SUBMIT_TEST = 8, ALL_TEST = 9, LAST_TEST = 10 @@ -162,6 +165,40 @@ private: COMPLETED }; + enum { // Memory checkers + UNKNOWN = 0, + VALGRIND, + PURIFY, + BOUNDS_CHECKER + }; + + enum { // Memory faults + ABR = 0, + ABW, + ABWL, + COR, + EXU, + FFM, + FIM, + FMM, + FMR, + FMW, + FUM, + IPR, + IPW, + MAF, + MLK, + MPK, + NPR, + ODS, + PAR, + PLK, + UMC, + UMR, + NO_MEMORY_FAULT + }; + + struct cmCTestTestResult { std::string m_Name; @@ -235,10 +272,20 @@ private: int m_TimeOut; + std::string m_MemoryTester; + std::string m_MemoryTesterOptions; + int m_MemoryTesterStyle; + std::string m_MemoryTesterOutputFile; + tm_VectorOfStrings m_MemoryTesterOptionsParsed; + int m_MemoryTesterGlobalResults[NO_MEMORY_FAULT]; + + int m_CompatibilityMode; + /** * Generate the Dart compatible output */ void GenerateDartTestOutput(std::ostream& os); + void GenerateDartMemCheckOutput(std::ostream& os); void GenerateDartBuildOutput(std::ostream& os, std::vector); @@ -259,6 +306,20 @@ private: std::string GenerateRegressionImages(const std::string& xml); const char* GetTestStatus(int status); + + //! Start CTest XML output file + void StartXML(ostream& ostr); + + //! End CTest XML output file + void EndXML(ostream& ostr); + + //! Parse Valgrind/Purify/Bounds Checker result out of the output string. After running, + // log holds the output and results hold the different memmory errors. + bool ProcessMemCheckOutput(const std::string& str, std::string& log, int* results); + bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log, int* results); + + //! Initialize memory checking subsystem. + bool InitializeMemoryChecking(); }; #endif diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c878899f44..3046abcc9d 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -909,8 +909,8 @@ void cmSystemTools::ExpandListArgument(const std::string& arg, } } -bool cmSystemTools::SimpleGlob(const std::string& glob, - std::vector& files, +bool cmSystemTools::SimpleGlob(const cmStdString& glob, + std::vector& files, int type /* = 0 */) { files.clear(); diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 4406b0e564..5d484a8387 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -139,7 +139,7 @@ public: * want to find. 0 means all files, -1 means directories, 1 means * files only. This method returns true if search was succesfull. */ - static bool SimpleGlob(const std::string& glob, std::vector& files, + static bool SimpleGlob(const cmStdString& glob, std::vector& files, int type = 0); ///! Copy a file. diff --git a/Source/ctest.cxx b/Source/ctest.cxx index ef7a5c7a8a..902955d479 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -197,10 +197,10 @@ int main (int argc, char *argv[]) inst.SetTestModel(cmCTest::EXPERIMENTAL); inst.SetTest("Test"); } - else if ( targ == "ExperimentalPurify" ) + else if ( targ == "ExperimentalMemCheck" || targ == "ExperimentalPurify" ) { inst.SetTestModel(cmCTest::EXPERIMENTAL); - inst.SetTest("Purify"); + inst.SetTest("MemCheck"); } else if ( targ == "ExperimentalCoverage" ) { @@ -248,10 +248,10 @@ int main (int argc, char *argv[]) inst.SetTestModel(cmCTest::CONTINUOUS); inst.SetTest("Test"); } - else if ( targ == "ContinuousPurify" ) + else if ( targ == "ContinuousMemCheck" || targ == "ContinuousPurify" ) { inst.SetTestModel(cmCTest::CONTINUOUS); - inst.SetTest("Purify"); + inst.SetTest("MemCheck"); } else if ( targ == "ContinuousCoverage" ) { @@ -299,10 +299,10 @@ int main (int argc, char *argv[]) inst.SetTestModel(cmCTest::NIGHTLY); inst.SetTest("Test"); } - else if ( targ == "NightlyPurify" ) + else if ( targ == "NightlyMemCheck" || targ == "NightlyPurify" ) { inst.SetTestModel(cmCTest::NIGHTLY); - inst.SetTest("Purify"); + inst.SetTest("MemCheck"); } else if ( targ == "NightlyCoverage" ) { @@ -320,7 +320,7 @@ int main (int argc, char *argv[]) inst.SetTest("Start"); inst.SetTest("Configure"); inst.SetTest("Build"); - inst.SetTest("Purify"); + inst.SetTest("MemCheck"); inst.SetTest("Coverage"); inst.SetTest("Submit"); } @@ -331,7 +331,7 @@ int main (int argc, char *argv[]) inst.SetTest("Update"); inst.SetTest("Configure"); inst.SetTest("Build"); - inst.SetTest("Purify"); + inst.SetTest("MemCheck"); inst.SetTest("Coverage"); inst.SetTest("Submit"); }