diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index fea985ae2..f0f369943 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -54,6 +54,8 @@ LINK_DIRECTORIES(${CMake_BINARY_DIR}/Sources) ADD_EXECUTABLE(cmake cmakemain) +ADD_EXECUTABLE(ctest ctest.cxx cmSystemTools.cxx cmRegularExpression.cxx) + IF(BUILD_TESTING) IF (DART_ROOT) ADD_EXECUTABLE(cmaketest cmaketest.cxx cmSystemTools.cxx) @@ -74,4 +76,5 @@ ENDIF(BUILD_TESTING) INSTALL_TARGETS(/bin cmake) +INSTALL_TARGETS(/bin ctest) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index bd2eb70ff..8ecd0c3af 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -824,17 +824,25 @@ bool cmSystemTools::IsOff(const char* val) bool cmSystemTools::RunCommand(const char* command, std::string& output, bool verbose) +{ + int foo; + return cmSystemTools::RunCommand(command, output, foo, verbose); +} + +bool cmSystemTools::RunCommand(const char* command, + std::string& output, + int &retVal, bool verbose) { const int BUFFER_SIZE = 4096; char buffer[BUFFER_SIZE]; - + #if defined(WIN32) && !defined(__CYGWIN__) std::string commandToFile = command; commandToFile += " > "; std::string tempFile; tempFile += cmSystemTools::TemporaryFileName(); commandToFile += tempFile; - system(commandToFile.c_str()); + retVal = system(commandToFile.c_str()); std::ifstream fin(tempFile.c_str()); if(!fin) { @@ -879,7 +887,7 @@ bool cmSystemTools::RunCommand(const char* command, output += buffer; fgets(buffer, BUFFER_SIZE, cpipe); } - pclose(cpipe); + retVal = pclose(cpipe); return true; #endif } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index a458b5484..d256913df 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -251,7 +251,9 @@ public: */ static bool RunCommand(const char* command, std::string& output, bool verbose = true); - + static bool RunCommand(const char* command, std::string& output, + int &retVal, bool verbose = true); + ///! Generate a temporary file name static std::string TemporaryFileName(); diff --git a/Source/cmUnixMakefileGenerator.cxx b/Source/cmUnixMakefileGenerator.cxx index 9df4254d2..9a878e710 100644 --- a/Source/cmUnixMakefileGenerator.cxx +++ b/Source/cmUnixMakefileGenerator.cxx @@ -1153,6 +1153,11 @@ void cmUnixMakefileGenerator::OutputMakeRules(std::ostream& fout) "all", "cmake.depends ${TARGETS} ${SUBDIR_BUILD} ${CMAKE_COMMAND}", 0); + this->OutputMakeRule(fout, + "run any tests", + "test", + "", + "ctest"); this->OutputMakeRule(fout, "remove generated files", "clean", diff --git a/Source/ctest.cxx b/Source/ctest.cxx new file mode 100644 index 000000000..cbda92cd7 --- /dev/null +++ b/Source/ctest.cxx @@ -0,0 +1,190 @@ +#include +#include "ctest.h" + +bool TryExecutable(const char *dir, const char *file, + std::string *fullPath, const char *subdir) +{ + // try current directory + std::string tryPath; + if (dir && strcmp(dir,"")) + { + tryPath = dir; + tryPath += "/"; + } + + if (subdir && strcmp(subdir,"")) + { + tryPath += subdir; + tryPath += "/"; + } + + tryPath += file; + if(cmSystemTools::FileExists(tryPath.c_str())) + { + *fullPath = cmSystemTools::CollapseFullPath(tryPath.c_str()); + return true; + } + tryPath += cmSystemTools::GetExecutableExtension(); + if(cmSystemTools::FileExists(tryPath.c_str())) + { + *fullPath = cmSystemTools::CollapseFullPath(tryPath.c_str()); + return true; + } + return false; +} + + +std::string ctest::FindExecutable(const char *exe) +{ + std::string fullPath = ""; + std::string dir; + std::string file; + + cmSystemTools::SplitProgramPath(exe, dir, file); + + if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,".")) + { + return fullPath; + } + + if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"")) + { + return fullPath; + } + + if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Release")) + { + return fullPath; + } + + if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"Debug")) + { + return fullPath; + } + + if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"MinSizeRel")) + { + return fullPath; + } + + if (TryExecutable(dir.c_str(),file.c_str(),&fullPath,"RelWithDebInfo")) + { + return fullPath; + } + + return fullPath; +} + + +void ctest::ProcessDirectory(int &passed, int &failed) +{ + // does the DartTestfile.txt exist ? + if(!cmSystemTools::FileExists("DartTestfile.txt")) + { + return; + } + + // parse the file + std::ifstream fin("DartTestfile.txt"); + if(!fin) + { + return; + } + + std::string name; + std::vector args; + while ( fin ) + { + if(cmSystemTools::ParseFunction(fin, name, args)) + { + if (name == "SUBDIRS") + { + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + for(std::vector::iterator j = args.begin(); + j != args.end(); ++j) + { + std::string nwd = cwd + "/"; + nwd += *j; + if (cmSystemTools::FileIsDirectory(nwd.c_str())) + { + cerr << "Changing directory into " << nwd.c_str() << "\n"; + cmSystemTools::ChangeDirectory(nwd.c_str()); + this->ProcessDirectory(passed,failed); + } + } + // return to the original directory + cmSystemTools::ChangeDirectory(cwd.c_str()); + } + + if (name == "ADD_TEST") + { + cerr << "Testing " << args[0] << " ... "; + // find the test executable + std::string testCommand = this->FindExecutable(args[1].c_str()); + // add the arguments + std::vector::iterator j = args.begin(); + ++j; + ++j; + for(;j != args.end(); ++j) + { + testCommand += " "; + testCommand += *j; + } + /** + * Run an executable command and put the stdout in output. + */ + std::string output; + int retVal; + + if (!cmSystemTools::RunCommand(testCommand.c_str(), output, + retVal, false) || retVal != 0) + { + std::cerr << " Failed\n"; + if (output != "") + { + std::cerr << output.c_str() << "\n"; + } + failed++; + } + else + { + std::cerr << " Passed\n"; + if (output != "") + { + std::cerr << output.c_str() << "\n"; + } + passed++; + } + } + } + } + +} + + +// this is a test driver program for cmake. +int main (int argc, char *argv[]) +{ + int passed = 0; + int failed = 0; + int total; + + ctest inst; + + // call process directory + inst.ProcessDirectory(passed, failed); + total = passed + failed; + + if (total == 0) + { + std::cerr << "No tests were found!!!\n"; + } + else + { + float percent = passed * 100.0 / total; + fprintf(stderr,"%f.0%% tests passed, %i tests failed out of %i\n", + percent,failed, total); + } + + return failed; +} diff --git a/Source/ctest.h b/Source/ctest.h new file mode 100644 index 000000000..9afe0b602 --- /dev/null +++ b/Source/ctest.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + +Copyright (c) 2001 Insight Consortium +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * The name of the Insight Consortium, nor the names of any consortium members, + nor of any contributors, may be used to endorse or promote products derived + from this software without specific prior written permission. + + * Modified source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================*/ + + +#include "cmStandardIncludes.h" +#include "cmSystemTools.h" + +class ctest +{ +public: + + /** + * Run the test for a directory and any subdirectories + */ + void ProcessDirectory(int &passed, int &failed); + + /** + * Find the executable for a test + */ + std::string FindExecutable(const char *exe); + + /** + * constructor + */ + ctest() {} + +private: +}; +