| 73 | using namespace test; |
| 74 | |
| 75 | bool run_test(TestBase &test, bool use_child_process = true) { |
| 76 | if (!use_child_process) { |
| 77 | exit(static_cast<int>(test.run())); |
| 78 | } |
| 79 | |
| 80 | printf("-- running test case: %s\n", test.name); |
| 81 | |
| 82 | fflush(stdout); |
| 83 | |
| 84 | test::TestStatus status = test::SUCCESS; |
| 85 | |
| 86 | #ifdef _WIN32 |
| 87 | char filename[256]; |
| 88 | GetModuleFileName(NULL, filename, 256); // TODO: check for error |
| 89 | std::string cmd_line = filename; |
| 90 | cmd_line += " --nofork "; |
| 91 | cmd_line += test.name; |
| 92 | |
| 93 | STARTUPINFO si; |
| 94 | PROCESS_INFORMATION pi; |
| 95 | ZeroMemory(&si, sizeof(si)); |
| 96 | si.cb = sizeof(si); |
| 97 | ZeroMemory(&pi, sizeof(pi)); |
| 98 | |
| 99 | if (!CreateProcessA(nullptr, const_cast<char *>(cmd_line.c_str()), nullptr, |
| 100 | nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) { |
| 101 | printf("unable to create process\n"); |
| 102 | exit(-1); |
| 103 | } |
| 104 | |
| 105 | WaitForSingleObject(pi.hProcess, INFINITE); |
| 106 | |
| 107 | DWORD exit_code; |
| 108 | GetExitCodeProcess(pi.hProcess, &exit_code); |
| 109 | switch (exit_code) { |
| 110 | case 3: |
| 111 | status = test::SIGNAL_ABORT; |
| 112 | break; |
| 113 | case 5: |
| 114 | status = test::EXCEPTION_UNCAUGHT; |
| 115 | break; |
| 116 | case EXCEPTION_ACCESS_VIOLATION: |
| 117 | status = test::SIGNAL_SEGFAULT; |
| 118 | break; |
| 119 | case EXCEPTION_STACK_OVERFLOW: |
| 120 | status = test::SIGNAL_SEGFAULT; |
| 121 | break; |
| 122 | case EXCEPTION_INT_DIVIDE_BY_ZERO: |
| 123 | status = test::SIGNAL_DIVZERO; |
| 124 | break; |
| 125 | } |
| 126 | printf("Exit code: %lu\n", exit_code); |
| 127 | |
| 128 | CloseHandle(pi.hProcess); |
| 129 | CloseHandle(pi.hThread); |
| 130 | |
| 131 | if (test.expected_status == test::ASSERT_FAIL) { |
| 132 | // assert calls abort on windows |