PlasCom2  1.0
XPACC Multi-physics simluation application
RunTest.C
Go to the documentation of this file.
1 #include <sstream>
7 #include <fstream>
8 
9 #include "UnixUtils.H"
10 #include "ComLine.H"
11 #include "FDUtils.H"
12 
13 #include "RunTest.H"
14 
15 namespace ix
16 {
17  int RunTest(int argc,char *argv[])
18  {
19 
20  RTSComLine comline((const char **)(argv));
21  // The call to comline.Initialize() reads the command line arguments
22  // from the array passed in the previous line.
23  comline.Initialize();
24  // The ProcessOptions() call does detailed examination of the command
25  // line arguments to check for user errors or other problems. This call
26  // will return non-zero if there were errors on the commandline.
27  int clerr = comline.ProcessOptions();
28  // Check if the user just wanted to get the help and exit
29  if(!comline.GetOption("help").empty()){
30  // Print out the "long usage" (i.e. help) message to stdout
31  std::cout << comline.LongUsage() << std::endl;
32  return(0);
33  }
34  if(clerr){
35  std::cout << comline.ErrorReport() << std::endl
36  << std::endl << comline.ShortUsage() << std::endl;
37  return(1);
38  }
39  // These outstreams allow the output to file to be set up and separated
40  // from the stdout.
41  // std::ofstream Ouf;
42  // std::ostream *Out = &std::cout;
43 
44  // The next few lines populate some strings based on the
45  // users input from the commandline.
46  std::string OutFileName(comline.GetOption("output"));
47  // std::string TestName(comline.GetOption("name"));
48  std::string ListName(comline.GetOption("list"));
49  std::string FileName(comline.GetOption("file"));
50  std::string sverb(comline.GetOption("verblevel"));
51  std::string HostName(comline.GetOption("hostname"));
52  std::string PlatformsName(comline.GetOption("platforms"));
53  std::string SourceDirectory(comline.GetOption("srcdir"));
54  std::string BinaryDirectory(comline.GetOption("bindir"));
55  std::string ScriptArgument(comline.GetOption("argument"));
56  bool keepFiles = !comline.GetOption("keep").empty();
57 
58  if(PlatformsName.empty() && ListName.empty() && FileName.empty()){
59  std::cout << comline.ShortUsage() << std::endl
60  << "ix::RunTest> Error: One of --list or --platform or --file"
61  << " must be specified. Exiting (fail)." << std::endl;
62  return(1);
63  }
64  if((!PlatformsName.empty() && !ListName.empty())||
65  (!FileName.empty() && (!PlatformsName.empty() || !ListName.empty()))){
66  std::cout << comline.ShortUsage() << std::endl;
67  std::cout << "ix::RunTest> Error: Ambigous settings. --list, --platform, and"
68  << " --file are mutually exclusive. Exiting (fail)." << std::endl;
69  return(1);
70  }
71  if(!HostName.empty() && PlatformsName.empty()){
72  std::cout << "ix::RunTest> Warning: Hostname option is meaningless without platforms file."
73  << std::endl;
74  }
75  // The following block parses and sets the verbosity level
76  int verblevel = 1;
77  if(!sverb.empty()){
78  verblevel = 1;
79  if(sverb != ".true."){
80  std::istringstream Istr(sverb);
81  Istr >> verblevel;
82  if(verblevel < 0)
83  verblevel = 1;
84  }
85  }
86  if(verblevel > 2)
87  std::cout << "ix::RunTest> Starting up with the following environment:" << std::endl
88  << "ix::RunTest> OutFileName = " << OutFileName << std::endl
89  << "ix::RunTest> ListName = " << ListName << std::endl
90  << "ix::RunTest> FileName = " << FileName << std::endl
91  << "ix::RunTest> HostName = " << HostName << std::endl
92  << "ix::RunTest> PlatformsName = " << PlatformsName << std::endl
93  << "ix::RunTest> SourceDirectory = " << SourceDirectory << std::endl
94  << "ix::RunTest> BinaryDirectory = " << BinaryDirectory << std::endl;
95 
96  // This block sets up the output file if the user specified one
97  bool keep_outfile = false;
98  if(!OutFileName.empty()){
99  keep_outfile = true;
100  // Ouf.open(OutFileName.c_str());
101  // if(!Ouf){
102  // std::cout << "ix::RunTests> Error: Could not open output file, "
103  // << OutFileName << " for test output. Exiting (fail)." << std::endl;
104  // return(1);
105  // }
106  // Out = &Ouf;
107  }
108  else{
109  std::string name_stub("test_script.o");
110  ix::sys::TempFileName(name_stub);
111  OutFileName = name_stub;
112  }
113 
114  if(HostName.empty()){
115  HostName = ix::sys::Hostname();
116  if(verblevel > 2){
117  std::cout << "ix::RunTest> Found HostName = " << HostName << std::endl;
118  }
119  }
120  // if(PlatformsName.empty())
121  // PlatformsName = "./share/platforms/parallel_platforms";
122 
123  std::string BasePath;
124  if(!PlatformsName.empty()){
125  // Open up the platforms file and find the host
126  std::ifstream PlatInf;
127  std::string::size_type x = PlatformsName.find_last_of("/");
128  if(x != std::string::npos)
129  BasePath.assign(PlatformsName.substr(0,x+1));
130  PlatInf.open(PlatformsName.c_str());
131  if(!PlatInf){
132  std::cout << "ix::RunTest> Error: Could not open platforms file, "
133  << PlatformsName << " for resolving platform-specific tests for "
134  << HostName << ". Exiting (fail)." << std::endl;
135  return(1);
136  }
137  // std::string PlatformFileName;
138  std::string splatform;
139  std::string defaultRunningName;
140  while(std::getline(PlatInf,splatform) && ListName.empty()){
141  std::istringstream Istr(splatform);
142  std::string platform_name;
143  std::string running_name;
144  Istr >> platform_name >> running_name;
145  if(platform_name == "DEFAULT")
146  defaultRunningName = running_name;
147  if(HostName == platform_name){
148  ListName.assign(running_name);
149  } else if(HostName.find(platform_name) != std::string::npos){
150  ListName.assign(running_name);
151  }
152  }
153  if(ListName.empty()){
154  std::cout << "ix::RunTest> Warning: Could not find a " << HostName
155  << "-specific configuration." << std::endl;
156  if(defaultRunningName.empty()){
157  std::cout << "ix::RunText> Error: No default platform, cannot continue."
158  << std::endl;
159  return(1);
160  } else {
161  std::cout << "ix::RunTest> Warning: Setting default configuration ("
162  << defaultRunningName << ")." << std::endl;
163  ListName.assign(defaultRunningName);
164  }
165  }
166  }
167 
168  // Now we either have a list, or a single named test.
169  std::vector<std::string> TestFileNames;
170  if(!ListName.empty()){
171  // Support both relative and absolute path
172  std::ifstream ListInf;
173  ListInf.open(ListName.c_str());
174  if(!ListInf){
175  std::string RelName;
176  if(!BasePath.empty()){
177  RelName.assign(BasePath+ListName);
178  ListInf.open(RelName.c_str());
179  }
180  if(!ListInf){
181  std::cout << "ix::RunTest> Error: Could not open list file, "
182  << ListName << ".";
183  if(!RelName.empty()){
184  std::cout << " Tried relative path (" << RelName << ").";
185  }
186  std::cout << " Exiting (fail)." << std::endl;
187  return(1);
188  }
189  }
190  if(BasePath.empty()){
191  std::string::size_type x = ListName.find_last_of("/");
192  if(x != std::string::npos)
193  BasePath.assign(ListName.substr(0,x+1));
194  }
195  std::string raw_test_name;
196  while(std::getline(ListInf,raw_test_name)){
197  if(!ix::sys::FILEEXISTS(raw_test_name)){
198  std::string RelName(BasePath+raw_test_name);
199  if(!ix::sys::FILEEXISTS(RelName)){
200  std::cout << "ix::RunTest> Warning: Could not find test "
201  << raw_test_name << " from " << ListName << "."
202  << std::endl;
203  }
204  else{
205  TestFileNames.push_back(RelName);
206  }
207  }
208  else{
209  TestFileNames.push_back(raw_test_name);
210  }
211  }
212  ListInf.close();
213  }
214  else { // An explicit filename must have been given
215  if(!ix::sys::FILEEXISTS(FileName)){
216  std::cout << "ix::RunTest> Error: Could not find specified test, "
217  << FileName << ". Exiting (fail)." << std::endl;
218  return(1);
219  }
220  TestFileNames.push_back(FileName);
221  }
222 
223  // Now we have a list of full paths to tests to run
224  int err = 0;
225  std::vector<std::string>::iterator ti = TestFileNames.begin();
226  while(ti != TestFileNames.end()){
227  // The following block simply makes a link to the testing
228  // script in the current directory for running.
229  std::string TestPath(*ti++);
230  std::string TestName(TestPath);
231  std::string::size_type x = TestName.find_last_of("/");
232  if(x != std::string::npos)
233  TestName = TestName.substr(x+1);
234  std::string LocalTest("./"+TestName);
235  if(verblevel > 1)
236  std::cout << "ix::RunTest> Linking " << TestPath << " to " << LocalTest << std::endl;
237  if(ix::sys::SymLink(TestPath,LocalTest)){
238  err++;
239  std::cout << "ix::RunTest> Warning: Could not create symbolic link "
240  << "to " << TestPath << " at " << LocalTest << "."
241  << std::endl;
242  }
243  if(verblevel > 1)
244  std::cout << "ix::RunTest> Running " << TestName << "." << std::endl;
245  std::string TmpComOut(ix::sys::TempFileName(OutFileName));
246  std::string Command(LocalTest+" "+TmpComOut);
247  if(!SourceDirectory.empty())
248  Command = Command + " " + SourceDirectory;
249  if(!BinaryDirectory.empty())
250  Command = Command + " " + BinaryDirectory;
251  if(!ScriptArgument.empty())
252  Command = Command + " " + ScriptArgument;
253  if(verblevel > 1)
254  std::cout << "ix::RunTest> Running command: " << Command << std::endl;
255  ix::sys::InProcess TestProcess(Command);
256  std::string testoutline;
257  while(std::getline(TestProcess,testoutline)){
258  if(verblevel)
259  std::cout << testoutline << std::endl;
260  }
261  if(!keepFiles)
262  ix::sys::Remove(LocalTest);
263  std::ifstream ComInf(TmpComOut.c_str());
264  if(!ComInf){
265  std::cout << "ix::RunTest> Warning: Cannot access test results from "
266  << TestName << ". Continuing." << std::endl;
267  err++;
268  }
269  else {
270  std::ofstream Ouf;
271  Ouf.open(OutFileName.c_str(),std::ios::app);
272  if(!Ouf){
273  std::cout << "ix::RunTest> Error: Cannot open outfile, " << OutFileName
274  << ". Exiting (fail)." << std::endl;
275  return(1);
276  }
277  std::string comline;
278  while(std::getline(ComInf,comline))
279  Ouf << comline << std::endl;
280  ComInf.close();
281  Ouf.close();
282  if(!keepFiles)
283  ix::sys::Remove(TmpComOut);
284  }
285  }
286  if(err && (verblevel > 1))
287  std::cout << "ix::RunTest> Warning: " << err << " errors occurred during testing."
288  << std::endl;
289  if(!keep_outfile){
290  std::ifstream Inf;
291  Inf.open(OutFileName.c_str());
292  if(!Inf){
293  std::cout << "ix::RunTest> Error: Could not open test output"
294  << ". Test must have gone wrong. Exiting (fail)."
295  << std::endl;
296  return(1);
297  }
298  std::string line;
299  while(std::getline(Inf,line))
300  std::cout << line << std::endl;
301  Inf.close();
302  if(!keepFiles)
303  ix::sys::Remove(OutFileName);
304  }
305  return(err);
306  }
307 };
308 
309 
310 int main(int argc,char *argv[])
311 {
312  return(ix::RunTest(argc,argv));
313 }
int ProcessOptions()
Processes all command line tokens.
Definition: ComLine.C:330
std::string ErrorReport()
Error reporting.
Definition: ComLine.C:473
std::string GetOption(const char &s)
Get the value of an option.
Definition: ComLine.H:291
int Remove(const std::string &fname)
Definition: UnixUtils.C:141
int RunTest(int argc, char *argv[])
Runs test programs and scripts through a standard interface.
Definition: RunTest.C:17
Defines MPI-specific parallel global and program classes.
ComLine object for test running utility.
Definition: RunTest.H:15
void const size_t const size_t const size_t const double const double * x
std::string TempFileName(const std::string &stub)
Definition: UnixUtils.C:313
int SymLink(const std::string &source, const std::string &target)
Definition: UnixUtils.C:136
bool FILEEXISTS(const std::string &fname)
Definition: UnixUtils.C:189
ComLineObject header.
const std::string Hostname(bool longname=false)
Definition: UnixUtils.C:17
int main(int argc, char *argv[])
Definition: RunTest.C:310
void Initialize()
virtual function for program specific Initialization.
Definition: RunTest.H:24
Unix System Tools interface.
Implements a command-line interface for runnning tests.
Implementation of stream object for Unix file descriptors.
std::string LongUsage()
Generate long usage string.
Definition: ComLine.C:188
std::string ShortUsage()
Generate short usage string.
Definition: ComLine.C:244