|
@@ -0,0 +1,116 @@
|
|
|
+#include <string>
|
|
|
+#include <iostream>
|
|
|
+#include <cstring>
|
|
|
+
|
|
|
+#include <spawn.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <sys/wait.h>
|
|
|
+
|
|
|
+// Integration test suite runner.
|
|
|
+
|
|
|
+int main(int argc, char **argv)
|
|
|
+{
|
|
|
+ const char * const test_dirs[] = { "basic", "environ" };
|
|
|
+ constexpr int num_tests = sizeof(test_dirs) / sizeof(test_dirs[0]);
|
|
|
+
|
|
|
+ int passed = 0;
|
|
|
+ int skipped = 0;
|
|
|
+ int failed = 0;
|
|
|
+
|
|
|
+ bool aborted_run = false;
|
|
|
+
|
|
|
+ std::cout << "============== INTEGRATION TESTS =====================" << std::endl;
|
|
|
+
|
|
|
+ for (int i = 0; i < num_tests; i++) {
|
|
|
+ const char * test_dir = test_dirs[i];
|
|
|
+
|
|
|
+ std::string prog_path = "./run-test.sh";
|
|
|
+ char * const p_argv[2] = { const_cast<char *>(prog_path.c_str()), nullptr };
|
|
|
+
|
|
|
+ std::cout << test_dir << "... ";
|
|
|
+
|
|
|
+ // "Use posix_spawn", they said. "It will be easy", they said.
|
|
|
+
|
|
|
+ if (chdir(test_dir) != 0) {
|
|
|
+ std::cerr << "Couldn't chdir: " << test_dir << ": " << strerror(errno) << std::endl;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ posix_spawn_file_actions_t p_actions;
|
|
|
+ posix_spawnattr_t p_attr;
|
|
|
+
|
|
|
+ if (posix_spawn_file_actions_init(&p_actions) != 0) {
|
|
|
+ // out of memory?
|
|
|
+ std::cerr << "Error launching process: " << test_dir << "/run-test.sh: " << strerror(errno) << std::endl;
|
|
|
+ aborted_run = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (posix_spawnattr_init(&p_attr) != 0) {
|
|
|
+ // out of memory?
|
|
|
+ std::cerr << "Error launching process: " << test_dir << "/run-test.sh: " << strerror(errno) << std::endl;
|
|
|
+ aborted_run = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ pid_t subproc_pid;
|
|
|
+ if (posix_spawn(&subproc_pid, prog_path.c_str(), &p_actions, &p_attr, p_argv, environ) != 0) {
|
|
|
+ // fail out
|
|
|
+ std::cerr << "Failed to run run-test.sh in " << test_dir << std::endl;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ int wstatus;
|
|
|
+ if (waitpid(subproc_pid, &wstatus, 0) == -1) {
|
|
|
+ std::cout << "(unknown)" << std::endl;
|
|
|
+ std::cerr << "waitpid() failed" << std::endl;
|
|
|
+ aborted_run = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (WIFEXITED(wstatus)) {
|
|
|
+ if (WEXITSTATUS(wstatus) == 0) {
|
|
|
+ std::cout << "PASSED" << std::endl;
|
|
|
+ passed++;
|
|
|
+ }
|
|
|
+ else if (WEXITSTATUS(wstatus) == 1) {
|
|
|
+ std::cout << "FAILED" << std::endl;
|
|
|
+ failed++;
|
|
|
+ }
|
|
|
+ else if (WEXITSTATUS(wstatus) == 2) {
|
|
|
+ std::cout << "SKIPPED" << std::endl;
|
|
|
+ skipped++;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ std::cout << "???" << std::endl;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ std::cout << "*** terminated abnormally ***" << std::endl;
|
|
|
+ aborted_run = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ posix_spawnattr_destroy(&p_attr);
|
|
|
+ posix_spawn_file_actions_destroy(&p_actions);
|
|
|
+ chdir("..");
|
|
|
+ }
|
|
|
+
|
|
|
+ std::cout << "======================================================" << std::endl;
|
|
|
+
|
|
|
+ if (! aborted_run) {
|
|
|
+ std::cout << "Test run finished.\n"
|
|
|
+ "Passed: " << passed << "\n"
|
|
|
+ "Failed: " << failed;
|
|
|
+ if (failed != 0) {
|
|
|
+ std::cout << " XXX";
|
|
|
+ }
|
|
|
+ std::cout << "\n"
|
|
|
+ "Skipped: " << skipped << std::endl;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ std::cout << "Test run aborted." << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ return failed == 0 ? 0 : 1;
|
|
|
+}
|