1 /*********************************************************************
2 * Copyright 2018, UCAR/Unidata
3 * See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 * $Header: /upc/share/CVS/netcdf-3/nctest/dimtests.c,v 1.14 2006/10/31 16:21:54 ed Exp $
5 *********************************************************************/
6
7 #include <config.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h> /* for free() */
11 #include "netcdf.h"
12 #include "emalloc.h"
13 #include "testcdf.h" /* defines in-memory test cdf structure */
14 #include "add.h" /* functions to update in-memory netcdf */
15 #include "error.h"
16 #include "tests.h"
17
18 /*
19 * Test ncdimdef
20 * try in data mode, check error
21 * check that returned id is one more than previous id
22 * try adding same dimension twice, check error
23 * try with illegal sizes, check error
24 * make sure unlimited size works, shows up in ncinquire(...,*xtendim)
25 * try to define a second unlimited dimension, check error
26 */
27 int
test_ncdimdef(path)28 test_ncdimdef(path)
29 const char *path; /* name of writable netcdf to open */
30 {
31 int nerrs = 0;
32 static char pname[] = "test_ncdimdef";
33 int cdfid; /* netcdf id */
34 static struct cdfdim mm = /* dimension */
35 {"mm", 1}; /* 1 should be a valid dimension size */
36 static struct cdfdim nn = /* dimension */
37 {"bogus", ___}; /* used for testing invalid dimension sizes */
38 static struct cdfdim rec = /* dimension */
39 {"rec", NC_UNLIMITED};
40 int ndims; /* number of dimensions */
41 int nvars; /* number of variables */
42 int natts; /* number of attributes */
43 int xdimid; /* id of unlimited dimension, or -1 if none */
44 int dimid; /* dimension id */
45
46 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
47
48 if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
49 error("%s: ncopen failed", pname);
50 return ++nerrs;
51 }
52 /* opened, defining a dimension should fail in data mode */
53 if (ncdimdef(cdfid, mm.name, mm.size) != -1) {
54 error("%s: ncdimdef should have failed in data mode", pname);
55 ncclose(cdfid); return ++nerrs;
56 }
57 /* enter define mode */
58 if (ncredef(cdfid) == -1) {
59 error("%s: cdredef failed", pname);
60 ncclose(cdfid); return ++nerrs;
61 }
62 /* in define mode OK, add a dimension */
63 if ((dimid = ncdimdef(cdfid, mm.name, mm.size)) == -1) {
64 error("%s: ncdimdef failed", pname);
65 ncclose(cdfid); return ++nerrs;
66 }
67 add_dim(&test, &mm); /* keep in-memory netcdf in sync */
68 /* check that dim id returned is one more than previous dim id */
69 if (dimid != test.ndims - 1) {
70 error("%s: ncdimdef returned %d for dim id, expected %d",
71 pname, dimid, test.ndims-1);
72 ncclose(cdfid); return ++nerrs;
73 }
74
75 /* try adding same dimension again, this should fail */
76 if (ncdimdef(cdfid, mm.name, mm.size) != -1) {
77 error("%s: ncdimdef should not have allowed redefinition", pname);
78 ncclose(cdfid); return ++nerrs;
79 }
80 /* try adding dimension with negative size, this should fail */
81 if (ncdimdef(cdfid, nn.name, (long) -10) != -1) {
82 error("%s: ncdimdef should not allow negative size dimension", pname);
83 ncclose(cdfid); return ++nerrs;
84 }
85 /* if there is not already an unlimited size dimension, try adding one */
86 if (ncinquire(cdfid, &ndims, &nvars, &natts, &xdimid) == -1) {
87 error("%s: ncinquire failed", pname);
88 ncclose(cdfid); return ++nerrs;
89 }
90 if (xdimid == -1) {
91 if (ncdimdef(cdfid, rec.name, rec.size) == -1) {
92 error("%s: ncdimdef failed on NC_UNLIMITED dimension", pname);
93 ncclose(cdfid); return ++nerrs;
94 }
95 add_dim(&test, &rec);
96 }
97 /* try adding another unlimited dimension, which should fail */
98 if (ncdimdef(cdfid, "rec2", rec.size) != -1) {
99 error("%s: ncdimdef should not allow second NC_UNLIMITED dimension",
100 pname);
101 ncclose(cdfid); return ++nerrs;
102 }
103 if (ncendef (cdfid) == -1) {
104 error("%s: ncendef failed", pname);
105 ncclose(cdfid); return ++nerrs;
106 }
107 if (ncclose (cdfid) == -1) {
108 error("%s: ncclose failed", pname);
109 return ++nerrs;
110 }
111 if (ncdimdef(cdfid, "rec2", rec.size) != -1) {
112 error("%s: ncdimdef should fail on bad netCDF id", pname);
113 nerrs++;
114 }
115 if (nerrs > 0)
116 (void) fprintf(stderr,"FAILED! ***\n");
117 else
118 (void) fprintf(stderr,"ok ***\n");
119
120 return nerrs;
121 }
122
123
124 /*
125 * Test ncdimid
126 * check return with defined dimension in both modes
127 * try with undefined dimension, check error
128 * check return with unlimited size dimension
129 * try with bad handle, check error
130 */
131 int
test_ncdimid(path)132 test_ncdimid(path)
133 const char *path; /* name of writable netcdf file to open */
134 {
135 int nerrs = 0;
136 static char pname[] = "test_ncdimid";
137 int cdfid; /* netcdf id */
138 int nn_dim; /* dimension id */
139 static struct cdfdim nn = /* dimension */
140 {"nn", 1}; /* 1 should be a valid dimension size */
141
142 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
143
144 if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
145 error("%s: ncopen failed", pname);
146 return ++nerrs;
147 }
148 /* opened, enter define mode */
149 if (ncredef(cdfid) == -1) {
150 error("%s: cdredef failed", pname);
151 ncclose(cdfid); return ++nerrs;
152 }
153 /* in define mode OK, add a dimension */
154 if ((nn_dim = ncdimdef(cdfid, nn.name, nn.size)) == -1) {
155 error("%s: ncdimdef failed", pname);
156 ncclose(cdfid); return ++nerrs;
157 }
158 add_dim(&test, &nn); /* keep in-memory netcdf in sync */
159 /* check id returned for name matches id returned from definition */
160 if (ncdimid(cdfid, nn.name) != nn_dim) {
161 error("%s: ncdimid returned wrong value in define mode", pname);
162 ncclose(cdfid); return ++nerrs;
163 }
164 if (ncendef (cdfid) == -1) {
165 error("%s: ncendef failed", pname);
166 ncclose(cdfid); return ++nerrs;
167 }
168 /* in data mode, check returned id for dimension just added */
169 if (ncdimid(cdfid, nn.name) != nn_dim) {
170 error("%s: ncdimid returned wrong value in data mode", pname);
171 ncclose(cdfid); return ++nerrs;
172 }
173 /* try with undefined dimension, should fail */
174 if (ncdimid(cdfid, "easter-bunny") != -1) {
175 error("%s: ncdimid with bogus name should have failed ", pname);
176 ncclose(cdfid); return ++nerrs;
177 }
178 /* try with unlimited dimension, assumed to be "rec" from earlier calls */
179 if (ncdimid(cdfid, "rec") != test.xdimid) {
180 error("%s: ncdimid returned bad value for record dimension", pname);
181 ncclose(cdfid); return ++nerrs;
182 }
183 if (ncclose (cdfid) == -1) {
184 error("%s: ncclose failed", pname);
185 return ++nerrs;
186 }
187 /* try on bad handle, should fail */
188 if (ncdimid(cdfid, nn.name) != -1) {
189 error("%s: ncdimid failed to report bad netcdf handle", pname);
190 nerrs++;
191 }
192 if (nerrs > 0)
193 (void) fprintf(stderr,"FAILED! ***\n");
194 else
195 (void) fprintf(stderr,"ok ***\n");
196
197 return nerrs;
198 }
199
200
201 /*
202 * Test ncdiminq
203 * try in both modes
204 * check returned name and size against defined name and size
205 * try with bad dimension handle, check error
206 * try with bad netCDF handle, check error
207 */
208 int
test_ncdiminq(path)209 test_ncdiminq(path)
210 const char *path; /* name of writable netcdf file to open */
211 {
212 int nerrs = 0;
213 static char pname[] = "test_ncdiminq";
214 int cdfid; /* netcdf id */
215 int dimid; /* dimension id */
216 struct cdfdim dim; /* dimension */
217
218 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
219
220 if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
221 error("%s: ncopen failed", pname);
222 return ++nerrs;
223 }
224 /* opened, in data mode */
225 dim.name = (char *) emalloc(MAX_NC_NAME);
226 for (dimid = 0 ; dimid < test.ndims; dimid++) { /* loop on all dim ids */
227 if (ncdiminq(cdfid, dimid, dim.name, &dim.size) == -1) {
228 error("%s: ncdiminq in data mode failed on dim id %d",
229 pname, dimid);
230 ncclose(cdfid); return ++nerrs;
231 }
232 /* compare returned with expected values */
233 if (strcmp(dim.name, test.dims[dimid].name) != 0) {
234 error("%s: ncdiminq (data mode), name %s, expected %s for id = %d",
235 pname, dim.name, test.dims[dimid].name, dimid);
236 nerrs++;
237 }
238 if (dim.size != test.dims[dimid].size) {
239 error("%s: ncdiminq (data mode), size %d, expected %d for id = %d",
240 pname, dim.size, test.dims[dimid].size, dimid);
241 nerrs++;
242 }
243 }
244 if (ncredef(cdfid) == -1) {
245 error("%s: ncredef failed", pname);
246 ncclose(cdfid); return ++nerrs;
247 }
248 /* in define mode, compare returned with expected values again */
249 for (dimid = 0 ; dimid < test.ndims; dimid++) { /* loop on all dim ids */
250 if (ncdiminq(cdfid, dimid, dim.name, &dim.size) == -1) {
251 error("%s: ncdiminq in define mode failed on dim id %d",
252 pname, dimid);
253 ncclose(cdfid); return ++nerrs;
254 }
255 /* compare returned with expected values */
256 if (strcmp(dim.name, test.dims[dimid].name) != 0) {
257 error("%s: ncdiminq (define), name %s, expected %s for id = %d",
258 pname, dim.name, test.dims[dimid].name, dimid);
259 nerrs++;
260 }
261 if (dim.size != test.dims[dimid].size) {
262 error("%s: ncdiminq (define), size %d, expected %d for id = %d",
263 pname, dim.size, test.dims[dimid].size, dimid);
264 nerrs++;
265 }
266 }
267 /* try with bad dimension handles, check for failure */
268 if (ncdiminq(cdfid, -1, dim.name, &dim.size) != -1 ||
269 ncdiminq(cdfid, test.ndims, dim.name, &dim.size) != -1) {
270 error("%s: ncdiminq should have failed on bad dimension ids",
271 pname, dimid);
272 ncclose(cdfid); return ++nerrs;
273 }
274 if (ncendef (cdfid) == -1) {
275 error("%s: ncendef failed", pname);
276 ncclose(cdfid); return ++nerrs;
277 }
278 if (ncclose (cdfid) == -1) {
279 error("%s: ncclose failed", pname);
280 return ++nerrs;
281 }
282 /* should fail, since bad handle */
283 if (test.ndims >= 1) { /* if any dimensions have been defined */
284 if (ncdiminq (cdfid, 0, dim.name, &dim.size) != -1) {
285 error("%s: ncdiminq failed to report bad netcdf handle ", pname);
286 nerrs++;
287 }
288 }
289 free(dim.name);
290 if (nerrs > 0)
291 (void) fprintf(stderr,"FAILED! ***\n");
292 else
293 (void) fprintf(stderr,"ok ***\n");
294
295 return nerrs;
296 }
297
298 /*
299 * Test ncdimrename
300 * check that proper rename worked with ncdiminq
301 * try renaming to existing dimension name, check error
302 * try with bad dimension handle, check error
303 * try with bad netCDF handle, check error
304 */
305 int
test_ncdimrename(path)306 test_ncdimrename(path)
307 const char *path; /* name of writable netcdf file to open */
308 {
309 int nerrs = 0;
310 static char pname[] = "test_ncdimrename";
311 int cdfid; /* netcdf id */
312 int pp_dim; /* dimension id */
313 static struct cdfdim pp = /* dimension */
314 {"pp", 7};
315 static char newname[MAX_NC_NAME] = /* dimension name */
316 "new_name";
317 struct cdfdim dim; /* dimension */
318 static struct cdfdim qq = /* dimension */
319 {"qq", 10};
320
321 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
322
323 if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
324 error("%s: ncopen failed", pname);
325 return ++nerrs;
326 }
327 /* opened */
328 if (ncredef(cdfid) == -1) {
329 error("%s: ncredef failed", pname);
330 ncclose(cdfid); return ++nerrs;
331 }
332 /* in define mode, add two dimensions */
333 if ((pp_dim = ncdimdef(cdfid, pp.name, pp.size)) == -1) {
334 error("%s: ncdimdef failed", pname);
335 ncclose(cdfid); return ++nerrs;
336 }
337 add_dim(&test, &pp); /* keep in-memory netcdf in sync */
338 if (ncdimdef(cdfid, qq.name, qq.size) == -1) {
339 error("%s: ncdimdef failed", pname);
340 ncclose(cdfid); return ++nerrs;
341 }
342 add_dim(&test, &qq); /* keep in-memory netcdf in sync */
343 /* rename first dimension */
344 if (ncdimrename(cdfid, pp_dim, newname) == -1) {
345 error("%s: ncdimrename failed", pname);
346 ncclose(cdfid); return ++nerrs;
347 }
348 /* check new name with ncdiminq */
349 dim.name = (char *) emalloc(MAX_NC_NAME);
350 if (ncdiminq(cdfid, pp_dim, dim.name, &dim.size) == -1) {
351 error("%s: ncdiminq failed", pname);
352 ncclose(cdfid); return ++nerrs;
353 }
354 if (strcmp(dim.name,pp.name) == 0) {
355 error("%s: ncdimrename failed to change name", pname);
356 ncclose(cdfid); return ++nerrs;
357 }
358 if (strcmp(dim.name,newname) != 0) {
359 error("%s: ncdimrename changed name to %s instead of %s",
360 pname, dim.name, newname);
361 ncclose(cdfid); return ++nerrs;
362 }
363 test.dims[pp_dim].name = (char *) erealloc((void *)test.dims[pp_dim].name,
364 strlen(newname)+1);
365 (void) strcpy(test.dims[pp_dim].name, newname); /* keep test consistent */
366 /* try to rename first dimension same as second, should fail */
367 if (ncdimrename(cdfid, pp_dim, qq.name) != -1) {
368 error("%s: ncdimrename should have failed with used name", pname);
369 ncclose(cdfid); return ++nerrs;
370 }
371 /* try with bad dimension handles, check for failure */
372 if (ncdimrename(cdfid, -1, dim.name) != -1 ||
373 ncdimrename(cdfid, test.ndims, dim.name) != -1) {
374 error("%s: ncdimrename should have failed on bad dimension ids",
375 pname);
376 ncclose(cdfid); return ++nerrs;
377 }
378 if (ncendef (cdfid) == -1) {
379 error("%s: ncendef failed", pname);
380 ncclose(cdfid); return ++nerrs;
381 }
382
383 /* in data mode, rename to shorter name */
384 if (ncdimrename(cdfid, pp_dim, "p") == -1) {
385 error("%s: ncdimrename to shorter name failed in data mode", pname);
386 ncclose(cdfid); return ++nerrs;
387 }
388 test.dims[pp_dim].name = (char *) erealloc((void *)test.dims[pp_dim].name,
389 strlen("p")+1);
390 (void) strcpy(test.dims[pp_dim].name, "p"); /* keep test consistent */
391 /* Check with ncdimid */
392 if (pp_dim != ncdimid(cdfid, "p")) {
393 error("%s: lookup by name in data mode failed after ncdimrename",
394 pname);
395 return ++nerrs;
396 }
397 /* in data mode, restore old name */
398 if (ncdimrename(cdfid, pp_dim, pp.name) == -1) {
399 error("%s: ncdimrename failed in data mode", pname);
400 ncclose(cdfid); return ++nerrs;
401 }
402 test.dims[pp_dim].name = (char *) erealloc((void *)test.dims[pp_dim].name,
403 strlen(pp.name)+1);
404 (void) strcpy(test.dims[pp_dim].name, pp.name); /* keep test consistent */
405 if (ncclose (cdfid) == -1) {
406 error("%s: ncclose failed", pname);
407 return ++nerrs;
408 }
409 /* should fail, since bad handle */
410 if (ncdimrename (cdfid, 0, dim.name) != -1) {
411 error("%s: ncdimrename failed to report bad netcdf handle ", pname);
412 nerrs++;
413 }
414 free (dim.name);
415 if (nerrs > 0)
416 (void) fprintf(stderr,"FAILED! ***\n");
417 else
418 (void) fprintf(stderr,"ok ***\n");
419
420 return nerrs;
421 }
422