CMS 3D CMS Logo

TestHelper.cc
Go to the documentation of this file.
1 //------------------------------------------------------------
2 //------------------------------------------------------------
3 #include <cerrno>
4 #include <cstdlib>
5 #include <exception>
6 #include <iostream>
7 #include <string>
8 
9 #include <sys/wait.h>
10 #include <unistd.h>
11 #include <cstring>
12 
13 #include "boost/version.hpp"
14 #include "boost/filesystem/convenience.hpp"
15 
21 
22 namespace bf = boost::filesystem;
23 
24 int run_script(std::string const& shell, std::string const& script) {
25  pid_t pid = 0;
26  int status = 0;
27 
28  if ((pid = fork()) < 0) {
29  std::cerr << "fork failed, to run " << script << std::endl;
30  return -1;
31  }
32 
33  if (pid == 0) { // child
34  execlp(shell.c_str(), "sh", "-c", script.c_str(), static_cast<char const*>(nullptr));
35  std::cerr << "child failed becuase '" << strerror(errno) << "'\n";
36  _exit(127); // signal parent and children processes
37  } else { // parent
38  while (waitpid(pid, &status, 0) < 0) {
39  if (errno != EINTR) {
40  std::cerr << "child process failed " << strerror(errno) << "\n";
41  status = -1;
42  break;
43  } else {
44  if (WIFSIGNALED(status)) {
45  std::cerr << "child existed because of a signal " << WTERMSIG(status) << "\n";
46  }
47  }
48  }
49  if (WIFSIGNALED(status)) {
50  std::cerr << "child existed because of a signal " << WTERMSIG(status) << "\n";
51  }
52  if (WIFEXITED(status)) {
53  }
54  }
55  return status;
56 }
57 
58 int do_work(int argc, char* argv[], char** env) {
59  bf::path currentPath(bf::initial_path().string());
60 
61  if (argc < 4) {
62  std::cout << "Usage: " << argv[0] << " shell subdir script1 script2 ... scriptN\n\n"
63  << "where shell is the path+shell (e.g., /bin/bash) intended to run the scripts\n"
64  << "and subdir is the subsystem/package/subdir in which the scripts are found\n"
65  << "(e.g., FWCore/Utilities/test)\n"
66  << std::endl;
67 
68  std::cout << "Current directory is: " << currentPath.string() << '\n';
69  std::cout << "Current environment:\n";
70  std::cout << "---------------------\n";
71  for (int i = 0; env[i] != nullptr; ++i)
72  std::cout << env[i] << '\n';
73  std::cout << "---------------------\n";
74  std::cout << "Executable name: " << argv[0] << '\n';
75  return -1;
76  }
77 
78  char const* goodDirectory = "[A-Za-z0-9/_.-]+";
79 
80  for (int i = 0; i < argc; ++i) {
81  std::cout << "argument " << i << ": " << argv[i] << '\n';
82  }
83 
85  std::cerr << "shell is: " << shell << '\n';
86 
87  std::cout << "Current directory is: " << currentPath.string() << '\n';
88  // It is unclear about which of these environment variables should
89  // be used.
90  char const* topdir = std::getenv("SCRAMRT_LOCALRT");
91  if (!topdir)
92  topdir = std::getenv("LOCALRT");
93  try {
94  if (!edm::untaintString(topdir, goodDirectory)) {
95  std::cerr << "Invalid top directory '" << topdir << "'" << std::endl;
96  return -1;
97  }
98  } catch (std::runtime_error const& e) {
99  std::cerr << "Invalid top directory '" << topdir << "'" << std::endl;
100  std::cerr << "e.what" << std::endl;
101  return -1;
102  }
103 
104  char const* arch = std::getenv("SCRAM_ARCH");
105 
106  if (!arch) {
107  // Try to synthesize SCRAM_ARCH value.
108  bf::path exepath(argv[0]);
109 #if (BOOST_VERSION / 100000) >= 1 && ((BOOST_VERSION / 100) % 1000) >= 47
110  std::string maybe_arch = exepath.parent_path().filename().string();
111 #else
112  std::string maybe_arch = exepath.branch_path().leaf();
113 #endif
114  if (setenv("SCRAM_ARCH", maybe_arch.c_str(), 1) != 0) {
115  std::cerr << "SCRAM_ARCH not set and attempt to set it failed\n";
116  return -1;
117  }
118  arch = std::getenv("SCRAM_ARCH");
119  }
120 
121  int rc = 0;
122 
123  if (!topdir) {
124  std::cerr << "Neither SCRAMRT_LOCALRT nor LOCALRT is defined" << std::endl;
125  return -1;
126  }
127 
128  try {
129  if (!edm::untaintString(argv[2], goodDirectory)) {
130  std::cerr << "Invalid test directory '" << argv[2] << "'" << std::endl;
131  return -1;
132  }
133  } catch (std::runtime_error const& e) {
134  std::cerr << "Invalid test directory '" << argv[2] << "'" << std::endl;
135  std::cerr << "e.what" << std::endl;
136  return -1;
137  }
138 
139  std::string testdir(topdir);
140  testdir += "/src/";
141  testdir += argv[2];
142  std::string tmpdir(topdir);
143  tmpdir += "/tmp/";
144  tmpdir += arch;
145  std::string testbin(topdir);
146  testbin += "/test/";
147  testbin += arch;
148 
149  std::cout << "topdir is: " << topdir << '\n';
150  std::cout << "testdir is: " << testdir << '\n';
151  std::cout << "tmpdir is: " << tmpdir << '\n';
152  std::cout << "testbin is: " << testbin << '\n';
153 
154  if (setenv("LOCAL_TEST_DIR", testdir.c_str(), 1) != 0) {
155  std::cerr << "Could not set LOCAL_TEST_DIR to " << testdir << std::endl;
156  return -1;
157  }
158  if (setenv("LOCAL_TMP_DIR", tmpdir.c_str(), 1) != 0) {
159  std::cerr << "Could not set LOCAL_TMP_DIR to " << tmpdir << std::endl;
160  return -1;
161  }
162  if (setenv("LOCAL_TOP_DIR", topdir, 1) != 0) {
163  std::cerr << "Could not set LOCAL_TOP_DIR to " << topdir << std::endl;
164  return -1;
165  }
166  if (setenv("LOCAL_TEST_BIN", testbin.c_str(), 1) != 0) {
167  std::cerr << "Could not set LOCAL_TEST_BIN to " << testbin << std::endl;
168  return -1;
169  }
170 
171  testdir += "/";
172 
173  for (int i = 3; i < argc && rc == 0; ++i) {
174  std::string scriptname(testdir);
175  scriptname += argv[i];
176  std::cout << "Running script: " << scriptname << std::endl;
177  rc = run_script(shell, scriptname);
178  }
179 
180  std::cout << "status = " << rc << std::endl;
181  return rc == 0 ? 0 : -1;
182 }
183 
184 int ptomaine(int argc, char* argv[], char** env) {
185  int rc = 1;
186  // Standalone executable, prints exception message
187  CMS_SA_ALLOW try { rc = do_work(argc, argv, env); } catch (edm::Exception& x) {
188  std::cerr << "Caught an edm::Exception in " << argv[0] << '\n' << x;
189  } catch (cms::Exception& x) {
190  std::cerr << "Caught a cms::Exception in " << argv[0] << '\n' << x;
191  } catch (std::exception& x) {
192  std::cerr << "Caught a std::exception in " << argv[0] << '\n' << x.what();
193  } catch (...) {
194  std::cerr << "Caught an unknown exception in " << argv[0];
195  }
196  return rc;
197 }
cmsBatch.argv
argv
Definition: cmsBatch.py:279
mps_fire.i
i
Definition: mps_fire.py:355
dir2webdir.argc
argc
Definition: dir2webdir.py:39
mps_update.status
status
Definition: mps_update.py:69
gather_cfg.cout
cout
Definition: gather_cfg.py:144
fileinputsource_cfi.shell
shell
Definition: fileinputsource_cfi.py:77
CMS_SA_ALLOW
#define CMS_SA_ALLOW
Definition: thread_safety_macros.h:5
ptomaine
int ptomaine(int argc, char *argv[], char **env)
Definition: TestHelper.cc:184
edm::Exception
Definition: EDMException.h:77
EDMException.h
vertices_cff.x
x
Definition: vertices_cff.py:29
edm::untaintString
bool untaintString(char const *pattern, char const *regexp)
Definition: RegexMatch.cc:12
AlCaHLTBitMon_QueryRunRegistry.string
string
Definition: AlCaHLTBitMon_QueryRunRegistry.py:256
web.browse_db.env
env
Definition: browse_db.py:18
cppFunctionSkipper.exception
exception
Definition: cppFunctionSkipper.py:10
beam_dqm_sourceclient-live_cfg.cerr
cerr
Definition: beam_dqm_sourceclient-live_cfg.py:17
thread_safety_macros.h
shell
Definition: shell.py:1
TestHelper.h
Exception.h
cms::Exception
Definition: Exception.h:70
castor_dqm_sourceclient_file_cfg.path
path
Definition: castor_dqm_sourceclient_file_cfg.py:37
run_script
int run_script(std::string const &shell, std::string const &script)
Definition: TestHelper.cc:24
RegexMatch.h
do_work
int do_work(int argc, char *argv[], char **env)
Definition: TestHelper.cc:58
MillePedeFileConverter_cfg.e
e
Definition: MillePedeFileConverter_cfg.py:37