summaryrefslogtreecommitdiffstats
path: root/test/ros3.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/ros3.c')
-rw-r--r--test/ros3.c1937
1 files changed, 1937 insertions, 0 deletions
diff --git a/test/ros3.c b/test/ros3.c
new file mode 100644
index 0000000..73b6ac2
--- /dev/null
+++ b/test/ros3.c
@@ -0,0 +1,1937 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Read-Only S3 Virtual File Driver (VFD)
+ *
+ * Purpose:
+ *
+ * Verify behavior for Read-Only S3 VFD
+ * at the VFL (virtual file layer) level.
+ *
+ * Demonstrates basic use cases and fapl/dxpl interaction.
+ *
+ * Programmer: Jacob Smith <jake.smith@hdfgroup.org>
+ * 2017-10-11
+ */
+
+#include "h5test.h"
+
+#include "H5FDprivate.h" /* Virtual File Driver utilities */
+#include "H5FDros3.h" /* this file driver's utilities */
+#include "H5FDs3comms.h" /* for loading of credentials */
+
+#ifdef H5_HAVE_ROS3_VFD
+
+/* only include the testing macros if needed */
+
+/*****************************************************************************
+ *
+ * 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
+
+
+/*----------------------------------------------------------------------------
+ *
+ * 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 not defined
+ *
+ * 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 /* ifdef/else JSVERIFY_EXP_ACT */
+
+/********************************
+ * OTHER MACROS AND DEFINITIONS *
+ ********************************/
+
+#define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
+
+#define S3_TEST_PROFILE_NAME "ros3_vfd_test"
+
+#define S3_TEST_MAX_URL_SIZE 256
+
+#define S3_TEST_RESOURCE_TEXT_RESTRICTED "t8.shakespeare.txt"
+#define S3_TEST_RESOURCE_TEXT_PUBLIC "Poe_Raven.txt"
+#define S3_TEST_RESOURCE_H5_PUBLIC "GMODO-SVM01.h5"
+#define S3_TEST_RESOURCE_MISSING "missing.csv"
+
+static char url_text_restricted[S3_TEST_MAX_URL_SIZE] = "";
+static char url_text_public[S3_TEST_MAX_URL_SIZE] = "";
+static char url_h5_public[S3_TEST_MAX_URL_SIZE] = "";
+static char url_missing[S3_TEST_MAX_URL_SIZE] = "";
+static char s3_test_bucket_url[S3_TEST_MAX_URL_SIZE] = "";
+static hbool_t s3_test_bucket_defined = FALSE;
+
+/* Global variables for aws test profile.
+ * An attempt is made to read ~/.aws/credentials and ~/.aws/config upon test
+ * startup -- if unable to open either file or cannot load region, id, and key,
+ * tests connecting with S3 will not be run
+ */
+static int s3_test_credentials_loaded = 0;
+static char s3_test_aws_region[16];
+static char s3_test_aws_access_key_id[64];
+static char s3_test_aws_secret_access_key[128];
+
+H5FD_ros3_fapl_t restricted_access_fa = {
+ H5FD_CURR_ROS3_FAPL_T_VERSION, /* fapl version */
+ TRUE, /* authenticate */
+ "", /* aws region */
+ "", /* access key id */
+ ""}; /* secret access key */
+
+H5FD_ros3_fapl_t anonymous_fa = {
+ H5FD_CURR_ROS3_FAPL_T_VERSION,
+ FALSE, "", "", "" };
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_fapl_config_validation()
+ *
+ * Purpose:
+ *
+ * Test data consistency of fapl configuration.
+ * Tests `H5FD_ros3_validate_config` indirectly through `H5Pset_fapl_ros3`.
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_fapl_config_validation(void)
+{
+
+ /*********************
+ * test-local macros *
+ *********************/
+
+ /*************************
+ * test-local structures *
+ *************************/
+
+ struct testcase {
+ const char *msg;
+ herr_t expected;
+ H5FD_ros3_fapl_t config;
+ };
+
+ /************************
+ * test-local variables *
+ ************************/
+
+ hid_t fapl_id = -1; /* file access property list ID */
+ H5FD_ros3_fapl_t config;
+ H5FD_ros3_fapl_t fa_fetch;
+ herr_t success = SUCCEED;
+ unsigned int i = 0;
+ unsigned int ncases = 8; /* should equal number of cases */
+ struct testcase *case_ptr = NULL; /* dumb work-around for possible */
+ /* dynamic cases creation because */
+ /* of compiler warnings Wlarger-than */
+ struct testcase cases_arr[] = {
+ { "non-authenticating config allows empties.\n",
+ SUCCEED,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION, /* version */
+ FALSE, /* authenticate */
+ "", /* aws_region */
+ "", /* secret_id */
+ "", /* secret_key */
+ },
+ },
+ { "authenticating config asks for populated strings.\n",
+ FAIL,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION,
+ TRUE,
+ "",
+ "",
+ "",
+ },
+ },
+ { "populated strings; key is the empty string?\n",
+ SUCCEED,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION,
+ TRUE,
+ "region",
+ "me",
+ "",
+ },
+ },
+ { "id cannot be empty.\n",
+ FAIL,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION,
+ TRUE,
+ "",
+ "me",
+ "",
+ },
+ },
+ { "region cannot be empty.\n",
+ FAIL,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION,
+ TRUE,
+ "where",
+ "",
+ "",
+ },
+ },
+ { "all strings populated.\n",
+ SUCCEED,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION,
+ TRUE,
+ "where",
+ "who",
+ "thisIsA GREAT seeeecrit",
+ },
+ },
+ { "incorrect version should fail\n",
+ FAIL,
+ { 12345,
+ FALSE,
+ "",
+ "",
+ "",
+ },
+ },
+ { "non-authenticating config cares not for (de)population"
+ "of strings.\n",
+ SUCCEED,
+ { H5FD_CURR_ROS3_FAPL_T_VERSION,
+ FALSE,
+ "someregion",
+ "someid",
+ "somekey",
+ },
+ },
+ };
+
+ TESTING("ROS3 fapl configuration validation");
+
+ /*********
+ * TESTS *
+ *********/
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ for (i = 0; i < ncases; i++) {
+
+ /*---------------
+ * per-test setup
+ *---------------
+ */
+ case_ptr = &cases_arr[i];
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_id < 0 ) /* sanity-check */
+
+ /*-----------------------------------
+ * Actually test.
+ * Mute stack trace in failure cases.
+ *-----------------------------------
+ */
+ H5E_BEGIN_TRY {
+ /* `H5FD_ros3_validate_config(...)` is static/private
+ * to src/ros3.c and cannot (and should not?) be tested directly?
+ * Instead, validate config through public api.
+ */
+ success = H5Pset_fapl_ros3(fapl_id, &case_ptr->config);
+ } H5E_END_TRY;
+
+ JSVERIFY( case_ptr->expected, success, case_ptr->msg )
+
+ /* Make sure we can get back what we put in.
+ * Only valid if the fapl configuration does not result in error.
+ */
+ if (success == SUCCEED) {
+ config = case_ptr->config;
+ JSVERIFY( SUCCEED,
+ H5Pget_fapl_ros3(fapl_id, &fa_fetch),
+ "unable to get fapl" )
+
+ JSVERIFY( H5FD_CURR_ROS3_FAPL_T_VERSION,
+ fa_fetch.version,
+ "invalid version number" )
+ JSVERIFY( config.version,
+ fa_fetch.version,
+ "version number mismatch" )
+ JSVERIFY( config.authenticate,
+ fa_fetch.authenticate,
+ "authentication flag mismatch" )
+ JSVERIFY_STR( config.aws_region,
+ fa_fetch.aws_region,
+ NULL )
+ JSVERIFY_STR( config.secret_id,
+ fa_fetch.secret_id,
+ NULL )
+ JSVERIFY_STR( config.secret_key,
+ fa_fetch.secret_key,
+ NULL )
+ }
+
+ /*-----------------------------
+ * per-test sanitation/teardown
+ *-----------------------------
+ */
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ } /* for each test case */
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (fapl_id < 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+ return 1;
+} /* test_fapl_config_validation */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: test_ros3_fapl()
+ *
+ * Purpose: Tests the file handle interface for the ROS3 driver
+ *
+ * As the ROS3 driver is 1) read only, 2) requires access
+ * to an S3 server, this test is quite
+ * different from the other tests.
+ *
+ * For now, test only fapl & flags. Extend as the
+ * work on the VFD continues.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: John Mainzer
+ * 7/12/17
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_ros3_fapl(void)
+{
+ /************************
+ * test-local variables *
+ ************************/
+
+ hid_t fapl_id = -1; /* file access property list ID */
+ hid_t driver_id = -1; /* ID for this VFD */
+ unsigned long driver_flags = 0; /* VFD feature flags */
+ H5FD_ros3_fapl_t ros3_fa_0 = {
+ H5FD_CURR_ROS3_FAPL_T_VERSION, /* version */
+ FALSE, /* authenticate */
+ "", /* aws_region */
+ "", /* secret_id */
+ "plugh", /* secret_key */
+ };
+
+ TESTING("ROS3 fapl ");
+
+ /* Set property list and file name for ROS3 driver.
+ */
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_id < 0 )
+
+ FAIL_IF( FAIL == H5Pset_fapl_ros3(fapl_id, &ros3_fa_0) )
+
+ driver_id = H5Pget_driver(fapl_id);
+ FAIL_IF( driver_id < 0 )
+
+ /****************
+ * Check that the VFD feature flags are correct
+ * SPEC MAY CHANGE
+ ******************/
+
+ FAIL_IF( H5FDdriver_query(driver_id, &driver_flags) < 0 )
+
+ JSVERIFY_NOT( 0, (driver_flags & H5FD_FEAT_DATA_SIEVE),
+ "bit(s) in `driver_flags` must align with "
+ "H5FD_FEAT_DATA_SIEVE" )
+
+ JSVERIFY( H5FD_FEAT_DATA_SIEVE, driver_flags,
+ "H5FD_FEAT_DATA_SIEVE should be the only supported flag")
+
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+
+ return 1;
+
+} /* test_ros3_fapl() */
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_vfd_open()
+ *
+ * Purpose:
+ *
+ * Demonstrate/specify VFD-level "Open" failure cases
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 1027-11-03
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_vfd_open(void)
+{
+
+ /*********************
+ * test-local macros *
+ *********************/
+
+
+#define FAPL_H5P_DEFAULT -2
+#define FAPL_FILE_ACCESS -3
+#define FAPL_ROS3_ANON -4
+
+ /*************************
+ * test-local structures *
+ *************************/
+
+ struct test_condition {
+ const char *message;
+ const char *url;
+ unsigned flags;
+ int which_fapl;
+ haddr_t maxaddr;
+ };
+
+ /************************
+ * test-local variables *
+ ************************/
+
+ struct test_condition tests[] = {
+ { "default property list (H5P_DEFAULT) is invalid",
+ url_text_public,
+ H5F_ACC_RDONLY,
+ FAPL_H5P_DEFAULT,
+ MAXADDR,
+ },
+ { "generic file access property list is invalid",
+ url_text_public,
+ H5F_ACC_RDONLY,
+ FAPL_FILE_ACCESS,
+ MAXADDR,
+ },
+ { "filename cannot be null",
+ NULL,
+ H5F_ACC_RDONLY,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "filename cannot be empty",
+ "",
+ H5F_ACC_RDONLY,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "filename must exist",
+ url_missing,
+ H5F_ACC_RDONLY,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "read-write flag not supported",
+ url_text_public,
+ H5F_ACC_RDWR,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "truncate flag not supported",
+ url_text_public,
+ H5F_ACC_TRUNC,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "create flag not supported",
+ url_text_public,
+ H5F_ACC_CREAT,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "EXCL flag not supported",
+ url_text_public,
+ H5F_ACC_EXCL,
+ FAPL_ROS3_ANON,
+ MAXADDR,
+ },
+ { "maxaddr cannot be 0 (caught in `H5FD_open()`)",
+ url_text_public,
+ H5F_ACC_RDONLY,
+ FAPL_ROS3_ANON,
+ 0,
+ },
+ };
+ H5FD_t *fd = NULL;
+ hbool_t curl_ready = FALSE;
+ hid_t fapl_id = -1;
+ hid_t fapl_file_access = -1;
+ unsigned i = 0;
+ unsigned tests_count = 10;
+
+ TESTING("ROS3 VFD-level open");
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ FAIL_IF( CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT) )
+ curl_ready = TRUE;
+
+ fapl_file_access = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_file_access < 0 )
+
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_id < 0 )
+ FAIL_IF( FAIL == H5Pset_fapl_ros3(fapl_id, &anonymous_fa) )
+
+ /*********
+ * TESTS *
+ *********/
+
+ /* all the test cases that will _not_ open
+ */
+ for (i = 0; i < tests_count; i++) {
+ struct test_condition T = tests[i];
+ hid_t _fapl_id = H5P_DEFAULT;
+
+ fd = NULL;
+
+ if (T.which_fapl == FAPL_FILE_ACCESS)
+ _fapl_id = fapl_file_access;
+ else if (T.which_fapl == FAPL_ROS3_ANON)
+ _fapl_id = fapl_id;
+
+ H5E_BEGIN_TRY {
+ fd = H5FDopen(T.url, T.flags, _fapl_id, T.maxaddr);
+ } H5E_END_TRY;
+ if (NULL != fd)
+ JSVERIFY(1, 0, T.message); /* wrapper to print message and fail */
+ }
+
+ FAIL_IF( NULL != fd )
+
+ /* finally, show that a file can be opened
+ */
+ fd = H5FDopen(
+ url_text_public,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ MAXADDR);
+ FAIL_IF( NULL == fd )
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5FDclose(fd) )
+ fd = NULL;
+
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ FAIL_IF( FAIL == H5Pclose(fapl_file_access) )
+ fapl_file_access = -1;
+
+ curl_global_cleanup();
+ curl_ready = FALSE;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (fd) {
+ (void)H5FDclose(fd);
+ }
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+ if (fapl_file_access >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_file_access);
+ } H5E_END_TRY;
+ }
+ if (curl_ready == TRUE) {
+ curl_global_cleanup();
+ }
+
+ return 1;
+
+#undef FAPL_FILE_ACCESS
+#undef FAPL_H5P_DEFAULT
+#undef FAPL_ROS3_ANON
+
+} /* test_vfd_open */
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_eof_eoa()
+ *
+ * Purpose:
+ *
+ * Demonstrate behavior of get_eof, get_eoa, and set_eoa.
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-08
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_eof_eoa(void)
+{
+
+ /*********************
+ * test-local macros *
+ *********************/
+
+ /*************************
+ * test-local structures *
+ *************************/
+
+ /************************
+ * test-local variables *
+ ************************/
+
+ H5FD_t *fd_shakespeare = NULL;
+ hbool_t curl_ready = FALSE;
+ hid_t fapl_id = -1;
+
+ TESTING("ROS3 eof/eoa gets and sets");
+
+ if (s3_test_credentials_loaded == 0) {
+ SKIPPED();
+ puts(" s3 credentials are not loaded");
+ fflush(stdout);
+ return 0;
+ }
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ /*********
+ * SETUP *
+ *********/
+
+ FAIL_IF( CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT) )
+ curl_ready = TRUE;
+
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( 0 > fapl_id )
+ FAIL_IF( FAIL == H5Pset_fapl_ros3(fapl_id, &restricted_access_fa) )
+
+ fd_shakespeare = H5FDopen(
+ url_text_restricted,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ HADDR_UNDEF);
+ FAIL_IF( NULL == fd_shakespeare )
+
+ /*********
+ * TESTS *
+ *********/
+
+ /* verify as found
+ */
+ JSVERIFY( 5458199, H5FDget_eof(fd_shakespeare, H5FD_MEM_DEFAULT), NULL )
+ JSVERIFY( H5FDget_eof(fd_shakespeare, H5FD_MEM_DEFAULT),
+ H5FDget_eof(fd_shakespeare, H5FD_MEM_DRAW),
+ "mismatch between DEFAULT and RAW memory types" )
+ JSVERIFY( 0,
+ H5FDget_eoa(fd_shakespeare, H5FD_MEM_DEFAULT),
+ "EoA should be unset by H5FDopen" )
+
+ /* set EoA below EoF
+ */
+ JSVERIFY( SUCCEED,
+ H5FDset_eoa(fd_shakespeare, H5FD_MEM_DEFAULT, 44442202),
+ "unable to set EoA (lower)" )
+ JSVERIFY( 5458199,
+ H5FDget_eof(fd_shakespeare, H5FD_MEM_DEFAULT),
+ "EoF changed" )
+ JSVERIFY( 44442202,
+ H5FDget_eoa(fd_shakespeare, H5FD_MEM_DEFAULT),
+ "EoA unchanged" )
+
+ /* set EoA above EoF
+ */
+ JSVERIFY( SUCCEED,
+ H5FDset_eoa(fd_shakespeare, H5FD_MEM_DEFAULT, 6789012),
+ "unable to set EoA (higher)" )
+ JSVERIFY( 5458199,
+ H5FDget_eof(fd_shakespeare, H5FD_MEM_DEFAULT),
+ "EoF changed" )
+ JSVERIFY( 6789012,
+ H5FDget_eoa(fd_shakespeare, H5FD_MEM_DEFAULT),
+ "EoA unchanged" )
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5FDclose(fd_shakespeare) )
+
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ curl_global_cleanup();
+ curl_ready = FALSE;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (fd_shakespeare) (void)H5FDclose(fd_shakespeare);
+ if (TRUE == curl_ready) curl_global_cleanup();
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+
+ return 1;
+
+} /* test_eof_eoa */
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * Function: test_H5FDread_without_eoa_set_fails()
+ *
+ * Purpose:
+ *
+ * Demonstrate a not-obvious constraint by the library, preventing
+ * file read before EoA is set
+ *
+ * Programmer: Jacob Smith
+ * 2018-01-26
+ *
+ *-----------------------------------------------------------------------------
+ */
+static int
+test_H5FDread_without_eoa_set_fails(void)
+{
+ char buffer[256];
+ unsigned int i = 0;
+ H5FD_t *file_shakespeare = NULL;
+ hid_t fapl_id = -1;
+
+ TESTING("ROS3 VFD read-eoa temporal coupling library limitation ");
+
+ if (s3_test_credentials_loaded == 0) {
+ SKIPPED();
+ puts(" s3 credentials are not loaded");
+ fflush(stdout);
+ return 0;
+ }
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ /*********
+ * SETUP *
+ *********/
+
+ /* create ROS3 fapl
+ */
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_id < 0 )
+ FAIL_IF( FAIL == H5Pset_fapl_ros3(fapl_id, &restricted_access_fa) )
+
+ file_shakespeare = H5FDopen(
+ url_text_restricted,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ MAXADDR);
+ FAIL_IF( NULL == file_shakespeare )
+
+ JSVERIFY( 0, H5FDget_eoa(file_shakespeare, H5FD_MEM_DEFAULT),
+ "EoA should remain unset by H5FDopen" )
+
+ for (i = 0; i < 256; i++)
+ buffer[i] = 0; /* zero buffer contents */
+
+ /********
+ * TEST *
+ ********/
+
+ H5E_BEGIN_TRY { /* mute stack trace on expected failure */
+ JSVERIFY( FAIL,
+ H5FDread(file_shakespeare,
+ H5FD_MEM_DRAW,
+ H5P_DEFAULT,
+ 1200699,
+ 102,
+ buffer),
+ "cannot read before eoa is set" )
+ } H5E_END_TRY;
+ JSVERIFY_STR( "", buffer, "buffer should remain untouched" )
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5FDclose(file_shakespeare) )
+ file_shakespeare = NULL;
+
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (file_shakespeare) { (void)H5FDclose(file_shakespeare); }
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+
+ return 1;
+
+} /* test_H5FDread_without_eoa_set_fails */
+
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_read()
+ *
+ * Purpose:
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-06
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_read(void)
+{
+
+ /*********************
+ * test-local macros *
+ *********************/
+
+ /*************************
+ * test-local structures *
+ *************************/
+ struct testcase {
+ const char *message; /* purpose of test case */
+ haddr_t eoa_set; /* set file EOA to this prior to read */
+ size_t addr; /* offset of read in file */
+ size_t len; /* length of read in file */
+ herr_t success; /* expected return value of read function */
+ const char *expected; /* expected contents of buffer; failure ignores */
+ };
+
+ /************************
+ * test-local variables *
+ ************************/
+ struct testcase cases[] = {
+ { "successful range-get",
+ 6464,
+ 5691,
+ 32, /* fancy quotes are three bytes each(?) */
+ SUCCEED,
+ "Quoth the Raven “Nevermore.”",
+ },
+ { "read past EOA fails (EOA < EOF < addr)",
+ 3000,
+ 4000,
+ 100,
+ FAIL,
+ NULL,
+ },
+ { "read overlapping EOA fails (EOA < addr < EOF < (addr+len))",
+ 3000,
+ 8000,
+ 100,
+ FAIL,
+ NULL,
+ },
+ { "read past EOA/EOF fails ((EOA==EOF) < addr)",
+ 6464,
+ 7000,
+ 100,
+ FAIL,
+ NULL,
+ },
+ { "read overlapping EOA/EOF fails (addr < (EOA==EOF) < (addr+len))",
+ 6464,
+ 6400,
+ 100,
+ FAIL,
+ NULL,
+ },
+ { "read between EOF and EOA fails (EOF < addr < (addr+len) < EOA)",
+ 8000,
+ 7000,
+ 100,
+ FAIL,
+ NULL,
+ },
+ };
+ unsigned testcase_count = 6;
+ unsigned test_i = 0;
+ struct testcase test;
+ herr_t open_return = FAIL;
+ char buffer[S3_TEST_MAX_URL_SIZE];
+ unsigned int i = 0;
+ H5FD_t *file_raven = NULL;
+ hid_t fapl_id = -1;
+
+ TESTING("ROS3 VFD read/range-gets");
+
+ if (s3_test_credentials_loaded == 0) {
+ SKIPPED();
+ puts(" s3 credentials are not loaded");
+ fflush(stdout);
+ return 0;
+ }
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ /*********
+ * SETUP *
+ *********/
+
+ /* create ROS3 fapl
+ */
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_id < 0 )
+ FAIL_IF( FAIL == H5Pset_fapl_ros3(fapl_id, &restricted_access_fa) )
+
+ /* open file
+ */
+ file_raven = H5FDopen( /* will open with "authenticating" fapl */
+ url_text_public, /* TODO: check return state: anon access of restricted says OK? (not NULL) */
+ H5F_ACC_RDONLY,
+ fapl_id,
+ HADDR_UNDEF); /* Demonstrate success with "automatic" value */
+ FAIL_IF( NULL == file_raven )
+
+ JSVERIFY( 6464, H5FDget_eof(file_raven, H5FD_MEM_DEFAULT), NULL )
+
+ /*********
+ * TESTS *
+ *********/
+
+ for (test_i = 0; test_i < testcase_count; test_i++) {
+
+ /* -------------- *
+ * per-test setup *
+ * -------------- */
+
+ test = cases[test_i];
+ open_return = FAIL;
+
+ FAIL_IF( S3_TEST_MAX_URL_SIZE < test.len ) /* buffer too small! */
+
+ FAIL_IF( FAIL ==
+ H5FD_set_eoa( file_raven, H5FD_MEM_DEFAULT, test.eoa_set) )
+
+ for (i = 0; i < S3_TEST_MAX_URL_SIZE; i++) /* zero buffer contents */
+ buffer[i] = 0;
+
+ /* ------------ *
+ * conduct test *
+ * ------------ */
+
+ H5E_BEGIN_TRY {
+ open_return = H5FDread(
+ file_raven,
+ H5FD_MEM_DRAW,
+ H5P_DEFAULT,
+ test.addr,
+ test.len,
+ buffer);
+ } H5E_END_TRY;
+
+ JSVERIFY( test.success,
+ open_return,
+ test.message )
+ if (open_return == SUCCEED)
+ JSVERIFY_STR( test.expected, buffer, NULL )
+
+ } /* for each testcase */
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5FDclose(file_raven) )
+ file_raven = NULL;
+
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (file_raven)
+ (void)H5FDclose(file_raven);
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+
+ return 1;
+
+} /* test_read */
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_noops_and_autofails()
+ *
+ * Purpose:
+ *
+ * Demonstrate the unavailable and do-nothing routines unique to
+ * Read-Only VFD.
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-06
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_noops_and_autofails(void)
+{
+ /*********************
+ * test-local macros *
+ *********************/
+
+ /*************************
+ * test-local structures *
+ *************************/
+
+ /************************
+ * test-local variables *
+ ************************/
+
+ hbool_t curl_ready = FALSE;
+ hid_t fapl_id = -1;
+ H5FD_t *file = NULL;
+ const char data[36] = "The Force shall be with you, always";
+
+ TESTING("ROS3 VFD always-fail and no-op routines");
+
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ /*********
+ * SETUP *
+ *********/
+
+ FAIL_IF( CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT) )
+ curl_ready = TRUE;
+
+ /* create ROS3 fapl
+ */
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( fapl_id < 0 )
+ JSVERIFY( SUCCEED, H5Pset_fapl_ros3(fapl_id, &anonymous_fa), NULL )
+
+ /* open file
+ */
+ file = H5FDopen(
+ url_text_public,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ HADDR_UNDEF);
+ FAIL_IF( NULL == file )
+
+ /*********
+ * TESTS *
+ *********/
+
+ /* auto-fail calls to write and truncate
+ */
+ H5E_BEGIN_TRY {
+ JSVERIFY( FAIL,
+ H5FDwrite(file, H5FD_MEM_DRAW, H5P_DEFAULT, 1000, 35, data),
+ "write must fail" )
+ } H5E_END_TRY;
+
+ H5E_BEGIN_TRY {
+ JSVERIFY( FAIL,
+ H5FDtruncate(file, H5P_DEFAULT, FALSE),
+ "truncate must fail" )
+ } H5E_END_TRY;
+
+ H5E_BEGIN_TRY {
+ JSVERIFY( FAIL,
+ H5FDtruncate(file, H5P_DEFAULT, TRUE),
+ "truncate must fail (closing)" )
+ } H5E_END_TRY;
+
+ /* no-op calls to `lock()` and `unlock()`
+ */
+ JSVERIFY( SUCCEED,
+ H5FDlock(file, TRUE),
+ "lock always succeeds; has no effect" )
+ JSVERIFY( SUCCEED,
+ H5FDlock(file, FALSE),
+ NULL )
+ JSVERIFY( SUCCEED,
+ H5FDunlock(file),
+ NULL )
+ /* Lock/unlock with null file or similar error crashes tests.
+ * HDassert in calling heirarchy, `H5FD[un]lock()` and `H5FD_[un]lock()`
+ */
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5FDclose(file) )
+ file = NULL;
+
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ curl_global_cleanup();
+ curl_ready = FALSE;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+ if (file) { (void)H5FDclose(file); }
+ if (curl_ready == TRUE) { curl_global_cleanup(); }
+
+ return 1;
+
+} /* test_noops_and_autofails*/
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_cmp()
+ *
+ * Purpose:
+ *
+ * Verify "file comparison" behavior.
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-06
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_cmp(void)
+{
+
+ /*********************
+ * test-local macros *
+ *********************/
+
+ /*************************
+ * test-local structures *
+ *************************/
+
+ /************************
+ * test-local variables *
+ ************************/
+
+ H5FD_t *fd_raven = NULL;
+ H5FD_t *fd_shakes = NULL;
+ H5FD_t *fd_raven_2 = NULL;
+ hbool_t curl_ready = FALSE;
+ hid_t fapl_id = -1;
+
+ TESTING("ROS3 cmp (comparison)");
+
+ if (s3_test_credentials_loaded == 0) {
+ SKIPPED();
+ puts(" s3 credentials are not loaded");
+ fflush(stdout);
+ return 0;
+ }
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ /*********
+ * SETUP *
+ *********/
+
+ FAIL_IF( CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT) )
+ curl_ready = TRUE;
+
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( 0 > fapl_id )
+ JSVERIFY( SUCCEED, H5Pset_fapl_ros3(fapl_id, &restricted_access_fa), NULL )
+
+ fd_raven = H5FDopen(
+ url_text_public,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ HADDR_UNDEF);
+ FAIL_IF( NULL == fd_raven )
+
+ fd_shakes = H5FDopen(
+ url_text_restricted,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ HADDR_UNDEF);
+ FAIL_IF( NULL == fd_shakes )
+
+ fd_raven_2 = H5FDopen(
+ url_text_public,
+ H5F_ACC_RDONLY,
+ fapl_id,
+ HADDR_UNDEF);
+ FAIL_IF( NULL == fd_raven_2 )
+
+ /*********
+ * TESTS *
+ *********/
+
+ JSVERIFY( 0, H5FDcmp(fd_raven, fd_raven_2), NULL )
+ JSVERIFY( -1, H5FDcmp(fd_raven, fd_shakes), NULL )
+ JSVERIFY( -1, H5FDcmp(fd_shakes, fd_raven_2), NULL )
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5FDclose(fd_raven) )
+ fd_raven = NULL;
+ FAIL_IF( FAIL == H5FDclose(fd_shakes) )
+ fd_shakes = NULL;
+ FAIL_IF( FAIL == H5FDclose(fd_raven_2) )
+ fd_raven_2 = NULL;
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ curl_global_cleanup();
+ curl_ready = FALSE;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+
+ if (fd_raven != NULL) (void)H5FDclose(fd_raven);
+ if (fd_raven_2 != NULL) (void)H5FDclose(fd_raven_2);
+ if (fd_shakes != NULL) (void)H5FDclose(fd_shakes);
+ if (TRUE == curl_ready) curl_global_cleanup();
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+
+ return 1;
+
+} /* test_cmp */
+
+
+/*---------------------------------------------------------------------------
+ *
+ * Function: test_H5F_integration()
+ *
+ * Purpose:
+ *
+ * Demonstrate S3 file-open through H5F API.
+ *
+ * Return:
+ *
+ * PASSED : 0
+ * FAILED : 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-11-07
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+test_H5F_integration(void)
+{
+ /*********************
+ * test-local macros *
+ *********************/
+
+ /*************************
+ * test-local structures *
+ *************************/
+
+ /************************
+ * test-local variables *
+ ************************/
+
+ hid_t file = -1;
+ hid_t fapl_id = -1;
+
+ TESTING("S3 file access through HD5F library (H5F API)");
+
+ if (s3_test_credentials_loaded == 0) {
+ SKIPPED();
+ puts(" s3 credentials are not loaded");
+ fflush(stdout);
+ return 0;
+ }
+
+ if (FALSE == s3_test_bucket_defined) {
+ SKIPPED();
+ puts(" environment variable HDF5_ROS3_TEST_BUCKET_URL not defined");
+ fflush(stdout);
+ return 0;
+ }
+
+ /*********
+ * SETUP *
+ *********/
+
+ fapl_id = H5Pcreate(H5P_FILE_ACCESS);
+ FAIL_IF( 0 > fapl_id )
+ FAIL_IF( FAIL == H5Pset_fapl_ros3(fapl_id, &restricted_access_fa) )
+
+ /*********
+ * TESTS *
+ *********/
+
+ /* Read-Write Open access is not allowed with this file driver.
+ */
+ H5E_BEGIN_TRY {
+ FAIL_IF( 0 <= H5Fopen(
+ url_h5_public,
+ H5F_ACC_RDWR,
+ fapl_id) )
+ } H5E_END_TRY;
+
+ /* H5Fcreate() is not allowed with this file driver.
+ */
+ H5E_BEGIN_TRY {
+ FAIL_IF( 0 <= H5Fcreate(
+ url_missing,
+ H5F_ACC_RDONLY,
+ H5P_DEFAULT,
+ fapl_id) )
+ } H5E_END_TRY;
+
+ /* Successful open.
+ */
+ file = H5Fopen(
+ url_h5_public,
+ H5F_ACC_RDONLY,
+ fapl_id);
+ FAIL_IF( file < 0 )
+
+ /************
+ * TEARDOWN *
+ ************/
+
+ FAIL_IF( FAIL == H5Fclose(file) )
+ file = -1;
+
+ FAIL_IF( FAIL == H5Pclose(fapl_id) )
+ fapl_id = -1;
+
+ PASSED();
+ return 0;
+
+error:
+ /***********
+ * CLEANUP *
+ ***********/
+HDprintf("\nerror!"); fflush(stdout);
+
+ if (fapl_id >= 0) {
+ H5E_BEGIN_TRY {
+ (void)H5Pclose(fapl_id);
+ } H5E_END_TRY;
+ }
+ if (file > 0)
+ (void)H5Fclose(file);
+
+ return 1;
+
+} /* test_H5F_integration */
+
+#endif /* H5_HAVE_ROS3_VFD */
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: main
+ *
+ * Purpose: Tests the basic features of Virtual File Drivers
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Jacob Smith
+ * 2017-10-23
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+#ifdef H5_HAVE_ROS3_VFD
+ int nerrors = 0;
+ const char *bucket_url_env = NULL;
+
+#endif /* H5_HAVE_ROS3_VFD */
+
+ HDprintf("Testing ros3 VFD functionality.\n");
+
+#ifdef H5_HAVE_ROS3_VFD
+
+ /************************
+ * initialize test urls *
+ ************************/
+
+ bucket_url_env = HDgetenv("HDF5_ROS3_TEST_BUCKET_URL");
+ if (bucket_url_env == NULL || bucket_url_env[0] == '\0') {
+ HDprintf("WARNING: S3 bucket url is not defined in enviornment " \
+ "variable 'HDF5_ROS3_TEST_BUCKET_URL'!\n");
+ } else {
+ HDstrncpy(s3_test_bucket_url, bucket_url_env, S3_TEST_MAX_URL_SIZE);
+ s3_test_bucket_defined = TRUE;
+ }
+
+ if (S3_TEST_MAX_URL_SIZE < HDsnprintf(
+ url_text_restricted,
+ (size_t)S3_TEST_MAX_URL_SIZE,
+ "%s/%s",
+ (const char *)s3_test_bucket_url,
+ (const char *)S3_TEST_RESOURCE_TEXT_RESTRICTED))
+ {
+ HDprintf("* ros3 setup failed (text_restricted) ! *\n");
+ return 1;
+ }
+ if (S3_TEST_MAX_URL_SIZE < HDsnprintf(
+ url_text_public,
+ (size_t)S3_TEST_MAX_URL_SIZE,
+ "%s/%s",
+ (const char *)s3_test_bucket_url,
+ (const char *)S3_TEST_RESOURCE_TEXT_PUBLIC))
+ {
+ HDprintf("* ros3 setup failed (text_public) ! *\n");
+ return 1;
+ }
+ if (S3_TEST_MAX_URL_SIZE < HDsnprintf(
+ url_h5_public,
+ (size_t)S3_TEST_MAX_URL_SIZE,
+ "%s/%s",
+ (const char *)s3_test_bucket_url,
+ (const char *)S3_TEST_RESOURCE_H5_PUBLIC))
+ {
+ HDprintf("* ros3 setup failed (h5_public) ! *\n");
+ return 1;
+ }
+ if (S3_TEST_MAX_URL_SIZE < HDsnprintf(
+ url_missing,
+ S3_TEST_MAX_URL_SIZE,
+ "%s/%s",
+ (const char *)s3_test_bucket_url,
+ (const char *)S3_TEST_RESOURCE_MISSING))
+ {
+ HDprintf("* ros3 setup failed (missing) ! *\n");
+ return 1;
+ }
+
+ /**************************************
+ * load credentials and prepare fapls *
+ **************************************/
+
+ /* "clear" profile data strings */
+ s3_test_aws_access_key_id[0] = '\0';
+ s3_test_aws_secret_access_key[0] = '\0';
+ s3_test_aws_region[0] = '\0';
+
+ /* attempt to load test credentials
+ * if unable, certain tests will be skipped
+ */
+ if (SUCCEED == H5FD_s3comms_load_aws_profile(
+ S3_TEST_PROFILE_NAME,
+ s3_test_aws_access_key_id,
+ s3_test_aws_secret_access_key,
+ s3_test_aws_region))
+ {
+ s3_test_credentials_loaded = 1;
+ HDstrncpy(restricted_access_fa.aws_region,
+ (const char *)s3_test_aws_region,
+ H5FD_ROS3_MAX_REGION_LEN);
+ HDstrncpy(restricted_access_fa.secret_id,
+ (const char *)s3_test_aws_access_key_id,
+ H5FD_ROS3_MAX_SECRET_ID_LEN);
+ HDstrncpy(restricted_access_fa.secret_key,
+ (const char *)s3_test_aws_secret_access_key,
+ H5FD_ROS3_MAX_SECRET_KEY_LEN);
+ }
+
+ /******************
+ * commence tests *
+ ******************/
+
+ h5_reset();
+
+ nerrors += test_fapl_config_validation();
+ nerrors += test_ros3_fapl();
+ nerrors += test_vfd_open();
+ nerrors += test_eof_eoa();
+ nerrors += test_H5FDread_without_eoa_set_fails();
+ nerrors += test_read();
+ nerrors += test_noops_and_autofails();
+ nerrors += test_cmp();
+ nerrors += test_H5F_integration();
+
+ if (nerrors > 0) {
+ HDprintf("***** %d ros3 TEST%s FAILED! *****\n",
+ nerrors,
+ nerrors > 1 ? "S" : "");
+ nerrors = 1;
+ } else {
+ HDprintf("All ros3 tests passed.\n");
+ }
+ return nerrors; /* 0 if no errors, 1 if any errors */
+
+#else
+
+ HDprintf("SKIPPED - read-only S3 VFD not built\n");
+ return EXIT_SUCCESS;
+
+#endif /* H5_HAVE_ROS3_VFD */
+
+} /* main() */
+