cmTestGenerator.cxx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmTestGenerator.h"
  14. #include "cmLocalGenerator.h"
  15. #include "cmMakefile.h"
  16. #include "cmSystemTools.h"
  17. #include "cmTarget.h"
  18. #include "cmTest.h"
  19. //----------------------------------------------------------------------------
  20. cmTestGenerator
  21. ::cmTestGenerator(cmTest* test,
  22. std::vector<std::string> const& configurations):
  23. cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations),
  24. Test(test)
  25. {
  26. this->ActionsPerConfig = !test->GetOldStyle();
  27. this->TestGenerated = false;
  28. }
  29. //----------------------------------------------------------------------------
  30. cmTestGenerator
  31. ::~cmTestGenerator()
  32. {
  33. }
  34. //----------------------------------------------------------------------------
  35. void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
  36. Indent const& indent)
  37. {
  38. // First create the tests.
  39. this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
  40. // Now generate the test properties.
  41. if(this->TestGenerated)
  42. {
  43. cmTest* test = this->Test;
  44. std::ostream& fout = os;
  45. cmPropertyMap::const_iterator pit;
  46. cmPropertyMap* mpit = &test->GetProperties();
  47. if ( mpit->size() )
  48. {
  49. fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
  50. for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
  51. {
  52. fout << " " << pit->first.c_str() << " \"";
  53. const char* value = pit->second.GetValue();
  54. for ( ; *value; ++ value )
  55. {
  56. switch ( *value )
  57. {
  58. case '\\':
  59. case '"':
  60. case ' ':
  61. case '#':
  62. case '(':
  63. case ')':
  64. case '$':
  65. case '^':
  66. fout << "\\" << *value;
  67. break;
  68. case '\t':
  69. fout << "\\t";
  70. break;
  71. case '\n':
  72. fout << "\\n";
  73. break;
  74. case '\r':
  75. fout << "\\r";
  76. break;
  77. default:
  78. fout << *value;
  79. }
  80. }
  81. fout << "\"";
  82. }
  83. fout << ")" << std::endl;
  84. }
  85. }
  86. }
  87. //----------------------------------------------------------------------------
  88. void cmTestGenerator::GenerateScriptActions(std::ostream& os,
  89. Indent const& indent)
  90. {
  91. if(this->ActionsPerConfig)
  92. {
  93. // This is the per-config generation in a single-configuration
  94. // build generator case. The superclass will call our per-config
  95. // method.
  96. this->cmScriptGenerator::GenerateScriptActions(os, indent);
  97. }
  98. else
  99. {
  100. // This is an old-style test, so there is only one config.
  101. //assert(this->Test->GetOldStyle());
  102. this->GenerateOldStyle(os, indent);
  103. }
  104. }
  105. //----------------------------------------------------------------------------
  106. void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
  107. const char* config,
  108. Indent const& indent)
  109. {
  110. this->TestGenerated = true;
  111. // Start the test command.
  112. os << indent << "ADD_TEST(" << this->Test->GetName() << " ";
  113. // Get the test command line to be executed.
  114. std::vector<std::string> const& command = this->Test->GetCommand();
  115. // Check whether the command executable is a target whose name is to
  116. // be translated.
  117. std::string exe = command[0];
  118. cmMakefile* mf = this->Test->GetMakefile();
  119. cmTarget* target = mf->FindTargetToUse(exe.c_str());
  120. if(target && target->GetType() == cmTarget::EXECUTABLE)
  121. {
  122. // Use the target file on disk.
  123. exe = target->GetFullPath(config);
  124. }
  125. else
  126. {
  127. // Use the command name given.
  128. cmSystemTools::ConvertToUnixSlashes(exe);
  129. }
  130. // Generate the command line with full escapes.
  131. cmLocalGenerator* lg = mf->GetLocalGenerator();
  132. os << lg->EscapeForCMake(exe.c_str());
  133. for(std::vector<std::string>::const_iterator ci = command.begin()+1;
  134. ci != command.end(); ++ci)
  135. {
  136. os << " " << lg->EscapeForCMake(ci->c_str());
  137. }
  138. // Finish the test command.
  139. os << ")\n";
  140. }
  141. //----------------------------------------------------------------------------
  142. void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
  143. Indent const& indent)
  144. {
  145. this->TestGenerated = true;
  146. // Get the test command line to be executed.
  147. std::vector<std::string> const& command = this->Test->GetCommand();
  148. std::string exe = command[0];
  149. cmSystemTools::ConvertToUnixSlashes(exe);
  150. fout << indent;
  151. fout << "ADD_TEST(";
  152. fout << this->Test->GetName() << " \"" << exe << "\"";
  153. for(std::vector<std::string>::const_iterator argit = command.begin()+1;
  154. argit != command.end(); ++argit)
  155. {
  156. // Just double-quote all arguments so they are re-parsed
  157. // correctly by the test system.
  158. fout << " \"";
  159. for(std::string::const_iterator c = argit->begin();
  160. c != argit->end(); ++c)
  161. {
  162. // Escape quotes within arguments. We should escape
  163. // backslashes too but we cannot because it makes the result
  164. // inconsistent with previous behavior of this command.
  165. if((*c == '"'))
  166. {
  167. fout << '\\';
  168. }
  169. fout << *c;
  170. }
  171. fout << "\"";
  172. }
  173. fout << ")" << std::endl;
  174. }