Commit 2f639d37 authored by Bill Hoffman's avatar Bill Hoffman
Browse files

ENH: add new command to create a test driver

parent 49bcc1ad
......@@ -131,6 +131,25 @@ IF(BUILD_TESTING)
wrapping
${CMake_BINARY_DIR}/Tests/Wrapping/bin)
ADD_TEST(testdriver1 ${CMake_BINARY_DIR}/Source/cmaketest
${CMake_SOURCE_DIR}/Tests/TestDriver
${CMake_BINARY_DIR}/Tests/TestDriver
TestDriverTest
${CMake_BINARY_DIR}/Tests/Wrapping/bin
TestDriverTest test1)
ADD_TEST(testdriver2 ${CMake_BINARY_DIR}/Source/cmaketest
${CMake_SOURCE_DIR}/Tests/TestDriver
${CMake_BINARY_DIR}/Tests/TestDriver
TestDriverTest
${CMake_BINARY_DIR}/Tests/Wrapping/bin
TestDriverTest test2)
ADD_TEST(testdriver3 ${CMake_BINARY_DIR}/Source/cmaketest
${CMake_SOURCE_DIR}/Tests/TestDriver
${CMake_BINARY_DIR}/Tests/TestDriver
TestDriverTest
${CMake_BINARY_DIR}/Tests/Wrapping/bin
TestDriverTest test3)
ENDIF (DART_ROOT)
ENDIF(BUILD_TESTING)
......
......@@ -33,6 +33,7 @@
#include "cmCableWrapTclCommand.cxx"
#include "cmConfigureFileCommand.cxx"
#include "cmConfigureGccXmlCommand.cxx"
#include "cmCreateTestSourceList.cxx"
#include "cmElseCommand.cxx"
#include "cmEnableTestingCommand.cxx"
#include "cmEndForEachCommand.cxx"
......@@ -99,6 +100,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands)
commands.push_back(new cmCableWrapTclCommand);
commands.push_back(new cmConfigureFileCommand);
commands.push_back(new cmConfigureGccXmlCommand);
commands.push_back(new cmCreateTestSourceList);
commands.push_back(new cmElseCommand);
commands.push_back(new cmEnableTestingCommand);
commands.push_back(new cmEndForEachCommand);
......
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Insight Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmCreateTestSourceList.h"
// cmCreateTestSourceList
bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& argsIn)
{
if (argsIn.size() < 5)
{
this->SetError("called with wrong number of arguments.");
return false;
}
std::vector<std::string> args;
cmSystemTools::ExpandListArguments(argsIn, args);
std::vector<std::string>::iterator i = args.begin();
const char* sourceList = i->c_str();
++i;
std::string driver = m_Makefile->GetCurrentOutputDirectory();
driver += "/";
driver += *i;
driver += ".cxx";
++i;
std::vector<std::string>::iterator testsBegin = i;
std::ofstream fout(driver.c_str());
if(!fout)
{
std::string err = "Could not create file ";
err += driver;
err += " for cmCreateTestSourceList command.";
this->SetError(err.c_str());
return false;
}
// Create the test driver file
fout << "#include <stdio.h>\n";
fout << "#include <string.h>\n";
fout << "// forward declare test functions\n";
for(i = testsBegin; i != args.end(); ++i)
{
fout << "int " << *i << "(int, char**);\n";
}
fout << "// Create map \n";
fout << "typedef int (*MainFuncPointer)(int , char**);\n";
fout << "struct functionMapEntry\n"
<< "{\n"
<< "const char* name;\n"
<< "MainFuncPointer func;\n"
<< "};\n\n";
fout << "functionMapEntry cmakeGeneratedFunctionMapEntries[] = {\n";
int numTests = 0;
for(i = testsBegin; i != args.end(); ++i)
{
fout << "{\"" << *i << "\", " << *i << "},\n";
numTests++;
}
fout << "};\n";
fout << "int main(int ac, char** av)\n"
<< "{\n";
fout << " int NumTests = " << numTests << ";\n";
fout << " int i;\n";
fout << " if(ac < 2)\n";
fout << " {\n";
fout << " printf(\"Available tests:\\n\");\n";
fout << " for(i =0; i < NumTests; ++i)\n";
fout << " {\n";
fout << " printf(\"%d. %s\\n\", i, cmakeGeneratedFunctionMapEntries[i].name);\n";
fout << " }\n";
fout << " printf(\"To run a test, enter the test number: \");\n";
fout << " int testNum = 0;\n";
fout << " scanf(\"%d\", &testNum);\n";
fout << " if(testNum >= NumTests)\n";
fout << " {\n";
fout << " printf(\"%d is an invalid test number.\\n\", testNum);\n";
fout << " return -1;\n";
fout << " }\n";
fout << " return (*cmakeGeneratedFunctionMapEntries[testNum].func)(ac-1, av+1);\n";
fout << " }\n";
fout << " for(i =0; i < NumTests; ++i)\n";
fout << " {\n";
fout << " if(strcmp(cmakeGeneratedFunctionMapEntries[i].name, av[1]) == 0)\n";
fout << " {\n";
fout << " return (*cmakeGeneratedFunctionMapEntries[i].func)(ac-1, av+1);\n";
fout << " }\n";
fout << " }\n";
fout << " printf(\"Available tests:\\n\");\n";
fout << " for(i =0; i < NumTests; ++i)\n";
fout << " {\n";
fout << " printf(\"%d. %s\\n\", i, cmakeGeneratedFunctionMapEntries[i].name);\n";
fout << " }\n";
fout << " printf(\"Failed: %s is an invalid test name.\\n\", av[1]);\n";
fout << " return -1;\n";
fout << "}\n";
fout.close();
// create the source list
cmSourceFile cfile;
cfile.SetIsAnAbstractClass(false);
cfile.SetName(args[1].c_str(), m_Makefile->GetCurrentOutputDirectory(),
"cxx", false);
m_Makefile->AddSource(cfile, sourceList);
for(i = testsBegin; i != args.end(); ++i)
{
cmSourceFile cfile;
cfile.SetIsAnAbstractClass(false);
cfile.SetName(i->c_str(), m_Makefile->GetCurrentDirectory(),
"cxx", false);
m_Makefile->AddSource(cfile, sourceList);
}
return true;
}
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Insight Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmCreateTestSourceList_h
#define cmCreateTestSourceList_h
#include "cmStandardIncludes.h"
#include "cmCommand.h"
/** \class cmCreateTestSourceList
* \brief
*
*/
class cmCreateTestSourceList : public cmCommand
{
public:
/**
* This is a virtual constructor for the command.
*/
virtual cmCommand* Clone()
{
return new cmCreateTestSourceList;
}
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
virtual bool InitialPass(std::vector<std::string> const& args);
/**
* This determines if the command gets propagated down
* to makefiles located in subdirectories.
*/
virtual bool IsInherited() {return true;}
/**
* The name of the command as specified in CMakeList.txt.
*/
virtual const char* GetName() {return "CREATE_TEST_SOURCELIST";}
/**
* Succinct documentation.
*/
virtual const char* GetTerseDocumentation()
{
return "Create a test driver and source list for building test programs.";
}
/**
* More documentation.
*/
virtual const char* GetFullDocumentation()
{
return
"CREATE_TEST_SOURCELIST(SourceListName DriverName test1 test2 test3"
"The list of source files needed to build the testdriver will be in SourceListName.\n"
"DriverName.cxx is the name of the test driver program.\n"
"The rest of the arguments consist of a list of test source files, can be "
"; separated. Each test source file should have a function in it that "
"is the same name as the file with no extension (foo.cxx should have int foo();) "
"DriverName.cxx will be able to call each of the tests by name on the command line.";
}
cmTypeMacro(cmCreateTestSourceList, cmCommand);
};
#endif
......@@ -86,12 +86,23 @@ int main (int argc, char *argv[])
std::string generator = "-G";
generator += CMAKE_GENERATOR;
args.push_back(generator);
std::vector<std::string> progArgs;
if(argc > 6)
{
for (int j = 6; j < argc ; j++)
if(strcmp(argv[6] , "CMAKE_ARGS") == 0)
{
for (int j = 7; j < argc ; j++)
{
args.push_back(argv[j]);
}
}
else
{
args.push_back(argv[j]);
for(int j = 6; j < argc; j++)
{
progArgs.push_back(argv[j]);
}
}
}
......@@ -254,6 +265,12 @@ int main (int argc, char *argv[])
return 1;
}
fullPath = cmSystemTools::ConvertToOutputPath(fullPath.c_str());
for(std::vector<std::string>::iterator p = progArgs.begin();
p != progArgs.end(); ++p)
{
fullPath += " ";
fullPath += *p;
}
std::cout << "Running test executable: " << fullPath.c_str() << "\n";
int ret = 0;
if (!cmSystemTools::RunCommand(fullPath.c_str(), output, ret, 0, true))
......
PROJECT(TestDriverTest)
CREATE_TEST_SOURCELIST(testSrcs TestDriverTest test1 test2 test3)
ADD_EXECUTABLE(TestDriverTest testSrcs)
#include <stdio.h>
int test1(int ac, char** av)
{
printf("test1\n");
for(int i =0; i < ac; i++)
printf("arg %d is %s\n", ac, av[i]);
return 0;
}
#include <stdio.h>
int test2(int ac, char** av)
{
printf("test2\n");
for(int i =0; i < ac; i++)
printf("arg %d is %s\n", ac, av[i]);
return 0;
}
#include <stdio.h>
int test3(int ac, char** av)
{
printf("test3\n");
for(int i =0; i < ac; i++)
printf("arg %d is %s\n", ac, av[i]);
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment