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 that HDF5 and NetCDF-4 can read and write the same file.
6
7   $Id: tst_interops.c,v 1.24 2010/06/01 15:34:52 ed Exp $
8*/
9#include <config.h>
10#include <nc_tests.h>
11#include "err_macros.h"
12#include <hdf5.h>
13#include <H5DSpublic.h>
14
15#define FILE_NAME "tst_interops.h5"
16#define DIMSCALE_NAME "dimscale"
17#define VAR1_NAME "var1"
18#define NDIMS 1
19#define DIM1_LEN 3
20#define NAME_ATTRIBUTE "dimscale_name_attribute"
21#define DIMSCALE_LABEL "dimscale_label"
22#define LAT_LEN 3
23#define LON_LEN 2
24#define DIMS_2 2
25#define LAT_NAME "lat"
26#define LON_NAME "lon"
27#define PRES_NAME "pres"
28#define TEMP_NAME "temp"
29#define ATT_NAME "song"
30#define NEW_FLOAT 1.0
31
32void
33printRes(const char *msg, int ires)
34{
35   printf("%s: %d\n", msgires);
36   if (ires < 0)
37   {
38      printf("bad ires: %d\n", ires);
39      /*H5Eprint2(ires, stdout);*/
40      exit(1);
41   }
42}
43
44static char song[] = "Oh, better far to live and die\n\
45Under the brave black flag I fly,\n\
46Than play a sanctimonious part,\n\
47With a pirate head and a pirate heart.\n\
48Away to the cheating world go you,\n\
49Where pirates all are well-to-do;\n\
50But I.ll be true to the song I sing,\n\
51And live and die a Pirate King.\n\
52For I am a Pirate King!\n\
53And it is, it is a glorious thing\n\
54To be a Pirate King!\n";
55
56int
57main(int argc, char **argv)
58{
59   printf("\n*** Testing HDF5/NetCDF-4 interoperability...\n");
60   printf("*** Creating a HDF5 file with one var with two dimension scales...");
61   {
62      hid_t fileidlat_spaceidlon_spaceidpres_spaceid;
63      hid_t pres_datasetidlat_dimscaleidlon_dimscaleid;
64      hsize_t dims[DIMS_2];
65      hid_t fapl_id = H5P_DEFAULTfcpl_id = H5P_DEFAULT;
66
67      /* Set latest_format in access propertly list and
68       * H5P_CRT_ORDER_TRACKED in the creation property list. This turns
69       * on HDF5 creation ordering. */
70      if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
71      if (H5Pset_libver_bounds(fapl_idH5F_LIBVER_LATESTH5F_LIBVER_LATEST) < 0) ERR;
72      if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
73      if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
74        H5P_CRT_ORDER_INDEXED)) < 0) ERR;
75
76      /* Create file. */
77      if ((fileid = H5Fcreate(FILE_NAMEH5F_ACC_TRUNCfcpl_idfapl_id)) < 0) ERR;
78      if (H5Pclose(fcpl_id) < 0) ERR;
79      if (H5Pclose(fapl_id) < 0) ERR;
80
81      /* Create the spaces that will be used for the dimscales. */
82      dims[0] = LAT_LEN;
83      if ((lat_spaceid = H5Screate_simple(1, dimsdims)) < 0) ERR;
84      dims[0] = LON_LEN;
85      if ((lon_spaceid = H5Screate_simple(1, dimsdims)) < 0) ERR;
86
87      /* Create the space for the dataset. */
88      dims[0] = LAT_LEN;
89      dims[1] = LON_LEN;
90      if ((pres_spaceid = H5Screate_simple(DIMS_2dimsdims)) < 0) ERR;
91
92      /* Create our dimension scales. */
93      if ((lat_dimscaleid = H5Dcreate(fileidLAT_NAMEH5T_NATIVE_INT,
94       lat_spaceidH5P_DEFAULT)) < 0) ERR;
95      if (H5DSset_scale(lat_dimscaleidNULL) < 0) ERR;
96      if ((lon_dimscaleid = H5Dcreate(fileidLON_NAMEH5T_NATIVE_INT,
97       lon_spaceidH5P_DEFAULT)) < 0) ERR;
98      if (H5DSset_scale(lon_dimscaleidNULL) < 0) ERR;
99
100      /* Create a variable which uses these two dimscales. */
101      if ((pres_datasetid = H5Dcreate(fileidPRES_NAMEH5T_NATIVE_FLOAT,
102       pres_spaceidH5P_DEFAULT)) < 0) ERR;
103      if (H5DSattach_scale(pres_datasetidlat_dimscaleid, 0) < 0) ERR;
104      if (H5DSattach_scale(pres_datasetidlon_dimscaleid, 1) < 0) ERR;
105
106      /* Fold up our tents. */
107      if (H5Dclose(lat_dimscaleid) < 0 ||
108   H5Dclose(lon_dimscaleid) < 0 ||
109   H5Dclose(pres_datasetid) < 0 ||
110   H5Sclose(lat_spaceid) < 0 ||
111   H5Sclose(lon_spaceid) < 0 ||
112   H5Sclose(pres_spaceid) < 0 ||
113   H5Fclose(fileid) < 0) ERR;
114   }
115   SUMMARIZE_ERR;
116   printf("*** Checking that HDF5 file can be read by netCDF-4, and adding an att...");
117   {
118      int ncid;
119      char name_in[NC_MAX_NAME + 1];
120      int natts_inndims_innvars_invarid_indimids_in[5], unlimdimid_in;
121      size_t len_in;
122      nc_type xtype_in;
123      size_t index[2];
124      float new_float = NEW_FLOAT;
125
126      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
127
128      /* Check it out. Can't count on creation order until HDF5 1.8.0,
129       * so the following code doesn't depend on it. */
130      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
131      if (ndims_in != 2 || nvars_in != 3 || natts_in != 0 || unlimdimid_in != -1) ERR;
132      if (nc_inq_varid(ncidPRES_NAME, &varid_in)) ERR;
133      if (nc_inq_var(ncidvarid_inname_in, &xtype_in, &ndims_indimids_in, &natts_in)) ERR;
134      if (strcmp(name_inPRES_NAME) || xtype_in != NC_FLOAT || ndims_in != 2 ||
135   natts_in != 0) ERR;
136      if (nc_inq_dim(nciddimids_in[0], name_in, &len_in)) ERR;
137      if (len_in != LAT_LEN || strcmp(name_inLAT_NAME)) ERR;
138      if (nc_inq_dim(nciddimids_in[1], name_in, &len_in)) ERR;
139      if (len_in != LON_LEN || strcmp(name_inLON_NAME)) ERR;
140
141      /* Change some data. */
142      index[0] = index[1] = 0;
143      if (nc_put_var1_float(ncidvarid_inindex, &new_float)) ERR;
144
145      /* Just for swank, add an attribute. Now we're talking
146       * interoperabity, dude! */
147      if (nc_put_att_text(ncidNC_GLOBALATT_NAME, strlen(song)+1,
148   song)) ERR;
149
150      if (nc_close(ncid)) ERR;
151   }
152   SUMMARIZE_ERR;
153   printf("*** Checking that one var, two dimscales, one att file can still be read by HDF5...");
154
155   {
156      hid_t fileidspaceiddatasetidattidtypeidgrpid;
157      char song_in[1024];
158      float pres_in[LAT_LEN][LON_LEN];
159
160      /* Open the file. */
161      if ((fileid = H5Fopen(FILE_NAMEH5F_ACC_RDWRH5P_DEFAULT)) < 0) ERR;
162      if ((grpid = H5Gopen(fileid, "/")) < 0) ERR;
163
164      /* Check it out. */
165      if ((datasetid = H5Dopen1(grpidPRES_NAME)) < 0) ERR;
166      if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
167      if (H5Dread(datasetidH5T_NATIVE_FLOATH5S_ALLH5S_ALL,
168   H5P_DEFAULTpres_in) < 0) ERR;
169      if (pres_in[0][0] != NEW_FLOATERR;
170      if ((attid = H5Aopen_name(grpidATT_NAME)) < 0) ERR;
171      if ((typeid = H5Aget_type(attid)) < 0) ERR;
172      if (H5Aread(attidtypeidsong_in) < 0) ERR;
173      if (strcmp(songsong_in)) ERR;
174
175      /* Close up the shop. */
176      if (H5Tclose(typeid) < 0 ||
177   H5Aclose(attid) < 0 ||
178   H5Sclose(spaceid) < 0 ||
179   H5Dclose(datasetid) < 0 ||
180   H5Gclose(grpid) < 0 ||
181   H5Fclose(fileid) < 0) ERR;
182   }
183   SUMMARIZE_ERR;
184   printf("*** Creating a HDF5 file with one var and no dimension scales...");
185   {
186      hid_t fileidpres_spaceidpres_datasetid;
187      hsize_t dims[DIMS_2];
188      hid_t fapl_idfcpl_id;
189      int ncidnvars_inndims_innatts_inunlimdim_in;
190      size_t len_in;
191
192      /* Set latest_format in access propertly list and
193       * H5P_CRT_ORDER_TRACKED in the creation property list. This
194       * turns on HDF5 creation ordering. */
195      if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
196      if (H5Pset_libver_bounds(fapl_idH5F_LIBVER_LATESTH5F_LIBVER_LATEST) < 0) ERR;
197      if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
198      if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
199        H5P_CRT_ORDER_INDEXED)) < 0) ERR;
200
201      /* Create file. */
202      if ((fileid = H5Fcreate(FILE_NAMEH5F_ACC_TRUNCfcpl_idfapl_id)) < 0) ERR;
203      if (H5Pclose(fcpl_id) < 0) ERR;
204      if (H5Pclose(fapl_id) < 0) ERR;
205
206      /* Create the space for the dataset. */
207      dims[0] = LAT_LEN;
208      dims[1] = LON_LEN;
209      if ((pres_spaceid = H5Screate_simple(DIMS_2dimsdims)) < 0) ERR;
210
211      /* Create a variable. It will not have dimension scales. */
212      if ((pres_datasetid = H5Dcreate(fileidPRES_NAMEH5T_NATIVE_FLOAT,
213       pres_spaceidH5P_DEFAULT)) < 0) ERR;
214
215      /* Ring down the curtain. */
216      if (H5Dclose(pres_datasetid) < 0 ||
217   H5Sclose(pres_spaceid) < 0 ||
218   H5Fclose(fileid) < 0) ERR;
219
220      /* Read the data with netCDF. */
221      if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
222      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdim_in)) ERR;
223      if (ndims_in != 2 || nvars_in != 1 || natts_in != 0 || unlimdim_in != -1) ERR;
224      if (nc_inq_dim(ncid, 0, NULL, &len_in)) ERR;
225      if (len_in != LAT_LENERR;
226      if (nc_inq_dim(ncid, 1, NULL, &len_in)) ERR;
227      if (len_in != LON_LENERR;
228      if (nc_close(ncid)) ERR;
229   }
230   SUMMARIZE_ERR;
231   printf("*** Creating a HDF5 file with one var and no dimension scales, without creation ordering...");
232   {
233      hid_t fileidpres_spaceidpres_datasetid;
234      hsize_t dims[DIMS_2];
235      int ncidnvars_inndims_innatts_inunlimdim_in;
236      size_t len_in;
237
238      /* Create file. */
239      if ((fileid = H5Fcreate(FILE_NAMEH5F_ACC_TRUNCH5P_DEFAULT,
240       H5P_DEFAULT)) < 0) ERR;
241
242      /* Create the space for the dataset. */
243      dims[0] = LAT_LEN;
244      dims[1] = LON_LEN;
245      if ((pres_spaceid = H5Screate_simple(DIMS_2dimsdims)) < 0) ERR;
246
247      /* Create a variable. It will not have dimension scales. */
248      if ((pres_datasetid = H5Dcreate(fileidPRES_NAMEH5T_NATIVE_FLOAT,
249       pres_spaceidH5P_DEFAULT)) < 0) ERR;
250
251      /* Ring down the curtain. */
252      if (H5Dclose(pres_datasetid) < 0 ||
253   H5Sclose(pres_spaceid) < 0 ||
254   H5Fclose(fileid) < 0) ERR;
255
256      /* Read the data with netCDF. */
257      if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
258      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdim_in)) ERR;
259      if (ndims_in != 2 || nvars_in != 1 || natts_in != 0 || unlimdim_in != -1) ERR;
260      if (nc_inq_dim(ncid, 0, NULL, &len_in)) ERR;
261      if (len_in != LAT_LENERR;
262      if (nc_inq_dim(ncid, 1, NULL, &len_in)) ERR;
263      if (len_in != LON_LENERR;
264      if (nc_close(ncid)) ERR;
265   }
266   SUMMARIZE_ERR;
267   printf("*** Creating a HDF5 file with two vars and no dimension scales, without creation ordering...");
268   {
269      hid_t fileidspaceidpres_datasetidtemp_datasetid;
270      hsize_t dims[DIMS_2];
271      int ncidnvars_inndims_innatts_inunlimdim_in;
272      size_t len_in;
273
274      /* Create file. */
275      if ((fileid = H5Fcreate(FILE_NAMEH5F_ACC_TRUNCH5P_DEFAULT,
276       H5P_DEFAULT)) < 0) ERR;
277
278      /* Create the space for the datasets. */
279      dims[0] = LAT_LEN;
280      dims[1] = LON_LEN;
281      if ((spaceid = H5Screate_simple(DIMS_2dimsdims)) < 0) ERR;
282
283      /* Create two datasets. They will not have dimension scales. */
284      if ((pres_datasetid = H5Dcreate(fileidPRES_NAMEH5T_NATIVE_FLOAT,
285       spaceidH5P_DEFAULT)) < 0) ERR;
286      if ((temp_datasetid = H5Dcreate(fileidTEMP_NAMEH5T_NATIVE_FLOAT,
287       spaceidH5P_DEFAULT)) < 0) ERR;
288
289      /* Ring down the curtain. */
290      if (H5Dclose(pres_datasetid) < 0 ||
291   H5Dclose(temp_datasetid) < 0 ||
292   H5Sclose(spaceid) < 0 ||
293   H5Fclose(fileid) < 0) ERR;
294
295      /* Read the data with netCDF. */
296      if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
297      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdim_in)) ERR;
298      if (ndims_in != 2 || nvars_in != 2 || natts_in != 0 || unlimdim_in != -1) ERR;
299      if (nc_inq_dim(ncid, 0, NULL, &len_in)) ERR;
300      if (len_in != LAT_LENERR;
301      if (nc_inq_dim(ncid, 1, NULL, &len_in)) ERR;
302      if (len_in != LON_LENERR;
303      if (nc_close(ncid)) ERR;
304   }
305   SUMMARIZE_ERR;
306   printf("*** Creating a HDF5 file with fixed length string...");
307   {
308#define ATT_LEN 3
309#define ATT_NAME2 "genius"
310#define MAX_LEN 6
311      hid_t fileidspaceidtypeidattidfapl_id;
312      hid_t class;
313      int ncidnvars_inndims_innatts_inunlimdim_in;
314      char data[ATT_LEN][MAX_LEN + 1] = {"Larry_", "Curley", "Moe111"};
315      char *data_in, *cur, *data_in2[ATT_LEN];
316      hsize_t dims[1] = {ATT_LEN};
317      nc_type type_in;
318      size_t size_in;
319      int i;
320
321      /* Create file. */
322      if ((fileid = H5Fcreate(FILE_NAMEH5F_ACC_TRUNCH5P_DEFAULT,
323       H5P_DEFAULT)) < 0) ERR;
324
325
326      if ((typeid =  H5Tcopy(H5T_C_S1)) < 0) ERR;
327      if (H5Tset_size(typeidMAX_LEN + 1) < 0) ERR;
328
329      /* Write an attribute of this (string) type. */
330      if ((spaceid = H5Screate_simple(1, dimsNULL)) < 0) ERR;
331      if ((attid = H5Acreate(fileidATT_NAME2typeidspaceid,
332      H5P_DEFAULT)) < 0) ERR;
333      if (H5Awrite(attidtypeiddata) < 0) ERR;
334
335      /* Close HDF5 objects. */
336      if (H5Aclose(attid) < 0) ERR;
337      if (H5Sclose(spaceid) < 0) ERR;
338      if (H5Tclose(typeid) < 0) ERR;
339      if (H5Fclose(fileid) < 0) ERR;
340
341      /* Open the file and read the attribute of fixed length
342       * strings. */
343      if ((fileid = H5Fopen(FILE_NAMEH5F_ACC_RDWRH5P_DEFAULT)) < 0) ERR;
344      if ((attid = H5Aopen_name(fileidATT_NAME2)) < 0) ERR;
345      if ((typeid = H5Aget_type(attid)) < 0) ERR;
346
347      /* Given this type id, how would we know this is a string
348       * attribute? */
349      if ((class = H5Tget_class(typeid)) < 0)
350  return NC_EHDFERR;
351      if (class != H5T_STRINGERR;
352/*      if (!(type_size = H5Tget_size(typeid))) ERR;
353 if ((is_str = H5Tis_variable_str(typeid)) < 0) ERR;*/
354
355      /* How many strings are in the string array? */
356      if ((spaceid = H5Aget_space(attid)) < 0) ERR;
357      if (H5Sget_simple_extent_dims(spaceiddimsNULL) < 0) ERR;
358      if (!(data_in = malloc(dims[0] * sizeof(char *) * (MAX_LEN + 1)))) ERR;
359
360      /* Now read the array of strings. The HDF5 library will allocate
361       * space for each string. */
362      if (H5Aread(attidtypeiddata_in) < 0) ERR;
363
364      /* Compare the values to make sure it worked... */
365      for (cur = data_ini = 0; i < ATT_LENi++)
366      {
367  if (strcmp(data[i], cur)) ERR;
368  cur += MAX_LEN + 1;
369      }
370
371      /* Free the memory that we allocated. */
372      free(data_in);
373
374      /* Close everything up. */
375      if (H5Aclose(attid) < 0) ERR;
376      if (H5Tclose(typeid) < 0) ERR;
377      if (H5Fclose(fileid) < 0) ERR;
378
379      /* Read the data with netCDF. */
380      if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
381      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdim_in)) ERR;
382      if (ndims_in != 0 || nvars_in != 0 || natts_in != 1 || unlimdim_in != -1) ERR;
383      if (nc_inq_att(ncidNC_GLOBALATT_NAME2, &type_in, &size_in)) ERR;
384      if (type_in != NC_STRING || size_in != ATT_LENERR;
385      if (nc_get_att_string(ncidNC_GLOBALATT_NAME2data_in2)) ERR;
386      for (i = 0; i < size_ini++)
387  if (strcmp(data[i], data_in2[i])) ERR;
388      if (nc_free_string(size_indata_in2)) ERR;
389
390      /* Open the file with HDF5 while netcdf still has it open. */
391      if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
392      /* Turn this off for*/
393#ifdef EXTRA_TESTS
394      if (H5Pset_fclose_degree(fapl_idH5F_CLOSE_SEMI)) ERR;
395#else
396      if (H5Pset_fclose_degree(fapl_idH5F_CLOSE_STRONG)) ERR;
397#endif
398      if ((fileid = H5Fopen(FILE_NAMEH5F_ACC_RDONLYfapl_id)) < 0) ERR;
399      if (H5Pclose(fapl_id) < 0) ERR;
400      if (H5Fclose(fileid) < 0) ERR;
401
402      if (nc_close(ncid)) ERR;
403   }
404   SUMMARIZE_ERR;
405/*    printf("**** testing 2D coordinate variable..."); */
406
407/*    { */
408/* #define VAR_NAME "Britany" */
409/* #define NDIMS 2 */
410/* #define TEXT_LEN 15 */
411/* #define D0_NAME "time" */
412/* #define D1_NAME "tl" */
413/*       int ncid, nvars_in, varids_in[1]; */
414/*       int time_dimids[NDIMS], time_id; */
415/*       size_t time_count[NDIMS], time_index[NDIMS] = {0, 0}; */
416/*       const char ttext[TEXT_LEN]="20051224.150000"; */
417/*       int nvars, ndims, ngatts, unlimdimid; */
418/*       int ndims_in, natts_in, dimids_in[NDIMS]; */
419/*       char var_name_in[NC_MAX_NAME + 1]; */
420/*       nc_type xtype_in; */
421
422/*       /\* Create a netcdf-4 file with 2D coordinate var. *\/ */
423/*       if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; */
424
425/*       if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR; */
426/*       if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR; */
427/*       if (nc_def_var(ncid, D0_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR; */
428
429/*       /\* Write one time to the coordinate variable. *\/ */
430/*       time_count[0] = 1; */
431/*       time_count[1] = TEXT_LEN; */
432/*       if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR; */
433/*       if (nc_close(ncid)) ERR; */
434
435/*       /\* Open the file and check. *\/ */
436/*       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR; */
437/*       if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR; */
438/*       if (nvars != 1 || ndims != 2 || ngatts != 0 || unlimdimid != 0) ERR; */
439/*       if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR; */
440/*       if (nvars_in != 1 || varids_in[0] != 0) ERR; */
441/*       if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR; */
442/*       if (strcmp(var_name_in, D0_NAME) || xtype_in != NC_CHAR || ndims_in != 2 || */
443/*  dimids_in[0] != 0 || dimids_in[1] != 1 || natts_in != 0) ERR; */
444/*       if (nc_close(ncid)) ERR; */
445/*    } */
446/*    SUMMARIZE_ERR; */
447   FINAL_RESULTS;
448}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed