diff options
Diffstat (limited to 'Source/cmTestGenerator.cxx')
-rw-r--r-- | Source/cmTestGenerator.cxx | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx new file mode 100644 index 0000000..f87a535 --- /dev/null +++ b/Source/cmTestGenerator.cxx @@ -0,0 +1,196 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmTestGenerator.h" + +#include "cmGeneratorExpression.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmTest.h" + +//---------------------------------------------------------------------------- +cmTestGenerator +::cmTestGenerator(cmTest* test, + std::vector<std::string> const& configurations): + cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations), + Test(test) +{ + this->ActionsPerConfig = !test->GetOldStyle(); + this->TestGenerated = false; +} + +//---------------------------------------------------------------------------- +cmTestGenerator +::~cmTestGenerator() +{ +} + +//---------------------------------------------------------------------------- +void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, + Indent const& indent) +{ + // Create the tests. + this->cmScriptGenerator::GenerateScriptConfigs(os, indent); +} + +//---------------------------------------------------------------------------- +void cmTestGenerator::GenerateScriptActions(std::ostream& os, + Indent const& indent) +{ + if(this->ActionsPerConfig) + { + // This is the per-config generation in a single-configuration + // build generator case. The superclass will call our per-config + // method. + this->cmScriptGenerator::GenerateScriptActions(os, indent); + } + else + { + // This is an old-style test, so there is only one config. + //assert(this->Test->GetOldStyle()); + this->GenerateOldStyle(os, indent); + } +} + +//---------------------------------------------------------------------------- +void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, + const std::string& config, + Indent const& indent) +{ + this->TestGenerated = true; + + // Set up generator expression evaluation context. + cmGeneratorExpression ge(&this->Test->GetBacktrace()); + + // Start the test command. + os << indent << "add_test(" << this->Test->GetName() << " "; + + // Get the test command line to be executed. + std::vector<std::string> const& command = this->Test->GetCommand(); + + // Check whether the command executable is a target whose name is to + // be translated. + std::string exe = command[0]; + cmMakefile* mf = this->Test->GetMakefile(); + cmTarget* target = mf->FindTargetToUse(exe); + if(target && target->GetType() == cmTarget::EXECUTABLE) + { + // Use the target file on disk. + exe = target->GetFullPath(config); + } + else + { + // Use the command name given. + exe = ge.Parse(exe.c_str())->Evaluate(mf, config); + cmSystemTools::ConvertToUnixSlashes(exe); + } + + // Generate the command line with full escapes. + cmLocalGenerator* lg = mf->GetLocalGenerator(); + os << lg->EscapeForCMake(exe); + for(std::vector<std::string>::const_iterator ci = command.begin()+1; + ci != command.end(); ++ci) + { + os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config)); + } + + // Finish the test command. + os << ")\n"; + + // Output properties for the test. + cmPropertyMap& pm = this->Test->GetProperties(); + if(!pm.empty()) + { + os << indent << "set_tests_properties(" << this->Test->GetName() + << " PROPERTIES "; + for(cmPropertyMap::const_iterator i = pm.begin(); + i != pm.end(); ++i) + { + os << " " << i->first + << " " << lg->EscapeForCMake( + ge.Parse(i->second.GetValue())->Evaluate(mf, config)); + } + os << ")" << std::endl; + } +} + +//---------------------------------------------------------------------------- +void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, + Indent const& indent) +{ + os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n"; +} + +//---------------------------------------------------------------------------- +bool cmTestGenerator::NeedsScriptNoConfig() const +{ + return (this->TestGenerated && // test generated for at least one config + this->ActionsPerConfig && // test is config-aware + this->Configurations.empty() && // test runs in all configs + !this->ConfigurationTypes->empty()); // config-dependent command +} + +//---------------------------------------------------------------------------- +void cmTestGenerator::GenerateOldStyle(std::ostream& fout, + Indent const& indent) +{ + this->TestGenerated = true; + + // Get the test command line to be executed. + std::vector<std::string> const& command = this->Test->GetCommand(); + + std::string exe = command[0]; + cmSystemTools::ConvertToUnixSlashes(exe); + fout << indent; + fout << "add_test("; + fout << this->Test->GetName() << " \"" << exe << "\""; + + for(std::vector<std::string>::const_iterator argit = command.begin()+1; + argit != command.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; + + // Output properties for the test. + cmMakefile* mf = this->Test->GetMakefile(); + cmLocalGenerator* lg = mf->GetLocalGenerator(); + cmPropertyMap& pm = this->Test->GetProperties(); + if(!pm.empty()) + { + fout << indent << "set_tests_properties(" << this->Test->GetName() + << " PROPERTIES "; + for(cmPropertyMap::const_iterator i = pm.begin(); + i != pm.end(); ++i) + { + fout << " " << i->first + << " " << lg->EscapeForCMake(i->second.GetValue()); + } + fout << ")" << std::endl; + } +} |