diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/cache.c | 41 | ||||
-rw-r--r-- | test/cache_common.c | 2 | ||||
-rw-r--r-- | test/dt_arith.c | 56 | ||||
-rw-r--r-- | test/gen_bogus.c | 14 | ||||
-rw-r--r-- | test/h5test.h | 2 | ||||
-rw-r--r-- | test/ohdr.c | 42 | ||||
-rw-r--r-- | test/tbogus.h5 | bin | 1944 -> 2216 bytes | |||
-rw-r--r-- | test/tid.c | 199 | ||||
-rw-r--r-- | test/tskiplist.c | 203 |
9 files changed, 522 insertions, 37 deletions
diff --git a/test/cache.c b/test/cache.c index a98a995..38adbda 100644 --- a/test/cache.c +++ b/test/cache.c @@ -9499,7 +9499,7 @@ check_flush_cache__flush_op_test(H5F_t * file_ptr, * Modifications: * * Updated test for minor changes in the behaviour - * of H5C_flush_single_entry(). + * of H5C__flush_single_entry(). * * JRM -- 2/16/15 * @@ -10575,7 +10575,7 @@ check_flush_cache__flush_op_eviction_test(H5F_t * file_ptr) failure_mssg = "unexpected size/len in flush op eviction test 12."; } - /* modifications to the H5C_flush_single_entry() function have + /* modifications to the H5C__flush_single_entry() function have * changed the behavior of the cache slightly, causing * this test to fail. Comment out for now -- come back and * fix if all goes well. @@ -10664,7 +10664,7 @@ check_flush_cache__flush_op_eviction_test(H5F_t * file_ptr) failure_mssg = "unexpected size/len in flush op eviction test 13."; } - /* modifications to the H5C_flush_single_entry() function have + /* modifications to the H5C__flush_single_entry() function have * changed the behavior of the cache slightly, causing * this test to fail. Comment out for now -- come back and * fix if all goes well. @@ -14207,8 +14207,7 @@ check_resize_entry(void) } else { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[LARGE_ENTRY_TYPE]), entry_ptr->addr, - (void *)entry_ptr, H5C__DIRTIED_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__DIRTIED_FLAG); if ( result < 0 ) { @@ -14293,8 +14292,7 @@ check_resize_entry(void) } else { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[LARGE_ENTRY_TYPE]), entry_ptr->addr, - (void *)entry_ptr, H5C__DIRTIED_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__DIRTIED_FLAG); if ( result < 0 ) { @@ -14654,8 +14652,7 @@ check_resize_entry(void) } else { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[LARGE_ENTRY_TYPE]), entry_ptr->addr, - (void *)entry_ptr, H5C__DIRTIED_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__DIRTIED_FLAG); if ( result < 0 ) { @@ -14742,8 +14739,7 @@ check_resize_entry(void) } else { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[LARGE_ENTRY_TYPE]), entry_ptr->addr, - (void *)entry_ptr, H5C__DIRTIED_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__DIRTIED_FLAG); if ( result < 0 ) { @@ -16246,8 +16242,7 @@ check_double_pin_err(void) if ( pass ) { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[0]), entry_ptr->addr, - (void *)entry_ptr, H5C__PIN_ENTRY_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__PIN_ENTRY_FLAG); if ( result > 0 ) { @@ -16331,8 +16326,7 @@ check_double_unpin_err(void) if ( pass ) { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[0]), entry_ptr->addr, - (void *)entry_ptr, H5C__UNPIN_ENTRY_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__UNPIN_ENTRY_FLAG); if ( result > 0 ) { @@ -16612,8 +16606,7 @@ check_double_unprotect_err(void) if ( pass ) { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[0]), entry_ptr->addr, - (void *)entry_ptr, H5C__NO_FLAGS_SET); + entry_ptr->addr, (void *)entry_ptr, H5C__NO_FLAGS_SET); if ( result > 0 ) { @@ -16989,8 +16982,7 @@ check_unprotect_ro_dirty_err(void) if ( pass ) { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[0]), entry_ptr->addr, - (void *)entry_ptr, H5C__DIRTIED_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__DIRTIED_FLAG); if ( result >= 0 ) { @@ -17033,8 +17025,7 @@ check_unprotect_ro_dirty_err(void) if ( pass ) { result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[0]), entry_ptr->addr, - (void *)entry_ptr, H5C__DIRTIED_FLAG); + entry_ptr->addr, (void *)entry_ptr, H5C__DIRTIED_FLAG); if ( result > 0 ) { @@ -34878,8 +34869,8 @@ check_stats__smoke_check_1(H5F_t * file_ptr) if ( ( cache_ptr->total_ht_insertions != 33 ) || ( cache_ptr->total_ht_deletions != 1 ) || - ( cache_ptr->successful_ht_searches != 65 ) || - ( cache_ptr->total_successful_ht_search_depth != 195 ) || + ( cache_ptr->successful_ht_searches != 32 ) || + ( cache_ptr->total_successful_ht_search_depth != 96 ) || ( cache_ptr->failed_ht_searches != 33 ) || ( cache_ptr->total_failed_ht_search_depth != 52 ) || ( cache_ptr->max_index_len != 32 ) || @@ -34989,8 +34980,8 @@ check_stats__smoke_check_1(H5F_t * file_ptr) if ( ( cache_ptr->total_ht_insertions != 33 ) || ( cache_ptr->total_ht_deletions != 33 ) || - ( cache_ptr->successful_ht_searches != 98 ) || - ( cache_ptr->total_successful_ht_search_depth != 198 ) || + ( cache_ptr->successful_ht_searches != 33 ) || + ( cache_ptr->total_successful_ht_search_depth != 99 ) || ( cache_ptr->failed_ht_searches != 33 ) || ( cache_ptr->total_failed_ht_search_depth != 52 ) || ( cache_ptr->max_index_len != 32 ) || diff --git a/test/cache_common.c b/test/cache_common.c index 8ccd7e3..f3da908 100644 --- a/test/cache_common.c +++ b/test/cache_common.c @@ -3959,7 +3959,7 @@ unprotect_entry(H5F_t * file_ptr, entry_ptr->is_dirty = TRUE; result = H5C_unprotect(file_ptr, H5P_DATASET_XFER_DEFAULT, - &(types[type]), entry_ptr->addr, (void *)entry_ptr, flags); + entry_ptr->addr, (void *)entry_ptr, flags); if ( ( result < 0 ) || ( ( entry_ptr->header.is_protected ) && diff --git a/test/dt_arith.c b/test/dt_arith.c index 8ededc7..b3f5cad 100644 --- a/test/dt_arith.c +++ b/test/dt_arith.c @@ -5032,8 +5032,32 @@ run_int_fp_conv(const char *name) #endif #endif /* H5_SIZEOF_LONG!=H5_SIZEOF_INT */ #if H5_SIZEOF_LONG_LONG!=H5_SIZEOF_LONG +#if H5_LLONG_TO_LDOUBLE_CORRECT nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LLONG, H5T_NATIVE_LDOUBLE); +#else /* H5_LLONG_TO_LDOUBLE_CORRECT */ + { + char str[256]; /*hello string */ + + HDsnprintf(str, sizeof(str), "Testing %s %s -> %s conversions", + name, "long long", "long double"); + printf("%-70s", str); + SKIPPED(); + HDputs(" Test skipped due to compiler error in handling conversion."); + } +#endif /* H5_LLONG_TO_LDOUBLE_CORRECT */ +#if H5_LLONG_TO_LDOUBLE_CORRECT nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULLONG, H5T_NATIVE_LDOUBLE); +#else /* H5_LLONG_TO_LDOUBLE_CORRECT */ + { + char str[256]; /*hello string */ + + HDsnprintf(str, sizeof(str), "Testing %s %s -> %s conversions", + name, "unsigned long long", "long double"); + printf("%-70s", str); + SKIPPED(); + HDputs(" Test skipped due to compiler not handling conversion."); + } +#endif /* H5_LLONG_TO_LDOUBLE_CORRECT */ #endif #endif @@ -5134,8 +5158,40 @@ run_fp_int_conv(const char *name) #endif /*H5_SIZEOF_LONG!=H5_SIZEOF_INT && H5_SIZEOF_LONG_DOUBLE!=0 */ #if H5_SIZEOF_LONG_LONG!=H5_SIZEOF_LONG && H5_SIZEOF_LONG_DOUBLE!=0 +#ifdef H5_LDOUBLE_TO_LLONG_ACCURATE nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_LDOUBLE, H5T_NATIVE_LLONG); +#else /*H5_LDOUBLE_TO_LLONG_ACCURATE*/ + { + char str[256]; /*string */ + + HDsnprintf(str, sizeof(str), "Testing %s %s -> %s conversions", + name, "long double", "long long"); + printf("%-70s", str); + SKIPPED(); +#if H5_SIZEOF_LONG_DOUBLE!=0 + HDputs(" Test skipped due to hardware conversion error."); +#else + HDputs(" Test skipped due to disabled long double."); +#endif + } +#endif /*H5_LDOUBLE_TO_LLONG_ACCURATE*/ +#if defined(H5_LDOUBLE_TO_LLONG_ACCURATE) nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_LDOUBLE, H5T_NATIVE_ULLONG); +#else /*H5_LDOUBLE_TO_LLONG_ACCURATE*/ + { + char str[256]; /*string */ + + HDsnprintf(str, sizeof(str), "Testing %s %s -> %s conversions", + name, "long double", "unsigned long long"); + printf("%-70s", str); + SKIPPED(); +#if H5_SIZEOF_LONG_DOUBLE!=0 + HDputs(" Test skipped due to hardware conversion error."); +#else + HDputs(" Test skipped due to disabled long double."); +#endif + } +#endif /*H5_LDOUBLE_TO_LLONG_ACCURATE*/ #endif #endif #ifndef H5_VMS diff --git a/test/gen_bogus.c b/test/gen_bogus.c index df1e81f..e9ce686 100644 --- a/test/gen_bogus.c +++ b/test/gen_bogus.c @@ -61,7 +61,7 @@ int main(void) if((did = H5Dcreate2(fid, "/Dataset1", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) goto error; if(H5Dclose(did) < 0) goto error; - /* Set "fail if unknown" message flag for bogus message */ + /* Set "fail if unknown and open for write" message flag for bogus message */ bogus_flags = H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE; if(H5Pset(dcpl, H5O_BOGUS_MSG_FLAGS_NAME, &bogus_flags) < 0) goto error; @@ -69,12 +69,20 @@ int main(void) if((did = H5Dcreate2(fid, "/Dataset2", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) goto error; if(H5Dclose(did) < 0) goto error; + /* Set "fail if unknown always" message flag for bogus message */ + bogus_flags = H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS; + if(H5Pset(dcpl, H5O_BOGUS_MSG_FLAGS_NAME, &bogus_flags) < 0) goto error; + + /* Create third dataset, with "fail if unknown always" message flag */ + if((did = H5Dcreate2(fid, "/Dataset3", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) goto error; + if(H5Dclose(did) < 0) goto error; + /* Set "mark if unknown" message flag for bogus message */ bogus_flags = H5O_MSG_FLAG_MARK_IF_UNKNOWN; if(H5Pset(dcpl, H5O_BOGUS_MSG_FLAGS_NAME, &bogus_flags) < 0) goto error; - /* Create second dataset, with "mark if unknown" message flag */ - if((did = H5Dcreate2(fid, "/Dataset3", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) goto error; + /* Create fourth dataset, with "mark if unknown" message flag */ + if((did = H5Dcreate2(fid, "/Dataset4", H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) goto error; if(H5Dclose(did) < 0) goto error; /* Close dataset creation property list */ diff --git a/test/h5test.h b/test/h5test.h index fa0c11b..5b203c6 100644 --- a/test/h5test.h +++ b/test/h5test.h @@ -158,7 +158,7 @@ H5TEST_DLL void ParseTestVerbosity(char *argv); H5TEST_DLL int GetTestNumErrs(void); H5TEST_DLL void IncTestNumErrs(void); H5TEST_DLL const void *GetTestParameters(void); -H5TEST_DLL int TestErrPrintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); +H5TEST_DLL int TestErrPrintf(const char *format, ...) H5_ATTR_FORMAT(printf, 1, 2); H5TEST_DLL void SetTest(const char *testname, int action); H5TEST_DLL void TestAlarmOn(void); H5TEST_DLL void TestAlarmOff(void); diff --git a/test/ohdr.c b/test/ohdr.c index 1ba2b10..45f2238 100644 --- a/test/ohdr.c +++ b/test/ohdr.c @@ -665,7 +665,9 @@ main(void) PASSED(); - /* Test reading datasets with undefined object header messages */ + /* Test reading datasets with undefined object header messages + * and the various "fail/mark if unknown" object header message flags + */ HDputs("Accessing objects with unknown header messages:"); { hid_t file2; /* File ID for 'bogus' object file */ @@ -687,7 +689,7 @@ main(void) PASSED(); - TESTING("object with unknown header message & 'fail if unknown and open for write' flag set"); + TESTING("object in r/o file with unknown header message & 'fail if unknown and open for write' flag set"); /* Open the dataset with the unknown header message, and "fail if unknown and open for write" flag */ if((dset = H5Dopen2(file2, "/Dataset2", H5P_DEFAULT)) < 0) @@ -697,10 +699,23 @@ main(void) PASSED(); + TESTING("object in r/o file with unknown header message & 'fail if unknown always' flag set"); + + /* Attempt to open the dataset with the unknown header message, and "fail if unknown always" flag */ + H5E_BEGIN_TRY { + dset = H5Dopen2(file2, "/Dataset3", H5P_DEFAULT); + } H5E_END_TRY; + if(dset >= 0) { + H5Dclose(dset); + TEST_ERROR + } /* end if */ + + PASSED(); + TESTING("object with unknown header message & 'mark if unknown' flag set"); /* Copy object with "mark if unknown" flag on message into file that can be modified */ - if(H5Ocopy(file2, "/Dataset3", file, "/Dataset3", H5P_DEFAULT, H5P_DEFAULT) < 0) + if(H5Ocopy(file2, "/Dataset4", file, "/Dataset4", H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR /* Close the file we created (to flush changes to file) */ @@ -712,7 +727,7 @@ main(void) TEST_ERROR /* Open the dataset with the "mark if unknown" message */ - if((dset = H5Dopen2(file, "/Dataset3", H5P_DEFAULT)) < 0) + if((dset = H5Dopen2(file, "/Dataset4", H5P_DEFAULT)) < 0) TEST_ERROR /* Check that the "unknown" message was _NOT_ marked */ @@ -732,7 +747,7 @@ main(void) TEST_ERROR /* Open the dataset with the "mark if unknown" message */ - if((dset = H5Dopen2(file, "/Dataset3", H5P_DEFAULT)) < 0) + if((dset = H5Dopen2(file, "/Dataset4", H5P_DEFAULT)) < 0) TEST_ERROR /* Create data space */ @@ -764,7 +779,7 @@ main(void) TEST_ERROR /* Re-open the dataset with the "mark if unknown" message */ - if((dset = H5Dopen2(file, "/Dataset3", H5P_DEFAULT)) < 0) + if((dset = H5Dopen2(file, "/Dataset4", H5P_DEFAULT)) < 0) TEST_ERROR /* Check that the "unknown" message was marked */ @@ -785,7 +800,7 @@ main(void) if((file2 = H5Fopen(testfile, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR - TESTING("object with unknown header message & 'fail if unknown and open for write' flag set"); + TESTING("object in r/w file with unknown header message & 'fail if unknown and open for write' flag set"); /* Attempt to open the dataset with the unknown header message, and "fail if unknown and open for write" flag */ H5E_BEGIN_TRY { @@ -796,6 +811,19 @@ main(void) TEST_ERROR } /* end if */ + PASSED(); + + TESTING("object in r/w file with unknown header message & 'fail if unknown always' flag set"); + + /* Attempt to open the dataset with the unknown header message, and "fail if unknown always" flag */ + H5E_BEGIN_TRY { + dset = H5Dopen2(file2, "/Dataset3", H5P_DEFAULT); + } H5E_END_TRY; + if(dset >= 0) { + H5Dclose(dset); + TEST_ERROR + } /* end if */ + /* Close the file with the bogus objects */ if(H5Fclose(file2) < 0) TEST_ERROR diff --git a/test/tbogus.h5 b/test/tbogus.h5 Binary files differindex 906921c..875fbd8 100644 --- a/test/tbogus.h5 +++ b/test/tbogus.h5 @@ -533,12 +533,211 @@ out: return -1; } + /* Test removing ids in callback for H5Iclear_type */ + +/* There was a rare bug where, if an id free callback being called by + * H5I_clear_type() removed another id in that type, a segfault could occur. + * This test tests for that error (and freeing ids "out of order" within + * H5Iclear_type() in general). */ +/* Macro definitions */ +#define TEST_RCT_MAX_NOBJS 25 +#define TEST_RCT_MIN_NOBJS 5 +#define TEST_RCT_NITER 50 + +/* Structure to hold the list of objects */ +typedef struct { + struct test_rct_obj_t *list; /* List of objects */ + long nobjs; /* Number of objects in list */ + long nobjs_rem; /* Number of objects in list that have not been freed */ +} test_rct_list_t; + +/* Structure for an object */ +typedef struct test_rct_obj_t { + hid_t id; /* ID for this object */ + int nfrees; /* Number of times this object has been freed */ + hbool_t freeing; /* Whether we are currently freeing this object directly (through H5Idec_ref()) */ + test_rct_list_t *obj_list; /* List of all objects */ +} test_rct_obj_t; + +/* Free callback */ +static herr_t test_rct_free(void *_obj) { + test_rct_obj_t *obj = (test_rct_obj_t *)_obj; + long rem_idx, i; + herr_t ret; /* return value */ + + /* Mark this object as freed */ + obj->nfrees++; + obj->obj_list->nobjs_rem--; + + /* Check freeing and nobjs_rem */ + if(!obj->freeing && (obj->obj_list->nobjs_rem > 0)) { + /* Remove a random object from the list */ + rem_idx = HDrandom() % obj->obj_list->nobjs_rem; + + /* Scan the list, finding the rem_idx'th object that has not been + * freed */ + for(i = 0; i < obj->obj_list->nobjs; i++) + if(obj->obj_list->list[i].nfrees == 0) { + if(rem_idx == 0) + break; + else + rem_idx--; + } /* end if */ + if(i == obj->obj_list->nobjs) { + ERROR("invalid obj_list"); + goto out; + } /* end if */ + else { + /* Remove the object. Mark as "freeing" so its own callback does + * not free another object. */ + obj->obj_list->list[i].freeing = TRUE; + ret = H5Idec_ref(obj->obj_list->list[i].id); + CHECK(ret, FAIL, "H5Idec_ref"); + if(ret == FAIL) + goto out; + obj->obj_list->list[i].freeing = FALSE; + } /* end else */ + } /* end if */ + + /* Verify nobjs_rem is non-negative */ + if(obj->obj_list->nobjs_rem < 0) { + ERROR("invalid nobjs_rem"); + goto out; + } /* end if */ + + return 0; + +out: + return -1; +} /* end test_rct_free() */ + +/* Test function */ +static int test_remove_clear_type(void) +{ + H5I_type_t obj_type; + test_rct_list_t obj_list; + test_rct_obj_t list[TEST_RCT_MAX_NOBJS]; + long i, j; + long nobjs_found; + hsize_t nmembers; + herr_t ret; /* return value */ + + /* Register type */ + obj_type = H5Iregister_type((size_t)8, 0, test_rct_free); + CHECK(obj_type, H5I_BADID, "H5Iregister_type"); + if(obj_type == H5I_BADID) + goto out; + + /* Init obj_list.list */ + obj_list.list = list; + + for(i = 0; i < TEST_RCT_NITER; i++) { + /* Build object list */ + obj_list.nobjs = obj_list.nobjs_rem = TEST_RCT_MIN_NOBJS + (HDrandom() % (long)(TEST_RCT_MAX_NOBJS - TEST_RCT_MIN_NOBJS + 1)); + for(j = 0; j < obj_list.nobjs; j++) { + list[j].nfrees = 0; + list[j].freeing = FALSE; + list[j].obj_list = &obj_list; + list[j].id = H5Iregister(obj_type, &list[j]); + CHECK(list[j].id, FAIL, "H5Iregister"); + if(list[j].id == FAIL) + goto out; + if(HDrandom() % 2) { + ret = H5Iinc_ref(list[j].id); + CHECK(ret, FAIL, "H5Iinc_ref"); + if(ret == FAIL) + goto out; + } /* end if */ + } /* end for */ + + /* Clear the type */ + ret = H5Iclear_type(obj_type, FALSE); + CHECK(ret, FAIL, "H5Iclear_type"); + if(ret == FAIL) + goto out; + + /* Verify list */ + nobjs_found = 0; + for(j = 0; j < obj_list.nobjs; j++) { + if(list[j].nfrees == 0) + nobjs_found++; + else { + VERIFY(list[j].nfrees, (long)1, "list[j].nfrees"); + if(list[j].nfrees != (long)1) + goto out; + } /* end else */ + VERIFY(list[j].freeing, FALSE, "list[j].freeing"); + if(list[j].freeing != FALSE) + goto out; + } /* end for */ + + /* Verify number of objects */ + VERIFY(obj_list.nobjs_rem, nobjs_found, "obj_list.nobjs_rem"); + if(obj_list.nobjs_rem != nobjs_found) + goto out; + ret = H5Inmembers(obj_type, &nmembers); + CHECK(ret, FAIL, "H5Inmembers"); + if(ret == FAIL) + goto out; + VERIFY(nmembers, (size_t)nobjs_found, "H5Inmembers"); + if(nmembers != (size_t)nobjs_found) + goto out; + + /* Clear the type with force set to TRUE */ + ret = H5Iclear_type(obj_type, TRUE); + CHECK(ret, FAIL, "H5Iclear_type"); + if(ret == FAIL) + goto out; + + /* Verify list */ + for(j = 0; j < obj_list.nobjs; j++) { + VERIFY(list[j].nfrees, (long)1, "list[j].nfrees"); + if(list[j].nfrees != (long)1) + goto out; + VERIFY(list[j].freeing, FALSE, "list[j].freeing"); + if(list[j].freeing != FALSE) + goto out; + } /* end for */ + + /* Verify number of objects is 0 */ + VERIFY(obj_list.nobjs_rem, (long)0, "obj_list.nobjs_rem"); + if(obj_list.nobjs_rem != (long)0) + goto out; + ret = H5Inmembers(obj_type, &nmembers); + CHECK(ret, FAIL, "H5Inmembers"); + if(ret == FAIL) + goto out; + VERIFY(nmembers, (size_t)0, "H5Inmembers"); + if(nmembers != (size_t)0) + goto out; + } /* end for */ + + /* Destroy type */ + ret = H5Idestroy_type(obj_type); + CHECK(ret, FAIL, "H5Idestroy_type"); + if(ret == FAIL) + goto out; + + return 0; + +out: + /* Cleanup. For simplicity, just destroy the types and ignore errors. */ + H5E_BEGIN_TRY + H5Idestroy_type(obj_type); + H5E_END_TRY + return -1; +} /* end test_remove_clear_type() */ + void test_ids(void) { + /* Set the random # seed */ + HDsrandom((unsigned)HDtime(NULL)); + if (basic_id_test() < 0) TestErrPrintf("Basic ID test failed\n"); if (id_predefined_test() < 0) TestErrPrintf("Predefined ID type test failed\n"); if (test_is_valid() < 0) TestErrPrintf("H5Iis_valid test failed\n"); if (test_get_type() < 0) TestErrPrintf("H5Iget_type test failed\n"); if (test_id_type_list() < 0) TestErrPrintf("ID type list test failed\n"); + if (test_remove_clear_type() < 0) TestErrPrintf("ID remove during H5Iclear_type test failed\n"); } diff --git a/test/tskiplist.c b/test/tskiplist.c index 07e63fd..62c5f8e 100644 --- a/test/tskiplist.c +++ b/test/tskiplist.c @@ -1171,6 +1171,208 @@ test_skiplist_free(void) /**************************************************************** ** +** test_skiplist_try_free_safe(): Test H5SL (skip list) code. +** Tests 'try_free_safe' operation in skip lists. +** +****************************************************************/ +/* Macro definitions */ +#define TEST_TFS_MAX_NOBJS 100 +#define TEST_TFS_MIN_NOBJS 5 +#define TEST_TFS_NITER 50 + +/* Structure to hold the list of objects */ +typedef struct { + H5SL_t *slist; /* Skiplist holding the objects */ + struct test_tfs_obj_t *list; /* Linear list of objects */ + int nobjs; /* Number of objects in list */ + int nobjs_rem; /* Number of objects in list that have not been freed */ +} test_tfs_list_t; + +/* Structure for an object */ +typedef struct test_tfs_obj_t { + int idx; /* Index (key) for this object */ + int nfrees; /* Number of times this object has been freed */ +} test_tfs_obj_t; + +/* op_data struct for H5SL_iterate() */ +typedef struct test_tfs_it_ud_t { + test_tfs_list_t *obj_list; /* List of objects */ + int last_idx; /* Index of last object visited in iteration */ + int ncalls; /* Number of times this callback was called */ +} test_tfs_it_ud_t; + +/* iterate callback */ +static herr_t test_tfs_iter(void *_obj, void *key, void *_udata) { + test_tfs_obj_t *obj = (test_tfs_obj_t *)_obj; + test_tfs_it_ud_t *udata = (test_tfs_it_ud_t *)_udata; + + /* Check consistency */ + VERIFY((void *)&obj->idx, key, "obj->idx"); + VERIFY(obj, &udata->obj_list->list[obj->idx], "obj_list->list[obj->idx]"); + + /* Increment number of calls */ + udata->ncalls++; + + /* Verify we were given the correct object */ + do { + udata->last_idx++; + } while(udata->obj_list->list[udata->last_idx].nfrees != 0); + VERIFY(udata->last_idx, obj->idx, "H5SL_iterate"); + + return 0; +} /* end test_tfs_iter() */ + +/* try_free_safe callback */ +static htri_t test_tfs_free(void *_obj, void *key, void *_obj_list) { + test_tfs_obj_t *obj = (test_tfs_obj_t *)_obj; + test_tfs_list_t *obj_list = (test_tfs_list_t *)_obj_list; + test_tfs_it_ud_t iter_ud; + int nrems, rem_idx, i, j; + test_tfs_obj_t *obj_ret; + herr_t ret; /* return value */ + htri_t ret_value; + + /* Check consistency */ + VERIFY((void *)&obj->idx, key, "obj->idx"); + VERIFY(obj, &obj_list->list[obj->idx], "obj_list->list[obj->idx]"); + + /* Mark this object as freed (to make sure it isn't recursively freed, that + * is not something we support, we will undo this if we decide later not to + * free the object) */ + obj->nfrees++; + obj_list->nobjs_rem--; + + /* Decide how many objects to remove */ + nrems = (int)(HDrandom() % (long)3); + + /* Remove objects */ + for(i = 0; i < nrems; i++) + /* Check nobjs_rem */ + if(obj_list->nobjs_rem > 0) { + /* Remove a random object from the list */ + rem_idx = (int)(HDrandom() % (long)obj_list->nobjs_rem); + + /* Scan the list, finding the rem_idx'th object that has not been + * freed */ + for(j = 0; j < obj_list->nobjs; j++) + if(obj_list->list[j].nfrees == 0) { + if(rem_idx == 0) + break; + else + rem_idx--; + } /* end if */ + if(j == obj_list->nobjs) + ERROR("invalid obj_list"); + else { + /* Remove the object */ + obj_ret = (test_tfs_obj_t *)H5SL_remove(obj_list->slist, &j); + CHECK(obj_ret, NULL, "H5SL_remove"); + obj_ret->nfrees++; + obj_list->nobjs_rem--; + } /* end else */ + } /* end if */ + + /* Mark this object as not freed so we know to expect it in the iterate call + */ + obj->nfrees--; + obj_list->nobjs_rem++; + + /* Iterate over skip list (maybe) */ + if(HDrandom() % (long)5) { + iter_ud.obj_list = obj_list; + iter_ud.last_idx = -1; + iter_ud.ncalls = 0; + ret = H5SL_iterate(obj_list->slist, test_tfs_iter, &iter_ud); + CHECK(ret, FAIL, "H5SL_iterate"); + VERIFY(iter_ud.ncalls, obj_list->nobjs_rem, "H5SL_iterate"); + } /* end if */ + + /* Verify nobjs_rem is non-negative */ + if(obj_list->nobjs_rem < 0) + ERROR("invalid nobjs_rem"); + + /* Decide whether this object should be freed */ + if(HDrandom() % (long)2) { + /* Free the object */ + ret_value = TRUE; + obj->nfrees++; + obj_list->nobjs_rem--; + } /* end if */ + else + /* Do not free the object */ + ret_value = FALSE; + + return ret_value; +} /* end test_tfs_free() */ + +/* Test function */ +static void +test_skiplist_try_free_safe(void) +{ + test_tfs_list_t obj_list; + test_tfs_obj_t list[TEST_TFS_MAX_NOBJS]; + int i, j; + int nobjs_found; + hsize_t count; + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Skip List 'Try Free Safe' Operation\n")); + + /* Create a skip list */ + obj_list.slist = H5SL_create(H5SL_TYPE_INT, NULL); + CHECK(obj_list.slist, NULL, "H5SL_create"); + + /* Init obj_list.list */ + obj_list.list = list; + for(j = 0; j < TEST_TFS_MAX_NOBJS; j++) + list[j].idx = j; + + for(i = 0; i < TEST_TFS_NITER; i++) { + /* Build object list */ + obj_list.nobjs = obj_list.nobjs_rem = (int)(TEST_TFS_MIN_NOBJS + (HDrandom() % (long)(TEST_TFS_MAX_NOBJS - TEST_TFS_MIN_NOBJS + 1))); + for(j = 0; j < obj_list.nobjs; j++) { + list[j].nfrees = 0; + ret = H5SL_insert(obj_list.slist, &list[j], &list[j].idx); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Call H5S_try_free_safe() - free most of the items in the skip list in + * a safe manner */ + ret = H5SL_try_free_safe(obj_list.slist, test_tfs_free, &obj_list); + CHECK(ret, FAIL, "H5SL_try_free_safe"); + + /* Verify list */ + nobjs_found = 0; + for(j = 0; j < obj_list.nobjs; j++) + if(list[j].nfrees == 0) + nobjs_found++; + else + VERIFY(list[j].nfrees, (long)1, "list[j].nfrees"); + + /* Verify number of objects */ + VERIFY(obj_list.nobjs_rem, nobjs_found, "obj_list.nobjs_rem"); + count = H5SL_count(obj_list.slist); + VERIFY(count, (size_t)nobjs_found, "H5SL_count"); + + /* Release the skip list, forcibly freeing all nodes (will not make + * callbacks) */ + ret = H5SL_release(obj_list.slist); + CHECK(ret, FAIL, "H5SL_release"); + + /* Verify number of objects is 0 */ + count = H5SL_count(obj_list.slist); + VERIFY(count, (size_t)0, "H5SL_count"); + } /* end for */ + + /* Close the skip list */ + ret = H5SL_close(obj_list.slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_try_free_safe() */ + +/**************************************************************** +** ** test_skiplist_less(): Test H5SL (skip list) code. ** Tests 'less' operation in skip lists. ** @@ -1577,6 +1779,7 @@ test_skiplist(void) test_skiplist_add(); /* Test 'add' operation */ test_skiplist_destroy(); /* Test 'destroy' operation */ test_skiplist_free(); /* Test 'free' operation */ + test_skiplist_try_free_safe(); /* Test 'try_free_safe' operation */ test_skiplist_less(); /* Test 'less' operation */ test_skiplist_greater(); /* Test 'greater' operation */ test_skiplist_below(); /* Test 'below' operation */ |