summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Smith <jake.smith@hdfgroup.org>2018-09-11 21:45:33 (GMT)
committerJacob Smith <jake.smith@hdfgroup.org>2018-09-11 21:45:33 (GMT)
commit7ef8d1d8484396ee220bf55ef1229c68b2b13534 (patch)
tree5e9a322eb0a9ab0899f3df9f8f639b402bd91a30
parent602dd3ac15c9f5cd47fc78985266ce66a68a8789 (diff)
downloadhdf5-7ef8d1d8484396ee220bf55ef1229c68b2b13534.zip
hdf5-7ef8d1d8484396ee220bf55ef1229c68b2b13534.tar.gz
hdf5-7ef8d1d8484396ee220bf55ef1229c68b2b13534.tar.bz2
Add new test file
-rw-r--r--test/ohdr_min.c1322
1 files changed, 1322 insertions, 0 deletions
diff --git a/test/ohdr_min.c b/test/ohdr_min.c
new file mode 100644
index 0000000..8636bb1
--- /dev/null
+++ b/test/ohdr_min.c
@@ -0,0 +1,1322 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Tests to verify behavior of minimized object headers.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "hdf5.h"
+#include "h5test.h"
+
+/******************
+ * TESTING MACROS *
+ ******************/
+
+#define DEBUG_OH_SIZE 0 /* toggle some debug printing (0 off, 1 on)*/
+
+#ifndef JSMITH_TESTING
+
+/*****************************************************************************
+ *
+ * FILE-LOCAL TESTING MACROS
+ *
+ * Purpose:
+ *
+ * 1) Upon test failure, goto-jump to single-location teardown in test
+ * function. E.g., `error:` (consistency with HDF corpus) or
+ * `failed:` (reflects purpose).
+ * >>> using "error", in part because `H5E_BEGIN_TRY` expects it.
+ * 2) Increase clarity and reduce overhead found with `TEST_ERROR`.
+ * e.g., "if(somefunction(arg, arg2) < 0) TEST_ERROR:"
+ * requires reading of entire line to know whether this if/call is
+ * part of the test setup, test operation, or a test unto itself.
+ * 3) Provide testing macros with optional user-supplied failure message;
+ * if not supplied (NULL), generate comparison output in the spirit of
+ * test-driven development. E.g., "expected 5 but was -3"
+ * User messages clarify test's purpose in code, encouraging description
+ * without relying on comments.
+ * 4) Configurable expected-actual order in generated comparison strings.
+ * Some prefer `VERIFY(expected, actual)`, others
+ * `VERIFY(actual, expected)`. Provide preprocessor ifdef switch
+ * to satifsy both parties, assuming one paradigm per test file.
+ * (One could #undef and redefine the flag through the file as desired,
+ * but _why_.)
+ *
+ * Provided as courtesy, per consideration for inclusion in the library
+ * proper.
+ *
+ * Macros:
+ *
+ * JSVERIFY_EXP_ACT - ifdef flag, configures comparison order
+ * FAIL_IF() - check condition
+ * FAIL_UNLESS() - check _not_ condition
+ * JSVERIFY() - long-int equality check; prints reason/comparison
+ * JSVERIFY_NOT() - long-int inequality check; prints
+ * JSVERIFY_STR() - string equality check; prints
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *****************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * ifdef flag: JSVERIFY_EXP_ACT
+ *
+ * JSVERIFY macros accept arguments as (EXPECTED, ACTUAL[, reason])
+ * default, if this is undefined, is (ACTUAL, EXPECTED[, reason])
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY_EXP_ACT 1L
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: JSFAILED_AT()
+ *
+ * Purpose:
+ *
+ * Preface a test failure by printing "*FAILED*" and location to stdout
+ * Similar to `H5_FAILED(); AT();` from h5test.h
+ *
+ * *FAILED* at somefile.c:12 in function_name()...
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSFAILED_AT() { \
+ HDprintf("*FAILED* at %s:%d in %s()...\n", __FILE__, __LINE__, FUNC); \
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: FAIL_IF()
+ *
+ * Purpose:
+ *
+ * Make tests more accessible and less cluttered than
+ * `if (thing == otherthing()) TEST_ERROR`
+ * paradigm.
+ *
+ * The following lines are roughly equivalent:
+ *
+ * `if (myfunc() < 0) TEST_ERROR;` (as seen elsewhere in HDF tests)
+ * `FAIL_IF(myfunc() < 0)`
+ *
+ * Prints a generic "FAILED AT" line to stdout and jumps to `error`,
+ * similar to `TEST_ERROR` in h5test.h
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ *----------------------------------------------------------------------------
+ */
+#define FAIL_IF(condition) \
+if (condition) { \
+ JSFAILED_AT() \
+ goto error; \
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: FAIL_UNLESS()
+ *
+ * Purpose:
+ *
+ * TEST_ERROR wrapper to reduce cognitive overhead from "negative tests",
+ * e.g., "a != b".
+ *
+ * Opposite of FAIL_IF; fails if the given condition is _not_ true.
+ *
+ * `FAIL_IF( 5 != my_op() )`
+ * is equivalent to
+ * `FAIL_UNLESS( 5 == my_op() )`
+ * However, `JSVERIFY(5, my_op(), "bad return")` may be even clearer.
+ * (see JSVERIFY)
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#if 0 /* UNUSED */
+#define FAIL_UNLESS(condition) \
+if (!(condition)) { \
+ JSFAILED_AT() \
+ goto error; \
+}
+#endif /* UNUSED */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: JSERR_LONG()
+ *
+ * Purpose:
+ *
+ * Print an failure message for long-int arguments.
+ * ERROR-AT printed first.
+ * If `reason` is given, it is printed on own line and newlined after
+ * else, prints "expected/actual" aligned on own lines.
+ *
+ * *FAILED* at myfile.c:488 in somefunc()...
+ * forest must be made of trees.
+ *
+ * or
+ *
+ * *FAILED* at myfile.c:488 in somefunc()...
+ * ! Expected 425
+ * ! Actual 3
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSERR_LONG(expected, actual, reason) { \
+ JSFAILED_AT() \
+ if (reason!= NULL) { \
+ HDprintf("%s\n", (reason)); \
+ } else { \
+ HDprintf(" ! Expected %ld\n ! Actual %ld\n", \
+ (long)(expected), (long)(actual)); \
+ } \
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: JSERR_STR()
+ *
+ * Purpose:
+ *
+ * Print an failure message for string arguments.
+ * ERROR-AT printed first.
+ * If `reason` is given, it is printed on own line and newlined after
+ * else, prints "expected/actual" aligned on own lines.
+ *
+ * *FAILED* at myfile.c:421 in myfunc()...
+ * Blue and Red strings don't match!
+ *
+ * or
+ *
+ * *FAILED* at myfile.c:421 in myfunc()...
+ * !!! Expected:
+ * this is my expected
+ * string
+ * !!! Actual:
+ * not what I expected at all
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSERR_STR(expected, actual, reason) { \
+ JSFAILED_AT() \
+ if ((reason) != NULL) { \
+ HDprintf("%s\n", (reason)); \
+ } else { \
+ HDprintf("!!! Expected:\n%s\n!!!Actual:\n%s\n", \
+ (expected), (actual)); \
+ } \
+}
+
+#ifdef JSVERIFY_EXP_ACT
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: JSVERIFY()
+ *
+ * Purpose:
+ *
+ * Verify that two long integers are equal.
+ * If unequal, print failure message
+ * (with `reason`, if not NULL; expected/actual if NULL)
+ * and jump to `error` at end of function
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY(expected, actual, reason) \
+if ((long)(actual) != (long)(expected)) { \
+ JSERR_LONG((expected), (actual), (reason)) \
+ goto error; \
+} /* JSVERIFY */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: JSVERIFY_NOT()
+ *
+ * Purpose:
+ *
+ * Verify that two long integers are _not_ equal.
+ * If equal, print failure message
+ * (with `reason`, if not NULL; expected/actual if NULL)
+ * and jump to `error` at end of function
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY_NOT(expected, actual, reason) \
+if ((long)(actual) == (long)(expected)) { \
+ JSERR_LONG((expected), (actual), (reason)) \
+ goto error; \
+} /* JSVERIFY_NOT */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Macro: JSVERIFY_STR()
+ *
+ * Purpose:
+ *
+ * Verify that two strings are equal.
+ * If unequal, print failure message
+ * (with `reason`, if not NULL; expected/actual if NULL)
+ * and jump to `error` at end of function
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-24
+ *
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY_STR(expected, actual, reason) \
+if (strcmp((actual), (expected)) != 0) { \
+ JSERR_STR((expected), (actual), (reason)); \
+ goto error; \
+} /* JSVERIFY_STR */
+
+#else /* JSVERIFY_EXP_ACT */
+ /* Repeats macros above, but with actual/expected parameters reversed. */
+
+
+/*----------------------------------------------------------------------------
+ * Macro: JSVERIFY()
+ * See: JSVERIFY documentation above.
+ * Programmer: Jacob Smith
+ * 2017-10-14
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY(actual, expected, reason) \
+if ((long)(actual) != (long)(expected)) { \
+ JSERR_LONG((expected), (actual), (reason)); \
+ goto error; \
+} /* JSVERIFY */
+
+
+/*----------------------------------------------------------------------------
+ * Macro: JSVERIFY_NOT()
+ * See: JSVERIFY_NOT documentation above.
+ * Programmer: Jacob Smith
+ * 2017-10-14
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY_NOT(actual, expected, reason) \
+if ((long)(actual) == (long)(expected)) { \
+ JSERR_LONG((expected), (actual), (reason)) \
+ goto error; \
+} /* JSVERIFY_NOT */
+
+
+/*----------------------------------------------------------------------------
+ * Macro: JSVERIFY_STR()
+ * See: JSVERIFY_STR documentation above.
+ * Programmer: Jacob Smith
+ * 2017-10-14
+ *----------------------------------------------------------------------------
+ */
+#define JSVERIFY_STR(actual, expected, reason) \
+if (strcmp((actual), (expected)) != 0) { \
+ JSERR_STR((expected), (actual), (reason)); \
+ goto error; \
+} /* JSVERIFY_STR */
+
+#endif /* JSVERIFY_EXP_ACT */
+
+#endif /* JSMITH_TESTING */
+
+/* used for object header size comparison */
+#define EQ 1
+#define LT 2
+#define GT 3
+
+/* pseudo-enumeration of symbols to select H5*close() function in macro */
+#define CLOSE_ATTRIBUTE 1
+#define CLOSE_DATASET 2
+#define CLOSE_DATASPACE 3
+#define CLOSE_DATATYPE 4
+#define CLOSE_FILE 5
+#define CLOSE_PLIST 6
+
+
+/* ---------------------------------------------------------------------------
+ * Macro: MUST_CLOSE(...)
+ *
+ * Trigger an error if calling close on the id fails (e.g., H5Fclose(fid).
+ * Uses #defined values to indicate expected id kind (plist vs file, &c.).
+ * Prints message on error.
+ * Please use only at "top level" of test function (because JSVERIFY).
+ * ---------------------------------------------------------------------------
+ */
+#define MUST_CLOSE(id, kind) \
+{ switch (kind) { \
+ case CLOSE_ATTRIBUTE : \
+ JSVERIFY(SUCCEED, H5Aclose((id)), "closing attribute") \
+ break; \
+ case CLOSE_DATASET : \
+ JSVERIFY(SUCCEED, H5Dclose((id)), "closing dataset") \
+ break; \
+ case CLOSE_DATASPACE : \
+ JSVERIFY(SUCCEED, H5Sclose((id)), "closing dataspace") \
+ break; \
+ case CLOSE_DATATYPE : \
+ JSVERIFY(SUCCEED, H5Tclose((id)), "closing datatype") \
+ break; \
+ case CLOSE_FILE : \
+ JSVERIFY(SUCCEED, H5Fclose((id)), "closing file") \
+ break; \
+ case CLOSE_PLIST : \
+ JSVERIFY(SUCCEED, H5Pclose((id)), "closing plist") \
+ break; \
+ default: \
+ JSVERIFY(0, 1, "Unidentified MUST_CLOSE constant") \
+ break; \
+ } \
+ (id) = -1; \
+}
+
+
+/* ---------------------------------------------------------------------------
+ * Macro: PRINT_DSET_OH_COMPARISON(...)
+ *
+ * Pretty-print metadata information about two dataset object headers.
+ * ---------------------------------------------------------------------------
+ */
+#define PRINT_DSET_OH_COMPARISON(did1, did2) \
+{ H5O_info_t info1; \
+ H5O_info_t info2; \
+ \
+ FAIL_IF( SUCCEED != H5Oget_info2((did1), &info1, H5O_INFO_HDR) ) \
+ FAIL_IF( SUCCEED != H5Oget_info2((did2), &info2, H5O_INFO_HDR) ) \
+ \
+ HDprintf("\n==HEADERS== UNMINIMIZED MINIMIZED\n"); \
+ HDprintf(" version: %11u %9u\n", \
+ info1.hdr.version, \
+ info2.hdr.version); \
+ HDprintf(" # messages: %11u %9u\n", \
+ info1.hdr.nmesgs, \
+ info2.hdr.nmesgs); \
+ HDprintf(" meta: %11llu %9llu\n", \
+ info1.hdr.space.meta, \
+ info2.hdr.space.meta); \
+ HDprintf(" free: %11llu %9llu\n", \
+ info1.hdr.space.free, \
+ info2.hdr.space.free); \
+ HDprintf(" total: %11llu %9llu\n", \
+ info1.hdr.space.total, \
+ info2.hdr.space.total); \
+}
+
+/*********************
+ * UTILITY FUNCTIONS *
+ *********************/
+
+
+/* ---------------------------------------------------------------------------
+ * Function: make_file()
+ *
+ * Purpose: Create a file with the name, and record its hid in out parameter.
+ *
+ * Return: 0 (success) or -1 (failure)
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+make_file( \
+ const char *filename, \
+ hid_t *fid)
+{
+ hid_t id = -1;
+ id = H5Fcreate(
+ filename,
+ H5F_ACC_TRUNC,
+ H5P_DEFAULT,
+ H5P_DEFAULT);
+ if (id < 0)
+ return FAIL;
+ *fid = id;
+
+ return SUCCEED;
+} /* make_file */
+
+
+/* ---------------------------------------------------------------------------
+ * Function: make_dataset()
+ *
+ * Purpose: Create a dataset and record its hid in out parameter `dset_id`.
+ *
+ * Return: 0 (success) or -1 (failure)
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+make_dataset( \
+ hid_t loc_id, \
+ const char *name, \
+ hid_t datatype_id, \
+ hid_t dataspace_id, \
+ hid_t dcpl_id, \
+ hid_t *dset_id)
+{
+ hid_t id = -1;
+
+ id = H5Dcreate(
+ loc_id,
+ name,
+ datatype_id,
+ dataspace_id,
+ H5P_DEFAULT, /* LCPL id */
+ dcpl_id,
+ H5P_DEFAULT); /* DAPL id */
+ if (id < 0)
+ return FAIL;
+ *dset_id = id;
+
+ return SUCCEED;
+} /* make_dataset */
+
+
+/* ---------------------------------------------------------------------------
+ * Function: put_attribute()
+ *
+ * Purpose: Set an attribute with the given information.
+ *
+ * If the out parameter `attr_id` is negative, a new attribute will be
+ * created with the given information. Else, it will attempt to update the
+ * attribute with the new value.
+ *
+ * Return: 0 (success) or -1 (failure)
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+put_attribute( \
+ hid_t loc_id, \
+ const char *attrname, \
+ const void *attrvalue, \
+ hid_t datatype_id, \
+ hid_t dataspace_id, /* ignored if attribute_id >= 0 */ \
+ hid_t *attribute_id)
+{
+ if ((*attribute_id) < 0) {
+ hid_t id = -1;
+ id = H5Acreate(
+ loc_id,
+ attrname,
+ datatype_id,
+ dataspace_id,
+ H5P_DEFAULT, /* acpl */
+ H5P_DEFAULT); /* aapl */
+ if (id < 0)
+ return FAIL;
+ *attribute_id = id;
+ }
+ return H5Awrite(*attribute_id, datatype_id, attrvalue);
+} /* put_attribute */
+
+
+/* ---------------------------------------------------------------------------
+ * Function: count_attributes()
+ *
+ * Purpose: Count the number of attributes attached to an object.
+ *
+ * TODO: If the location id is that of a file, tries to count all the
+ * attributes present in the file.
+ *
+ * Return: -1 if an error occurred, else the number of attributes.
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+count_attributes(hid_t dset_id)
+{
+ H5O_info_t info;
+
+ if (0 > H5Oget_info(dset_id, &info, H5O_INFO_ALL))
+ return -1;
+ else
+ return (int)info.num_attrs; /* should never exceed int bounds */
+} /* count_attributes */
+
+
+/* ---------------------------------------------------------------------------
+ * Function: oh_compare()
+ *
+ * Purpose: Compare the TOTAL space used by datasets' object headers.
+ *
+ *
+ * Return: -1 if an error occurred, else positive #defined indicator value.
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+oh_compare( \
+ hid_t did1, \
+ hid_t did2)
+{
+ H5O_info_t info;
+ hsize_t space1 = 0;
+ hsize_t space2 = 0;
+
+ if (FAIL == H5Oget_info2(did1, &info, H5O_INFO_HDR))
+ return -1;
+ space1 = info.hdr.space.total;
+
+ if (FAIL == H5Oget_info2(did2, &info, H5O_INFO_HDR))
+ return -2;
+ space2 = info.hdr.space.total;
+
+ if (space1 < space2)
+ return LT;
+ else if (space1 > space2)
+ return GT;
+ else
+ return EQ;
+}
+
+/******************
+ * TEST FUNCTIONS *
+ ******************/
+
+
+/* ---------------------------------------------------------------------------
+ * Function: test_attribute_addition()
+ *
+ * Purpose: Demonstrate attribute addition to datasets.
+ *
+ * Return: 0 (pass) or 1 (failure)
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+test_attribute_addition(void)
+{
+ hid_t int_type_id = -1;
+ hid_t char_type_id = -1;
+ hid_t dcpl_id = -1;
+ hid_t dspace_id = -1;
+ hid_t dspace_scalar_id = -1;
+ hid_t dset_id = -1;
+ hid_t mindset_id = -1;
+ hid_t attr_1_id = -1;
+ hid_t attr_1a_id = -1;
+ hid_t attr_2_id = -1;
+ hid_t attr_2a_id = -1;
+ hid_t attr_3_id = -1;
+ hid_t attr_3a_id = -1;
+ hid_t file_id = -1;
+ hsize_t array_10[1] = {10}; /* dataspace extent */
+ char buffer[10] = ""; /* to inspect string attribute */
+ int a_out = 0;
+
+ TESTING("attribute additions to [un]minimized dataset")
+
+ /*********
+ * SETUP *
+ *********/
+
+ dspace_id = H5Screate_simple(
+ 1, /* rank */
+ array_10, /* current dimensions */
+ NULL); /* maximum dimensions */
+ FAIL_IF( 0 > dspace_id )
+
+ dspace_scalar_id = H5Screate(H5S_SCALAR);
+ FAIL_IF( 0 > dspace_scalar_id )
+
+ char_type_id = H5Tcopy(H5T_NATIVE_CHAR);
+ FAIL_IF( 0 > char_type_id )
+
+ int_type_id = H5Tcopy(H5T_NATIVE_INT);
+ FAIL_IF( 0 > int_type_id )
+
+ dcpl_id = H5Pcreate(H5P_DATASET_CREATE);
+ FAIL_IF( 0 > dcpl_id )
+ JSVERIFY( SUCCEED, \
+ H5Pset_dset_no_attrs_hint(dcpl_id, TRUE), \
+ "can't set DCPL to minimize object header")
+
+ JSVERIFY( SUCCEED, \
+ make_file( \
+ "ohdr_min_a.h5", \
+ &file_id), \
+ "unable to create file")
+
+ H5E_BEGIN_TRY {
+ JSVERIFY( -1, \
+ count_attributes(dset_id), \
+ "shouldn't be able to count missing dataset")
+ } H5E_END_TRY;
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_id, /* shorthand for root group? */ \
+ "dataset", \
+ int_type_id, \
+ dspace_id, \
+ H5P_DEFAULT, /* default DCPL */ \
+ &dset_id), \
+ "unable to create dataset")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_id, \
+ "mindataset", \
+ int_type_id, \
+ dspace_id, \
+ dcpl_id, \
+ &mindset_id), \
+ "unable to create minimizing dataset")
+
+ /********************
+ * TEST/DEMONSTRATE *
+ ********************/
+
+ /* -------------------
+ * no attributes added
+ */
+
+ JSVERIFY( 0, \
+ count_attributes(dset_id), \
+ NULL)
+ JSVERIFY( 0, \
+ count_attributes(mindset_id), \
+ NULL)
+
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(dset_id, mindset_id)
+
+ /* -----------------
+ * add one attribute
+ */
+
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ dset_id, \
+ "PURPOSE", \
+ "DEMO", \
+ char_type_id, \
+ dspace_id, \
+ &attr_1_id), \
+ "unable to set attribute 'PURPOSE:DEMO'")
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ mindset_id, \
+ "PURPOSE", \
+ "DEMO", \
+ char_type_id, \
+ dspace_id, \
+ &attr_1a_id), \
+ "unable to set attribute 'PURPOSE:DEMO'")
+
+ JSVERIFY( 1, \
+ count_attributes(dset_id), \
+ NULL)
+ JSVERIFY( 1, \
+ count_attributes(mindset_id), \
+ NULL)
+
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_1_id, char_type_id, buffer),
+ "can't read attribute 'PURPOSE'")
+ JSVERIFY_STR( "DEMO", buffer, NULL )
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_1a_id, char_type_id, buffer),
+ "can't read attribute 'PURPOSE'")
+ JSVERIFY_STR( "DEMO", buffer, NULL )
+
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(dset_id, mindset_id)
+
+ /* -----------------
+ * modify one attribute
+ */
+
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ dset_id, \
+ "PURPOSE", \
+ "REWRITE", \
+ char_type_id, \
+ -1, \
+ &attr_1_id), \
+ "unable to rewrite attribute 'PURPOSE:REWRITE'")
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ mindset_id, \
+ "PURPOSE", \
+ "REWRITE", \
+ char_type_id, \
+ -1, \
+ &attr_1a_id), \
+ "unable to rewrite attribute 'PURPOSE:REWRITE'")
+
+ JSVERIFY( 1, \
+ count_attributes(dset_id), \
+ NULL)
+ JSVERIFY( 1, \
+ count_attributes(mindset_id), \
+ NULL)
+
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_1_id, char_type_id, buffer),
+ "can't read attribute 'PURPOSE'")
+ JSVERIFY_STR( "REWRITE", buffer, NULL )
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_1a_id, char_type_id, buffer),
+ "can't read attribute 'PURPOSE'")
+ JSVERIFY_STR( "REWRITE", buffer, NULL )
+
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(dset_id, mindset_id)
+
+ /* -----------------
+ * add second attribute
+ */
+
+ a_out = 5;
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ dset_id, \
+ "RANK", \
+ &a_out, \
+ int_type_id, \
+ dspace_scalar_id, \
+ &attr_2_id), \
+ "unable to set attribute 'RANK:5'")
+ a_out = 3;
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ mindset_id, \
+ "RANK", \
+ &a_out, \
+ int_type_id, \
+ dspace_scalar_id, \
+ &attr_2a_id), \
+ "unable to set attribute (minimized) 'RANK:3'")
+
+ JSVERIFY( 2, \
+ count_attributes(dset_id), \
+ NULL)
+ JSVERIFY( 2, \
+ count_attributes(mindset_id), \
+ NULL)
+
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_2_id, int_type_id, &a_out),
+ "can't read attribute 'RANK'")
+ JSVERIFY( 5, a_out, NULL )
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_2a_id, int_type_id, &a_out),
+ "can't read attribute (minimized) 'RANK'")
+ JSVERIFY( 3, a_out, NULL )
+
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(dset_id, mindset_id)
+
+ /* -----------------
+ * add third attribute
+ */
+
+ a_out = -86;
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ dset_id, \
+ "FLAVOR", \
+ &a_out, \
+ int_type_id, \
+ dspace_scalar_id, \
+ &attr_3_id), \
+ "unable to set attribute 'FLAVOR:-86'")
+ a_out = 2185;
+ JSVERIFY( SUCCEED, \
+ put_attribute( \
+ mindset_id, \
+ "FLAVOR", \
+ &a_out, \
+ int_type_id, \
+ dspace_scalar_id, \
+ &attr_3a_id), \
+ "unable to set attribute (minimized) 'FLAVOR:2185'")
+
+ JSVERIFY( 3, \
+ count_attributes(dset_id), \
+ NULL)
+ JSVERIFY( 3, \
+ count_attributes(mindset_id), \
+ NULL)
+
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_3_id, int_type_id, &a_out),
+ "can't read attribute 'RANK'")
+ JSVERIFY( -86, a_out, NULL )
+ JSVERIFY( SUCCEED,
+ H5Aread(attr_3a_id, int_type_id, &a_out),
+ "can't read attribute (minimized) 'RANK'")
+ JSVERIFY( 2185, a_out, NULL )
+
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(dset_id, mindset_id)
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ MUST_CLOSE(int_type_id, CLOSE_DATATYPE)
+ MUST_CLOSE(char_type_id, CLOSE_DATATYPE)
+ MUST_CLOSE(dcpl_id, CLOSE_PLIST)
+ MUST_CLOSE(dspace_id, CLOSE_DATASPACE)
+ MUST_CLOSE(dset_id, CLOSE_DATASET)
+ MUST_CLOSE(mindset_id, CLOSE_DATASET)
+ MUST_CLOSE(attr_1_id, CLOSE_ATTRIBUTE)
+ MUST_CLOSE(attr_1a_id, CLOSE_ATTRIBUTE)
+ MUST_CLOSE(attr_2_id, CLOSE_ATTRIBUTE)
+ MUST_CLOSE(attr_2a_id, CLOSE_ATTRIBUTE)
+ MUST_CLOSE(attr_3_id, CLOSE_ATTRIBUTE)
+ MUST_CLOSE(attr_3a_id, CLOSE_ATTRIBUTE)
+ MUST_CLOSE(file_id, CLOSE_FILE)
+
+ PASSED()
+ return 0;
+
+error :
+ H5E_BEGIN_TRY {
+ (void)H5Tclose(int_type_id);
+ (void)H5Tclose(char_type_id);
+ (void)H5Pclose(dcpl_id);
+ (void)H5Sclose(dspace_id);
+ (void)H5Dclose(dset_id);
+ (void)H5Dclose(mindset_id);
+ (void)H5Aclose(attr_1_id);
+ (void)H5Aclose(attr_1a_id);
+ (void)H5Aclose(attr_2_id);
+ (void)H5Aclose(attr_2a_id);
+ (void)H5Aclose(attr_3_id);
+ (void)H5Aclose(attr_3a_id);
+ (void)H5Fclose(file_id);
+ } H5E_END_TRY;
+ return 1;
+} /* test_attribute_addition */
+
+
+/* ---------------------------------------------------------------------------
+ * Function: test_size_comparisons()
+ *
+ * Purpose: Examine when headers have been minimized.
+ *
+ * Return: 0 (pass) or 1 (failure)
+ *
+ * ---------------------------------------------------------------------------
+ */
+static int
+test_size_comparisons(void)
+{
+ hsize_t array_10[1] = {10}; /* dataspace extents */
+
+ /* IDs that are file-agnostic */
+ hid_t dspace_id = -1;
+ hid_t int_type_id = -1;
+ hid_t dcpl_minimize = -1;
+ hid_t dcpl_dontmin = -1;
+
+ /* IDs for non-minimzed file open */
+ hid_t file_f_id = -1; /* lower 'f' for standard file setting */
+ hid_t dset_f_x_id = -1; /* 'x' for default */
+ hid_t dset_f_N_id = -1; /* 'N' for explcit non-minimized dset */
+ hid_t dset_f_Y_id = -1; /* 'Y' for minimzed dset */
+
+ /* IDs for minimzed file open */
+ hid_t file_F_id = -1; /* upper 'F' for minimzed file setting */
+ hid_t dset_F_x_id = -1; /* 'x' for default */
+ hid_t dset_F_N_id = -1; /* 'N' for explcit non-minimized dset */
+ hid_t dset_F_Y_id = -1; /* 'Y' for minimzed dset */
+
+ TESTING("size comparisons");
+
+ /*********
+ * SETUP *
+ *********/
+
+ dcpl_minimize = H5Pcreate(H5P_DATASET_CREATE);
+ FAIL_IF( 0 > dcpl_minimize )
+ JSVERIFY( SUCCEED,
+ H5Pset_dset_no_attrs_hint(dcpl_minimize, TRUE),
+ NULL )
+
+ dcpl_dontmin = H5Pcreate(H5P_DATASET_CREATE);
+ FAIL_IF( 0 > dcpl_dontmin )
+ JSVERIFY( SUCCEED,
+ H5Pset_dset_no_attrs_hint(dcpl_dontmin, FALSE),
+ NULL )
+
+ dspace_id = H5Screate_simple(
+ 1, /* rank */
+ array_10, /* current dimensions */
+ NULL); /* maximum dimensions */
+ FAIL_IF( 0 > dspace_id )
+
+ int_type_id = H5Tcopy(H5T_NATIVE_INT);
+ FAIL_IF( 0 > int_type_id )
+
+ JSVERIFY( SUCCEED, \
+ make_file( \
+ "ohdr_min_a.h5", \
+ &file_f_id), \
+ "unable to create file 'ohdr_min_a.h5'")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_f_id, \
+ "default", \
+ int_type_id, \
+ dspace_id, \
+ H5P_DEFAULT, \
+ &dset_f_x_id), \
+ "unable to create dataset fx")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_f_id, \
+ "dsetNOT", \
+ int_type_id, \
+ dspace_id, \
+ dcpl_dontmin, \
+ &dset_f_N_id), \
+ "unable to create dataset fN")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_f_id, \
+ "dsetMIN", \
+ int_type_id, \
+ dspace_id, \
+ dcpl_minimize, \
+ &dset_f_Y_id), \
+ "unable to create dataset fY")
+
+ JSVERIFY( SUCCEED, \
+ make_file( \
+ "ohdr_min_b.h5", \
+ &file_F_id), \
+ "unable to create file 'ohdr_min_b.h5'")
+ FAIL_IF( 0 > H5Fset_dset_no_attrs_hint(file_F_id, TRUE) )
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_F_id, \
+ "default", \
+ int_type_id, \
+ dspace_id, \
+ H5P_DEFAULT, \
+ &dset_F_x_id), \
+ "unable to create dataset Fx")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_F_id, \
+ "dsetNOT", \
+ int_type_id, \
+ dspace_id, \
+ dcpl_dontmin, \
+ &dset_F_N_id), \
+ "unable to create dataset FN")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_F_id, \
+ "dsetMIN", \
+ int_type_id, \
+ dspace_id, \
+ dcpl_minimize, \
+ &dset_F_Y_id), \
+ "unable to create dataset FY")
+
+ /*********
+ * TESTS *
+ *********/
+
+ JSVERIFY( EQ, oh_compare(dset_f_x_id, dset_f_x_id), NULL ) /* identity */
+
+ JSVERIFY( EQ, oh_compare(dset_f_x_id, dset_f_N_id), NULL )
+ JSVERIFY( GT, oh_compare(dset_f_x_id, dset_f_Y_id), NULL )
+ JSVERIFY( GT, oh_compare(dset_f_N_id, dset_f_Y_id), NULL )
+
+ JSVERIFY( EQ, oh_compare(dset_F_x_id, dset_F_N_id), NULL )
+ JSVERIFY( EQ, oh_compare(dset_F_x_id, dset_F_Y_id), NULL )
+ JSVERIFY( EQ, oh_compare(dset_F_N_id, dset_F_Y_id), NULL )
+
+ JSVERIFY( EQ, oh_compare(dset_F_x_id, dset_f_Y_id), NULL )
+ JSVERIFY( LT, oh_compare(dset_F_x_id, dset_f_x_id), NULL )
+
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(dset_f_x_id, dset_F_x_id)
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ MUST_CLOSE(dspace_id, CLOSE_DATASPACE)
+ MUST_CLOSE(int_type_id, CLOSE_DATATYPE)
+ MUST_CLOSE(dcpl_minimize, CLOSE_PLIST)
+ MUST_CLOSE(dcpl_dontmin, CLOSE_PLIST)
+
+ MUST_CLOSE(file_f_id, CLOSE_FILE)
+ MUST_CLOSE(dset_f_x_id, CLOSE_DATASET)
+ MUST_CLOSE(dset_f_N_id, CLOSE_DATASET)
+ MUST_CLOSE(dset_f_Y_id, CLOSE_DATASET)
+
+ MUST_CLOSE(file_F_id, CLOSE_FILE)
+ MUST_CLOSE(dset_F_x_id, CLOSE_DATASET)
+ MUST_CLOSE(dset_F_N_id, CLOSE_DATASET)
+ MUST_CLOSE(dset_F_Y_id, CLOSE_DATASET)
+
+ PASSED()
+ return 0;
+
+error :
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(dcpl_minimize);
+ (void)H5Pclose(dcpl_dontmin);
+ (void)H5Sclose(dspace_id);
+ (void)H5Tclose(int_type_id);
+
+ (void)H5Fclose(file_f_id);
+ (void)H5Dclose(dset_f_x_id);
+ (void)H5Dclose(dset_f_N_id);
+ (void)H5Dclose(dset_f_Y_id);
+
+ (void)H5Fclose(file_F_id);
+ (void)H5Dclose(dset_F_x_id);
+ (void)H5Dclose(dset_F_N_id);
+ (void)H5Dclose(dset_F_Y_id);
+ } H5E_END_TRY;
+ return 1;
+} /* test_size_comparisons */
+
+
+/* ---------------------------------------------------------------------------
+ * Test minimized dataset header with filter/pipeline message
+ * ---------------------------------------------------------------------------
+ */
+static int
+test_minimized_with_filter(void)
+{
+ hid_t dspace_id = -1;
+ hid_t dtype_id = -1;
+ hid_t fdcpl_id = -1;
+ hid_t mindcpl_id = -1;
+ hid_t minfdcpl_id = -1;
+ hid_t dset_id = -1;
+ hid_t fdset_id = -1;
+ hid_t mindset_id = -1;
+ hid_t minfdset_id = -1;
+ hid_t file_id = -1;
+ hsize_t extents[1] = {10};
+ unsigned filter_values[] = {0};
+ const hsize_t chunk_dim[] = {2};
+
+/* | default | minimize
+ * ----------+---------+---------
+ * no filter | dset | mindset
+ * ----------+---------+---------
+ * filter | fdset | minfdset
+ */
+
+ TESTING("minimized header with filter message");
+
+ /*********
+ * SETUP *
+ *********/
+
+ mindcpl_id = H5Pcreate(H5P_DATASET_CREATE);
+ FAIL_IF( 0 > mindcpl_id )
+ JSVERIFY( SUCCEED,
+ H5Pset_dset_no_attrs_hint(mindcpl_id, TRUE),
+ NULL )
+
+ fdcpl_id = H5Pcreate(H5P_DATASET_CREATE);
+ FAIL_IF( 0 > fdcpl_id )
+ JSVERIFY( SUCCEED,
+ H5Pset_chunk(fdcpl_id, 1, chunk_dim),
+ "unable to chunk dataset")
+ JSVERIFY( SUCCEED,
+ H5Pset_filter(
+ fdcpl_id,
+ H5Z_FILTER_DEFLATE,
+ H5Z_FLAG_OPTIONAL,
+ 0,
+ filter_values),
+ "unable to set compression")
+
+ minfdcpl_id = H5Pcreate(H5P_DATASET_CREATE);
+ FAIL_IF( 0 > minfdcpl_id )
+ JSVERIFY( SUCCEED,
+ H5Pset_dset_no_attrs_hint(minfdcpl_id, TRUE),
+ "unable to minimize to-be-filtered dataset header")
+ JSVERIFY( SUCCEED,
+ H5Pset_chunk(minfdcpl_id, 1, chunk_dim),
+ "unable to chunk minimized dataset")
+ JSVERIFY( SUCCEED,
+ H5Pset_filter(
+ minfdcpl_id,
+ H5Z_FILTER_DEFLATE,
+ H5Z_FLAG_OPTIONAL,
+ 0,
+ filter_values),
+ "unable to set compression (minimized)")
+
+ dspace_id = H5Screate_simple(1, extents, extents);
+ FAIL_IF( 0 > dspace_id )
+
+ dtype_id = H5Tcopy(H5T_NATIVE_INT);
+ FAIL_IF( 0 > dtype_id )
+
+ JSVERIFY( SUCCEED, \
+ make_file( \
+ "ohdr_min_a.h5", \
+ &file_id), \
+ "unable to create file 'ohdr_min_a.h5'")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_id, \
+ "dset", \
+ dtype_id, \
+ dspace_id, \
+ H5P_DEFAULT, \
+ &dset_id), \
+ "unable to create dataset fx")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_id, \
+ "mindset", \
+ dtype_id, \
+ dspace_id, \
+ mindcpl_id, \
+ &mindset_id), \
+ "unable to create dataset (minoh)")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_id, \
+ "gzipdset", \
+ dtype_id, \
+ dspace_id, \
+ fdcpl_id, \
+ &fdset_id), \
+ "unable to create dataset (gzip)")
+
+ JSVERIFY( SUCCEED, \
+ make_dataset( \
+ file_id, \
+ "mingzipdset", \
+ dtype_id, \
+ dspace_id, \
+ fdcpl_id, \
+ &minfdset_id), \
+ "unable to create dataset (minimized, gzip)")
+
+ /*********
+ * TESTS *
+ *********/
+
+ JSVERIFY( LT, oh_compare(mindset_id, dset_id), NULL )
+ JSVERIFY( LT, oh_compare(mindset_id, fdset_id), NULL )
+ JSVERIFY( GT, oh_compare(minfdset_id, mindset_id), NULL )
+ JSVERIFY( EQ, oh_compare(minfdset_id, fdset_id), NULL ) /* TODO: why are these equal? */
+
+#if 1
+ if (DEBUG_OH_SIZE)
+ PRINT_DSET_OH_COMPARISON(fdset_id, minfdset_id)
+#endif
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ MUST_CLOSE(dspace_id, CLOSE_DATASPACE)
+ MUST_CLOSE(dtype_id, CLOSE_DATATYPE)
+ MUST_CLOSE(fdcpl_id, CLOSE_PLIST)
+ MUST_CLOSE(mindcpl_id, CLOSE_PLIST)
+ MUST_CLOSE(minfdcpl_id, CLOSE_PLIST)
+ MUST_CLOSE(dset_id, CLOSE_DATASET)
+ MUST_CLOSE(fdset_id, CLOSE_DATASET)
+ MUST_CLOSE(mindset_id, CLOSE_DATASET)
+ MUST_CLOSE(minfdset_id, CLOSE_DATASET)
+ MUST_CLOSE(file_id, CLOSE_FILE)
+
+ PASSED()
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ (void)H5Sclose(dspace_id);
+ (void)H5Tclose(dtype_id);
+ (void)H5Pclose(fdcpl_id);
+ (void)H5Pclose(mindcpl_id);
+ (void)H5Pclose(minfdcpl_id);
+ (void)H5Dclose(dset_id);
+ (void)H5Dclose(fdset_id);
+ (void)H5Dclose(mindset_id);
+ (void)H5Dclose(minfdset_id);
+ (void)H5Fclose(file_id);
+ } H5E_END_TRY;
+ return 1;
+} /* test_minimized_with_filter */
+
+/********
+ * MAIN *
+ ********/
+
+
+/* ---------------------------------------------------------------------------
+ * Main function is main. Runs tests.
+ * ---------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ int nerrors = 0;
+
+ HDprintf("Testing minimized dataset object headers.\n");
+
+ nerrors += test_attribute_addition();
+ nerrors += test_size_comparisons();
+ nerrors += test_minimized_with_filter();
+/* TODO: external file links */
+/* TODO: modification times */
+/* TODO: fill value + "backwards compatability" */
+
+ if (nerrors > 0) {
+ HDprintf("***** %d MINIMIZED DATASET OHDR TEST%s FAILED! *****\n",
+ nerrors,
+ nerrors > 1 ? "S" : "");
+ } else {
+ HDprintf("All minimized dataset object header tests passed.\n");
+ }
+
+ return nerrors;
+} /* main */
+
+