/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/***********************************************************
 *
 *  Test program:    version_bounds_1_10.c
 *
 *  Test 1.10 compatibility with version bounds for files
 *  generated by gen_bounds.c in develop branch.
 *
 *
 *  The following tests are for testing datasets with references
 *  and selections respectively:
 *  --test_ref_bounds()
 *  --test_sel_bounds()
 *
 *************************************************************/
#include "h5test.h"
#include "H5srcdir.h"

/* File names used in test_ref_bounds() */
#define FILENAME_REF_E_L       "bounds_ref_earliest_latest.h5"
#define FILENAME_REF_L_L       "bounds_ref_latest_latest.h5"
#define FILENAME_REF_V112_V112 "bounds_ref_v112_v112.h5"
#define FILENAME_REF_V110_V110 "bounds_ref_v110_v110.h5"
#define FILENAME_REF_V18_V18   "bounds_ref_v18_v18.h5"

/* Dataset names used in test_ref_bounds() */
#define REVISED_REFS_DSET "Revised_refs_dset"
#define OLD_REF_OBJ_DSET  "Old_ref_object_dset"
#define OLD_REF_REG_DSET  "Old_ref_region_dset"

/* File names used in test_sel_bounds() */
#define FILENAME_SEL_E_L       "bounds_sel_earliest_latest.h5"
#define FILENAME_SEL_L_L       "bounds_sel_latest_latest.h5"
#define FILENAME_SEL_V112_V112 "bounds_sel_v112_v112.h5"
#define FILENAME_SEL_V110_V110 "bounds_sel_v110_v110.h5"

/* Dataset names used in test_sel_bounds() */
#define SEL_EX_REG_DSET "Sel_ex32_reg_dset"
#define SEL_EX_IRR_DSET "Sel_ex32_irr_dset"
#define SEL_EX_PT_DSET  "Sel_ex32_pt_dset"

/***********************************************************************
 *
 *  Used by test_sel_bounds() to verify:
 *  --the dataset "dset_name" can be opened (or not)"
 *  --the selection in "dset_name" can be accessed (or not)"
 *
 ***********************************************************************/
static herr_t
test_sel_check(hid_t fid, const char *dset_name, int should_open, int should_access)
{
    hid_t           did = H5I_INVALID_HID;
    hid_t           sid = H5I_INVALID_HID;
    hdset_reg_ref_t ref_rbuf[1]; /* The buffer for the reference */

    /* Open and read the referenced dataset */
    H5E_BEGIN_TRY
    {
        did = H5Dopen2(fid, dset_name, H5P_DEFAULT);
    }
    H5E_END_TRY;

    if (should_open && (H5I_INVALID_HID == did))
        FAIL_PUTS_ERROR("*** Should have been able to open the dataset ***");
    if (!should_open && (H5I_INVALID_HID != did))
        FAIL_PUTS_ERROR("*** Should NOT have been able to open the dataset ***");

    if (did != H5I_INVALID_HID) {
        if (H5Dread(did, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref_rbuf) < 0)
            TEST_ERROR

        /* Open access to the region reference from the dataset's dataspace */
        H5E_BEGIN_TRY
        {
            sid = H5Rget_region(did, H5R_DATASET_REGION, &ref_rbuf[0]);
        }
        H5E_END_TRY;

        if (should_access && (H5I_INVALID_HID == sid))
            FAIL_PUTS_ERROR("*** Should have been able to open the dataspace ***");
        if (!should_access && (H5I_INVALID_HID != sid))
            FAIL_PUTS_ERROR("*** Should NOT have been able to open the dataspace ***");

        if (H5Dclose(did) < 0)
            TEST_ERROR

        if (should_access && H5Sclose(sid) < 0)
            TEST_ERROR
    }

    return SUCCEED;

error:
    H5E_BEGIN_TRY
    {
        H5Dclose(did);
        H5Sclose(sid);
    }
    H5E_END_TRY;

    return FAIL;
} /* test_sel_check() */

/***********************************************************************
 * test_sel_bounds():
 *      This routine will be used to read in the following test files
 *      generated by gen_bounds.c in develop branch:
 *          (1) FILENAME_SEL_E_L--"bounds_sel_earliest_latest.h5"
 *          (2) FILENAME_SEL_L_L--"bounds_sel_latest_latest.h5"
 *          (3) FILENAME_SEL_V110_V110--"bounds_sel_v110_v110.h5"
 *          (4) FILENAME_SEL_V112_V112--"bounds_sel_v112_v112.h5"
 *      See detailed description of datasets created in those files in
 *      gen_bounds.c in develop branch.
 *
 *
 * This test verifies the following:
 *  File #1, #3:
 *  a) dataset SEL_EX_REG_DSET--"Sel_ex32_reg_dset"
 *      --if existed, succeed to open and read the dataset; also,
 *        succeed to access the selection
 *  b) dataset SEL_EX_IRR_DSET--"Sel_ex32_irr_dset"
 *      --if existed, succeed to open and read the dataset but fail to
 *        access the selection due to hyperslab selection version 3
 *  c) dataset SEL_EX_PT_DSET--"Sel_ex32_pt_dset"
 *      --if existed, succeed to open and read the dataset but fail to
 *        access the selection due to point selection version 2
 *
 *  Files #2, #4:
 *  a) dataset SEL_EX_REG_DSET--"Sel_ex32_reg_dset"
 *      --if existed, succeed to open the datasets but fail to access
 *        the selection due to hyperslab selection version 3
 *  b) dataset SEL_EX_IRR_DSET--"Sel_ex32_irr_dset"
 *      --if existed, succeed to open the datasets but fail to access
 *        the selection due to hyperslab selection version 3
 *  c) dataset SEL_EX_PT_DSET--"Sel_ex32_pt_dset"
 *      --if existed, succeed to open the datasets but fail to access
 *        the selection due to point selection version 2
 *
 ***********************************************************************/
static herr_t
test_sel_bounds(const char *filename)
{
    hid_t       fid = H5I_INVALID_HID;
    const char *path;
    htri_t      exists;

    HDprintf("Test file: %s\n", filename);
    TESTING("selection version bounds");

    path = H5_get_srcdir_filename(filename);

    if (H5I_INVALID_HID == (fid = H5Fopen(path, H5F_ACC_RDONLY, H5P_DEFAULT)))
        TEST_ERROR

    if (!HDstrcmp(filename, FILENAME_SEL_E_L) || !HDstrcmp(filename, FILENAME_SEL_V110_V110)) {

        if ((exists = H5Lexists(fid, SEL_EX_REG_DSET, H5P_DEFAULT)) < 0)
            TEST_ERROR
        if (exists && test_sel_check(fid, SEL_EX_REG_DSET, TRUE, TRUE) < 0)
            goto error;

        if ((exists = H5Lexists(fid, SEL_EX_IRR_DSET, H5P_DEFAULT)) < 0)
            TEST_ERROR
        if (exists && test_sel_check(fid, SEL_EX_IRR_DSET, TRUE, FALSE) < 0)
            goto error;

        if ((exists = H5Lexists(fid, SEL_EX_PT_DSET, H5P_DEFAULT)) < 0)
            TEST_ERROR
        if (exists && test_sel_check(fid, SEL_EX_PT_DSET, TRUE, FALSE) < 0)
            goto error;
    }
    else {

        if ((exists = H5Lexists(fid, SEL_EX_REG_DSET, H5P_DEFAULT)) < 0)
            TEST_ERROR
        if (exists && test_sel_check(fid, SEL_EX_REG_DSET, TRUE, FALSE) < 0)
            goto error;

        if ((exists = H5Lexists(fid, SEL_EX_IRR_DSET, H5P_DEFAULT)) < 0)
            TEST_ERROR
        if (exists && test_sel_check(fid, SEL_EX_IRR_DSET, TRUE, FALSE) < 0)
            goto error;

        if ((exists = H5Lexists(fid, SEL_EX_PT_DSET, H5P_DEFAULT)) < 0)
            TEST_ERROR
        if (test_sel_check(fid, SEL_EX_PT_DSET, TRUE, FALSE) < 0)
            goto error;
    }

    if (H5Fclose(fid) < 0)
        TEST_ERROR

    PASSED();
    return SUCCEED;

error:
    H5E_BEGIN_TRY
    {
        H5Fclose(fid);
    }
    H5E_END_TRY;

    return FAIL;
} /* test_sel_bounds() */

/***********************************************************************
 *
 *  Used by test_ref_bounds() to verify:
 *  --the dataset "dset_name" can be opened (or not)
 *
 ***********************************************************************/
static herr_t
test_ref_check(hid_t fid, const char *dset_name, hbool_t should_open)
{
    hid_t did = H5I_INVALID_HID; /* Dataset ID */

    H5E_BEGIN_TRY
    {
        did = H5Dopen2(fid, dset_name, H5P_DEFAULT);
    }
    H5E_END_TRY;

    if (should_open && (H5I_INVALID_HID == did))
        FAIL_PUTS_ERROR("*** Should have been able to open the dataset ***");
    if (!should_open && (H5I_INVALID_HID != did))
        FAIL_PUTS_ERROR("*** Should NOT have been able to open the dataset ***");

    if (should_open && H5Dclose(did) < 0)
        TEST_ERROR

    return SUCCEED;
error:
    return FAIL;

} /* test_ref_check() */

/***********************************************************************
 * test_ref_bounds():
 *      This routine will be used to read in the following test files
 *      generated by gen_bounds.c in develop branch:
 *          (1) FILENAME_REF_E_L--"bounds_ref_earliest_latest.h5"
 *          (2) FILENAME_REF_L_L--"bounds_ref_latest_latest.h5"
 *          (3) FILENAME_REF_V112_V112--"bounds_ref_v112_v112.h5"
 *          (4) FILENAME_REF_V110_V110--"bounds_ref_v110_v110.h5"
 *          (5) FILENAME_REF_V18_V18--"bounds_ref_v18_v18.h5"
 *      See detailed description of datasets created in those files in
 *      gen_bounds.c in develop branch.
 *
 *
 * This test verifies the following:
 *  Files #1 to #5:
 *  a) dataset REVISED_REFS_DSET--"Revised_refs_dset"
 *    --if existed, fail to open this dataset due to datatype message version 4
 *  b) dataset OLD_REF_OBJ_DSET--"Old_ref_object_dset"
 *    --if existed, succeed to open the dataset
 *  c) dataset OLD_REF_REG_DSET--"Old_ref_region_dset"
 *    --if existed, succeed to open the dataset
 *
 ***********************************************************************/
static herr_t
test_ref_bounds(const char *filename)
{
    const char *path;
    hid_t       fid = H5I_INVALID_HID;
    htri_t      exists;

    HDprintf("Test file: %s\n", filename);
    TESTING("reference version bounds");

    path = H5_get_srcdir_filename(filename);

    if (H5I_INVALID_HID == (fid = H5Fopen(path, H5F_ACC_RDONLY, H5P_DEFAULT)))
        TEST_ERROR

    if ((exists = H5Lexists(fid, REVISED_REFS_DSET, H5P_DEFAULT)) < 0)
        TEST_ERROR
    if (exists && test_ref_check(fid, REVISED_REFS_DSET, FALSE) < 0)
        goto error;

    if ((exists = H5Lexists(fid, OLD_REF_OBJ_DSET, H5P_DEFAULT)) < 0)
        TEST_ERROR
    if (exists && test_ref_check(fid, OLD_REF_OBJ_DSET, TRUE) < 0)
        goto error;

    if ((exists = H5Lexists(fid, OLD_REF_REG_DSET, H5P_DEFAULT)) < 0)
        TEST_ERROR
    if (exists && test_ref_check(fid, OLD_REF_REG_DSET, TRUE) < 0)
        goto error;

    if (H5Fclose(fid) < 0)
        TEST_ERROR

    PASSED();
    return SUCCEED;

error:
    H5E_BEGIN_TRY
    {
        H5Fclose(fid);
    }
    H5E_END_TRY;

    return FAIL;
} /* test_ref_bounds() */

/*************************************************************************
**
**      Main routine to test version bounds with 1.10 library
**
*************************************************************************/
int
main(void)
{
    int nerrors = 0;

    h5_reset();

    HDprintf("Testing reference and selection version bounds.\n");

    /* Verify the reference datasets in the test files */
    nerrors += test_ref_bounds(FILENAME_REF_E_L) < 0 ? 1 : 0;
    nerrors += test_ref_bounds(FILENAME_REF_L_L) < 0 ? 1 : 0;
    nerrors += test_ref_bounds(FILENAME_REF_V112_V112) < 0 ? 1 : 0;
    nerrors += test_ref_bounds(FILENAME_REF_V110_V110) < 0 ? 1 : 0;
    nerrors += test_ref_bounds(FILENAME_REF_V18_V18) < 0 ? 1 : 0;

    /* Verify the selections of reference datasets in the test files */
    nerrors += test_sel_bounds(FILENAME_SEL_E_L) < 0 ? 1 : 0;
    nerrors += test_sel_bounds(FILENAME_SEL_L_L) < 0 ? 1 : 0;
    nerrors += test_sel_bounds(FILENAME_SEL_V112_V112) < 0 ? 1 : 0;
    nerrors += test_sel_bounds(FILENAME_SEL_V110_V110) < 0 ? 1 : 0;

    if (nerrors) {
        HDprintf("***** %d Reference and selection version bounds TEST%s FAILED! *****\n", nerrors,
                 nerrors > 1 ? "S" : "");
        return EXIT_FAILURE;
    }

    HDprintf("All reference and selection version bounds tests passed.\n");

    return EXIT_SUCCESS;
}
