1 /* This is part of the netCDF package. Copyright 2005-2018 University
2 Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
3 for conditions of use.
4
5 Test handling of formats.
6
7 Ed Hartnett, 11/22/17
8 */
9
10 #include "config.h"
11 #include <nc_tests.h>
12 #include "err_macros.h"
13
14 #define FILE_NAME_BASE "tst_formats"
15 #define HDF4_FILE "ref_contiguous.hdf4"
16 #define NDIM1 1
17 #define DIM_LEN 10
18 #define VAR_NAME "Copernicus_var"
19 #define DIM_NAME "Copernicus_dim"
20 #define NUM_FILL_WRITE_TESTS 2
21 #define NUM_FILL_WRITE_METHOD_TESTS 2
22
23 /* Determine how many formats are available, and what they are. */
24 void
determine_test_formats(int * num_formats,int * format)25 determine_test_formats(int *num_formats, int *format)
26 {
27 int ind = 0;
28 int num;
29
30 /* Check inputs. */
31 assert(num_formats && format);
32
33 /* We always have classic and 64-bit offset */
34 num = 2;
35 format[ind++] = NC_FORMAT_CLASSIC;
36 format[ind++] = NC_FORMAT_64BIT_OFFSET;
37
38 /* Do we have netCDF-4 and netCDF-4 classic? */
39 #ifdef USE_HDF5
40 num += 2;
41 format[ind++] = NC_FORMAT_NETCDF4;
42 format[ind++] = NC_FORMAT_NETCDF4_CLASSIC;
43 #endif /* USE_HDF5 */
44
45 /* Do we have CDF5? */
46 #ifdef ENABLE_CDF5
47 num++;
48 format[ind++] = NC_FORMAT_CDF5;
49 #endif /* ENABLE_CDF5 */
50
51 *num_formats = num;
52 }
53
54 /* Function to test nc_inq_format(). */
55 int
check_inq_format(int ncid,int expected_format,int expected_extended_format,int expected_mode)56 check_inq_format(int ncid, int expected_format, int expected_extended_format, int expected_mode)
57 {
58 int format;
59 int extended_format;
60 int mode;
61
62 if (nc_inq_format(ncid + 66000, NULL) != NC_EBADID) ERR;
63 if (nc_inq_format(ncid, NULL)) ERR;
64 if (nc_inq_format(ncid, &format)) ERR;
65 if (format != expected_format) {
66 printf("format %d expected_format %d\n", format, expected_format);
67 ERR;
68 }
69 if (nc_inq_format_extended(ncid + 66000, &extended_format, &mode) != NC_EBADID) ERR;
70 {
71 int mode;
72 if (nc_inq_format_extended(ncid, NULL, &mode)) ERR;
73 if (mode != expected_mode) {
74 printf("expected_mode %x mode %x\n", expected_mode, mode);
75 /*ERR;*/
76 }
77 }
78 {
79 int extended_format;
80 if (nc_inq_format_extended(ncid, &extended_format, NULL)) ERR;
81 if (extended_format != expected_extended_format) ERR;
82 }
83
84 if (nc_inq_format_extended(ncid, &extended_format, &mode)) ERR;
85 if (mode != expected_mode) ERR;
86 if (extended_format != expected_extended_format) ERR;
87
88 /* Nothing to do with inq_format, but let's check the base_pe
89 * functions. */
90 if (nc_set_base_pe(ncid, 0)) ERR;
91 if (nc_inq_base_pe(ncid, NULL)) ERR;
92
93 return 0;
94 }
95
96 int
main(int argc,char ** argv)97 main(int argc, char **argv)
98 {
99 printf("\n*** Testing netcdf format functions.\n");
100 {
101 int ncid;
102 int f, d, a;
103 int format[MAX_NUM_FORMATS];
104 int num_formats;
105 int ret;
106
107 /* How many formats to be tested? */
108 determine_test_formats(&num_formats, format);
109
110 for (f = 0; f < num_formats; f++)
111 {
112 printf("*** testing nc_inq_format() and nc_inq_format_extended() with format %d...", format[f]);
113 {
114 char file_name[NC_MAX_NAME + 1];
115 int expected_mode;
116 int expected_extended_format;
117
118 sprintf(file_name, "%s_%d.nc", FILE_NAME_BASE, format[f]);
119
120 /* Set up test. */
121 switch (format[f]) {
122 case NC_FORMAT_CLASSIC:
123 expected_extended_format = NC_FORMATX_NC3;
124 expected_mode = 0;
125 break;
126 case NC_FORMAT_64BIT_OFFSET:
127 expected_extended_format = NC_FORMATX_NC3;
128 expected_mode = NC_64BIT_OFFSET;
129 break;
130 case NC_FORMAT_CDF5:
131 expected_extended_format = NC_FORMATX_NC3;
132 expected_mode = NC_CDF5;
133 break;
134 case NC_FORMAT_NETCDF4:
135 expected_extended_format = NC_FORMATX_NC4;
136 expected_mode = NC_NETCDF4;
137 break;
138 case NC_FORMAT_NETCDF4_CLASSIC:
139 expected_extended_format = NC_FORMATX_NC4;
140 expected_mode = NC_NETCDF4|NC_CLASSIC_MODEL;
141 break;
142 }
143 if (nc_set_default_format(format[f], NULL)) ERR;
144
145 /* Create a file. */
146 if (nc_create(file_name, 0, &ncid)) ERR;
147 if (check_inq_format(ncid, format[f], expected_extended_format, expected_mode)) ERR;
148 if (nc_close(ncid)) ERR;
149
150 /* Re-open the file and check it again. */
151 if (nc_open(file_name, 0, &ncid)) ERR;
152 /* Classic flag is not set on mode in nc_open(). Not sure if
153 * this is a bug or not. */
154 if (format[f] == NC_FORMAT_NETCDF4_CLASSIC)
155 expected_mode = NC_NETCDF4;
156 if (check_inq_format(ncid, format[f], expected_extended_format, expected_mode)) ERR;
157 if (nc_close(ncid)) ERR;
158 }
159 SUMMARIZE_ERR;
160 /* Test without and with actual data write. */
161 for (d = 0; d < NUM_FILL_WRITE_TESTS; d++)
162 {
163 /* Test setting _FillValue directly or calling nc_def_var_fill(). */
164 for (a = 0; a < NUM_FILL_WRITE_METHOD_TESTS; a++)
165 {
166 printf("*** testing late fill handling with format %d writing %d "
167 "using def_var_fill %d...", format[f], d, a);
168 char file_name[NC_MAX_NAME + 1];
169 int dimid, varid;
170 size_t index = {DIM_LEN - 1};
171 int data = TEST_VAL_42;
172 int data_in;
173 int fill_value = TEST_VAL_42 * 2;
174
175 /* Try to set fill mode after data have been written. */
176 sprintf(file_name, "%s_%d_%d_%d_elatefill.nc", FILE_NAME_BASE, format[f], d, a);
177 if (nc_set_default_format(format[f], NULL)) ERR;
178 if (nc_create(file_name, 0, &ncid)) ERR;
179 if (nc_def_dim(ncid, DIM_NAME, DIM_LEN, &dimid)) ERR;
180 if (nc_def_var(ncid, VAR_NAME, NC_INT, NDIM1, &dimid, &varid)) ERR;
181 if (nc_enddef(ncid)) ERR;
182 /* For netCDF-4, we don't actually have to write data to
183 * prevent future setting of the fill value. Once the user
184 * leaves calls enddef after defining a var, fill values
185 * can no longer be set. */
186 if (d)
187 if (nc_put_var1_int(ncid, varid, &index, &data)) ERR;
188 if (nc_redef(ncid)) ERR;
189 if (a)
190 {
191 ret = nc_def_var_fill(ncid, varid, NC_FILL, &fill_value);
192 }
193 else
194 {
195 ret = nc_put_att_int(ncid, varid, "_FillValue", NC_INT, 1,
196 &fill_value);
197 }
198
199 /* Setting the fill value after data are written is
200 * allowed in classic formats, but not netcdf-4. */
201 if (format[f] == NC_FORMAT_CLASSIC || format[f] == NC_FORMAT_64BIT_OFFSET ||
202 format[f] == NC_FORMAT_CDF5)
203 {
204 if (ret) ERR;
205 }
206 else
207 {
208 if (ret != (a ? NC_ELATEDEF: NC_ELATEFILL)) ERR;
209 }
210 if (nc_enddef(ncid)) ERR;
211 if (nc_close(ncid)) ERR;
212
213 /* Open the file and check data. */
214 if (nc_open(file_name, NC_NOWRITE, &ncid)) ERR;
215 if (nc_get_var1_int(ncid, varid, &index, &data_in)) ERR;
216 if (data_in != (d ? data : NC_FILL_INT)) ERR;
217 if (nc_close(ncid)) ERR;
218 SUMMARIZE_ERR;
219 } /* next fill value method test */
220 } /* next fill val write test */
221
222 #define NDIM2 2
223 #define DIM1_NAME "dim1"
224 #define DIM2_NAME "dim2"
225 #define NTYPE 6
226 #define DATA_LEN 4
227
228 printf("*** testing handling of null strides with format %d... ",
229 format[f]);
230 {
231 char file_name[NC_MAX_NAME + 1];
232 char var_name[NC_MAX_NAME + 1];
233 int dimid[NDIM2];
234 int xtype[NTYPE] = {NC_BYTE, NC_CHAR, NC_SHORT, NC_INT, NC_FLOAT, NC_DOUBLE};
235 int type_size[NTYPE] = {1, 1, 2, 4, 4, 8};
236 int varid[NTYPE];
237 size_t start[NDIM2] = {0, 0};
238 size_t count[NDIM2] = {2, 2};
239 signed char data_byte[DATA_LEN] = {1, 2, 3, 4};
240 unsigned char data_char[DATA_LEN] = {1, 2, 3, 4};
241 short data_short[DATA_LEN] = {1, 2, 3, 4};
242 int data_int[DATA_LEN] = {1, 2, 3, 4};
243 float data_float[DATA_LEN] = {1, 2, 3, 4};
244 double data_double[DATA_LEN] = {1, 2, 3, 4};
245 void *data_ptr[NTYPE] = {data_byte, data_char, data_short, data_int, data_float, data_double};
246 int t;
247
248 /* Create the test file. */
249 sprintf(file_name, "%s_%d_null_strides.nc", FILE_NAME_BASE, format[f]);
250 if (nc_set_default_format(format[f], NULL)) ERR;
251 if (nc_create(file_name, 0, &ncid)) ERR;
252 if (nc_def_dim(ncid, DIM1_NAME, DIM_LEN, &dimid[0])) ERR;
253 if (nc_def_dim(ncid, DIM2_NAME, DIM_LEN, &dimid[1])) ERR;
254 for (t = 0; t < NTYPE; t++)
255 {
256 sprintf(var_name, "var_%d", xtype[t]);
257 if (nc_def_var(ncid, var_name, xtype[t], NDIM2, dimid, &varid[t])) ERR;
258 }
259 if (nc_enddef(ncid)) ERR;
260
261 /* Write some data. */
262 for (t = 0; t < NTYPE; t++)
263 {
264 if (nc_put_vars(ncid, varid[t], start, count, NULL, data_ptr[t])) ERR;
265 }
266 if (nc_close(ncid)) ERR;
267
268 /* Open the file and check data. */
269 {
270 int ndims, nvars, ngatts, unlimdimid;
271
272 if (nc_open(file_name, NC_NOWRITE, &ncid)) ERR;
273 if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
274 if (ndims != 2 || nvars != NTYPE || ngatts != 0 || unlimdimid != -1) ERR;
275 for (t = 0; t < NTYPE; t++)
276 {
277 nc_type my_type;
278 int var_ndims, natts;
279 int var_dimid[NDIM2];
280 void *data_in;
281
282 if (nc_inq_var(ncid, varid[t], NULL, &my_type, &var_ndims, var_dimid, &natts)) ERR;
283 if (my_type != xtype[t] || var_ndims != 2 || var_dimid[0] != dimid[0] ||
284 var_dimid[1] != dimid[1] || natts != 0) ERR;
285 if (!(data_in = malloc(DATA_LEN * type_size[t]))) ERR;
286 if (nc_get_vars(ncid, varid[t], start, count, NULL, data_in)) ERR;
287 if (memcmp(data_in, data_ptr[t], DATA_LEN * type_size[t])) ERR;
288 free(data_in);
289
290 }
291 if (nc_close(ncid)) ERR;
292 }
293
294 }
295 SUMMARIZE_ERR;
296 printf("*** testing bad name for nc_open/nc_create with format %d... ", format[f]);
297 {
298 int ncid;
299 if (nc_set_default_format(format[f], NULL)) ERR;
300 if (nc_create(NULL, 0, &ncid) != NC_EINVAL) ERR;
301 if (nc_open(NULL, NC_NOWRITE, &ncid) != NC_EINVAL) ERR;
302 if (nc_delete(NULL) != NC_EINVAL) ERR;
303 }
304 SUMMARIZE_ERR;
305 } /* next format */
306 }
307 FINAL_RESULTS;
308 }
309