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