ENH: Refactor generation of CTestTestfile content

This moves code which generates ADD_TEST and SET_TESTS_PROPERTIES calls
into CTestTestfile.cmake files out of cmLocalGenerator and into a
cmTestGenerator class.  This will allow more advanced generation without
cluttering cmLocalGenerator.  The cmTestGenerator class derives from
cmScriptGenerator to get support for per-configuration script
generation (not yet enabled).
This commit is contained in:
Brad King 2009-03-16 10:40:46 -04:00
parent e67f5138b8
commit 66d69f864a
8 changed files with 220 additions and 81 deletions

View File

@ -215,6 +215,8 @@ SET(SRCS
cmTarget.h
cmTest.cxx
cmTest.h
cmTestGenerator.cxx
cmTestGenerator.h
cmVariableWatch.cxx
cmVariableWatch.h
cmVersion.cxx

View File

@ -16,6 +16,8 @@
=========================================================================*/
#include "cmAddTestCommand.h"
#include "cmTestGenerator.h"
#include "cmTest.h"
@ -42,7 +44,14 @@ bool cmAddTestCommand
arguments.push_back(*it);
}
cmTest* test = this->Makefile->CreateTest(args[0].c_str());
// Create the test but add a generator only the first time it is
// seen. This preserves behavior from before test generators.
cmTest* test = this->Makefile->GetTest(args[0].c_str());
if(!test)
{
test = this->Makefile->CreateTest(args[0].c_str());
this->Makefile->AddTestGenerator(new cmTestGenerator(test));
}
test->SetCommand(args[1].c_str());
test->SetArguments(arguments);

View File

@ -26,6 +26,7 @@
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmTest.h"
#include "cmTestGenerator.h"
#include "cmVersion.h"
#include "cmake.h"
@ -212,6 +213,20 @@ void cmLocalGenerator::GenerateTestFiles()
{
return;
}
// Compute the set of configurations.
std::vector<std::string> configurationTypes;
if(const char* types =
this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
{
cmSystemTools::ExpandListArgument(types, configurationTypes);
}
const char* config = 0;
if(configurationTypes.empty())
{
config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
}
std::string file = this->Makefile->GetStartOutputDirectory();
file += "/";
file += "CTestTestfile.cmake";
@ -239,76 +254,13 @@ void cmLocalGenerator::GenerateTestFiles()
fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
}
const std::vector<cmTest*> *tests = this->Makefile->GetTests();
std::vector<cmTest*>::const_iterator it;
for ( it = tests->begin(); it != tests->end(); ++ it )
// Ask each test generator to write its code.
std::vector<cmTestGenerator*> const&
testers = this->Makefile->GetTestGenerators();
for(std::vector<cmTestGenerator*>::const_iterator gi = testers.begin();
gi != testers.end(); ++gi)
{
cmTest* test = *it;
fout << "ADD_TEST(";
fout << test->GetName() << " \"" << test->GetCommand() << "\"";
std::vector<cmStdString>::const_iterator argit;
for (argit = test->GetArguments().begin();
argit != test->GetArguments().end(); ++argit)
{
// Just double-quote all arguments so they are re-parsed
// correctly by the test system.
fout << " \"";
for(std::string::const_iterator c = argit->begin();
c != argit->end(); ++c)
{
// Escape quotes within arguments. We should escape
// backslashes too but we cannot because it makes the result
// inconsistent with previous behavior of this command.
if((*c == '"'))
{
fout << '\\';
}
fout << *c;
}
fout << "\"";
}
fout << ")" << std::endl;
cmPropertyMap::const_iterator pit;
cmPropertyMap* mpit = &test->GetProperties();
if ( mpit->size() )
{
fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
{
fout << " " << pit->first.c_str() << " \"";
const char* value = pit->second.GetValue();
for ( ; *value; ++ value )
{
switch ( *value )
{
case '\\':
case '"':
case ' ':
case '#':
case '(':
case ')':
case '$':
case '^':
fout << "\\" << *value;
break;
case '\t':
fout << "\\t";
break;
case '\n':
fout << "\\n";
break;
case '\r':
fout << "\\r";
break;
default:
fout << *value;
}
}
fout << "\"";
}
fout << ")" << std::endl;
}
(*gi)->Generate(fout, config, configurationTypes);
}
if ( this->Children.size())
{

View File

@ -32,6 +32,7 @@
# include "cmVariableWatch.h"
#endif
#include "cmInstallGenerator.h"
#include "cmTestGenerator.h"
#include "cmake.h"
#include <stdlib.h> // required for atoi
@ -108,7 +109,6 @@ cmMakefile::cmMakefile(const cmMakefile& mf)
this->Targets = mf.Targets;
this->SourceFiles = mf.SourceFiles;
this->Tests = mf.Tests;
this->OrderedTests = mf.OrderedTests;
this->IncludeDirectories = mf.IncludeDirectories;
this->LinkDirectories = mf.LinkDirectories;
this->SystemIncludeDirectories = mf.SystemIncludeDirectories;
@ -116,6 +116,7 @@ cmMakefile::cmMakefile(const cmMakefile& mf)
this->OutputFiles = mf.OutputFiles;
this->LinkLibraries = mf.LinkLibraries;
this->InstallGenerators = mf.InstallGenerators;
this->TestGenerators = mf.TestGenerators;
this->IncludeFileRegularExpression = mf.IncludeFileRegularExpression;
this->ComplainFileRegularExpression = mf.ComplainFileRegularExpression;
this->SourceFileExtensions = mf.SourceFileExtensions;
@ -181,6 +182,12 @@ cmMakefile::~cmMakefile()
{
delete *i;
}
for(std::vector<cmTestGenerator*>::iterator
i = this->TestGenerators.begin();
i != this->TestGenerators.end(); ++i)
{
delete *i;
}
for(std::vector<cmSourceFile*>::iterator i = this->SourceFiles.begin();
i != this->SourceFiles.end(); ++i)
{
@ -3324,7 +3331,6 @@ cmTest* cmMakefile::CreateTest(const char* testName)
test->SetName(testName);
test->SetMakefile(this);
this->Tests[testName] = test;
this->OrderedTests.push_back(test);
return test;
}
@ -3343,12 +3349,6 @@ cmTest* cmMakefile::GetTest(const char* testName) const
return 0;
}
//----------------------------------------------------------------------------
const std::vector<cmTest*> *cmMakefile::GetTests() const
{
return &this->OrderedTests;
}
std::string cmMakefile::GetListFileStack()
{
cmOStringStream tmp;

View File

@ -41,6 +41,7 @@ class cmLocalGenerator;
class cmMakeDepend;
class cmSourceFile;
class cmTest;
class cmTestGenerator;
class cmVariableWatch;
class cmake;
class cmMakefileCall;
@ -769,7 +770,6 @@ public:
* not found, then a null pointer is returned.
*/
cmTest* GetTest(const char* testName) const;
const std::vector<cmTest*> *GetTests() const;
/**
* Get a list of macros as a ; separated string
@ -805,6 +805,11 @@ public:
std::vector<cmInstallGenerator*>& GetInstallGenerators()
{ return this->InstallGenerators; }
void AddTestGenerator(cmTestGenerator* g)
{ if(g) this->TestGenerators.push_back(g); }
std::vector<cmTestGenerator*>& GetTestGenerators()
{ return this->TestGenerators; }
// Define the properties
static void DefineProperties(cmake *cm);
@ -850,7 +855,6 @@ protected:
// Tests
std::map<cmStdString, cmTest*> Tests;
std::vector<cmTest*> OrderedTests;
// The include and link-library paths. These may have order
// dependency, so they must be vectors (not set).
@ -868,6 +872,7 @@ protected:
cmTarget::LinkLibraryVectorType LinkLibraries;
std::vector<cmInstallGenerator*> InstallGenerators;
std::vector<cmTestGenerator*> TestGenerators;
std::string IncludeFileRegularExpression;
std::string ComplainFileRegularExpression;

126
Source/cmTestGenerator.cxx Normal file
View File

@ -0,0 +1,126 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html 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 "cmTestGenerator.h"
#include "cmTest.h"
//----------------------------------------------------------------------------
cmTestGenerator
::cmTestGenerator(cmTest* test,
std::vector<std::string> const& configurations):
cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations),
Test(test)
{
this->ActionsPerConfig = false;
this->TestGenerated = false;
}
//----------------------------------------------------------------------------
cmTestGenerator
::~cmTestGenerator()
{
}
//----------------------------------------------------------------------------
void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
Indent const& indent)
{
// First create the tests.
this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
// Now generate the test properties.
if(this->TestGenerated)
{
cmTest* test = this->Test;
std::ostream& fout = os;
cmPropertyMap::const_iterator pit;
cmPropertyMap* mpit = &test->GetProperties();
if ( mpit->size() )
{
fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
{
fout << " " << pit->first.c_str() << " \"";
const char* value = pit->second.GetValue();
for ( ; *value; ++ value )
{
switch ( *value )
{
case '\\':
case '"':
case ' ':
case '#':
case '(':
case ')':
case '$':
case '^':
fout << "\\" << *value;
break;
case '\t':
fout << "\\t";
break;
case '\n':
fout << "\\n";
break;
case '\r':
fout << "\\r";
break;
default:
fout << *value;
}
}
fout << "\"";
}
fout << ")" << std::endl;
}
}
}
//----------------------------------------------------------------------------
void cmTestGenerator::GenerateScriptActions(std::ostream& fout,
Indent const& indent)
{
this->TestGenerated = true;
cmTest* test = this->Test;
fout << indent;
fout << "ADD_TEST(";
fout << test->GetName() << " \"" << test->GetCommand() << "\"";
std::vector<cmStdString>::const_iterator argit;
for (argit = test->GetArguments().begin();
argit != test->GetArguments().end(); ++argit)
{
// Just double-quote all arguments so they are re-parsed
// correctly by the test system.
fout << " \"";
for(std::string::const_iterator c = argit->begin();
c != argit->end(); ++c)
{
// Escape quotes within arguments. We should escape
// backslashes too but we cannot because it makes the result
// inconsistent with previous behavior of this command.
if((*c == '"'))
{
fout << '\\';
}
fout << *c;
}
fout << "\"";
}
fout << ")" << std::endl;
}

44
Source/cmTestGenerator.h Normal file
View File

@ -0,0 +1,44 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html 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 cmTestGenerator_h
#define cmTestGenerator_h
#include "cmScriptGenerator.h"
class cmTest;
/** \class cmTestGenerator
* \brief Support class for generating install scripts.
*
*/
class cmTestGenerator: public cmScriptGenerator
{
public:
cmTestGenerator(cmTest* test,
std::vector<std::string> const&
configurations = std::vector<std::string>());
virtual ~cmTestGenerator();
protected:
virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
cmTest* Test;
bool TestGenerated;
};
#endif

View File

@ -171,6 +171,7 @@ CMAKE_CXX_SOURCES="\
cmSourceFile \
cmSourceFileLocation \
cmSystemTools \
cmTestGenerator \
cmVersion \
cmFileTimeComparison \
cmGlobalUnixMakefileGenerator3 \