/*============================================================================ 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 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) { // First create the tests. this->cmScriptGenerator::GenerateScriptConfigs(os, indent); // Now generate the test properties. if(this->TestGenerated) { cmTest* test = this->Test; cmMakefile* mf = test->GetMakefile(); cmLocalGenerator* lg = mf->GetLocalGenerator(); 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 << " " << lg->EscapeForCMake(pit->second.GetValue()); } fout << ")" << std::endl; } } } //---------------------------------------------------------------------------- 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 char* 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 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.c_str()); 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.c_str()); for(std::vector::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"; } //---------------------------------------------------------------------------- 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 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::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; }