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:
parent
3a8e7599b1
commit
d395b563ed
|
@ -71,6 +71,8 @@ SET(SRCS
|
|||
cmSystemTools.h
|
||||
cmTarget.cxx
|
||||
cmTarget.h
|
||||
cmTest.cxx
|
||||
cmTest.h
|
||||
cmVariableWatch.cxx
|
||||
cmVariableWatch.h
|
||||
cmVersion.cxx
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue