Skip to content

Commit

Permalink
Updates that allow accum SWMR tests to work on Windows (#493)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
derobins and github-actions[bot] authored Mar 27, 2021
1 parent 6b13310 commit e0eb5c6
Showing 1 changed file with 102 additions and 60 deletions.
162 changes: 102 additions & 60 deletions test/accum.c
Original file line number Diff line number Diff line change
Expand Up @@ -2074,13 +2074,14 @@ HDfprintf(stderr, "Random # seed was: %u\n", seed);
/*-------------------------------------------------------------------------
* 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
Expand All @@ -2092,24 +2093,31 @@ HDfprintf(stderr, "Random # seed was: %u\n", seed);
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 */
char filename[1024];
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.
*/
Expand Down Expand Up @@ -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 */
Expand All @@ -2287,11 +2333,7 @@ test_swmr_write_big(hbool_t newest_format)

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() */

Expand Down

0 comments on commit e0eb5c6

Please sign in to comment.