1 /* This is part of the netCDF package.  Copyright 2018 University
2    Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
3    conditions of use.
4 
5    This program tests fixes for bugs reported with accessing
6    fixed-length scalar string variables and variable-length scalar
7    string attributes from HDF5 files through the netCDF-4 API.
8 
9    Here's a HDF5 sample programs:
10    http://hdf.ncsa.uiuc.edu/training/other-ex5/sample-programs/strings.c
11 */
12 
13 #include <config.h>
14 #include <nc_tests.h>
15 #include <err_macros.h>
16 #include <hdf5.h>
17 
18 #define FILE_NAME "tst_h_strbug.h5"
19 #define VS_ATT_NAME "vsatt"
20 #define FS_ATT_NAME "fsatt"
21 #define VS_VAR_NAME "vsvar"
22 #define FS_VAR_NAME "fsvar"
23 #define V1D_VAR_NAME "v1dvar"
24 #define FSTR_LEN 20
25 #define DIM1      4
26 #define RANK      1
27 
28 int
main()29 main()
30 {
31     char *vs    = "variable-length string";
32     char fsdata[]   = "fixed-length string";
33     char *v1ddata[DIM1] = {"strings","of","variable","length"};
34     int i;
35 
36     printf("\n*** Creating file for checking fix to bugs in accessing strings from HDF5 non-netcdf-4 file.\n");
37     {
38 	hid_t fileid, scalar_spaceid, vstypeid, fstypeid, vsattid, fsattid, vsdsetid, fsdsetid;
39 	size_t type_size = FSTR_LEN;
40 	hid_t v1ddsetid;
41 	hid_t v1dspaceid;
42 	hsize_t dims[1] = {DIM1};
43 
44 	if ((scalar_spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;
45 	if ((v1dspaceid = H5Screate_simple(RANK, dims, NULL)) < 0) ERR;
46 
47 	/* Create variable-length and fixed-length string types. */
48 	if ((vstypeid =  H5Tcopy(H5T_C_S1)) < 0) ERR;
49 	if (H5Tset_size(vstypeid, H5T_VARIABLE) < 0) ERR;
50 
51 	if ((fstypeid =  H5Tcopy(H5T_C_S1)) < 0) ERR;
52 	if (H5Tset_size(fstypeid, type_size) < 0) ERR;
53 
54 	/* Create new file, using default properties. */
55 	if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
56 
57 	/* Create scalar datasets of variable- and fixed-length strings. */
58 	if ((vsdsetid = H5Dcreate (fileid, VS_VAR_NAME, vstypeid, scalar_spaceid,
59 				   H5P_DEFAULT)) < 0) ERR;
60 	if (H5Dwrite (vsdsetid, vstypeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &vs)) ERR;
61 	if ((fsdsetid = H5Dcreate (fileid, FS_VAR_NAME, fstypeid, scalar_spaceid,
62 				   H5P_DEFAULT)) < 0) ERR;
63 	if (H5Dwrite (fsdsetid, fstypeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &fsdata)) ERR;
64 
65 	/* Create 1D dataset of variable-length strings. */
66 	if ((v1ddsetid = H5Dcreate (fileid, V1D_VAR_NAME, vstypeid, v1dspaceid,
67 				   H5P_DEFAULT)) < 0) ERR;
68 	if (H5Dwrite (v1ddsetid, vstypeid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &v1ddata)) ERR;
69 
70 	/* Write scalar global attributes of these types. */
71 	if ((vsattid = H5Acreate(fileid, VS_ATT_NAME, vstypeid, scalar_spaceid,
72 				 H5P_DEFAULT)) < 0) ERR;
73 	if (H5Awrite(vsattid, vstypeid, &vs) < 0) ERR;
74 	if ((fsattid = H5Acreate(fileid, FS_ATT_NAME, fstypeid, scalar_spaceid,
75 				 H5P_DEFAULT)) < 0) ERR;
76 	if (H5Awrite(fsattid, fstypeid, &fsdata) < 0) ERR;
77 
78 	/* Close up. */
79 	if (H5Aclose(vsattid) < 0) ERR;
80 	if (H5Aclose(fsattid) < 0) ERR;
81 	if (H5Sclose(scalar_spaceid) < 0) ERR;
82 	if (H5Sclose(v1dspaceid) < 0) ERR;
83 	if (H5Tclose(vstypeid) < 0) ERR;
84 	if (H5Tclose(fstypeid) < 0) ERR;
85 	if (H5Dclose(vsdsetid) < 0) ERR;
86 	if (H5Dclose(fsdsetid) < 0) ERR;
87 	if (H5Dclose(v1ddsetid) < 0) ERR;
88 	if (H5Fclose(fileid) < 0) ERR;
89     }
90 
91     printf("*** Checking reading variable-length HDF5 string var through netCDF-4 API...");
92     {
93 	int ncid, varid, ndims;
94 	nc_type type;
95 	char *data_in;
96 	if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
97 	if (nc_inq_varid(ncid, VS_VAR_NAME, &varid)) ERR;
98 	if (nc_inq_vartype(ncid, varid, &type)) ERR;
99 	if (type != NC_STRING) ERR;
100 	if (nc_inq_varndims(ncid, varid, &ndims )) ERR;
101 	if (ndims != 0) ERR;
102 	if (nc_get_var_string(ncid, varid, &data_in)) ERR;
103 	if (strcmp(vs, data_in)) ERR;
104 	if (nc_free_string(1, &data_in)) ERR;
105 	if (nc_close(ncid)) ERR;
106     }
107     SUMMARIZE_ERR;
108 
109     printf("*** Checking reading fixed-length HDF5 string var through netCDF-4 API...");
110     {
111     	int ncid, varid, ndims;
112     	nc_type type;
113     	char *data_in;
114     	if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
115     	if (nc_inq_varid(ncid, FS_VAR_NAME, &varid)) ERR;
116     	if (nc_inq_vartype(ncid, varid, &type)) ERR;
117     	if (type != NC_STRING) ERR;
118     	if (nc_inq_varndims(ncid, varid, &ndims )) ERR;
119     	if (ndims != 0) ERR;
120     	if (nc_get_var_string(ncid, varid, &data_in)) ERR;
121     	if (strcmp(fsdata, data_in)) ERR;
122 	if (nc_free_string(1, &data_in)) ERR;
123     	if (nc_close(ncid)) ERR;
124     }
125     SUMMARIZE_ERR;
126 
127     printf("*** Checking reading variable-length HDF5 string att through netCDF-4 API...");
128     {
129 	int ncid;
130 	nc_type type;
131 	size_t len;
132 	char *data_in;
133 	if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
134 	if (nc_inq_att(ncid, NC_GLOBAL, VS_ATT_NAME, &type, &len)) ERR;
135 	if (type != NC_STRING) ERR;
136 	if (len != 1) ERR;
137         if (nc_get_att_string(ncid, NC_GLOBAL, VS_ATT_NAME, &data_in)) ERR;
138 	if (strcmp(vs, data_in)) ERR;
139 	if (nc_free_string(1, &data_in)) ERR;
140 	if (nc_close(ncid)) ERR;
141     }
142     SUMMARIZE_ERR;
143 
144     printf("*** Checking reading fixed-length HDF5 string att through netCDF-4 API...");
145     {
146 	int ncid;
147 	nc_type type;
148 	size_t len;
149 	char *data_in;
150 	if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
151 	if (nc_inq_att(ncid, NC_GLOBAL, FS_ATT_NAME, &type, &len)) ERR;
152 	if (type != NC_CHAR) ERR;
153 	if (len != FSTR_LEN) ERR;
154 	if (!(data_in = malloc(len))) ERR;
155         /* if (nc_get_att_string(ncid, NC_GLOBAL, FS_ATT_NAME, &data_in)) ERR; */
156         if (nc_get_att_text(ncid, NC_GLOBAL, FS_ATT_NAME, data_in)) ERR;
157 	if (strcmp(fsdata, data_in)) ERR;
158 	free(data_in);
159 	if (nc_close(ncid)) ERR;
160     }
161     SUMMARIZE_ERR;
162 
163     printf("*** Checking reading variable-length HDF5 strings var through netCDF-4 API...");
164     {
165     	int ncid, varid, ndims;
166     	nc_type type;
167 	int *dimids;
168 	size_t nstrings;
169     	char **data_in;
170     	if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
171     	if (nc_inq_varid(ncid, V1D_VAR_NAME, &varid)) ERR;
172     	if (nc_inq_vartype(ncid, varid, &type)) ERR;
173     	if (type != NC_STRING) ERR;
174     	if (nc_inq_varndims(ncid, varid, &ndims )) ERR;
175     	if (ndims != RANK) ERR;
176 	if (!(dimids = malloc(ndims * sizeof(int)))) ERR;
177     	if (nc_inq_vardimid(ncid, varid, dimids)) ERR;
178 	if (nc_inq_dimlen(ncid, dimids[0], &nstrings)) ERR;
179 	if (!(data_in = (char **)malloc(nstrings * sizeof(char *)))) ERR;
180     	if (nc_get_var_string(ncid, varid, data_in)) ERR;
181 	for (i = 0; i < nstrings; i++) {
182 	    if(strcmp(v1ddata[i], data_in[i])) ERR;
183 	}
184     	if (nc_free_string(nstrings, data_in)) ERR;
185 	free(data_in);
186 	free(dimids);
187     	if (nc_close(ncid)) ERR;
188     }
189     SUMMARIZE_ERR;
190     FINAL_RESULTS;
191 }
192