1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * All rights reserved.                                                      *
4  *                                                                           *
5  * This file is part of HDF5. The full HDF5 copyright notice, including      *
6  * terms governing use, modification, and redistribution, is contained in    *
7  * the COPYING file, which can be found at the root of the source code       *
8  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
9  * If you do not have access to either file, you may request a copy from     *
10  * help@hdfgroup.org.                                                        *
11  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 /*
13  * Programmer:	Raymond Lu
14  *              24 April 2013
15  *
16  * Purpose:	Tests H5Zunregister function
17  */
18 #include "h5test.h"
19 
20 #include "H5CXprivate.h"        /* API Contexts                         */
21 
22 const char *FILENAME[] = {
23     "unregister_filter_1",
24     "unregister_filter_2",
25     NULL
26 };
27 
28 #define GROUP_NAME              "test_group"
29 #define DSET_NAME               "test_dataset"
30 #define FILENAME_BUF_SIZE       1024
31 #define DSET_DIM1               100
32 #define DSET_DIM2               200
33 #define FILTER_CHUNK_DIM1       2
34 #define FILTER_CHUNK_DIM2       25
35 #define GROUP_ITERATION         1000
36 
37 #define H5Z_FILTER_DUMMY        312
38 
39 static size_t do_nothing(unsigned int flags, size_t cd_nelmts,
40     const unsigned int *cd_values, size_t nbytes, size_t *buf_size, void **buf);
41 
42 /* Dummy filter for test_unregister_filters only */
43 const H5Z_class2_t H5Z_DUMMY[1] = {{
44     H5Z_CLASS_T_VERS,           /* H5Z_class_t version              */
45     H5Z_FILTER_DUMMY,           /* Filter ID number                 */
46     1, 1,                       /* Encoding and decoding enabled    */
47     "dummy",                    /* Filter name for debugging        */
48     NULL,                       /* The "can apply" callback         */
49     NULL,                       /* The "set local" callback         */
50     do_nothing,                 /* The actual filter function       */
51 }};
52 
53 
54 /*-------------------------------------------------------------------------
55  * Function:    do_nothing
56  *
57  * Purpose:     A dummy compression method that doesn't do anything. This
58  *              filter is only for test_unregister_filters. Please don't
59  *              use it for other tests because it may mess up this test.
60  *
61  * Return:      Data chunk size
62  *
63  *-------------------------------------------------------------------------
64  */
65 static size_t
do_nothing(unsigned int H5_ATTR_UNUSED flags,size_t H5_ATTR_UNUSED cd_nelmts,const unsigned int H5_ATTR_UNUSED * cd_values,size_t nbytes,size_t H5_ATTR_UNUSED * buf_size,void H5_ATTR_UNUSED ** buf)66 do_nothing(unsigned int H5_ATTR_UNUSED flags, size_t H5_ATTR_UNUSED cd_nelmts,
67       const unsigned int H5_ATTR_UNUSED *cd_values, size_t nbytes,
68       size_t H5_ATTR_UNUSED *buf_size, void H5_ATTR_UNUSED **buf)
69 {
70     return nbytes;
71 }
72 
73 /*-------------------------------------------------------------------------
74  * Function:    test_unregister_filters
75  *
76  * Purpose:     Tests unregistering filter before closing the file
77  *
78  * Return:      SUCCEED/FAIL
79  *
80  *-------------------------------------------------------------------------
81  */
82 static herr_t
test_unregister_filters(hid_t fapl_id)83 test_unregister_filters(hid_t fapl_id)
84 {
85     hid_t       fid1        = H5I_INVALID_HID;
86     hid_t       fid2        = H5I_INVALID_HID;
87     hid_t       dcpl_id     = H5I_INVALID_HID;
88     hid_t       gcpl_id     = H5I_INVALID_HID;
89     hid_t       gid         = H5I_INVALID_HID;
90     hid_t       gid_loop    = H5I_INVALID_HID;
91     hid_t       did         = H5I_INVALID_HID;
92     hid_t       sid         = H5I_INVALID_HID;
93     int         i, j, n;
94     char        group_name[32];
95     char        filename[FILENAME_BUF_SIZE];
96     const hsize_t chunk_dims[2] = {FILTER_CHUNK_DIM1, FILTER_CHUNK_DIM2};  /* Chunk dimensions */
97     hsize_t     dims[2];
98     int	        data[DSET_DIM1][DSET_DIM2];
99     herr_t      ret;
100 
101     TESTING("Unregistering filter");
102 
103     /* Create first file */
104     h5_fixname(FILENAME[0], fapl_id, filename, sizeof(filename));
105     if((fid1 = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
106         goto error;
107 
108     /* Create second file */
109     h5_fixname(FILENAME[1], fapl_id, filename, sizeof(filename));
110     if((fid2 = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id)) < 0)
111         goto error;
112 
113     /* Register DUMMY filter */
114     if (H5Zregister(H5Z_DUMMY) < 0)
115         goto error;
116     if (H5Zfilter_avail(H5Z_FILTER_DUMMY) != TRUE)
117         goto error;
118 
119     /*******************
120      * PART 1 - GROUPS *
121      *******************/
122 
123     /* Use DUMMY filter for creating groups */
124     if((gcpl_id = H5Pcreate(H5P_GROUP_CREATE)) < 0)
125         goto error;
126     if(H5Pset_filter(gcpl_id, H5Z_FILTER_DUMMY, H5Z_FLAG_MANDATORY, (size_t)0, NULL) < 0)
127         goto error;
128 
129     /* Create a group using this filter */
130     if((gid = H5Gcreate2(fid1, GROUP_NAME, H5P_DEFAULT, gcpl_id, H5P_DEFAULT)) < 0)
131         goto error;
132 
133     /* Create multiple groups under the main group */
134     for(i = 0; i < GROUP_ITERATION; i++) {
135         HDsprintf(group_name, "group_%d", i);
136         if((gid_loop = H5Gcreate2(gid, group_name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
137             goto error;
138         if(H5Gclose(gid_loop) < 0)
139             goto error;
140     }
141 
142     /* Flush the file containing the groups */
143     if(H5Fflush(fid1, H5F_SCOPE_GLOBAL) < 0)
144         goto error;
145 
146     /* Unregister the filter before closing the group.  It should fail */
147     H5E_BEGIN_TRY {
148         ret = H5Zunregister(H5Z_FILTER_DUMMY);
149     } H5E_END_TRY;
150     if(ret >= 0) {
151         H5_FAILED();
152         HDprintf("    Line %d: Should not be able to unregister filter\n", __LINE__);
153         goto error;
154     }
155 
156     /* Close the group */
157     if(H5Gclose(gid) < 0)
158         goto error;
159 
160     /* Clean up objects used for this test */
161     if(H5Pclose (gcpl_id) < 0)
162         goto error;
163 
164     /*********************
165      * PART 2 - DATASETS *
166      *********************/
167 
168     /* Use DUMMY filter for creating datasets */
169     if((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
170         goto error;
171     if(H5Pset_chunk(dcpl_id, 2, chunk_dims) < 0)
172         goto error;
173     if(H5Pset_filter(dcpl_id, H5Z_FILTER_DUMMY, 0, (size_t)0, NULL) < 0)
174         goto error;
175 
176     /* Initialize the data for writing */
177     for(i = n = 0; i < DSET_DIM1; i++)
178         for(j = 0; j < DSET_DIM2; j++)
179             data[i][j] = n++;
180 
181     /* Create the dataspace */
182     dims[0] = DSET_DIM1;
183     dims[1] = DSET_DIM2;
184     if((sid = H5Screate_simple(2, dims, NULL)) < 0)
185         goto error;
186 
187     /* Create a dataset in the first file */
188     if((did = H5Dcreate2(fid1, DSET_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
189         goto error;
190 
191     /* Write the data to the dataset */
192     if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
193         goto error;
194 
195     /* Unregister the filter before closing the dataset.  It should fail */
196     H5E_BEGIN_TRY {
197         ret = H5Zunregister(H5Z_FILTER_DUMMY);
198     } H5E_END_TRY;
199     if(ret >= 0) {
200         H5_FAILED();
201         HDprintf("    Line %d: Should not be able to unregister filter\n", __LINE__);
202         goto error;
203     }
204 
205     /* Close the dataset */
206     if(H5Dclose(did) < 0)
207         goto error;
208 
209     /* Create a dataset in the second file */
210     if((did = H5Dcreate2(fid2, DSET_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
211         goto error;
212 
213     /* Write the data to the dataset */
214     if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
215         goto error;
216 
217     /* Close the dataset in the second file */
218     if(H5Dclose(did) < 0)
219         goto error;
220 
221     /* Unregister the filter after closing all objects but before closing files.
222      * It should flush all files.
223      */
224     if(H5Zunregister(H5Z_FILTER_DUMMY) < 0)
225         goto error;
226 
227     /* Clean up objects used for this test */
228     if(H5Pclose(dcpl_id) < 0)
229         goto error;
230     if(H5Fclose(fid1) < 0)
231         goto error;
232     if(H5Fclose(fid2) < 0)
233         goto error;
234 
235     PASSED();
236     return SUCCEED;
237 
238 error:
239     H5E_BEGIN_TRY {
240         H5Fclose(fid1);
241         H5Fclose(fid2);
242         H5Pclose(dcpl_id);
243         H5Pclose(gcpl_id);
244         H5Gclose(gid);
245         H5Gclose(gid_loop);
246         H5Dclose(did);
247         H5Sclose(sid);
248     } H5E_END_TRY;
249 
250     return FAIL;
251 }
252 
253 
254 /*-------------------------------------------------------------------------
255  * Function:    main
256  *
257  * Purpose:     Tests unregistering filter with H5Zunregister
258  *
259  * Return:      EXIT_SUCCESS/EXIT_FAILURE
260  *
261  *-------------------------------------------------------------------------
262  */
263 int
main(void)264 main(void)
265 {
266     hid_t       fapl_id = H5I_INVALID_HID;
267     int         nerrors = 0;
268     hbool_t     api_ctx_pushed = FALSE;             /* Whether API context pushed */
269 
270     /* Testing setup */
271     h5_reset();
272     fapl_id = h5_fileaccess();
273 
274     /* Push API context */
275     if(H5CX_push() < 0) FAIL_STACK_ERROR
276     api_ctx_pushed = TRUE;
277 
278     /* Test unregistering filter in its own file */
279     nerrors += (test_unregister_filters(fapl_id) < 0           ? 1 : 0);
280 
281     h5_cleanup(FILENAME, fapl_id);
282 
283     if (nerrors)
284         goto error;
285     HDprintf("All filter unregistration tests passed.\n");
286 
287     /* Pop API context */
288     if(api_ctx_pushed && H5CX_pop() < 0) FAIL_STACK_ERROR
289     api_ctx_pushed = FALSE;
290 
291 
292     HDexit(EXIT_SUCCESS);
293 
294 error:
295     nerrors = MAX(1, nerrors);
296     HDprintf("***** %d FILTER UNREGISTRATION TEST%s FAILED! *****\n",
297             nerrors, 1 == nerrors ? "" : "S");
298 
299     if(api_ctx_pushed) H5CX_pop();
300 
301     HDexit(EXIT_FAILURE);
302 } /* end main() */
303 
304