summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/tfile.c2
-rw-r--r--test/th5s.c194
-rw-r--r--test/trefer.c178
-rw-r--r--test/vds.c5
4 files changed, 329 insertions, 50 deletions
diff --git a/test/tfile.c b/test/tfile.c
index 677fd06..b630ee0 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -4967,7 +4967,7 @@ test_libver_bounds_real(H5F_libver_t libver_create, unsigned oh_vers_create,
#define VERBFNAME "tverbounds_dspace.h5"
#define VERBDSNAME "dataset 1"
#define SPACE1_DIM1 3
-static void
+static int
test_libver_bounds_open(void)
{
hid_t file = -1; /* File ID */
diff --git a/test/th5s.c b/test/th5s.c
index 0619571..9d5273f 100644
--- a/test/th5s.c
+++ b/test/th5s.c
@@ -93,6 +93,10 @@ struct space4_struct {
char c2;
} space4_data={'v',987123,-3.14F,'g'}; /* Test data for 4th dataspace */
+
+/* Used in test_h5s_encode_irregular_exceed32() and test_h5s_encode_points_exceed32() */
+#define POWER32 4294967296 /* 2^32 */
+
/****************************************************************
**
** test_h5s_basic(): Test basic H5S (dataspace) code.
@@ -2504,6 +2508,188 @@ test_versionbounds(void)
/****************************************************************
**
+** test_h5s_encode_regular_exceed32():
+** Test to verify HDFFV-9947 is fixed.
+** Verify that selection encoding that exceeds (2^32 - 1)
+** (32 bit integer limit) is correctly encoded.
+**
+** Note: See encoding changes for 1.10 in
+** "RFC: H5Sencode/H5Sdecode Format Change".
+**
+****************************************************************/
+static void
+test_h5s_encode_regular_exceed32(void)
+{
+ hid_t sid; /* Dataspace ID */
+ hid_t decoded_sid; /* Dataspace ID from H5Sdecode */
+ size_t sbuf_size=0; /* Buffer size for H5Sencode */
+ unsigned char *sbuf=NULL; /* Buffer for H5Sencode */
+ hssize_t num; /* Number of elements in the dataspace selection */
+ hssize_t decoded_num; /* Number of elements in the dataspace selection from H5Sdeocde */
+ hsize_t numparticles = 8388608;
+ unsigned num_dsets = 513;
+ hsize_t total_particles = numparticles * num_dsets;
+ hsize_t vdsdims[1] = {total_particles};
+ hsize_t start, count, block;
+ herr_t ret; /* Generic return value */
+
+ MESSAGE(5, ("Testing Dataspace encoding regular hyperslabs that exceeds 32 bits\n"));
+
+ /*-------------------------------------------------------------------------
+ * Test encoding and decoding of simple dataspace and hyperslab selection.
+ *-------------------------------------------------------------------------
+ */
+ sid = H5Screate_simple(1, vdsdims, NULL);
+ CHECK(sid, FAIL, "H5Screate_simple");
+
+ start = 0;
+ block = total_particles;
+ count = 1;
+
+ ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, &start, NULL, &count, &block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Encode simple data space in a buffer */
+ ret = H5Sencode(sid, NULL, &sbuf_size);
+ CHECK(ret, FAIL, "H5Sencode2");
+
+ if(sbuf_size > 0) {
+ sbuf = (unsigned char*)HDcalloc((size_t)1, sbuf_size);
+ CHECK(sbuf, NULL, "H5Sencode");
+ }
+
+ /* The version used for encoding should be 2 */
+ ret = H5Sencode(sid, sbuf, &sbuf_size);
+ CHECK(ret, FAIL, "H5Sencode");
+ VERIFY((uint32_t)sbuf[35], 2, "Version for regular hyperslab that exceeds 32 bits");
+
+ /* Decode from the dataspace buffer and return an object handle */
+ decoded_sid = H5Sdecode(sbuf);
+ CHECK(decoded_sid, FAIL, "H5Sdecode");
+
+ /* Verify the decoded dataspace */
+ decoded_num = H5Sget_select_npoints(decoded_sid);
+ CHECK(decoded_num, FAIL, "H5Sget_select_npoints");
+
+ num = H5Sget_select_npoints(sid);
+ CHECK(num, FAIL, "H5Sget_select_npoints");
+
+ VERIFY(num, decoded_num, "H5Sget_select_npoints");
+
+ ret = H5Sclose(decoded_sid);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ if(sbuf)
+ HDfree(sbuf);
+
+ ret = H5Sclose(sid);
+ CHECK(ret, FAIL, "H5Sclose");
+
+} /* test_h5s_encode_regular_exceed32() */
+
+/****************************************************************
+**
+** test_h5s_encode_irregular_exceed32():
+** This test verifies that 1.10 H5Sencode() will fail for
+** irregular hyperslab selection that exceeds 32 bits.
+**
+** Note: See encoding changes for 1.10 in
+** "RFC: H5Sencode/H5Sdecode Format Change".
+**
+****************************************************************/
+static void
+test_h5s_encode_irregular_exceed32(void)
+{
+ hid_t sid; /* Dataspace ID */
+ hsize_t numparticles = 8388608;
+ unsigned num_dsets = 513;
+ hsize_t total_particles = numparticles * num_dsets;
+ hsize_t vdsdims[1] = {total_particles}; /* Dimension size */
+ hsize_t start, stride, count, block; /* Selection info */
+ size_t sbuf_size=0; /* Buffer size for H5Sencode */
+ htri_t is_regular; /* Is this a regular hyperslab */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Dataspace encoding irregular hyperslab that exceeds 32 bits\n"));
+
+ sid = H5Screate_simple(1, vdsdims, NULL);
+ CHECK(sid, FAIL, "H5Screate_simple");
+
+ start = 0;
+ block = total_particles;
+ count = 1;
+
+ ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, &start, NULL, &count, &block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ start = 8;
+ count = 5;
+ block = 2;
+ stride = POWER32;
+
+ ret = H5Sselect_hyperslab(sid, H5S_SELECT_OR, &start, &stride, &count, &block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Should be irregular hyperslab */
+ is_regular = H5Sis_regular_hyperslab(sid);
+ VERIFY(is_regular, FALSE, "H5Sis_regular_hyperslab");
+
+ /* Should fail because selection exceeds 32 bits */
+ ret = H5Sencode(sid, NULL, &sbuf_size);
+ VERIFY(ret, FAIL, "H5Sencode");
+
+ ret = H5Sclose(sid);
+ CHECK(ret, FAIL, "H5Sclose");
+
+} /* test_h5s_encode_irregular_exceed32() */
+
+/****************************************************************
+**
+** test_h5s_encode_points_exceed32():
+** This test verifies that 1.10 H5Sencode() will fail for
+** point selection that exceeds 32 bits.
+**
+** Note: See encoding changes for 1.10 in
+** "RFC: H5Sencode/H5Sdecode Format Change".
+**
+****************************************************************/
+static void
+test_h5s_encode_points_exceed32(void)
+{
+ hid_t sid; /* Dataspace ID */
+ hsize_t numparticles = 8388608;
+ unsigned num_dsets = 513;
+ hsize_t total_particles = numparticles * num_dsets;
+ hsize_t vdsdims[1] = {total_particles}; /* Dimension size */
+ hsize_t coord[4]; /* The point coordinates */
+ size_t sbuf_size=0; /* Buffer size for H5Sencode */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Dataspace encoding points selection that exceeds 32 bits\n"));
+
+ sid = H5Screate_simple(1, vdsdims, NULL);
+ CHECK(sid, FAIL, "H5Screate_simple");
+
+ coord[0] = 5;
+ coord[1] = 15;
+ coord[2] = POWER32;
+ coord[3] = 19;
+ ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)4, coord);
+ CHECK(ret, FAIL, "H5Sselect_elements");
+
+ /* Should fail because selection exceeds 32 bits */
+ ret = H5Sencode(sid, NULL, &sbuf_size);
+ VERIFY(ret, FAIL, "H5Sencode");
+
+ ret = H5Sclose(sid);
+ CHECK(ret, FAIL, "H5Sclose");
+
+} /* test_h5s_encode_points_exceed32() */
+
+/****************************************************************
+**
** test_h5s(): Main H5S (dataspace) testing routine.
**
****************************************************************/
@@ -2517,8 +2703,12 @@ test_h5s(void)
test_h5s_null(); /* Test Null dataspace H5S code */
test_h5s_zero_dim(); /* Test dataspace with zero dimension size */
test_h5s_encode(); /* Test encoding and decoding */
- test_h5s_scalar_write(); /* Test scalar H5S writing code */
- test_h5s_scalar_read(); /* Test scalar H5S reading code */
+ test_h5s_encode_regular_exceed32(); /* Test encoding regular hyperslab selection that exceeds 32 bits */
+ test_h5s_encode_irregular_exceed32(); /* Testing encoding irregular hyperslab selection that exceeds 32 bits */
+ test_h5s_encode_points_exceed32(); /* Testing encoding point selection that exceeds 32 bits */
+
+ test_h5s_scalar_write(); /* Test scalar H5S writing code */
+ test_h5s_scalar_read(); /* Test scalar H5S reading code */
test_h5s_compound_scalar_write(); /* Test compound datatype scalar H5S writing code */
test_h5s_compound_scalar_read(); /* Test compound datatype scalar H5S reading code */
diff --git a/test/trefer.c b/test/trefer.c
index 7cbb77f..55172c0 100644
--- a/test/trefer.c
+++ b/test/trefer.c
@@ -490,46 +490,70 @@ test_reference_obj(void)
** test_reference_region(): Test basic H5R (reference) object reference code.
** Tests references to various kinds of objects
**
+** Add test to verify that dataspace selection exceeding
+** 32 bits is correctly encoded and referenced.
+**
+** Note: The "new_format" parameter is added to create the file with
+** either the old or latest format. This is done so that the
+** 1.10 encoding of dataspace selection for H5R_DATASET_REGION
+** in the internal library will be done according to the file
+** format setting in fapl.
+** See encoding changes for 1.10 in
+** "RFC: H5Sencode/H5Sdecode Format Change".
+**
****************************************************************/
static void
-test_reference_region(void)
+test_reference_region(hbool_t new_format)
{
- hid_t fid1; /* HDF5 File IDs */
- hid_t dset1, /* Dataset ID */
- dset2; /* Dereferenced dataset ID */
- hid_t sid1, /* Dataspace ID #1 */
- sid2; /* Dataspace ID #2 */
- hid_t dapl_id; /* Dataset access property list */
- hsize_t dims1[] = {SPACE1_DIM1},
- dims2[] = {SPACE2_DIM1, SPACE2_DIM2};
- hsize_t start[SPACE2_RANK]; /* Starting location of hyperslab */
- hsize_t stride[SPACE2_RANK]; /* Stride of hyperslab */
- hsize_t count[SPACE2_RANK]; /* Element count of hyperslab */
- hsize_t block[SPACE2_RANK]; /* Block size of hyperslab */
- hsize_t coord1[POINT1_NPOINTS][SPACE2_RANK]; /* Coordinates for point selection */
- hsize_t * coords; /* Coordinate buffer */
- hsize_t low[SPACE2_RANK]; /* Selection bounds */
- hsize_t high[SPACE2_RANK]; /* Selection bounds */
- hdset_reg_ref_t *wbuf, /* buffer to write to disk */
- *rbuf; /* buffer read from disk */
- hdset_reg_ref_t nvrbuf[3]={{0},{101},{255}}; /* buffer with non-valid refs */
- uint8_t *dwbuf, /* Buffer for writing numeric data to disk */
- *drbuf; /* Buffer for reading numeric data from disk */
- uint8_t *tu8; /* Temporary pointer to uint8 data */
- H5O_type_t obj_type; /* Type of object */
- int i, j; /* counting variables */
- hssize_t hssize_ret; /* hssize_t return value */
- htri_t tri_ret; /* htri_t return value */
- herr_t ret; /* Generic return value */
- haddr_t addr = HADDR_UNDEF; /* test for undefined reference */
- hid_t dset_NA; /* Dataset id for undefined reference */
- hid_t space_NA; /* Dataspace id for undefined reference */
- hsize_t dims_NA[1] = {1}; /* Dims array for undefined reference */
- hdset_reg_ref_t wdata_NA[1], /* Write buffer */
- rdata_NA[1]; /* Read buffer */
+ hid_t fid1; /* HDF5 File IDs */
+ hid_t fapl = -1; /* File access property list */
+ hid_t dset1, /* Dataset ID */
+ dset2, /* Dereferenced dataset ID */
+ dset3; /* Dereferenced dataset ID */
+ hid_t sid1, /* Dataspace ID #1 */
+ sid2, /* Dataspace ID #2 */
+ sid3; /* Dataspace ID #3 */
+ hid_t dapl_id; /* Dataset access property list */
+ hsize_t dims1[] = {SPACE1_DIM1},
+ dims2[] = {SPACE2_DIM1, SPACE2_DIM2};
+ hsize_t start[SPACE2_RANK]; /* Starting location of hyperslab */
+ hsize_t stride[SPACE2_RANK]; /* Stride of hyperslab */
+ hsize_t count[SPACE2_RANK]; /* Element count of hyperslab */
+ hsize_t block[SPACE2_RANK]; /* Block size of hyperslab */
+ hsize_t coord1[POINT1_NPOINTS][SPACE2_RANK]; /* Coordinates for point selection */
+ hsize_t *coords; /* Coordinate buffer */
+ hsize_t low[SPACE2_RANK]; /* Selection bounds */
+ hsize_t high[SPACE2_RANK]; /* Selection bounds */
+ hdset_reg_ref_t *wbuf, /* buffer to write to disk */
+ *rbuf; /* buffer read from disk */
+ hdset_reg_ref_t nvrbuf[3]={{0},{101},{255}}; /* buffer with non-valid refs */
+ uint8_t *dwbuf, /* Buffer for writing numeric data to disk */
+ *drbuf; /* Buffer for reading numeric data from disk */
+ uint8_t *tu8; /* Temporary pointer to uint8 data */
+ H5O_type_t obj_type; /* Type of object */
+ int i, j; /* counting variables */
+ hssize_t hssize_ret; /* hssize_t return value */
+ htri_t tri_ret; /* htri_t return value */
+ herr_t ret; /* Generic return value */
+ haddr_t addr = HADDR_UNDEF; /* test for undefined reference */
+ hid_t dset_NA; /* Dataset id for undefined reference */
+ hid_t space_NA; /* Dataspace id for undefined reference */
+ hsize_t dims_NA[1] = {1}; /* Dims array for undefined reference */
+ hdset_reg_ref_t wdata_NA[1], /* Write buffer */
+ rdata_NA[1]; /* Read buffer */
+ hsize_t numparticles = 8388608;
+ hsize_t ret_particles;
+ unsigned num_dsets = 513;
+ hsize_t total_particles = numparticles * num_dsets;
+ hsize_t vdsdims[1] = {total_particles};
+ hsize_t start3, count3, block3;
/* Output message about test being performed */
- MESSAGE(5, ("Testing Dataset Region Reference Functions\n"));
+ if(new_format) {
+ MESSAGE(5, ("Testing Dataset Region Reference Functions for new format\n"));
+ } else {
+ MESSAGE(5, ("Testing Dataset Region Reference Functions for old format\n"));
+ }
/* Allocate write & read buffers */
wbuf = (hdset_reg_ref_t *)HDcalloc(sizeof(hdset_reg_ref_t), (size_t)SPACE1_DIM1);
@@ -537,8 +561,16 @@ test_reference_region(void)
dwbuf = (uint8_t *)HDmalloc(sizeof(uint8_t) * SPACE2_DIM1 * SPACE2_DIM2);
drbuf = (uint8_t *)HDcalloc(sizeof(uint8_t), (size_t)(SPACE2_DIM1 * SPACE2_DIM2));
+ /* Set to use the latest file format */
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ CHECK(fapl, FAIL, "H5Pcreate");
+ if(new_format) {
+ ret = H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
+ CHECK(ret, FAIL, "H5Pset_libver_bounds");
+ }
+
/* Create file */
- fid1 = H5Fcreate(FILE2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ fid1 = H5Fcreate(FILE2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
CHECK(fid1, FAIL, "H5Fcreate");
/* Create dataspace for datasets */
@@ -564,11 +596,30 @@ test_reference_region(void)
ret = H5Dclose(dset2);
CHECK(ret, FAIL, "H5Dclose");
+ /* Create dataspace with selection exceeding 32 bits */
+ sid3 = H5Screate_simple(1, vdsdims, NULL);
+ CHECK(sid3, FAIL, "H5Screate_simple");
+
+ start3 = 0;
+ block3 = total_particles;
+ count3 = 1;
+
+ ret = H5Sselect_hyperslab(sid3, H5S_SELECT_SET, &start3, NULL, &count3, &block3);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Create the dataset with dataspace exceeding 32 bits */
+ dset3 = H5Dcreate2(fid1, "Dataset3", H5T_STD_U8LE, sid3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dset3, FAIL, "H5Dcreate2");
+
+ /* Close Dataset */
+ ret = H5Dclose(dset3);
+ CHECK(ret, FAIL, "H5Dclose");
+
/* Create dataspace for the reference dataset */
sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
CHECK(sid1, FAIL, "H5Screate_simple");
- /* Create a dataset */
+ /* Create the reference dataset */
dset1 = H5Dcreate2(fid1, "Dataset1", H5T_STD_REF_DSETREG, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(ret, FAIL, "H5Dcreate2");
@@ -627,10 +678,18 @@ test_reference_region(void)
/* Store third dataset region */
ret = H5Rcreate(&wbuf[2], fid1, "/Dataset2", H5R_DATASET_REGION, sid2);
CHECK(ret, FAIL, "H5Rcreate");
- ret = H5Rget_obj_type2(dset1, H5R_DATASET_REGION, &wbuf[0], &obj_type);
+ ret = H5Rget_obj_type2(dset1, H5R_DATASET_REGION, &wbuf[2], &obj_type);
CHECK(ret, FAIL, "H5Rget_obj_type2");
VERIFY(obj_type, H5O_TYPE_DATASET, "H5Rget_obj_type2");
+ /* Store fourth dataset region */
+ ret = H5Rcreate(&wbuf[3], fid1, "/Dataset3", H5R_DATASET_REGION, sid3);
+ CHECK(ret, FAIL, "H5Rcreate");
+ ret = H5Rget_obj_type2(dset1, H5R_DATASET_REGION, &wbuf[3], &obj_type);
+ CHECK(ret, FAIL, "H5Rget_obj_type2");
+ VERIFY(obj_type, H5O_TYPE_DATASET, "H5Rget_obj_type2");
+
+
/* Write selection to disk */
ret = H5Dwrite(dset1, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT, wbuf);
CHECK(ret, FAIL, "H5Dwrite");
@@ -672,6 +731,9 @@ test_reference_region(void)
ret = H5Sclose(sid2);
CHECK(ret, FAIL, "H5Sclose");
+ ret = H5Sclose(sid3);
+ CHECK(ret, FAIL, "H5Sclose");
+
/* Close file */
ret = H5Fclose(fid1);
CHECK(ret, FAIL, "H5Fclose");
@@ -727,6 +789,28 @@ test_reference_region(void)
dset2 = H5Rdereference2(dset1, dapl_id, H5R_DATASET_REGION, &addr);
VERIFY(dset2, FAIL, "H5Rdereference2 haddr_undef");
+
+ /* Try to open the referenced dataset with dataspace exceeding 32 bits */
+ dset3 = H5Rdereference2(dset1, dapl_id, H5R_DATASET_REGION, &rbuf[3]);
+ CHECK(dset3, FAIL, "H5Rdereference2");
+
+ /* Check what H5Rget_obj_type2 function returns */
+ ret = H5Rget_obj_type2(dset1, H5R_DATASET_REGION, &rbuf[3], &obj_type);
+ CHECK(ret, FAIL, "H5Rget_obj_type2");
+ VERIFY(obj_type, H5O_TYPE_DATASET, "H5Rget_obj_type2");
+
+ /* Check information in the referenced dataset */
+ sid3 = H5Dget_space(dset3);
+ CHECK(sid3, FAIL, "H5Dget_space");
+ ret_particles = H5Sget_select_npoints(sid3);
+ VERIFY(ret_particles, total_particles, "H5Sget_select_npoints");
+
+ /* Close the dataspace and dataset */
+ ret = H5Sclose(sid3);
+ CHECK(ret, FAIL, "H5Sclose");
+ ret = H5Dclose(dset3);
+ CHECK(ret, FAIL, "H5Dclose");
+
/* Try to open objects */
dset2 = H5Rdereference2(dset1, dapl_id, H5R_DATASET_REGION, &rbuf[0]);
CHECK(dset2, FAIL, "H5Rdereference2");
@@ -889,7 +973,7 @@ test_reference_region(void)
**
****************************************************************/
static void
-test_reference_region_1D(void)
+test_reference_region_1D(hbool_t new_format)
{
hid_t fid1; /* HDF5 File IDs */
hid_t dset1, /* Dataset ID */
@@ -1736,14 +1820,16 @@ test_reference(void)
/* Output message about test being performed */
MESSAGE(5, ("Testing References\n"));
- test_reference_params(); /* Test for correct parameter checking */
- test_reference_obj(); /* Test basic H5R object reference code */
- test_reference_region(); /* Test basic H5R dataset region reference code */
- test_reference_region_1D(); /* Test H5R dataset region reference code for 1-D datasets */
- test_reference_obj_deleted(); /* Test H5R object reference code for deleted objects */
- test_reference_group(); /* Test operations on dereferenced groups */
+ test_reference_params(); /* Test for correct parameter checking */
+ test_reference_obj(); /* Test basic H5R object reference code */
+ test_reference_region(FALSE); /* Test basic H5R dataset region reference code */
+ test_reference_region(TRUE); /* Test basic H5R dataset region reference code */
+ test_reference_region_1D(FALSE); /* Test H5R dataset region reference code for 1-D datasets */
+ test_reference_region_1D(TRUE); /* Test H5R dataset region reference code for 1-D datasets */
+ test_reference_obj_deleted(); /* Test H5R object reference code for deleted objects */
+ test_reference_group(); /* Test operations on dereferenced groups */
#ifndef H5_NO_DEPRECATED_SYMBOLS
- test_reference_compat(); /* Test operations with old API routines */
+ test_reference_compat(); /* Test operations with old API routines */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
} /* test_reference() */
diff --git a/test/vds.c b/test/vds.c
index 7a659cb..42bb0b8 100644
--- a/test/vds.c
+++ b/test/vds.c
@@ -618,7 +618,10 @@ test_api(test_api_config_t config, hid_t fapl)
TEST_ERROR
/* Get examination DCPL */
- if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)213) < 0)
+
+
+ /* Should be a value of 174, not 213. HDFFV-10469 */
+ if(test_api_get_ex_dcpl(config, fapl, dcpl, &ex_dcpl, vspace[0], filename, (hsize_t)174) < 0)
TEST_ERROR
/* Test H5Pget_virtual_count */