From c058e71306d87c1736b0d298688223909c54c8f3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 18:45:54 +0000 Subject: [PATCH 1/3] Initial plan From 0422529594c7fe3986ae9db37c88376e15105f49 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 19:02:20 +0000 Subject: [PATCH 2/3] Create test_spio_rearr_contig.cpp and test_pioc.cpp in new C++ style, remove test_pioc.c Co-authored-by: jayeshkrishna <7873429+jayeshkrishna@users.noreply.github.com> --- tests/cunit/CMakeLists.txt | 7 +- tests/cunit/{test_pioc.c => test_pioc.cpp} | 335 +++++++++++++++- tests/cunit/test_spio_rearr_contig.cpp | 421 +++++++++++++++++++++ 3 files changed, 744 insertions(+), 19 deletions(-) rename tests/cunit/{test_pioc.c => test_pioc.cpp} (90%) create mode 100644 tests/cunit/test_spio_rearr_contig.cpp diff --git a/tests/cunit/CMakeLists.txt b/tests/cunit/CMakeLists.txt index ff6c39d6b5..0c38c80cef 100644 --- a/tests/cunit/CMakeLists.txt +++ b/tests/cunit/CMakeLists.txt @@ -74,7 +74,7 @@ if (NOT PIO_USE_MPISERIAL) add_spio_executable (test_iosystem3_simple TRUE "" test_iosystem3_simple.c test_common.c) add_spio_executable (test_iosystem3_simple2 TRUE "" test_iosystem3_simple2.c test_common.c) add_spio_executable (test_iosystem3 TRUE "" test_iosystem3.c test_common.c) - add_spio_executable (test_pioc TRUE "" test_pioc.c test_common.c test_shared.c) + add_spio_executable (test_pioc TRUE "" test_pioc.cpp test_common.c) add_spio_executable (test_pioc_unlim TRUE "" test_pioc_unlim.c test_common.c test_shared.c) add_spio_executable (test_pioc_putget TRUE "" test_pioc_putget.c test_common.c test_shared.c) add_spio_executable (test_pioc_fill TRUE "" test_pioc_fill.c test_common.c test_shared.c) @@ -104,10 +104,12 @@ add_spio_executable (test_spio_ltimer TRUE "" test_spio_ltimer.cpp) add_spio_executable (test_spio_serializer TRUE "" test_spio_serializer.cpp) add_spio_executable (test_spio_tree TRUE "" test_spio_tree.cpp) add_spio_executable (test_spio_file_mvcache TRUE "" test_spio_file_mvcache.cpp) +add_spio_executable (test_spio_rearr_contig TRUE "" test_spio_rearr_contig.cpp test_common.c) add_spio_executable (test_sdecomp_regex TRUE "" test_sdecomp_regex.cpp test_common.c) add_spio_executable(test_req_block_wait TRUE "" test_req_block_wait.c test_common.c) add_dependencies (tests test_spmd test_spio_ltimer test_spio_serializer test_spio_tree - test_spio_file_mvcache test_sdecomp_regex test_req_block_wait) + test_spio_file_mvcache test_spio_rearr_contig test_sdecomp_regex + test_req_block_wait) # Test Timeout in seconds. if (PIO_VALGRIND_CHECK) @@ -127,6 +129,7 @@ add_test(NAME test_spio_ltimer COMMAND test_spio_ltimer) add_test(NAME test_spio_serializer COMMAND test_spio_serializer) add_test(NAME test_spio_tree COMMAND test_spio_tree) add_test(NAME test_spio_file_mvcache COMMAND test_spio_file_mvcache) +add_test(NAME test_spio_rearr_contig COMMAND test_spio_rearr_contig) add_test(NAME test_sdecomp_regex COMMAND test_sdecomp_regex) if (PIO_USE_MPISERIAL) diff --git a/tests/cunit/test_pioc.c b/tests/cunit/test_pioc.cpp similarity index 90% rename from tests/cunit/test_pioc.c rename to tests/cunit/test_pioc.cpp index b66637ef30..a8e8a15a7b 100644 --- a/tests/cunit/test_pioc.c +++ b/tests/cunit/test_pioc.cpp @@ -3,9 +3,31 @@ * * Ed Hartnett */ -#include -#include -#include +#include +#include +#include + +#include "pio_config.h" +#include "pio.h" +#include "pio_internal.h" +#include "pio_tests.h" + +#ifdef SPIO_ENABLE_GPTL_TIMING +#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL +#include "gptl.h" +#endif +#endif + +#define LOG_RANK0(rank, ...) \ + do{ \ + if(rank == 0) \ + { \ + fprintf(stderr, __VA_ARGS__); \ + } \ + }while(0); + +static const int FAIL = -1; + /* The number of tasks this test should run on. */ #define TARGET_NTASKS 4 @@ -97,7 +119,7 @@ int create_decomposition(int ntasks, int my_rank, int iosysid, int dim1_len, int elements_per_pe = dim1_len / ntasks; /* Allocate space for the decomposition array. */ - if (!(compdof = malloc(elements_per_pe * sizeof(PIO_Offset)))) + if (!(compdof = (PIO_Offset *)malloc(elements_per_pe * sizeof(PIO_Offset)))) return PIO_ENOMEM; /* Describe the decomposition. The new init_decomp uses a 0-based @@ -218,10 +240,10 @@ int test_darray(int iosysid, int ioid, int num_flavors, int *flavor, int my_rank ERR(ret); /* Write some data. */ - PIO_Offset arraylen = 1; + const PIO_Offset arraylen = 1; float fillvalue = 0.0; float *fillvaluep = fv ? &fillvalue : NULL; - float test_data[arraylen]; + float test_data[1]; for (int f = 0; f < arraylen; f++) test_data[f] = my_rank * 10 + f; if ((ret = PIOc_write_darray(ncid, varid, ioid, arraylen, test_data, fillvaluep))) @@ -464,24 +486,24 @@ int check_error_strings(int my_rank, int num_tries, int *errcode, int ret; /* Try each test code. */ - for (int try = 0; try < num_tries; try++) + for (int t = 0; t < num_tries; t++) { char errstr[PIO_MAX_NAME + 1]; /* Get the error string for this errcode. */ - if ((ret = PIOc_strerror(errcode[try], errstr, PIO_MAX_NAME))) + if ((ret = PIOc_strerror(errcode[t], errstr, PIO_MAX_NAME))) return ret; - printf("%d for errcode = %d message = %s\n", my_rank, errcode[try], errstr); + printf("%d for errcode = %d message = %s\n", my_rank, errcode[t], errstr); /* Check that it was as expected. */ - if (strncmp(errstr, expected[try], strlen(expected[try]))) + if (strncmp(errstr, expected[t], strlen(expected[t]))) { - printf("%d expected %s got %s\n", my_rank, expected[try], errstr); + printf("%d expected %s got %s\n", my_rank, expected[t], errstr); return ERR_AWFUL; } if (!my_rank) - printf("%d errcode = %d passed\n", my_rank, errcode[try]); + printf("%d errcode = %d passed\n", my_rank, errcode[t]); } return PIO_NOERR; @@ -2180,10 +2202,289 @@ int test_all(int iosysid, int num_flavors, int *flavor, int my_rank, MPI_Comm te return PIO_NOERR; } -/* Run all tests. */ -int main(int argc, char **argv) +/* Run non-async PIO tests. */ +static int run_tests_no_async(int my_rank, int num_flavors, int *flavor, + MPI_Comm test_comm, int target_ntasks) +{ + int niotasks = target_ntasks; + int ioproc_stride = 1; + int ioproc_start = 0; + PIO_Offset elements_per_pe; + int iosysid; + int ioid; + PIO_Offset *compdof; + int slice_dimlen[2]; + int ret; + + slice_dimlen[0] = X_DIM_LEN; + slice_dimlen[1] = Y_DIM_LEN; + + /* Initialize the PIO IO system. */ + if ((ret = PIOc_Init_Intracomm(test_comm, niotasks, ioproc_stride, + ioproc_start, PIO_REARR_SUBSET, &iosysid))) + return ret; + + /* Describe the decomposition. This is a 0-based array, so don't add 1! */ + elements_per_pe = X_DIM_LEN * Y_DIM_LEN / target_ntasks; + if (!(compdof = (PIO_Offset *)malloc(elements_per_pe * sizeof(PIO_Offset)))) + return PIO_ENOMEM; + for (int i = 0; i < elements_per_pe; i++) + compdof[i] = my_rank * elements_per_pe + i; + + /* Create the PIO decomposition for this test. */ + if ((ret = PIOc_init_decomp(iosysid, PIO_FLOAT, 2, slice_dimlen, + (PIO_Offset)elements_per_pe, compdof, &ioid, 0, + NULL, NULL))) + { + free(compdof); + return ret; + } + free(compdof); + + /* Run tests. */ + if ((ret = test_all(iosysid, num_flavors, flavor, my_rank, test_comm, 0))) + return ret; + + /* Free the PIO decomposition. */ + if ((ret = PIOc_freedecomp(iosysid, ioid))) + return ret; + + /* Finalize PIO system. */ + if ((ret = PIOc_finalize(iosysid))) + return ret; + + return PIO_NOERR; +} + +/* Run async PIO tests. */ +static int run_tests_async(int my_rank, int num_flavors, int *flavor, + MPI_Comm test_comm, int component_count, + int num_io_procs, int target_ntasks) +{ + int iosysid[COMPONENT_COUNT]; + int num_procs[COMPONENT_COUNT]; + MPI_Comm io_comm; + MPI_Comm comp_comm[COMPONENT_COUNT]; + int mpierr; + int ret; + + num_procs[0] = target_ntasks - 1; + + /* Is the current process a computation task? */ + int comp_task = my_rank < num_io_procs ? 0 : 1; + + /* Initialize the IO system. */ + if ((ret = PIOc_init_async(test_comm, num_io_procs, NULL, component_count, + num_procs, NULL, &io_comm, comp_comm, + PIO_REARR_BOX, iosysid))) + return ret; + + /* All the netCDF calls are only executed on the computation tasks. */ + if (comp_task) + { + for (int c = 0; c < component_count; c++) + { + if ((ret = test_all(iosysid[c], num_flavors, flavor, my_rank, + comp_comm[0], 1))) + return ret; + + /* Finalize the IO system. */ + if ((ret = PIOc_finalize(iosysid[c]))) + return ret; + if ((mpierr = MPI_Comm_free(&comp_comm[c]))) + return PIO_EIO; + } + } + else + { + if ((mpierr = MPI_Comm_free(&io_comm))) + return PIO_EIO; + } + + return PIO_NOERR; +} + +int test_driver(MPI_Comm comm, int wrank, int wsz, int *num_errors) +{ + int nerrs = 0, ret = PIO_NOERR; + assert((comm != MPI_COMM_NULL) && (wrank >= 0) && (wsz > 0) && num_errors); + + if (wsz < MIN_NTASKS) + { + LOG_RANK0(wrank, "ERROR: Need at least %d tasks.\n", MIN_NTASKS); + *num_errors += 1; + return 1; + } + + /* Change error handling so we can test invalid parameters. */ + if ((ret = PIOc_set_iosystem_error_handling(PIO_DEFAULT, PIO_RETURN_ERROR, NULL))) + { + LOG_RANK0(wrank, + "PIOc_set_iosystem_error_handling() FAILED, ret = %d\n", ret); + *num_errors += 1; + return ret; + } + + int num_flavors; + int flavor[NUM_FLAVORS]; + + /* Figure out iotypes. */ + if ((ret = get_iotypes(&num_flavors, flavor))) + { + LOG_RANK0(wrank, "get_iotypes() FAILED, ret = %d\n", ret); + *num_errors += 1; + return ret; + } + LOG_RANK0(wrank, "Running tests for %d flavors\n", num_flavors); + + /* Run tests without async feature. */ + try + { + ret = run_tests_no_async(wrank, num_flavors, flavor, comm, wsz); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "run_tests_no_async() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "run_tests_no_async() PASSED\n"); + } + + /* Run tests with async. */ + try + { + ret = run_tests_async(wrank, num_flavors, flavor, comm, COMPONENT_COUNT, + NUM_IO_PROCS, wsz); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "run_tests_async() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "run_tests_async() PASSED\n"); + } + + *num_errors += nerrs; + return nerrs; +} + +int main(int argc, char *argv[]) { - /* Change the 5th arg to 3 to turn on logging. */ - return run_test_main(argc, argv, MIN_NTASKS, TARGET_NTASKS, 3, - TEST_NAME, dim_len, COMPONENT_COUNT, NUM_IO_PROCS); + int ret; + int wrank, wsz; + int num_errors; +#ifdef SPIO_ENABLE_GPTL_TIMING +#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL + ret = GPTLinitialize(); + if (ret != 0) + { + LOG_RANK0(wrank, "GPTLinitialize() FAILED, ret = %d\n", ret); + return ret; + } +#endif /* TIMING_INTERNAL */ +#endif /* TIMING */ + + ret = MPI_Init(&argc, &argv); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Init() FAILED, ret = %d\n", ret); + return ret; + } + + ret = MPI_Comm_rank(MPI_COMM_WORLD, &wrank); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Comm_rank() FAILED, ret = %d\n", ret); + MPI_Finalize(); + return ret; + } + ret = MPI_Comm_size(MPI_COMM_WORLD, &wsz); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Comm_size() FAILED, ret = %d\n", ret); + MPI_Finalize(); + return ret; + } + + /* Create a communicator with exactly TARGET_NTASKS tasks. */ + MPI_Comm test_comm; + if (wsz > TARGET_NTASKS) + { + int color = (wrank < TARGET_NTASKS) ? 0 : 1; + int key = wrank; + ret = MPI_Comm_split(MPI_COMM_WORLD, color, key, &test_comm); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Comm_split() FAILED, ret = %d\n", ret); + MPI_Finalize(); + return ret; + } + } + else + { + ret = MPI_Comm_dup(MPI_COMM_WORLD, &test_comm); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Comm_dup() FAILED, ret = %d\n", ret); + MPI_Finalize(); + return ret; + } + } + + /* Turn on logging. */ + if ((ret = PIOc_set_log_level(3))) + { + LOG_RANK0(wrank, "PIOc_set_log_level() FAILED, ret = %d\n", ret); + MPI_Comm_free(&test_comm); + MPI_Finalize(); + return ret; + } + + num_errors = 0; + if (wrank < TARGET_NTASKS) + { + ret = test_driver(test_comm, wrank, TARGET_NTASKS, &num_errors); + if (ret != 0) + { + LOG_RANK0(wrank, "Test driver FAILED\n"); + } + else + { + LOG_RANK0(wrank, "All tests PASSED\n"); + } + } + + MPI_Barrier(MPI_COMM_WORLD); + MPI_Comm_free(&test_comm); + MPI_Finalize(); + +#ifdef SPIO_ENABLE_GPTL_TIMING +#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL + ret = GPTLfinalize(); + if (ret != 0) + { + LOG_RANK0(wrank, "GPTLfinalize() FAILED, ret = %d\n", ret); + return ret; + } +#endif /* TIMING_INTERNAL */ +#endif /* TIMING */ + + if (num_errors != 0) + { + LOG_RANK0(wrank, "Total errors = %d\n", num_errors); + return FAIL; + } + return 0; } diff --git a/tests/cunit/test_spio_rearr_contig.cpp b/tests/cunit/test_spio_rearr_contig.cpp new file mode 100644 index 0000000000..36b3edc4c6 --- /dev/null +++ b/tests/cunit/test_spio_rearr_contig.cpp @@ -0,0 +1,421 @@ +#include + +#include "pio_config.h" +#include "pio.h" +#include "pio_internal.h" +#include "pio_tests.h" + +#ifdef SPIO_ENABLE_GPTL_TIMING +#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL +#include "gptl.h" +#endif +#endif + +#define LOG_RANK0(rank, ...) \ + do{ \ + if(rank == 0) \ + { \ + fprintf(stderr, __VA_ARGS__); \ + } \ + }while(0); + +static const int FAIL = -1; + +/* Test the find_region() function with a simple 1-D contiguous map. */ +int test_find_region_1d(int wrank) +{ + const int ndims = 1; + int gdimlen[1] = {4}; + int maplen = 1; + PIO_Offset map[1] = {1}; + PIO_Offset start[1]; + PIO_Offset count[1]; + PIO_Offset regionlen; + + /* Call the function under test. */ + regionlen = find_region(ndims, gdimlen, maplen, map, start, count); + + /* Check results: single element at index 0. */ + if (regionlen != 1 || start[0] != 0 || count[0] != 1) + { + LOG_RANK0(wrank, "test_find_region_1d() failed: " + "expected regionlen=1, start[0]=0, count[0]=1, " + "got regionlen=%lld, start[0]=%lld, count[0]=%lld\n", + regionlen, start[0], count[0]); + return PIO_EINTERNAL; + } + + return PIO_NOERR; +} + +/* Test find_region() with a contiguous 1-D map of length > 1. */ +int test_find_region_1d_contiguous(int wrank) +{ + const int ndims = 1; + int gdimlen[1] = {8}; + int maplen = 4; + /* 1-based map: elements 1,2,3,4 are contiguous */ + PIO_Offset map[4] = {1, 2, 3, 4}; + PIO_Offset start[1]; + PIO_Offset count[1]; + PIO_Offset regionlen; + + /* Call the function under test. */ + regionlen = find_region(ndims, gdimlen, maplen, map, start, count); + + /* Check results: 4 contiguous elements starting at index 0. */ + if (regionlen != 4 || start[0] != 0 || count[0] != 4) + { + LOG_RANK0(wrank, "test_find_region_1d_contiguous() failed: " + "expected regionlen=4, start[0]=0, count[0]=4, " + "got regionlen=%lld, start[0]=%lld, count[0]=%lld\n", + regionlen, start[0], count[0]); + return PIO_EINTERNAL; + } + + return PIO_NOERR; +} + +/* Test the expand_region() function with a trivial 1-D case. */ +int test_expand_region_1d(int wrank) +{ + const int dim = 0; + int gdims[1] = {1}; + int maplen = 1; + PIO_Offset map[1] = {5}; + int region_size = 1; + int region_stride = 1; + int max_size[1] = {10}; + PIO_Offset count[1] = {0}; + + /* Call the function under test. */ + expand_region(dim, gdims, maplen, map, region_size, region_stride, + max_size, count); + + /* With gdims[0]=1, only one element fits; count[0] should be 1. */ + if (count[0] != 1) + { + LOG_RANK0(wrank, + "test_expand_region_1d() failed: expected count[0]=1, got count[0]=%lld\n", + count[0]); + return PIO_EINTERNAL; + } + + return PIO_NOERR; +} + +/* Test expand_region() with room to expand along a 1-D dimension. */ +int test_expand_region_1d_multi(int wrank) +{ + const int dim = 0; + int gdims[1] = {8}; + int maplen = 4; + /* 1-based contiguous map: 1,2,3,4 */ + PIO_Offset map[4] = {1, 2, 3, 4}; + int region_size = 1; + int region_stride = 1; + int max_size[1] = {8}; + PIO_Offset count[1] = {0}; + + /* Call the function under test. */ + expand_region(dim, gdims, maplen, map, region_size, region_stride, + max_size, count); + + /* All 4 elements are contiguous, so count[0] should be 4. */ + if (count[0] != 4) + { + LOG_RANK0(wrank, + "test_expand_region_1d_multi() failed: expected count[0]=4, got count[0]=%lld\n", + count[0]); + return PIO_EINTERNAL; + } + + return PIO_NOERR; +} + +/* Test the get_regions() function with a simple 1-D map. */ +int test_get_regions_1d(int wrank) +{ + const int ndims = 1; + const int gdimlen[1] = {8}; + /* Two non-contiguous elements */ + const int maplen = 2; + /* 1-based: element 1 and element 3 are not contiguous */ + PIO_Offset map[2] = {1, 3}; + int maxregions; + io_region *ior = NULL; + int ret; + + /* Allocate a region. */ + if ((ret = alloc_region2(NULL, ndims, &ior))) + { + LOG_RANK0(wrank, + "test_get_regions_1d() failed: alloc_region2() returned %d\n", ret); + return ret; + } + ior->next = NULL; + ior->count[0] = 1; + + /* Call the function under test. */ + if ((ret = get_regions(ndims, gdimlen, maplen, map, &maxregions, ior))) + { + free_region_list(ior); + LOG_RANK0(wrank, + "test_get_regions_1d() failed: get_regions() returned %d\n", ret); + return ret; + } + + /* Two non-contiguous elements should produce two regions. */ + if (maxregions != 2) + { + free_region_list(ior); + LOG_RANK0(wrank, + "test_get_regions_1d() failed: expected maxregions=2, got %d\n", + maxregions); + return PIO_EINTERNAL; + } + + /* Free the region list. */ + free_region_list(ior); + + return PIO_NOERR; +} + +/* Test get_regions() with a contiguous 1-D map (should yield one region). */ +int test_get_regions_1d_contiguous(int wrank) +{ + const int ndims = 1; + const int gdimlen[1] = {8}; + const int maplen = 4; + /* 1-based contiguous map: elements 1,2,3,4 */ + PIO_Offset map[4] = {1, 2, 3, 4}; + int maxregions; + io_region *ior = NULL; + int ret; + + /* Allocate a region. */ + if ((ret = alloc_region2(NULL, ndims, &ior))) + { + LOG_RANK0(wrank, + "test_get_regions_1d_contiguous() failed: alloc_region2() returned %d\n", ret); + return ret; + } + ior->next = NULL; + ior->count[0] = 1; + + /* Call the function under test. */ + if ((ret = get_regions(ndims, gdimlen, maplen, map, &maxregions, ior))) + { + free_region_list(ior); + LOG_RANK0(wrank, + "test_get_regions_1d_contiguous() failed: get_regions() returned %d\n", ret); + return ret; + } + + /* Four contiguous elements should produce one region. */ + if (maxregions != 1) + { + free_region_list(ior); + LOG_RANK0(wrank, + "test_get_regions_1d_contiguous() failed: expected maxregions=1, got %d\n", + maxregions); + return PIO_EINTERNAL; + } + + /* Free the region list. */ + free_region_list(ior); + + return PIO_NOERR; +} + +int test_driver(MPI_Comm comm, int wrank, int wsz, int *num_errors) +{ + int nerrs = 0, ret = PIO_NOERR; + assert((comm != MPI_COMM_NULL) && (wrank >= 0) && (wsz > 0) && num_errors); + + /* Test find_region() with a single-element 1-D map. */ + try + { + ret = test_find_region_1d(wrank); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "test_find_region_1d() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "test_find_region_1d() PASSED\n"); + } + + /* Test find_region() with a contiguous multi-element 1-D map. */ + try + { + ret = test_find_region_1d_contiguous(wrank); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "test_find_region_1d_contiguous() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "test_find_region_1d_contiguous() PASSED\n"); + } + + /* Test expand_region() with a trivial 1-D case. */ + try + { + ret = test_expand_region_1d(wrank); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "test_expand_region_1d() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "test_expand_region_1d() PASSED\n"); + } + + /* Test expand_region() with room to expand along a 1-D dimension. */ + try + { + ret = test_expand_region_1d_multi(wrank); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "test_expand_region_1d_multi() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "test_expand_region_1d_multi() PASSED\n"); + } + + /* Test get_regions() with two non-contiguous elements. */ + try + { + ret = test_get_regions_1d(wrank); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "test_get_regions_1d() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "test_get_regions_1d() PASSED\n"); + } + + /* Test get_regions() with four contiguous elements. */ + try + { + ret = test_get_regions_1d_contiguous(wrank); + } + catch(...) + { + ret = PIO_EINTERNAL; + } + if (ret != PIO_NOERR) + { + LOG_RANK0(wrank, "test_get_regions_1d_contiguous() FAILED, ret = %d\n", ret); + nerrs++; + } + else + { + LOG_RANK0(wrank, "test_get_regions_1d_contiguous() PASSED\n"); + } + + *num_errors += nerrs; + return nerrs; +} + +int main(int argc, char *argv[]) +{ + int ret; + int wrank, wsz; + int num_errors; +#ifdef SPIO_ENABLE_GPTL_TIMING +#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL + ret = GPTLinitialize(); + if (ret != 0) + { + LOG_RANK0(wrank, "GPTLinitialize() FAILED, ret = %d\n", ret); + return ret; + } +#endif /* TIMING_INTERNAL */ +#endif /* TIMING */ + + ret = MPI_Init(&argc, &argv); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Init() FAILED, ret = %d\n", ret); + return ret; + } + + ret = MPI_Comm_rank(MPI_COMM_WORLD, &wrank); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Comm_rank() FAILED, ret = %d\n", ret); + return ret; + } + ret = MPI_Comm_size(MPI_COMM_WORLD, &wsz); + if (ret != MPI_SUCCESS) + { + LOG_RANK0(wrank, "MPI_Comm_size() FAILED, ret = %d\n", ret); + return ret; + } + + num_errors = 0; + ret = test_driver(MPI_COMM_WORLD, wrank, wsz, &num_errors); + if (ret != 0) + { + LOG_RANK0(wrank, "Test driver FAILED\n"); + return FAIL; + } + else + { + LOG_RANK0(wrank, "All tests PASSED\n"); + } + + MPI_Finalize(); + +#ifdef SPIO_ENABLE_GPTL_TIMING +#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL + ret = GPTLfinalize(); + if (ret != 0) + { + LOG_RANK0(wrank, "GPTLfinalize() FAILED, ret = %d\n", ret); + return ret; + } +#endif /* TIMING_INTERNAL */ +#endif /* TIMING */ + + if (num_errors != 0) + { + LOG_RANK0(wrank, "Total errors = %d\n", num_errors); + return FAIL; + } + return 0; +} From 1c9351110b1599a47666702661696c293c6cc9f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 19:16:02 +0000 Subject: [PATCH 3/3] Rebase test_pioc.cpp changes onto jayeshkrishna/async_thread_support: update api usage, remove test_spio_rearr_contig.cpp Co-authored-by: jayeshkrishna <7873429+jayeshkrishna@users.noreply.github.com> --- tests/cunit/CMakeLists.txt | 138 ++++++-- tests/cunit/test_pioc.cpp | 18 +- tests/cunit/test_spio_rearr_contig.cpp | 421 ------------------------- 3 files changed, 114 insertions(+), 463 deletions(-) delete mode 100644 tests/cunit/test_spio_rearr_contig.cpp diff --git a/tests/cunit/CMakeLists.txt b/tests/cunit/CMakeLists.txt index 0c38c80cef..0652b72557 100644 --- a/tests/cunit/CMakeLists.txt +++ b/tests/cunit/CMakeLists.txt @@ -9,7 +9,8 @@ include(SPIOUtils) #============================================================================== # SET THE COMPILER OPTIONS #============================================================================== -include_directories("${SCORPIO_SOURCE_DIR}/tests/cunit" "${SCORPIO_SOURCE_DIR}/src/clib" "${SCORPIO_BINARY_DIR}/src/clib") +# FIXME: Use an interface lib to track these include deps +include_directories("${SCORPIO_SOURCE_DIR}/tests/cunit" "${SCORPIO_SOURCE_DIR}/src/clib" "${SCORPIO_BINARY_DIR}/src/clib" "${SCORPIO_SOURCE_DIR}/src/clib/core" "${SCORPIO_SOURCE_DIR}/src/clib/core/util" "${SCORPIO_SOURCE_DIR}/src/clib/core/rearr" "${SCORPIO_SOURCE_DIR}/src/clib/core/progress_engine" "${SCORPIO_SOURCE_DIR}/src/clib/core/iolib/hdf5" "${SCORPIO_SOURCE_DIR}/src/clib/util") # Compiler-specific compiler options string (TOUPPER "${CMAKE_C_COMPILER_ID}" CMAKE_C_COMPILER_NAME) @@ -64,52 +65,72 @@ endif () # Exclude tests that require more than 1 procs when using the MPI serial library if (NOT PIO_USE_MPISERIAL) - add_spio_executable (test_intercomm2 TRUE "" test_intercomm2.c test_common.c) - add_spio_executable (test_async_simple TRUE "" test_async_simple.c test_common.c) - add_spio_executable (test_async_3proc TRUE "" test_async_3proc.c test_common.c) - add_spio_executable (test_async_4proc TRUE "" test_async_4proc.c test_common.c) - add_spio_executable (test_iosystem2_simple TRUE "" test_iosystem2_simple.c test_common.c) - add_spio_executable (test_iosystem2_simple2 TRUE "" test_iosystem2_simple2.c test_common.c) - add_spio_executable (test_iosystem2 TRUE "" test_iosystem2.c test_common.c) - add_spio_executable (test_iosystem3_simple TRUE "" test_iosystem3_simple.c test_common.c) - add_spio_executable (test_iosystem3_simple2 TRUE "" test_iosystem3_simple2.c test_common.c) - add_spio_executable (test_iosystem3 TRUE "" test_iosystem3.c test_common.c) - add_spio_executable (test_pioc TRUE "" test_pioc.cpp test_common.c) - add_spio_executable (test_pioc_unlim TRUE "" test_pioc_unlim.c test_common.c test_shared.c) - add_spio_executable (test_pioc_putget TRUE "" test_pioc_putget.c test_common.c test_shared.c) - add_spio_executable (test_pioc_fill TRUE "" test_pioc_fill.c test_common.c test_shared.c) - add_spio_executable (test_darray TRUE "" test_darray.c test_common.c) - add_spio_executable (test_darray_multi TRUE "" test_darray_multi.c test_common.c) - add_spio_executable (test_darray_multivar TRUE "" test_darray_multivar.c test_common.c) - add_spio_executable (test_darray_multivar2 TRUE "" test_darray_multivar2.c test_common.c) - add_spio_executable (test_darray_1d TRUE "" test_darray_1d.c test_common.c) - add_spio_executable (test_darray_3d TRUE "" test_darray_3d.c test_common.c) - add_spio_executable (test_decomp_uneven TRUE "" test_decomp_uneven.c test_common.c) - add_spio_executable (test_decomps TRUE "" test_decomps.c test_common.c) - add_spio_executable (test_rearr TRUE "" test_rearr.c test_common.c) + add_spio_executable (test_intercomm2 TRUE "" test_intercomm2.cpp test_common.cpp) + add_spio_executable (test_async_simple TRUE "" test_async_simple.cpp test_common.cpp) + add_spio_executable (test_async_3proc TRUE "" test_async_3proc.cpp test_common.cpp) + add_spio_executable (test_async_4proc TRUE "" test_async_4proc.cpp test_common.cpp) + add_spio_executable (test_iosystem2_simple TRUE "" test_iosystem2_simple.cpp test_common.cpp) + add_spio_executable (test_iosystem2_simple2 TRUE "" test_iosystem2_simple2.cpp test_common.cpp) + add_spio_executable (test_iosystem2 TRUE "" test_iosystem2.cpp test_common.cpp) + add_spio_executable (test_iosystem3_simple TRUE "" test_iosystem3_simple.cpp test_common.cpp) + add_spio_executable (test_iosystem3_simple2 TRUE "" test_iosystem3_simple2.cpp test_common.cpp) + add_spio_executable (test_iosystem3 TRUE "" test_iosystem3.cpp test_common.cpp) + add_spio_executable (test_pioc TRUE "" test_pioc.cpp test_common.cpp) + add_spio_executable (test_pioc_unlim TRUE "" test_pioc_unlim.cpp test_common.cpp test_shared.cpp) + add_spio_executable (test_pioc_putget TRUE "" test_pioc_putget.cpp test_common.cpp test_shared.cpp) + add_spio_executable (test_pioc_fill TRUE "" test_pioc_fill.cpp test_common.cpp test_shared.cpp) + add_spio_executable (test_darray TRUE "" test_darray.cpp test_common.cpp) + add_spio_executable (test_darray_multi TRUE "" test_darray_multi.cpp test_common.cpp) + add_spio_executable (test_darray_multivar TRUE "" test_darray_multivar.cpp test_common.cpp) + add_spio_executable (test_darray_multivar2 TRUE "" test_darray_multivar2.cpp test_common.cpp) + add_spio_executable (test_darray_1d TRUE "" test_darray_1d.cpp test_common.cpp) + add_spio_executable (test_darray_3d TRUE "" test_darray_3d.cpp test_common.cpp) + add_spio_executable (test_decomp_uneven TRUE "" test_decomp_uneven.cpp test_common.cpp) + add_spio_executable (test_decomps TRUE "" test_decomps.cpp test_common.cpp) + add_spio_executable (test_rearr TRUE "" test_rearr.cpp test_common.cpp) add_dependencies (tests test_intercomm2 test_async_simple test_async_3proc test_async_4proc test_iosystem2_simple test_iosystem2_simple2 test_iosystem2 test_iosystem3_simple test_iosystem3_simple2 test_iosystem3 test_pioc test_pioc_unlim test_pioc_putget test_pioc_fill test_darray test_darray_multi test_darray_multivar test_darray_multivar2 test_darray_1d test_darray_3d test_decomp_uneven test_decomps test_rearr) if (PIO_USE_MALLOC) - add_spio_executable (test_darray_async_simple TRUE "" test_darray_async_simple.c test_common.c) - add_spio_executable (test_darray_async TRUE "" test_darray_async.c test_common.c) - add_spio_executable (test_darray_async_many TRUE "" test_darray_async_many.c test_common.c) + add_spio_executable (test_darray_async_simple TRUE "" test_darray_async_simple.cpp test_common.cpp) + add_spio_executable (test_darray_async TRUE "" test_darray_async.cpp test_common.cpp) + add_spio_executable (test_darray_async_many TRUE "" test_darray_async_many.cpp test_common.cpp) add_dependencies (tests test_darray_async_simple test_darray_async test_darray_async_many) endif () endif () -add_spio_executable (test_spmd TRUE "" test_spmd.c test_common.c) +add_spio_executable (test_spmd TRUE "" test_spmd.cpp test_common.cpp) add_spio_executable (test_spio_ltimer TRUE "" test_spio_ltimer.cpp) add_spio_executable (test_spio_serializer TRUE "" test_spio_serializer.cpp) add_spio_executable (test_spio_tree TRUE "" test_spio_tree.cpp) add_spio_executable (test_spio_file_mvcache TRUE "" test_spio_file_mvcache.cpp) -add_spio_executable (test_spio_rearr_contig TRUE "" test_spio_rearr_contig.cpp test_common.c) -add_spio_executable (test_sdecomp_regex TRUE "" test_sdecomp_regex.cpp test_common.c) -add_spio_executable(test_req_block_wait TRUE "" test_req_block_wait.c test_common.c) +add_spio_executable (test_spio_sort_utils TRUE "" test_spio_sort_utils.cpp) +add_spio_executable (test_spio_rearr_utils_gather TRUE "" test_spio_rearr_utils_gather.cpp) +add_spio_executable (test_spio_rearr_utils_scatter TRUE "" test_spio_rearr_utils_scatter.cpp) +add_spio_executable (test_spio_rearr_utils_alltoall TRUE "" test_spio_rearr_utils_alltoall.cpp) +add_spio_executable (test_spio_rearr_contig TRUE "" test_spio_rearr_contig.cpp) +add_spio_executable (test_spio_rearr_contig_nvars TRUE "" test_spio_rearr_contig_nvars.cpp) +add_spio_executable (test_spio_rearr_contig_fillval TRUE "" test_spio_rearr_contig_fillval.cpp) +add_spio_executable (test_spio_decomp_logger TRUE "" test_spio_decomp_logger.cpp) +add_spio_executable (test_sdecomp_regex TRUE "" test_sdecomp_regex.cpp test_common.cpp) +add_spio_executable(test_req_block_wait TRUE "" test_req_block_wait.cpp test_common.cpp) +add_spio_executable(test_spio_dt_converter TRUE "" test_spio_dt_converter.cpp) add_dependencies (tests test_spmd test_spio_ltimer test_spio_serializer test_spio_tree - test_spio_file_mvcache test_spio_rearr_contig test_sdecomp_regex - test_req_block_wait) + test_spio_file_mvcache test_spio_sort_utils test_spio_rearr_utils_gather + test_spio_rearr_utils_scatter test_spio_rearr_utils_alltoall + test_spio_rearr_contig test_spio_rearr_contig_nvars test_spio_rearr_contig_fillval + test_spio_decomp_logger test_sdecomp_regex test_req_block_wait + test_spio_dt_converter) + +if(PIO_USE_ASYNC_WR_THREAD) + add_spio_executable (test_mtq TRUE "" test_async_mtq.cpp test_common.cpp) + add_spio_executable (test_mtq_signal TRUE "" test_async_mtq_signal.cpp test_common.cpp) + add_spio_executable (test_mtq_pool TRUE "" test_async_tpool.cpp test_common.cpp) + add_dependencies(tests test_mtq test_mtq_signal test_mtq_pool) +endif() + +set (SPIO_TEST_MAX_NPROCS 4) # Test Timeout in seconds. if (PIO_VALGRIND_CHECK) @@ -129,8 +150,15 @@ add_test(NAME test_spio_ltimer COMMAND test_spio_ltimer) add_test(NAME test_spio_serializer COMMAND test_spio_serializer) add_test(NAME test_spio_tree COMMAND test_spio_tree) add_test(NAME test_spio_file_mvcache COMMAND test_spio_file_mvcache) -add_test(NAME test_spio_rearr_contig COMMAND test_spio_rearr_contig) +add_test(NAME test_spio_dt_converter COMMAND test_spio_dt_converter) add_test(NAME test_sdecomp_regex COMMAND test_sdecomp_regex) +add_test(NAME test_spio_sort_utils COMMAND test_spio_sort_utils) + +if(PIO_USE_ASYNC_WR_THREAD) + add_test(NAME test_mtq COMMAND test_mtq) + add_test(NAME test_mtq_signal COMMAND test_mtq_signal) + add_test(NAME test_mtq_pool COMMAND test_mtq_pool) +endif() if (PIO_USE_MPISERIAL) add_test(NAME test_pioc @@ -152,6 +180,48 @@ else () EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_req_block_wait NUMPROCS 4 TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_rearr_utils_gather${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_rearr_utils_gather + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_rearr_utils_scatter${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_rearr_utils_scatter + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_rearr_utils_alltoall${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_rearr_utils_alltoall + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_rearr_contig${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_rearr_contig + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_rearr_contig_nvars${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_rearr_contig_nvars + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_rearr_contig_fillval${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_rearr_contig_fillval + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() + foreach(nproc RANGE 1 ${SPIO_TEST_MAX_NPROCS}) + add_mpi_test(test_spio_decomp_logger${nproc} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spio_decomp_logger + NUMPROCS ${nproc} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + endforeach() add_mpi_test(test_spmd EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_spmd NUMPROCS ${AT_LEAST_FOUR_TASKS} diff --git a/tests/cunit/test_pioc.cpp b/tests/cunit/test_pioc.cpp index a8e8a15a7b..cbe4be6dfb 100644 --- a/tests/cunit/test_pioc.cpp +++ b/tests/cunit/test_pioc.cpp @@ -119,7 +119,7 @@ int create_decomposition(int ntasks, int my_rank, int iosysid, int dim1_len, int elements_per_pe = dim1_len / ntasks; /* Allocate space for the decomposition array. */ - if (!(compdof = (PIO_Offset *)malloc(elements_per_pe * sizeof(PIO_Offset)))) + if (!(compdof = (PIO_Offset *) malloc(elements_per_pe * sizeof(PIO_Offset)))) return PIO_ENOMEM; /* Describe the decomposition. The new init_decomp uses a 0-based @@ -486,24 +486,24 @@ int check_error_strings(int my_rank, int num_tries, int *errcode, int ret; /* Try each test code. */ - for (int t = 0; t < num_tries; t++) + for (int i = 0; i < num_tries; i++) { char errstr[PIO_MAX_NAME + 1]; /* Get the error string for this errcode. */ - if ((ret = PIOc_strerror(errcode[t], errstr, PIO_MAX_NAME))) + if ((ret = PIOc_strerror(errcode[i], errstr, PIO_MAX_NAME))) return ret; - printf("%d for errcode = %d message = %s\n", my_rank, errcode[t], errstr); + printf("%d for errcode = %d message = %s\n", my_rank, errcode[i], errstr); /* Check that it was as expected. */ - if (strncmp(errstr, expected[t], strlen(expected[t]))) + if (strncmp(errstr, expected[i], strlen(expected[i]))) { - printf("%d expected %s got %s\n", my_rank, expected[t], errstr); + printf("%d expected %s got %s\n", my_rank, expected[i], errstr); return ERR_AWFUL; } if (!my_rank) - printf("%d errcode = %d passed\n", my_rank, errcode[t]); + printf("%d errcode = %d passed\n", my_rank, errcode[i]); } return PIO_NOERR; @@ -1661,7 +1661,7 @@ int test_malloc_iodesc2(int iosysid, int my_rank) for (int t = 0; t < num_types; t++) { - if ((ret = malloc_iodesc(ios, test_type[t], 1, &iodesc))) + if ((ret = malloc_iodesc(ios, test_type[t], 1, 1, &iodesc))) return ret; if (iodesc->mpitype != mpi_type[t]) return ERR_WRONG; @@ -1670,6 +1670,8 @@ int test_malloc_iodesc2(int iosysid, int my_rank) ioid = pio_add_to_iodesc_list(iodesc, MPI_COMM_NULL); if (iodesc->firstregion) free_region_list(iodesc->firstregion); + free(iodesc->map); + free(iodesc->dimlen); if ((ret = pio_delete_iodesc_from_list(ioid))) return ret; } diff --git a/tests/cunit/test_spio_rearr_contig.cpp b/tests/cunit/test_spio_rearr_contig.cpp deleted file mode 100644 index 36b3edc4c6..0000000000 --- a/tests/cunit/test_spio_rearr_contig.cpp +++ /dev/null @@ -1,421 +0,0 @@ -#include - -#include "pio_config.h" -#include "pio.h" -#include "pio_internal.h" -#include "pio_tests.h" - -#ifdef SPIO_ENABLE_GPTL_TIMING -#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL -#include "gptl.h" -#endif -#endif - -#define LOG_RANK0(rank, ...) \ - do{ \ - if(rank == 0) \ - { \ - fprintf(stderr, __VA_ARGS__); \ - } \ - }while(0); - -static const int FAIL = -1; - -/* Test the find_region() function with a simple 1-D contiguous map. */ -int test_find_region_1d(int wrank) -{ - const int ndims = 1; - int gdimlen[1] = {4}; - int maplen = 1; - PIO_Offset map[1] = {1}; - PIO_Offset start[1]; - PIO_Offset count[1]; - PIO_Offset regionlen; - - /* Call the function under test. */ - regionlen = find_region(ndims, gdimlen, maplen, map, start, count); - - /* Check results: single element at index 0. */ - if (regionlen != 1 || start[0] != 0 || count[0] != 1) - { - LOG_RANK0(wrank, "test_find_region_1d() failed: " - "expected regionlen=1, start[0]=0, count[0]=1, " - "got regionlen=%lld, start[0]=%lld, count[0]=%lld\n", - regionlen, start[0], count[0]); - return PIO_EINTERNAL; - } - - return PIO_NOERR; -} - -/* Test find_region() with a contiguous 1-D map of length > 1. */ -int test_find_region_1d_contiguous(int wrank) -{ - const int ndims = 1; - int gdimlen[1] = {8}; - int maplen = 4; - /* 1-based map: elements 1,2,3,4 are contiguous */ - PIO_Offset map[4] = {1, 2, 3, 4}; - PIO_Offset start[1]; - PIO_Offset count[1]; - PIO_Offset regionlen; - - /* Call the function under test. */ - regionlen = find_region(ndims, gdimlen, maplen, map, start, count); - - /* Check results: 4 contiguous elements starting at index 0. */ - if (regionlen != 4 || start[0] != 0 || count[0] != 4) - { - LOG_RANK0(wrank, "test_find_region_1d_contiguous() failed: " - "expected regionlen=4, start[0]=0, count[0]=4, " - "got regionlen=%lld, start[0]=%lld, count[0]=%lld\n", - regionlen, start[0], count[0]); - return PIO_EINTERNAL; - } - - return PIO_NOERR; -} - -/* Test the expand_region() function with a trivial 1-D case. */ -int test_expand_region_1d(int wrank) -{ - const int dim = 0; - int gdims[1] = {1}; - int maplen = 1; - PIO_Offset map[1] = {5}; - int region_size = 1; - int region_stride = 1; - int max_size[1] = {10}; - PIO_Offset count[1] = {0}; - - /* Call the function under test. */ - expand_region(dim, gdims, maplen, map, region_size, region_stride, - max_size, count); - - /* With gdims[0]=1, only one element fits; count[0] should be 1. */ - if (count[0] != 1) - { - LOG_RANK0(wrank, - "test_expand_region_1d() failed: expected count[0]=1, got count[0]=%lld\n", - count[0]); - return PIO_EINTERNAL; - } - - return PIO_NOERR; -} - -/* Test expand_region() with room to expand along a 1-D dimension. */ -int test_expand_region_1d_multi(int wrank) -{ - const int dim = 0; - int gdims[1] = {8}; - int maplen = 4; - /* 1-based contiguous map: 1,2,3,4 */ - PIO_Offset map[4] = {1, 2, 3, 4}; - int region_size = 1; - int region_stride = 1; - int max_size[1] = {8}; - PIO_Offset count[1] = {0}; - - /* Call the function under test. */ - expand_region(dim, gdims, maplen, map, region_size, region_stride, - max_size, count); - - /* All 4 elements are contiguous, so count[0] should be 4. */ - if (count[0] != 4) - { - LOG_RANK0(wrank, - "test_expand_region_1d_multi() failed: expected count[0]=4, got count[0]=%lld\n", - count[0]); - return PIO_EINTERNAL; - } - - return PIO_NOERR; -} - -/* Test the get_regions() function with a simple 1-D map. */ -int test_get_regions_1d(int wrank) -{ - const int ndims = 1; - const int gdimlen[1] = {8}; - /* Two non-contiguous elements */ - const int maplen = 2; - /* 1-based: element 1 and element 3 are not contiguous */ - PIO_Offset map[2] = {1, 3}; - int maxregions; - io_region *ior = NULL; - int ret; - - /* Allocate a region. */ - if ((ret = alloc_region2(NULL, ndims, &ior))) - { - LOG_RANK0(wrank, - "test_get_regions_1d() failed: alloc_region2() returned %d\n", ret); - return ret; - } - ior->next = NULL; - ior->count[0] = 1; - - /* Call the function under test. */ - if ((ret = get_regions(ndims, gdimlen, maplen, map, &maxregions, ior))) - { - free_region_list(ior); - LOG_RANK0(wrank, - "test_get_regions_1d() failed: get_regions() returned %d\n", ret); - return ret; - } - - /* Two non-contiguous elements should produce two regions. */ - if (maxregions != 2) - { - free_region_list(ior); - LOG_RANK0(wrank, - "test_get_regions_1d() failed: expected maxregions=2, got %d\n", - maxregions); - return PIO_EINTERNAL; - } - - /* Free the region list. */ - free_region_list(ior); - - return PIO_NOERR; -} - -/* Test get_regions() with a contiguous 1-D map (should yield one region). */ -int test_get_regions_1d_contiguous(int wrank) -{ - const int ndims = 1; - const int gdimlen[1] = {8}; - const int maplen = 4; - /* 1-based contiguous map: elements 1,2,3,4 */ - PIO_Offset map[4] = {1, 2, 3, 4}; - int maxregions; - io_region *ior = NULL; - int ret; - - /* Allocate a region. */ - if ((ret = alloc_region2(NULL, ndims, &ior))) - { - LOG_RANK0(wrank, - "test_get_regions_1d_contiguous() failed: alloc_region2() returned %d\n", ret); - return ret; - } - ior->next = NULL; - ior->count[0] = 1; - - /* Call the function under test. */ - if ((ret = get_regions(ndims, gdimlen, maplen, map, &maxregions, ior))) - { - free_region_list(ior); - LOG_RANK0(wrank, - "test_get_regions_1d_contiguous() failed: get_regions() returned %d\n", ret); - return ret; - } - - /* Four contiguous elements should produce one region. */ - if (maxregions != 1) - { - free_region_list(ior); - LOG_RANK0(wrank, - "test_get_regions_1d_contiguous() failed: expected maxregions=1, got %d\n", - maxregions); - return PIO_EINTERNAL; - } - - /* Free the region list. */ - free_region_list(ior); - - return PIO_NOERR; -} - -int test_driver(MPI_Comm comm, int wrank, int wsz, int *num_errors) -{ - int nerrs = 0, ret = PIO_NOERR; - assert((comm != MPI_COMM_NULL) && (wrank >= 0) && (wsz > 0) && num_errors); - - /* Test find_region() with a single-element 1-D map. */ - try - { - ret = test_find_region_1d(wrank); - } - catch(...) - { - ret = PIO_EINTERNAL; - } - if (ret != PIO_NOERR) - { - LOG_RANK0(wrank, "test_find_region_1d() FAILED, ret = %d\n", ret); - nerrs++; - } - else - { - LOG_RANK0(wrank, "test_find_region_1d() PASSED\n"); - } - - /* Test find_region() with a contiguous multi-element 1-D map. */ - try - { - ret = test_find_region_1d_contiguous(wrank); - } - catch(...) - { - ret = PIO_EINTERNAL; - } - if (ret != PIO_NOERR) - { - LOG_RANK0(wrank, "test_find_region_1d_contiguous() FAILED, ret = %d\n", ret); - nerrs++; - } - else - { - LOG_RANK0(wrank, "test_find_region_1d_contiguous() PASSED\n"); - } - - /* Test expand_region() with a trivial 1-D case. */ - try - { - ret = test_expand_region_1d(wrank); - } - catch(...) - { - ret = PIO_EINTERNAL; - } - if (ret != PIO_NOERR) - { - LOG_RANK0(wrank, "test_expand_region_1d() FAILED, ret = %d\n", ret); - nerrs++; - } - else - { - LOG_RANK0(wrank, "test_expand_region_1d() PASSED\n"); - } - - /* Test expand_region() with room to expand along a 1-D dimension. */ - try - { - ret = test_expand_region_1d_multi(wrank); - } - catch(...) - { - ret = PIO_EINTERNAL; - } - if (ret != PIO_NOERR) - { - LOG_RANK0(wrank, "test_expand_region_1d_multi() FAILED, ret = %d\n", ret); - nerrs++; - } - else - { - LOG_RANK0(wrank, "test_expand_region_1d_multi() PASSED\n"); - } - - /* Test get_regions() with two non-contiguous elements. */ - try - { - ret = test_get_regions_1d(wrank); - } - catch(...) - { - ret = PIO_EINTERNAL; - } - if (ret != PIO_NOERR) - { - LOG_RANK0(wrank, "test_get_regions_1d() FAILED, ret = %d\n", ret); - nerrs++; - } - else - { - LOG_RANK0(wrank, "test_get_regions_1d() PASSED\n"); - } - - /* Test get_regions() with four contiguous elements. */ - try - { - ret = test_get_regions_1d_contiguous(wrank); - } - catch(...) - { - ret = PIO_EINTERNAL; - } - if (ret != PIO_NOERR) - { - LOG_RANK0(wrank, "test_get_regions_1d_contiguous() FAILED, ret = %d\n", ret); - nerrs++; - } - else - { - LOG_RANK0(wrank, "test_get_regions_1d_contiguous() PASSED\n"); - } - - *num_errors += nerrs; - return nerrs; -} - -int main(int argc, char *argv[]) -{ - int ret; - int wrank, wsz; - int num_errors; -#ifdef SPIO_ENABLE_GPTL_TIMING -#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL - ret = GPTLinitialize(); - if (ret != 0) - { - LOG_RANK0(wrank, "GPTLinitialize() FAILED, ret = %d\n", ret); - return ret; - } -#endif /* TIMING_INTERNAL */ -#endif /* TIMING */ - - ret = MPI_Init(&argc, &argv); - if (ret != MPI_SUCCESS) - { - LOG_RANK0(wrank, "MPI_Init() FAILED, ret = %d\n", ret); - return ret; - } - - ret = MPI_Comm_rank(MPI_COMM_WORLD, &wrank); - if (ret != MPI_SUCCESS) - { - LOG_RANK0(wrank, "MPI_Comm_rank() FAILED, ret = %d\n", ret); - return ret; - } - ret = MPI_Comm_size(MPI_COMM_WORLD, &wsz); - if (ret != MPI_SUCCESS) - { - LOG_RANK0(wrank, "MPI_Comm_size() FAILED, ret = %d\n", ret); - return ret; - } - - num_errors = 0; - ret = test_driver(MPI_COMM_WORLD, wrank, wsz, &num_errors); - if (ret != 0) - { - LOG_RANK0(wrank, "Test driver FAILED\n"); - return FAIL; - } - else - { - LOG_RANK0(wrank, "All tests PASSED\n"); - } - - MPI_Finalize(); - -#ifdef SPIO_ENABLE_GPTL_TIMING -#ifndef SPIO_ENABLE_GPTL_TIMING_INTERNAL - ret = GPTLfinalize(); - if (ret != 0) - { - LOG_RANK0(wrank, "GPTLfinalize() FAILED, ret = %d\n", ret); - return ret; - } -#endif /* TIMING_INTERNAL */ -#endif /* TIMING */ - - if (num_errors != 0) - { - LOG_RANK0(wrank, "Total errors = %d\n", num_errors); - return FAIL; - } - return 0; -}