ENH: Improve internal test handling by creating a test class. Command cmEnableTesting now only sets CMAKE_TESTING_ENABLED and cmAddTest only adds a test to the list. The actual test files are written by local generator. This way we can at some point in the future replace DartTestfile with some XML file

This commit is contained in:
Andy Cedilnik 2005-04-24 15:59:51 -04:00
parent 3a8e7599b1
commit d395b563ed
13 changed files with 279 additions and 168 deletions

View File

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

View File

@ -16,6 +16,9 @@
=========================================================================*/
#include "cmAddTestCommand.h"
#include "cmTest.h"
// cmExecutableCommand
bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args)
{
@ -32,67 +35,12 @@ bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args)
// store the arguments for the final pass
// also expand any CMake variables
m_Args = args;
std::vector<cmStdString> arguments;
arguments.assign(args.begin() + 2, args.end());
cmTest* test = m_Makefile->CreateTest(args[0].c_str());
test->SetCommand(args[1].c_str());
test->SetArguments(arguments);
return true;
}
// we append to the file in the final pass because Enable Testing command
// creates the file in the final pass.
void cmAddTestCommand::FinalPass()
{
// Create a full path filename for output Testfile
std::string fname;
fname = m_Makefile->GetStartOutputDirectory();
fname += "/";
if ( m_Makefile->IsSet("CTEST_NEW_FORMAT") )
{
fname += "CTestTestfile.cmake";
}
else
{
fname += "DartTestfile.txt";
}
// If the file doesn't exist, then ENABLE_TESTING hasn't been run
if (cmSystemTools::FileExists(fname.c_str()))
{
// Open the output Testfile
std::ofstream fout(fname.c_str(), std::ios::app);
if (!fout)
{
cmSystemTools::Error("Error Writing ", fname.c_str());
return;
}
std::vector<std::string>::iterator it;
// for each arg in the test
fout << "ADD_TEST(";
it = m_Args.begin();
fout << (*it).c_str();
++it;
for (; it != m_Args.end(); ++it)
{
// Just double-quote all arguments so they are re-parsed
// correctly by the test system.
fout << " \"";
for(std::string::iterator c = it->begin(); c != it->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;
fout.close();
}
return;
}

View File

@ -41,12 +41,6 @@ public:
*/
virtual bool InitialPass(std::vector<std::string> const& args);
/**
* This is called at the end after all the information
* specified by the command is accumulated.
*/
virtual void FinalPass();
/**
* The name of the command as specified in CMakeList.txt.
*/
@ -79,7 +73,7 @@ public:
cmTypeMacro(cmAddTestCommand, cmCommand);
private:
std::vector<std::string> m_Args;
std::string m_Test;
};

View File

@ -24,91 +24,3 @@ bool cmEnableTestingCommand::InitialPass(std::vector<std::string> const&)
m_Makefile->AddDefinition("CMAKE_TESTING_ENABLED","1");
return true;
}
void cmEnableTestingCommand::FinalPass()
{
// initialize the DartTestfile files for the tree
this->CreateDartTestfileForMakefile(m_Makefile);
}
void cmEnableTestingCommand::CreateDartTestfileForMakefile(cmMakefile *mf)
{
// Create a full path filename for output Testfile
std::string fname;
fname = mf->GetStartOutputDirectory();
fname += "/";
if ( m_Makefile->IsSet("CTEST_NEW_FORMAT") )
{
fname += "CTestTestfile.cmake";
}
else
{
fname += "DartTestfile.txt";
}
cmSystemTools::MakeDirectory(mf->GetStartOutputDirectory());
// Open the output Testfile
std::ofstream fout(fname.c_str());
if (!fout)
{
cmSystemTools::Error("Error Writing ", fname.c_str());
cmSystemTools::ReportLastSystemError("");
return;
}
fout << "# CMake generated Testfile for " << std::endl
<< "#\tSource directory: "
<< mf->GetStartDirectory()
<< std::endl
<< "#\tBuild directory: " << mf->GetStartOutputDirectory()
<< std::endl
<< "# " << std::endl
<< "# This file replicates the SUBDIRS() and ADD_TEST() commands from the source"
<< std::endl
<< "# tree CMakeLists.txt file, skipping any SUBDIRS() or ADD_TEST() commands"
<< std::endl
<< "# that are excluded by CMake control structures, i.e. IF() commands."
<< std::endl
<< "#" << std::endl
<< "# The next line is critical for Dart to work" << std::endl
<< "# Duh :-)" << std::endl << std::endl;
// get our output directory
std::string outDir = mf->GetStartOutputDirectory();
outDir += "/";
// write out the subdirs for the current directory
std::vector<cmLocalGenerator *>& children =
mf->GetLocalGenerator()->GetChildren();
unsigned int i;
if (children.size())
{
fout << "SUBDIRS(";
std::string binP = children[0]->GetMakefile()->GetStartOutputDirectory();
cmSystemTools::ReplaceString(binP, outDir.c_str(), "");
fout << binP.c_str();
for(i = 1; i < children.size(); ++i)
{
binP = children[i]->GetMakefile()->GetStartOutputDirectory();
cmSystemTools::ReplaceString(binP, outDir.c_str(), "");
fout << " " << binP.c_str();
}
fout << ")" << std::endl << std::endl;;
}
fout.close();
// then recurse
if (children.size())
{
for(i = 0; i < children.size(); ++i)
{
this->CreateDartTestfileForMakefile(children[i]->GetMakefile());
}
}
return;
}

View File

@ -49,14 +49,6 @@ public:
*/
virtual bool InitialPass(std::vector<std::string> const&);
/**
* This is called at the end after all the information
* specified by the command is accumulated. Most commands do
* not implement this method. At this point, reading and
* writing to the cache can be done.
*/
virtual void FinalPass();
/**
* The name of the command as specified in CMakeList.txt.
*/

View File

@ -607,6 +607,7 @@ void cmGlobalGenerator::Generate()
{
m_LocalGenerators[i]->Generate();
m_LocalGenerators[i]->GenerateInstallRules();
m_LocalGenerators[i]->GenerateTestFiles();
m_CMakeInstance->UpdateProgress("Generating",
(i+1.0f)/m_LocalGenerators.size());
}

View File

@ -21,6 +21,7 @@
#include "cmGeneratedFileStream.h"
#include "cmSourceFile.h"
#include "cmOrderLinkDirectories.h"
#include "cmTest.h"
#include <ctype.h> // for isalpha
cmLocalGenerator::cmLocalGenerator()
@ -83,15 +84,95 @@ void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
gg->GetCMakeInstance()->GetHomeDirectory());
m_Makefile->SetHomeOutputDirectory(
gg->GetCMakeInstance()->GetHomeOutputDirectory());
}
void cmLocalGenerator::ConfigureFinalPass()
{
m_Makefile->ConfigureFinalPass();
}
void cmLocalGenerator::GenerateTestFiles()
{
if ( !m_Makefile->IsOn("CMAKE_TESTING_ENABLED") )
{
return;
}
std::string file = m_Makefile->GetStartOutputDirectory();
file += "/";
if ( m_Makefile->IsSet("CTEST_NEW_FORMAT") )
{
file += "CTestTestfile.cmake";
}
else
{
file += "DartTestfile.txt";
}
cmGeneratedFileStream fout(file.c_str());
fout.SetCopyIfDifferent(true);
fout << "# CMake generated Testfile for " << std::endl
<< "# Source directory: " << m_Makefile->GetStartDirectory() << std::endl
<< "# Build directory: " << m_Makefile->GetStartOutputDirectory() << std::endl
<< "# " << std::endl
<< "# This file replicates the SUBDIRS() and ADD_TEST() commands from the source" << std::endl
<< "# tree CMakeLists.txt file, skipping any SUBDIRS() or ADD_TEST() commands" << std::endl
<< "# that are excluded by CMake control structures, i.e. IF() commands." << std::endl
<< "#" << std::endl
<< "# The next line is critical for Dart to work" << std::endl
<< "# Duh :-)" << std::endl << std::endl;
const std::vector<cmTest*> *tests = m_Makefile->GetTests();
std::vector<cmTest*>::const_iterator it;
for ( it = tests->begin(); it != tests->end(); ++ it )
{
cmTest* test = *it;
fout << "ADD_TEST(";
fout << test->GetName() << " \"" << test->GetCommand() << "\"";
std::vector<cmStdString>::iterator it;
for (it = test->GetArguments().begin();
it != test->GetArguments().end(); ++it)
{
// Just double-quote all arguments so they are re-parsed
// correctly by the test system.
fout << " \"";
for(std::string::iterator c = it->begin(); c != it->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;
}
if ( this->Children.size())
{
fout << "SUBDIRS(";
size_t i;
std::string outDir = m_Makefile->GetStartOutputDirectory();
outDir += "/";
for(i = 0; i < this->Children.size(); ++i)
{
std::string binP = this->Children[i]->GetMakefile()->GetStartOutputDirectory();
cmSystemTools::ReplaceString(binP, outDir.c_str(), "");
if ( i > 0 )
{
fout << " ";
}
fout << binP.c_str();
}
fout << ")" << std::endl << std::endl;;
}
}
void cmLocalGenerator::GenerateInstallRules()
{
const cmTargets &tgts = m_Makefile->GetTargets();

View File

@ -59,6 +59,12 @@ public:
*/
virtual void GenerateInstallRules();
/**
* Generate the test files for tests.
*/
virtual void GenerateTestFiles();
///! Get the makefile for this generator
cmMakefile *GetMakefile() {
return this->m_Makefile; };
@ -188,7 +194,7 @@ protected:
void CreateCustomTargetsAndCommands(std::set<cmStdString> const&);
virtual void AddInstallRule(std::ostream& fout, const char* dest, int type,
const char* files, bool optional = false, const char* properties = 0);
cmMakefile *m_Makefile;
cmGlobalGenerator *m_GlobalGenerator;
// members used for relative path function ConvertToMakefilePath

View File

@ -24,6 +24,7 @@
#include "cmCacheManager.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
#include "cmTest.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
# include "cmVariableWatch.h"
#endif
@ -126,6 +127,11 @@ cmMakefile::~cmMakefile()
{
delete *i;
}
for(std::vector<cmTest*>::iterator i = m_Tests.begin();
i != m_Tests.end(); ++i)
{
delete *i;
}
for(unsigned int i=0; i < m_UsedCommands.size(); i++)
{
delete m_UsedCommands[i];
@ -2465,3 +2471,43 @@ cmTarget* cmMakefile::FindTarget(const char* name)
}
return 0;
}
cmTest* cmMakefile::CreateTest(const char* testName)
{
if ( !testName )
{
return 0;
}
cmTest* test = this->GetTest(testName);
if ( test )
{
return test;
}
test = new cmTest;
test->SetName(testName);
m_Tests.push_back(test);
return test;
}
cmTest* cmMakefile::GetTest(const char* testName) const
{
if ( !testName )
{
return 0;
}
std::vector<cmTest*>::const_iterator it;
for ( it = m_Tests.begin(); it != m_Tests.end(); ++ it )
{
if ( strcmp((*it)->GetName(), testName) == 0 )
{
return *it;
}
}
return 0;
}
const std::vector<cmTest*> *cmMakefile::GetTests() const
{
return &m_Tests;
}

View File

@ -31,6 +31,7 @@ class cmCommand;
class cmLocalGenerator;
class cmMakeDepend;
class cmSourceFile;
class cmTest;
class cmVariableWatch;
class cmake;
@ -642,6 +643,15 @@ public:
*/
void AddMacro(const char* name, const char* signature);
///! Add a new cmTest to the list of tests for this makefile.
cmTest* CreateTest(const char* testName);
/** Get a cmTest pointer for a given test name, if the name is
* 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
*/
@ -686,6 +696,9 @@ protected:
cmTargets m_Targets;
std::vector<cmSourceFile*> m_SourceFiles;
// Tests
std::vector<cmTest*> m_Tests;
// The include and link-library paths. These may have order
// dependency, so they must be vectors (not set).
std::vector<std::string> m_IncludeDirectories;

51
Source/cmTest.cxx Normal file
View File

@ -0,0 +1,51 @@
/*=========================================================================
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 "cmTest.h"
#include "cmSystemTools.h"
cmTest::cmTest()
{
}
cmTest::~cmTest()
{
}
void cmTest::SetName(const char* name)
{
if ( !name )
{
name = "";
}
m_Name = name;
}
void cmTest::SetCommand(const char* command)
{
if ( !command )
{
command = "";
}
m_Command = command;
}
void cmTest::SetArguments(const std::vector<cmStdString>& args)
{
m_Args = args;
}

64
Source/cmTest.h Normal file
View File

@ -0,0 +1,64 @@
/*=========================================================================
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 cmTest_h
#define cmTest_h
#include "cmCustomCommand.h"
/** \class cmTest
* \brief Represent a test
*
* cmTest is representation of a test.
*/
class cmTest
{
public:
/**
*/
cmTest();
~cmTest();
///! Set the test name
void SetName(const char* name);
const char* GetName() { return m_Name.c_str(); }
void SetCommand(const char* command);
const char* GetCommand() { return m_Command.c_str(); }
void SetArguments(const std::vector<cmStdString>& args);
std::vector<cmStdString>& GetArguments()
{
return m_Args;
}
/**
* Print the structure to std::cout.
*/
void Print() const;
///! Set/Get a property of this source file
void SetProperty(const char *prop, const char *value);
const char *GetProperty(const char *prop) const;
bool GetPropertyAsBool(const char *prop) const;
private:
std::map<cmStdString,cmStdString> m_Properties;
cmStdString m_Name;
cmStdString m_Command;
std::vector<cmStdString> m_Args;
};
#endif

View File

@ -53,6 +53,7 @@ CMAKE_CXX_SOURCES="\
cmBootstrapCommands \
cmCommands \
cmTarget \
cmTest \
cmCustomCommand \
cmCacheManager \
cmListFileCache \