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