1 /* This is part of the netCDF package.
2    Copyright 2005 University Corporation for Atmospheric Research/Unidata
3    See COPYRIGHT file for conditions of use.
4 
5    Test HDF5 file code. These are not intended to be exhaustive tests,
6    but they use HDF5 the same way that netCDF-4 does, so if these
7    tests don't work, than netCDF-4 won't work either.
8 
9    This files tests dataset creation and writing.
10 */
11 
12 #include "h5_err_macros.h"
13 #include <hdf5.h>
14 
15 #define FILE_NAME "tst_h_vars.h5"
16 #define GRP_NAME "Henry_V"
17 #define VAR_BOOL_NAME "Southhamptons_Battle_Record"
18 #define GRP2_NAME "Some_3D_Met_Data"
19 #define DIM1_LEN 3
20 #define MAX_DIMS 255
21 
22 int
main()23 main()
24 {
25    hid_t fileid, grpid, spaceid, datasetid;
26    int bool_out[DIM1_LEN] = {0, 1, 0};
27    hsize_t dims[1];
28 
29    printf("\n*** Checking HDF5 variable functions.\n");
30    printf("*** Checking HDF5 boolen variables...");
31 
32    /* Open file and create group. */
33    if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
34 			   H5P_DEFAULT)) < 0) ERR;
35    if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
36 
37    /* Write an array of bools. */
38    dims[0] = DIM1_LEN;
39    if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
40    if ((datasetid = H5Dcreate(grpid, VAR_BOOL_NAME, H5T_NATIVE_HBOOL,
41 			      spaceid, H5P_DEFAULT)) < 0) ERR;
42    if (H5Dwrite(datasetid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, H5P_DEFAULT,
43 		bool_out) < 0) ERR;
44    if (H5Dclose(datasetid) < 0 ||
45        H5Sclose(spaceid) < 0 ||
46        H5Gclose(grpid) < 0 ||
47        H5Fclose(fileid) < 0)
48       ERR;
49 
50    SUMMARIZE_ERR;
51 
52    printf("*** Checking HDF5 variable with unlimited dimension...");
53    {
54 #define LAT_LEN 2
55 #define LON_LEN 3
56 #define NDIMS 3
57 #define LAT_NAME "Lat"
58 #define LON_NAME "Lon"
59 #define TIME_NAME "Time"
60 #define PRES_NAME "Pressure"
61 #define TEMP_NAME "Temperature"
62 
63       hid_t fileid, grpid, spaceid, write_spaceid, spaceid_in, mem_spaceid;
64       hid_t pres_dsid, temp_dsid, cparmsid;
65       float float_data_out[LAT_LEN][LON_LEN];
66       hsize_t dims[NDIMS], max_dims[NDIMS];
67       hsize_t dims_in[NDIMS], max_dims_in[NDIMS];
68       hsize_t start[MAX_DIMS], count[MAX_DIMS];
69       int lat, lon;
70 
71       /* Set up some phoney data, 1 record's worth. In C, first
72        * dimension varies most slowly. */
73       for (lat = 0; lat < LAT_LEN; lat++)
74 	 for (lon = 0; lon < LON_LEN; lon++)
75 	    float_data_out[lat][lon] = -666.666;
76 
77       /* Create file and group. */
78       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
79 			      H5P_DEFAULT)) < 0) ERR;
80       if ((grpid = H5Gcreate(fileid, GRP2_NAME, 0)) < 0) ERR;
81 
82       /* Create a space corresponding to these three dimensions. */
83       dims[0] = 0;
84       dims[1] = LAT_LEN;
85       dims[2] = LON_LEN;
86       max_dims[0] = H5S_UNLIMITED;
87       max_dims[1] = LAT_LEN;
88       max_dims[2] = LON_LEN;
89       if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;
90 
91       /* Enable chunking for unlimited datasets.  */
92       if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
93       dims[0] = 1;
94       dims[1] = 1;
95       dims[2] = 1;
96       if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
97 
98       /* Create two variables which use this space. */
99       if ((pres_dsid = H5Dcreate(grpid, PRES_NAME, H5T_NATIVE_FLOAT,
100 				 spaceid, cparmsid)) < 0) ERR;
101       if ((temp_dsid = H5Dcreate(grpid, TEMP_NAME, H5T_NATIVE_FLOAT,
102 				 spaceid, cparmsid)) < 0) ERR;
103 
104       /* Get the spaceid and check various things. */
105       if ((spaceid_in = H5Dget_space(pres_dsid)) < 0) ERR;
106       if (H5Sget_simple_extent_dims(spaceid_in, dims_in,
107 				    max_dims_in) < 0) ERR;
108       if (dims_in[0] != 0 || dims_in[1] != LAT_LEN || dims_in[2] != LON_LEN) ERR;
109       if (max_dims_in[0] != H5S_UNLIMITED || max_dims_in[1] != LAT_LEN || max_dims_in[2] != LON_LEN) ERR;
110 
111       /* Extend each of them to hold one record. */
112       dims[0] = 1;
113       dims[1] = LAT_LEN;
114       dims[2] = LON_LEN;
115       if (H5Dextend(pres_dsid, dims) < 0) ERR;
116       if (H5Dextend(temp_dsid, dims) < 0) ERR;
117 
118       /* Create a space to deal with one record at a time in memory. */
119       if ((mem_spaceid = H5Screate_simple(NDIMS, dims, NULL)) < 0) ERR;
120 
121       /* Create a space to write one record. */
122       if ((write_spaceid = H5Screate_simple(NDIMS, dims, NULL)) < 0) ERR;
123 
124       /* Write one record of data to each dataset. */
125       if (H5Dwrite(pres_dsid, H5T_IEEE_F32BE, mem_spaceid, write_spaceid,
126 		   H5P_DEFAULT, float_data_out) < 0) ERR;
127       if (H5Dwrite(temp_dsid, H5T_IEEE_F32LE, mem_spaceid, write_spaceid,
128 		   H5P_DEFAULT, float_data_out) < 0) ERR;
129 
130       /* Get the spaceid and check various things. */
131       if ((spaceid_in = H5Dget_space(temp_dsid)) < 0) ERR;
132       if (H5Sget_simple_extent_dims(spaceid_in, dims_in,
133 				    max_dims_in) < 0) ERR;
134       if (dims_in[0] != 1 || dims_in[1] != LAT_LEN || dims_in[2] != LON_LEN) ERR;
135       if (max_dims_in[0] != H5S_UNLIMITED || max_dims_in[1] != LAT_LEN || max_dims_in[2] != LON_LEN) ERR;
136 
137       /* Extend each of them to hold a second record. */
138       dims[0] = 2;
139       dims[1] = LAT_LEN;
140       dims[2] = LON_LEN;
141       if (H5Dextend(pres_dsid, dims) < 0) ERR;
142       if (H5Dextend(temp_dsid, dims) < 0) ERR;
143 
144       /* Create a space to write second record. */
145       if ((write_spaceid = H5Screate_simple(NDIMS, dims, NULL)) < 0) ERR;
146       count[0] = 1;
147       count[1] = LAT_LEN;
148       count[2] = LON_LEN;
149       start[0] = 1;
150       start[1] = 0;
151       start[2] = 0;
152       if (H5Sselect_hyperslab(write_spaceid, H5S_SELECT_SET,
153 			      start, NULL, count, NULL) < 0) ERR;
154 
155       /* Write second record of data to each dataset. */
156       if (H5Dwrite(pres_dsid, H5T_IEEE_F32LE, mem_spaceid, write_spaceid,
157 		   H5P_DEFAULT, float_data_out) < 0) ERR;
158       if (H5Dwrite(temp_dsid, H5T_IEEE_F32LE, mem_spaceid, write_spaceid,
159 		   H5P_DEFAULT, float_data_out) < 0) ERR;
160 
161       /* Get the spaceid and check various things. */
162       if ((spaceid_in = H5Dget_space(pres_dsid)) < 0) ERR;
163       if (H5Sget_simple_extent_dims(spaceid_in, dims_in,
164 				    max_dims_in) < 0) ERR;
165       if (dims_in[0] != 2 || dims_in[1] != LAT_LEN || dims_in[2] != LON_LEN) ERR;
166       if (max_dims_in[0] != H5S_UNLIMITED || max_dims_in[1] != LAT_LEN || max_dims_in[2] != LON_LEN) ERR;
167 
168       /* Close up the shop. */
169       if (H5Dclose(pres_dsid) < 0 ||
170 	  H5Dclose(temp_dsid) < 0 ||
171 	  H5Sclose(spaceid) < 0 ||
172 	  H5Gclose(grpid) < 0 ||
173 	  H5Fclose(fileid) < 0) ERR;
174 
175    }
176 
177    SUMMARIZE_ERR;
178    printf("*** Checking HDF5 deflate filter setting and getting...");
179 #define DEFLATE_LEVEL 9
180 #define MAX_NAME 100
181 #define NUM_CD_ELEM 10
182 /* HDF5 defines this... */
183 #define DEFLATE_NAME "deflate"
184    {
185       H5Z_filter_t filter;
186       int num_filters;
187       hid_t propid;
188       unsigned int flags, cd_values[NUM_CD_ELEM], filter_config;
189       size_t cd_nelems = NUM_CD_ELEM;
190       size_t namelen = MAX_NAME;
191       char name[MAX_NAME + 1];
192 
193 
194       /* Open file and create group. */
195       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
196 			      H5P_DEFAULT)) < 0) ERR;
197       if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
198 
199       /* Write an array of bools, with compression. */
200       dims[0] = DIM1_LEN;
201       if ((propid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
202       if (H5Pset_layout(propid, H5D_CHUNKED)) ERR;
203       if (H5Pset_chunk(propid, 1, dims)) ERR;
204       if (H5Pset_deflate(propid, DEFLATE_LEVEL)) ERR;
205       if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
206       if ((datasetid = H5Dcreate(grpid, VAR_BOOL_NAME, H5T_NATIVE_HBOOL,
207 				 spaceid, propid)) < 0) ERR;
208       if (H5Dwrite(datasetid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, H5P_DEFAULT,
209 		   bool_out) < 0) ERR;
210       if (H5Dclose(datasetid) < 0 ||
211 	  H5Pclose(propid) < 0 ||
212 	  H5Sclose(spaceid) < 0 ||
213 	  H5Gclose(grpid) < 0 ||
214 	  H5Fclose(fileid) < 0)
215 	 ERR;
216 
217       /* Now reopen the file and check. */
218       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR;
219       if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
220       if ((datasetid = H5Dopen1(grpid, VAR_BOOL_NAME)) < 0) ERR;
221       if ((propid = H5Dget_create_plist(datasetid)) < 0) ERR;
222 
223       /* The possible values of filter (which is just an int) can be
224        * found in H5Zpublic.h. */
225       if ((num_filters = H5Pget_nfilters(propid)) < 0) ERR;
226       if (num_filters != 1) ERR;
227       if ((filter = H5Pget_filter2(propid, 0, &flags, &cd_nelems, cd_values,
228 				  namelen, name, &filter_config)) < 0) ERR;
229       if (filter != H5Z_FILTER_DEFLATE || cd_nelems != 1 ||
230 	  cd_values[0] != DEFLATE_LEVEL || strcmp(name, DEFLATE_NAME)) ERR;
231 
232       if (H5Dclose(datasetid) < 0 ||
233 	  H5Pclose(propid) < 0 ||
234 	  H5Gclose(grpid) < 0 ||
235 	  H5Fclose(fileid) < 0)
236 	 ERR;
237    }
238 
239    SUMMARIZE_ERR;
240    printf("*** Checking HDF5 deflate, fletcher32, shuffle filter setting and getting...");
241    {
242       H5Z_filter_t filter;
243       int num_filters;
244       hid_t propid;
245       unsigned int flags, cd_values[NUM_CD_ELEM], filter_config;
246       size_t cd_nelems = NUM_CD_ELEM;
247       size_t namelen = MAX_NAME;
248       char name[MAX_NAME + 1];
249       int found_shuffle = 0, found_fletcher32 = 0, found_deflate = 0;
250       int f;
251 
252       /* Open file and create group. */
253       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
254 			      H5P_DEFAULT)) < 0) ERR;
255       if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
256 
257       /* Write an array of bools, with compression, fletcher32
258        * checksum, shuffle filters. Like a hoogie with "the works." */
259       dims[0] = DIM1_LEN;
260       if ((propid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
261       if (H5Pset_layout(propid, H5D_CHUNKED)) ERR;
262       if (H5Pset_chunk(propid, 1, dims)) ERR;
263       if (H5Pset_shuffle(propid)) ERR;
264       if (H5Pset_deflate(propid, DEFLATE_LEVEL)) ERR;
265       if (H5Pset_fletcher32(propid)) ERR;
266       if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
267       if ((datasetid = H5Dcreate(grpid, VAR_BOOL_NAME, H5T_NATIVE_HBOOL,
268 				 spaceid, propid)) < 0) ERR;
269       if (H5Dwrite(datasetid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, H5P_DEFAULT,
270 		   bool_out) < 0) ERR;
271       if (H5Dclose(datasetid) < 0 ||
272 	  H5Pclose(propid) < 0 ||
273 	  H5Sclose(spaceid) < 0 ||
274 	  H5Gclose(grpid) < 0 ||
275 	  H5Fclose(fileid) < 0)
276 	 ERR;
277 
278       /* Now reopen the file and check. */
279       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR;
280       if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
281       if ((datasetid = H5Dopen1(grpid, VAR_BOOL_NAME)) < 0) ERR;
282       if ((propid = H5Dget_create_plist(datasetid)) < 0) ERR;
283 
284       /* The possible values of filter (which is just an int) can be
285        * found in H5Zpublic.h. */
286       if ((num_filters = H5Pget_nfilters(propid)) < 0) ERR;
287       if (num_filters != 3) ERR;
288       for (f = 0; f < num_filters; f++)
289       {
290 	 if ((filter = H5Pget_filter2(propid, f, &flags, &cd_nelems, cd_values,
291 				      namelen, name, &filter_config)) < 0) ERR;
292 	 switch (filter)
293 	 {
294 	    case H5Z_FILTER_SHUFFLE:
295 	       found_shuffle++;
296 	       break;
297 	    case H5Z_FILTER_FLETCHER32:
298 	       found_fletcher32++;
299 	       break;
300 	    case H5Z_FILTER_DEFLATE:
301 	       found_deflate++;
302 	       if (cd_nelems != 1 || cd_values[0] != DEFLATE_LEVEL ||
303 		   strcmp(name, DEFLATE_NAME)) ERR;
304 	       break;
305 	    default:
306 	       break;
307 	 }
308       }
309       if (!found_fletcher32 || !found_deflate || !found_shuffle) ERR;
310 
311       if (H5Dclose(datasetid) < 0 ||
312 	  H5Pclose(propid) < 0 ||
313 	  H5Gclose(grpid) < 0 ||
314 	  H5Fclose(fileid) < 0)
315 	 ERR;
316    }
317 
318    SUMMARIZE_ERR;
319    printf("*** Checking HDF5 endianness control...");
320 
321 #define NATIVE_VAR_NAME "native_var"
322 #define LE_VAR_NAME "le_var"
323 #define BE_VAR_NAME "be_var"
324    {
325       int data[DIM1_LEN], data_in[DIM1_LEN];
326       hid_t typeid, native_typeid;
327       hid_t native_did, le_did, be_did;
328       H5T_order_t order;
329       htri_t equal;
330       int i;
331 
332       for (i = 0; i < DIM1_LEN; i++)
333 	 data[i] = i;
334 
335       /* Open file and create group. */
336       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
337 			      H5P_DEFAULT)) < 0) ERR;
338       if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
339 
340       /* Create a dataset of native endian. */
341       dims[0] = DIM1_LEN;
342       if ((spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
343       if ((native_did = H5Dcreate(grpid, NATIVE_VAR_NAME, H5T_NATIVE_INT,
344 				  spaceid, H5P_DEFAULT)) < 0) ERR;
345       if ((le_did = H5Dcreate(grpid, LE_VAR_NAME, H5T_STD_I32LE,
346 			      spaceid, H5P_DEFAULT)) < 0) ERR;
347       if ((be_did = H5Dcreate(grpid, BE_VAR_NAME, H5T_STD_I32BE,
348 			      spaceid, H5P_DEFAULT)) < 0) ERR;
349       if (H5Dwrite(native_did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
350 		   data) < 0) ERR;
351       if (H5Dwrite(le_did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
352 		   data) < 0) ERR;
353       if (H5Dwrite(be_did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
354 		   data) < 0) ERR;
355       if (H5Dclose(native_did) < 0 ||
356 	  H5Dclose(le_did) < 0 ||
357 	  H5Dclose(be_did) < 0 ||
358 	  H5Sclose(spaceid) < 0 ||
359 	  H5Gclose(grpid) < 0 ||
360 	  H5Fclose(fileid) < 0)
361 	 ERR;
362 
363       /* Now reopen the file and check. */
364       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR;
365       if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
366 
367       if ((native_did = H5Dopen1(grpid, NATIVE_VAR_NAME)) < 0) ERR;
368       if ((typeid = H5Dget_type(native_did)) < 0) ERR;
369       if ((native_typeid = H5Tget_native_type(typeid, H5T_DIR_DESCEND)) < 0) ERR;
370       if ((order = H5Tget_order(typeid)) < 0) ERR;
371       if ((equal = H5Tequal(typeid, native_typeid)) < 0) ERR;
372       if (!equal) ERR;
373 
374       if (H5Dread(native_did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
375 		   data_in) < 0) ERR;
376       for (i = 0; i < DIM1_LEN; i++)
377 	 if (data[i] != data_in[i]) ERR;
378 
379       if ((le_did = H5Dopen1(grpid, LE_VAR_NAME)) < 0) ERR;
380       if ((typeid = H5Dget_type(le_did)) < 0) ERR;
381       if ((order = H5Tget_order(typeid)) < 0) ERR;
382       if (order != H5T_ORDER_LE) ERR;
383 
384       if (H5Dread(le_did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
385 		   data_in) < 0) ERR;
386       for (i = 0; i < DIM1_LEN; i++)
387 	 if (data[i] != data_in[i]) ERR;
388 
389       if ((be_did = H5Dopen1(grpid, BE_VAR_NAME)) < 0) ERR;
390       if ((typeid = H5Dget_type(be_did)) < 0) ERR;
391       if ((order = H5Tget_order(typeid)) < 0) ERR;
392       if (order != H5T_ORDER_BE) ERR;
393 
394       if (H5Dread(be_did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
395 		   data_in) < 0) ERR;
396       for (i = 0; i < DIM1_LEN; i++)
397 	 if (data[i] != data_in[i]) ERR;
398 
399       if (H5Dclose(native_did) < 0 ||
400 	  H5Dclose(le_did) < 0 ||
401 	  H5Dclose(be_did) < 0 ||
402 	  H5Gclose(grpid) < 0 ||
403 	  H5Fclose(fileid) < 0)
404 	 ERR;
405    }
406 
407    SUMMARIZE_ERR;
408    FINAL_RESULTS;
409 }
410