From e0eb5c6e1dbf527db240faa0f398617577ec783f Mon Sep 17 00:00:00 2001 From: Dana Robinson <43805+derobins@users.noreply.github.com> Date: Fri, 26 Mar 2021 20:07:59 -0700 Subject: Updates that allow accum SWMR tests to work on Windows (#493) * Committing clang-format changes * Updates the accum test to work on Windows Uses CreateProcess() on Windows * Source formatting * Fix for Unix child result * Fixes process return code bug on Windows Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- test/accum.c | 162 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 60 deletions(-) diff --git a/test/accum.c b/test/accum.c index 51a03c6..c3346bc 100644 --- a/test/accum.c +++ b/test/accum.c @@ -2074,13 +2074,14 @@ error: /*------------------------------------------------------------------------- * Function: test_swmr_write_big * - * Purpose: A SWMR test: verifies that writing "large" metadata to a file - * opened with SWMR_WRITE will flush the existing metadata in the - * accumulator to disk first before writing the "large" metadata - * to disk. - * This test will fork and exec a reader "accum_swmr_reader" which - * opens the same file with SWMR_READ and verifies that the correct - * metadata is read from disk. + * Purpose: A SWMR test: verifies that writing "large" metadata to a file + * opened with SWMR_WRITE will flush the existing metadata in the + * accumulator to disk first before writing the "large" metadata + * to disk. + * + * This test will fork and exec a reader "accum_swmr_reader" which + * opens the same file with SWMR_READ and verifies that the correct + * metadata is read from disk. * * Return: Success: 0 * Failure: 1 @@ -2092,7 +2093,7 @@ error: unsigned test_swmr_write_big(hbool_t newest_format) { -#ifdef H5_HAVE_UNISTD_H + hid_t fid = -1; /* File ID */ hid_t fapl = -1; /* File access property list */ H5F_t * rf = NULL; /* File pointer */ @@ -2100,16 +2101,23 @@ test_swmr_write_big(hbool_t newest_format) uint8_t *wbuf2 = NULL, *rbuf = NULL; /* Buffers for reading & writing */ uint8_t wbuf[1024]; /* Buffer for reading & writing */ unsigned u; /* Local index variable */ - pid_t pid; /* Process ID */ - int status; /* Status returned from child process */ - char * driver = NULL; /* VFD string (from env variable) */ - hbool_t api_ctx_pushed = FALSE; /* Whether API context pushed */ + hbool_t process_success = FALSE; + char * driver = NULL; /* VFD string (from env variable) */ + hbool_t api_ctx_pushed = FALSE; /* Whether API context pushed */ if (newest_format) TESTING("SWMR write of large metadata: with latest format") else TESTING("SWMR write of large metadata: with non-latest-format") +#if !defined(H5_HAVE_UNISTD_H) && !defined(H5_HAVE_WIN32_API) + + /* Not a Windows or POSIX system */ + SKIPPED(); + HDputs(" Test skipped: Not a Windows or POSIX system."); + return 0; + +#else /* Skip this test if SWMR I/O is not supported for the VFD specified * by the environment variable. */ @@ -2219,56 +2227,94 @@ test_swmr_write_big(hbool_t newest_format) if (HDmemcmp(wbuf2, rbuf, (size_t)BIG_BUF_SIZE) != 0) TEST_ERROR; - /* Fork child process to verify that the data at [1024, 2014] does get written to disk */ - if ((pid = HDfork()) < 0) { - HDperror("fork"); - FAIL_STACK_ERROR; - } - else if (0 == pid) { /* Child process */ - /* By convention, argv[0] tells the name of program invoked. - * - * execv on NetBSD 8 will actually return EFAULT if there is a - * NULL at argv[0], so we follow the convention unconditionally. - */ - char swmr_reader[] = SWMR_READER; - char *const new_argv[] = {swmr_reader, NULL}; - /* Run the reader */ - status = HDexecv(SWMR_READER, new_argv); - HDprintf("errno from execv = %s\n", HDstrerror(errno)); - FAIL_STACK_ERROR; - } /* end if */ +#if defined(H5_HAVE_WIN32_API) + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD exit_code = EXIT_FAILURE; - /* Parent process -- wait for the child process to complete */ - while (pid != HDwaitpid(pid, &status, 0)) - /*void*/; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); - /* Check if child process terminates normally and its return value */ - if (WIFEXITED(status) && !WEXITSTATUS(status)) { - /* Flush the accumulator */ - if (accum_reset(rf) < 0) + if (0 == CreateProcess(NULL, SWMR_READER, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + HDprintf("CreateProcess failed (%d).\n", GetLastError()); FAIL_STACK_ERROR; + } - /* Close and remove the file */ - if (H5Fclose(fid) < 0) - FAIL_STACK_ERROR; + (void)WaitForSingleObject(pi.hProcess, INFINITE); + + if (FALSE == GetExitCodeProcess(pi.hProcess, &exit_code) || EXIT_FAILURE == exit_code) + process_success = FALSE; + else + process_success = TRUE; - /* Close the property list */ - if (H5Pclose(fapl) < 0) + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } +#else /* defined(H5_HAVE_WIN32_API) */ + { + pid_t pid; /* Process ID */ + int status; /* Status returned from child process */ + + /* Fork child process to verify that the data at [1024, 2014] does get written to disk */ + if ((pid = HDfork()) < 0) { + HDperror("fork"); + FAIL_STACK_ERROR; + } + else if (0 == pid) { /* Child process */ + /* By convention, argv[0] tells the name of program invoked. + * + * execv on NetBSD 8 will actually return EFAULT if there is a + * NULL at argv[0], so we follow the convention unconditionally. + */ + char swmr_reader[] = SWMR_READER; + char *const new_argv[] = {swmr_reader, NULL}; + /* Run the reader */ + status = HDexecv(SWMR_READER, new_argv); + HDprintf("errno from execv = %s\n", HDstrerror(errno)); FAIL_STACK_ERROR; + } /* end if */ - /* Pop API context */ - if (api_ctx_pushed && H5CX_pop(FALSE) < 0) - FAIL_STACK_ERROR - api_ctx_pushed = FALSE; - - /* Release memory */ - if (wbuf2) - HDfree(wbuf2); - if (rbuf) - HDfree(rbuf); - PASSED(); - return 0; - } /* end if */ + /* Parent process -- wait for the child process to complete */ + while (pid != HDwaitpid(pid, &status, 0)) + /*void*/; + + /* Check if child process terminates normally and its return value */ + if (WIFEXITED(status) && !WEXITSTATUS(status)) + process_success = TRUE; + } +#endif /* defined(H5_HAVE_WIN32_API) */ + + /* Check if the process terminated correctly */ + if (!process_success) + FAIL_PUTS_ERROR("child process exited abnormally") + + /* Flush the accumulator */ + if (accum_reset(rf) < 0) + FAIL_STACK_ERROR; + + /* Close and remove the file */ + if (H5Fclose(fid) < 0) + FAIL_STACK_ERROR; + + /* Close the property list */ + if (H5Pclose(fapl) < 0) + FAIL_STACK_ERROR; + + /* Pop API context */ + if (api_ctx_pushed && H5CX_pop(FALSE) < 0) + FAIL_STACK_ERROR + api_ctx_pushed = FALSE; + + /* Release memory */ + if (wbuf2) + HDfree(wbuf2); + if (rbuf) + HDfree(rbuf); + + PASSED(); + return 0; error: /* Closing and remove the file */ @@ -2287,11 +2333,7 @@ error: return 1; -#else /* H5_HAVE_UNISTD_H */ - SKIPPED(); - HDputs(" Test skipped due to fork, waitpid, or pid_t not defined."); - return 0; -#endif /* H5_HAVE_UNISTD_H */ +#endif /* !defined(H5_HAVE_UNISTD_H) && !defined(H5_HAVE_WIN32_API) */ } /* end test_swmr_write_big() */ -- cgit v0.12