1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/nctest/atttests.c,v 1.18 2006/10/31 16:21:45 ed Exp $
5 *********************************************************************/
6
7#ifdef _MPW
8#define __SEG__  toobig    /* under MPW on MacOS, makes it fit */
9#endif
10
11#include <config.h>
12#include <stdio.h>
13#include <string.h>
14#include <stdlib.h> /* for free() */
15#include "netcdf.h"
16#include "testcdf.h" /* defines in-memory test cdf structure */
17#include "add.h" /* functions to update in-memory netcdf */
18#include "error.h"
19#include "emalloc.h"
20#include "tests.h"
21#include "val.h"
22
23#define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
24
25
26/*
27 * Test ncattput
28 *    check that new attribute put works in define mode
29 *    check that NC_GLOBAL variable id works
30 *    check that changing type of existing attribute works in define mode
31 *    check that increasing length of attribute works in define mode
32 *    check that changing value of existing attribute works in define mode
33 *    try with bad datatype, should fail
34 *    try with negative length, should fail
35 *    try increasing length of attribute in data mode, should fail
36 *    try putting new attribute in data mode, should fail
37 *    check that changing type of existing attribute works in data mode
38 *    check that decreasing length of attribute works in data mode
39 *    check that changing value of existing attribute works in data mode
40 *    try with bad variable handle, should fail
41 *    try with bad netCDF handle, check error
42 */
43int
44test_ncattput(path)
45     const char *path; /* name of writable netcdf file to open */
46{
47    int nerrs = 0;
48    static char pname[] = "test_ncattput";
49    int cdfid; /* netcdf id */
50    int ndims; /* number of dimensions */
51    int nvars; /* number of variables */
52    int ngatts_prevngatts; /* number of global attributes */
53    int xdimid; /* id of unlimited dimension */
54    int iaid;
55    static char byte_vals[] = {'a', 'b'};
56    static char char_vals[] = "chars";
57    static short short_vals[] = {-999, 0, 999};
58    static nclong long_vals[] = {10, 20};
59    static float float_vals[] = {1.5, 2.5, 3.5 };
60    static double double_vals[] = {4.5, 5.5, 6.5, 7.5};
61    /*
62     * test attributes; it is important for this test that the size
63     * required for the attribute values increases monotonically.
64     */
65    static struct cdfatt atts[] = {
66 {___, "att0", NC_BYTELEN_OF(byte_vals), (void *) byte_vals},
67 {___, "att1", NC_CHARLEN_OF(char_vals), (void *) char_vals},
68 {___, "att2", NC_SHORTLEN_OF(short_vals), (void *) short_vals},
69 {___, "att3", NC_LONGLEN_OF(long_vals), (void *) long_vals},
70 {___, "att4", NC_FLOATLEN_OF(float_vals), (void *) float_vals},
71 {___, "att5", NC_DOUBLELEN_OF(double_vals), (void *) double_vals}
72    };
73    int na = LEN_OF(atts); /* number of test attributes */
74    int ww_id; /* variable id */
75    static struct cdfvar ww = /* new variable */
76      {"ww", NC_LONG, 1, ___, 0};
77    static struct cdfatt tmp; /* attribute */
78
79    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
80
81    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
82 error("%s: ncopen failed", pname);
83 return ++nerrs;
84    }
85    /* enter define mode */
86    if (ncredef(cdfid) == -1) {
87 error("%s: cdredef failed", pname);
88 ncclose(cdfid); return ++nerrs;
89    }
90    /* get count of global attributes */
91    if (ncinquire(cdfid, &ndims, &nvars, &ngatts, &xdimid) == -1) {
92 error("%s: ncinquire failed", pname);
93 ncclose(cdfid); return ++nerrs;
94    }
95    ngatts_prev = ngatts;
96    /* in define mode, add global attributes of every type */
97    for (ia = 0; ia < naia++) {
98 if (ncattput(cdfidNC_GLOBALatts[ia].nameatts[ia].type,
99       atts[ia].lenatts[ia].val) == -1) {
100     error("%s: ncattput of NC_GLOBAL attribute failed", pname);
101     ncclose(cdfid); return ++nerrs;
102 }
103 add_att(&testNC_GLOBAL, &atts[ia]); /* keep in-memory netcdf updated */
104    }
105    /* make sure count of global attributes has been updated */
106    if (ncinquire(cdfid, &ndims, &nvars, &ngatts, &xdimid) == -1) {
107 error("%s: ncinquire failed", pname);
108 ncclose(cdfid); return ++nerrs;
109    }
110    if (ngatts != ngatts_prev + na) {
111 error("%s: number of global = %d, expected %d",
112       pnamengattsngatts_prev + na);
113 nerrs++;
114    }
115    /* check with ncattinq and ncattget that NC_GLOBAL attributes put OK */
116    for (ia = 0; ia < naia++) {
117 if (ncattinq(cdfidNC_GLOBALatts[ia].name,
118       &tmp.type, &tmp.len) == -1) {
119     error("%s: ncattinq of global attribute failed", pname);
120     ncclose(cdfid); return ++nerrs;
121 }
122 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
123     error("%s: NC_GLOBAL ncattinq got unexpected type or len",
124   pname);
125     ncclose(cdfid); return ++nerrs;
126 }
127 /* allocate space to hold the attribute value to be retrieved */
128 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
129 if (ncattget(cdfidNC_GLOBALatts[ia].nametmp.val) == -1) {
130     error("%s: ncattget of variable attribute failed", pname);
131     ncclose(cdfid); return ++nerrs;
132 }
133 if (val_cmp(tmp.typetmp.lentmp.valatts[ia].val) != 0) {
134     error("%s: ncattget got bad values after put of NC_GLOBAL attrs",
135   pname);
136     nerrs++;
137 }
138 free (tmp.val);
139    }
140    /* add a variable, then variable attributes of every type */
141    ww.dims = (int *) emalloc(sizeof(int) * ww.ndims);
142    for (id = 0; id < ww.ndimsid++)
143      ww.dims[id] = id;
144    if ((ww_id = ncvardef(cdfid,
145    ww.nameww.typeww.ndimsww.dims)) == -1) {
146 error("%s: ncvardef failed", pname);
147 ncclose(cdfid); return ++nerrs;
148    }
149    add_var(&test, &ww); /* keep in-memory netcdf in sync */
150    for (ia = 0; ia < naia++) {
151 if (ncattput(cdfidww_id,
152       atts[ia].nameatts[ia].typeatts[ia].lenatts[ia].val)
153     == -1) {
154     error("%s: ncattput of variable attribute failed", pname);
155     ncclose(cdfid); return ++nerrs;
156 }
157 add_att(&testww_id, &atts[ia]); /* keep in-memory netcdf updated */
158    }
159    /* check with ncattinq and ncattget that variable attributes put OK */
160    for (ia = 0; ia < naia++) {
161 if (ncattinq(cdfidww_idatts[ia].name,
162       &tmp.type, &tmp.len) == -1) {
163     error("%s: ncattinq of variable attribute failed", pname);
164     ncclose(cdfid); return ++nerrs;
165 }
166 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
167     error("%s: ncattinq for new attribute got bad type or len",
168   pname);
169     ncclose(cdfid); return ++nerrs;
170 }
171 /* allocate space to hold the attribute value to be retrieved */
172 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
173 if (ncattget(cdfidww_idatts[ia].nametmp.val) == -1) {
174     error("%s: ncattget of variable attribute failed", pname);
175     ncclose(cdfid); return ++nerrs;
176 }
177 if (val_cmp(tmp.typetmp.lentmp.valatts[ia].val) != 0) {
178     error("%s: ncattget got bad values after put of variable attrs",
179   pname);
180     nerrs++;
181 }
182 free (tmp.val);
183    }
184    /*
185     * check that changing type of existing attribute, increasing
186     * length of attribute, and changing value of existing attribute
187     * work OK in define mode.
188     */
189    tmp.name = (char *) emalloc(MAX_NC_NAME);
190    for (ia = 1; ia < naia++) {
191 if (ncattput(cdfidww_idatts[ia-1].nameatts[ia].type,
192       atts[ia].lenatts[ia].val) == -1) {
193     error("%s: ncattput of larger attribute failed", pname);
194     ncclose(cdfid); return ++nerrs;
195 }
196 tmp.var = atts[ia].var;
197 (void) strcpy (tmp.nameatts[ia-1].name);
198 tmp.type = atts[ia].type;
199 tmp.len = atts[ia].len;
200 tmp.val = atts[ia].val;
201 add_att(&testww_id, &tmp); /* keep in-memory netcdf updated */
202    }
203    /* check with ncattinq and ncattget that variable attributes put OK */
204    for (ia = 1; ia < naia++) {
205 if (ncattinq(cdfidww_idatts[ia-1].name,
206       &tmp.type, &tmp.len) == -1) {
207     error("%s: ncattinq of larger attribute failed", pname);
208     ncclose(cdfid); return ++nerrs;
209 }
210 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
211     error("%s: ncattinq for larger attribute got bad type or len",
212   pname);
213     ncclose(cdfid); return ++nerrs;
214 }
215 /* allocate space to hold the attribute value to be retrieved */
216 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
217 if (ncattget(cdfidww_idatts[ia-1].nametmp.val) == -1) {
218     error("%s: ncattget of variable attribute failed", pname);
219     ncclose(cdfid); return ++nerrs;
220 }
221 if (val_cmp(tmp.typetmp.lentmp.valatts[ia].val) != 0) {
222     error("%s: ncattget got bad values after put of larger attrs",
223   pname);
224     nerrs++;
225 }
226 free (tmp.val);
227    }
228    /* try with bad datatype, should fail */
229    if (ncattput(cdfidww_id, "bogus_att1", BAD_TYPE,
230   atts[0].lenatts[0].val) != -1) {
231 error("%s: ncattput should fail with bad type", pname);
232 nerrs++;
233    }
234    /* try with negative length, should fail */
235    if (ncattput(cdfidww_id, "bogus_att2", atts[0].type,
236   -1, atts[0].val) != -1) {
237 error("%s: ncattput should fail with bad length", pname);
238 nerrs++;
239    }
240    if (ncendef (cdfid) == -1) {
241 error("%s: ncendef failed", pname);
242 ncclose(cdfid); return ++nerrs;
243    }
244    /* in data mode try increasing length of attribute, should fail */
245    if (ncattput(cdfidww_idatts[0].nameatts[0].type,
246   atts[0].len + 10, atts[0].val) != -1) {
247 error("%s: ncattput should fail with increased length in data mode",
248       pname);
249 nerrs++;
250 /* reset to correct length for later tests */
251 if (ncattput(cdfidww_idatts[0].nameatts[0].type,
252       atts[0].lenatts[0].val) != -1) {
253     error("%s: ncattput failed to reset length in data mode", pname);
254     nerrs++;
255 }
256    }
257    /* try creating new attribute in data mode, should fail */
258    if (ncattput(cdfidww_id, "new_name", atts[0].type,
259   atts[0].lenatts[0].val) != -1) {
260 error("%s: ncattput of new attribute in data mode should fail",
261       pname);
262 ncclose(cdfid); return ++nerrs;
263    }
264    /*
265     * check that changing type of existing attribute, decreasing
266     * length of attribute, and changing value of existing attribute
267     * work OK in data mode
268     */
269    for (ia = 0; ia < na - 1; ia++) {
270 if (ncattput(cdfidww_idatts[ia+1].nameatts[ia].type,
271       atts[ia].lenatts[ia].val) == -1) {
272     error("%s: ncattput of smaller attribute failed in data mode",
273   pname);
274     ncclose(cdfid); return ++nerrs;
275 }
276 tmp.var = atts[ia].var;
277 (void) strcpy (tmp.nameatts[ia+1].name);
278 tmp.type = atts[ia].type;
279 tmp.len = atts[ia].len;
280 tmp.val = atts[ia].val;
281 add_att(&testww_id, &tmp); /* keep in-memory netcdf updated */
282    }
283    /* check with ncattinq and ncattget that variable attributes put OK */
284    for (ia = 0; ia < na - 1; ia++) {
285 if (ncattinq(cdfidww_idatts[ia+1].name, &tmp.type, &tmp.len)
286     == -1) {
287     error("%s: ncattinq of variable attribute failed in data mode",
288   pname);
289     ncclose(cdfid); return ++nerrs;
290 }
291 if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
292     error("%s: VARIABLE ncattinq got bad type or len in data mode",
293   pname);
294     ncclose(cdfid); return ++nerrs;
295 }
296 /* allocate space to hold the attribute value to be retrieved */
297 tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
298 if (ncattget(cdfidww_idatts[ia+1].nametmp.val) == -1) {
299     error("%s: ncattget of variable attribute failed in data mode",
300   pname);
301     ncclose(cdfid); return ++nerrs;
302 }
303 if (val_cmp(tmp.typetmp.lentmp.valatts[ia].val) != 0) {
304     error("%s: ncattget got bad values in data mode", pname);
305     nerrs++;
306 }
307 free (tmp.val);
308    }
309    /* try with bad variable handle, should fail */
310    if (ncattput(cdfidtest.nvarsatts[0].nameatts[0].typeatts[0].len,
311   atts[0].val) != -1) {
312 error("%s: ncattput should fail with bad variable handle", pname);
313 ncclose(cdfid); return ++nerrs;
314    }
315    if (ncclose (cdfid) == -1) {
316 error("%s: ncclose failed", pname);
317 return ++nerrs;
318    }
319    /* try with bad netcdf handle, should fail */
320    if (ncattput(cdfidww_idatts[0].nameatts[0].typeatts[0].len,
321   atts[0].val) != -1) {
322 error("%s: ncattput should fail with bad netcdf handle", pname);
323 ncclose(cdfid); return ++nerrs;
324    }
325    free(tmp.name);
326    free(ww.dims);
327    if (nerrs > 0)
328      (void) fprintf(stderr,"FAILED! ***\n");
329    else
330      (void) fprintf(stderr,"ok ***\n");
331
332    return nerrs;
333}
334
335
336/*
337 * Test ncattinq
338 *    check returned values of properly created attributes
339 *    try with nonexisting attribute, check error
340 *    try with bad variable handle, check error
341 *    try with bad netCDF handle, check error
342 */
343int
344test_ncattinq(path)
345     const char *path; /* name of writable netcdf file to open */
346{
347    int nerrs = 0;
348    static char pname[] = "test_ncattinq";
349    int cdfid; /* netcdf id */
350    int iaid; /* attribute number */
351    nc_type type;
352    int len;
353    int vv_id; /* variable id */
354    static struct cdfvar vv = /* new variable */
355      {"vv", NC_SHORT, 2, ___, 0};
356
357    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
358
359    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
360 error("%s: ncopen failed", pname);
361 return ++nerrs;
362    }
363    /* in data mode, check all attributes against test netcdf */
364    for (ia = 0; ia < test.nattsia++) {
365 if (ncattinq(cdfidtest.atts[ia].vartest.atts[ia].name,
366       &type, &len) == -1) {
367     error("%s: ncattinq failed", pname);
368     ncclose(cdfid);
369     return ++nerrs;
370 }
371 if (type != test.atts[ia].type) {
372     error("%s: ncattinq returned wrong type", pname);
373     ncclose(cdfid);
374     return ++nerrs;
375 }
376 if (len != test.atts[ia].len) {
377     error("%s: ncattinq returned wrong len", pname);
378     ncclose(cdfid);
379     return ++nerrs;
380 }
381    }
382
383    /* enter define mode */
384    if (ncredef(cdfid) == -1) {
385 error("%s: cdredef failed", pname);
386 ncclose(cdfid); return ++nerrs;
387    }
388    /* in define mode, add a variable */
389    vv.dims = (int *) emalloc(sizeof(int) * vv.ndims);
390    for (id = 0; id < vv.ndimsid++)
391      vv.dims[id] = id; /* assumes vv.ndims <= test.ndims */
392    if ((vv_id = ncvardef(cdfidvv.namevv.typevv.ndimsvv.dims))
393 == -1) {
394 error("%s: ncvardef failed", pname);
395 ncclose(cdfid); return ++nerrs;
396    }
397    add_var(&test, &vv); /* keep in-memory netcdf in sync */
398
399    /* try with nonexisting attribute, should fail */
400    if (ncattinq(cdfidvv_id, "nonesuch", &type, &len) != -1) {
401 error("%s: ncattinq should fail with nonexisting attribute", pname);
402 ncclose(cdfid); return ++nerrs;
403    }
404    /* try with bad variable handle, should fail */
405    if (ncattinq(cdfidtest.nvarstest.atts[0].name, &type, &len) != -1) {
406 error("%s: ncattinq should fail with bad variable id", pname);
407 ncclose(cdfid); return ++nerrs;
408    }
409    /* in define mode check all attributes against test netcdf */
410    for (ia = 0; ia < test.nattsia++) {
411 if (ncattinq(cdfidtest.atts[ia].vartest.atts[ia].name,
412       &type, &len) == -1) {
413     error("%s: ncattinq in define mode failed", pname);
414     ncclose(cdfid);
415     return ++nerrs;
416 }
417 if (type != test.atts[ia].type) {
418     error("%s: ncattinq in define mode returned wrong type", pname);
419     ncclose(cdfid);
420     return ++nerrs;
421 }
422 if (len != test.atts[ia].len) {
423     error("%s: ncattinq in define mode returned wrong len", pname);
424     ncclose(cdfid);
425     return ++nerrs;
426 }
427    }
428    if (ncendef (cdfid) == -1) {
429 error("%s: ncendef failed", pname);
430 ncclose(cdfid); return ++nerrs;
431    }
432    if (ncclose (cdfid) == -1) {
433 error("%s: ncclose failed", pname);
434 return ++nerrs;
435    }
436    if (ncattinq(cdfidNC_GLOBALtest.atts[0].name, &type, &len) != -1) {
437 error("%s: ncattinq should fail with bad cdfid", pname);
438 nerrs++;
439    }
440    if (nerrs > 0)
441      (void) fprintf(stderr,"FAILED! ***\n");
442    else
443      (void) fprintf(stderr,"ok ***\n");
444
445    free(vv.dims);
446    return nerrs;
447}
448
449/*
450 * Test ncattget
451 *    check that NC_GLOBAL variable id works
452 *    check in both modes
453 *    check that proper call worked after ncattput
454 *    try with bad variable handle, check error
455 *    try with nonexisting attribute, check error
456 *    try with bad netCDF handle, check error
457 */
458int
459test_ncattget(path)
460     const char *path; /* name of writable netcdf file to open */
461{
462    int nerrs = 0;
463    int cdfid; /* netcdf id */
464    int iaid;
465    static struct cdfatt tmp; /* attribute */
466    int uu_id; /* variable id */
467    static struct cdfvar uu = /* variable */
468      {"uu", NC_LONG, 2, ___, 0};
469    static nclong uumax = 1000; /* attribute value */
470    static struct cdfatt vmax = /* attribute */
471 {___, "valid_max", NC_LONG, 1, (void *) &uumax};
472
473    static char pname[] = "test_ncattget";
474
475    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
476
477    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
478 error("%s: ncopen failed", pname);
479 return ++nerrs;
480    }
481    /* enter define mode */
482    if (ncredef(cdfid) == -1) {
483 error("%s: cdredef failed", pname);
484 ncclose(cdfid); return ++nerrs;
485    }
486    /* add a variable */
487    uu.dims = (int *) emalloc(sizeof(int) * uu.ndims);
488    for (id = 0; id < uu.ndimsid++)
489      uu.dims[id] = id;
490    if ((uu_id = ncvardef(cdfid,
491    uu.nameuu.typeuu.ndimsuu.dims)) == -1) {
492 error("%s: ncvardef failed", pname);
493 ncclose(cdfid); return ++nerrs;
494    }
495    add_var(&test, &uu); /* keep in-memory netcdf in sync */
496
497    /* add an attribute */
498    if (ncattput(cdfiduu_id,
499   vmax.namevmax.typevmax.lenvmax.val)
500 == -1) {
501 error("%s: ncattput of variable attribute failed", pname);
502 ncclose(cdfid); return ++nerrs;
503    }
504    add_att(&testuu_id, &vmax); /* keep in-memory netcdf updated */
505
506    /* in define mode, check all attributes values against test netcdf */
507    for (ia = 0; ia < test.nattsia++) {
508 if (ncattinq(cdfidtest.atts[ia].vartest.atts[ia].name,
509       &tmp.type, &tmp.len) == -1) {
510     error("%s: ncattinq in define mode failed", pname);
511     ncclose(cdfid); return ++nerrs;
512 }
513 if (tmp.type != test.atts[ia].type) {
514     error("%s: ncattinq in define mode returned wrong type", pname);
515     ncclose(cdfid);
516     return ++nerrs;
517 }
518 if (tmp.len != test.atts[ia].len) {
519     error("%s: ncattinq in define mode returned wrong len", pname);
520     ncclose(cdfid); return ++nerrs;
521 }
522 /* allocate space to hold the attribute value to be retrieved */
523 tmp.val = emalloc(tmp.len * nctypelen(tmp.type));
524 if (ncattget(cdfidtest.atts[ia].vartest.atts[ia].nametmp.val)
525     == -1) {
526     error("%s: ncattget of variable attribute failed in define mode",
527   pname);
528     ncclose(cdfid); return ++nerrs;
529 }
530 if (val_cmp(tmp.typetmp.lentmp.valtest.atts[ia].val) != 0) {
531     error("%s: ncattget got bad values in define mode", pname);
532     error("   cdfid=%d, varname=%s, attname=%s, type=%d, len=%d",
533   cdfidtest.vars[test.atts[ia].var].name,
534   test.atts[ia].nametest.atts[ia].typetest.atts[ia].len);
535     (void)fprintf(stderr,"should have got:");
536     val_out(test.atts[ia].typetest.atts[ia].len,
537    test.atts[ia].val);
538     (void)fprintf(stderr,"    instead got:");
539     val_out(tmp.typetmp.lentmp.val);
540     nerrs++;
541 }
542 free (tmp.val);
543    }
544    if (ncendef (cdfid) == -1) {
545 error("%s: ncendef failed", pname);
546 ncclose(cdfid); return ++nerrs;
547    }
548
549    /* in data mode, check all attributes values against test netcdf */
550    for (ia = 0; ia < test.nattsia++) {
551 if (ncattinq(cdfidtest.atts[ia].vartest.atts[ia].name,
552       &tmp.type, &tmp.len) == -1) {
553     error("%s: ncattinq failed", pname);
554     ncclose(cdfid);
555     return ++nerrs;
556 }
557 if (tmp.type != test.atts[ia].type) {
558     error("%s: ncattinq returned wrong type", pname);
559     ncclose(cdfid);
560     return ++nerrs;
561 }
562 if (tmp.len != test.atts[ia].len) {
563     error("%s: ncattinq returned wrong len", pname);
564     ncclose(cdfid);
565     return ++nerrs;
566 }
567 /* allocate space to hold the attribute value to be retrieved */
568 tmp.val = emalloc(tmp.len * nctypelen(tmp.type));
569 if (ncattget(cdfidtest.atts[ia].vartest.atts[ia].nametmp.val)
570     == -1) {
571     error("%s: ncattget of variable attribute failed in data mode",
572   pname);
573     ncclose(cdfid); return ++nerrs;
574 }
575 if (val_cmp(tmp.typetmp.lentmp.valtest.atts[ia].val) != 0) {
576     error("%s: ncattget got bad values in data mode", pname);
577     error("   cdfid=%d, varname=%s, attname=%s, type=%d, len=%d",
578   cdfidtest.vars[test.atts[ia].var].name,
579   test.atts[ia].nametest.atts[ia].typetest.atts[ia].len);
580     (void)fprintf(stderr,"should have got:");
581     val_out(test.atts[ia].typetest.atts[ia].len,
582    test.atts[ia].val);
583     (void)fprintf(stderr,"    instead got:");
584     val_out(tmp.typetmp.lentmp.val);
585     nerrs++;
586 }
587 free (tmp.val);
588    }
589    /* try with bad variable handle, should fail */
590    if (ncattget(cdfidtest.nvarsvmax.namevmax.val) != -1) {
591 error("%s: ncattget should fail with bad variable handle", pname);
592 ncclose(cdfid); return ++nerrs;
593    }
594    /* try getting non-existent attribute, should fail */
595    if (ncattget(cdfiduu_id, "nonesuch", vmax.val) != -1) {
596 error("%s: ncattget should fail with nonexistent attribute", pname);
597 ncclose(cdfid); return ++nerrs;
598    }
599    if (ncclose (cdfid) == -1) {
600 error("%s: ncclose failed", pname);
601 return ++nerrs;
602    }
603    /* try with bad netcdf handle, should fail */
604    if (ncattget(cdfiduu_idvmax.namevmax.val) != -1) {
605 error("%s: ncattput should fail with bad netcdf handle", pname);
606 ncclose(cdfid); return ++nerrs;
607    }
608    if (nerrs > 0)
609      (void) fprintf(stderr,"FAILED! ***\n");
610    else
611      (void) fprintf(stderr,"ok ***\n");
612
613    free(uu.dims);
614    return nerrs;
615}
616
617
618/*
619 * Test ncattcopy
620 *    check that NC_GLOBAL variable for source or target works
621 *    check that new attribute put works with target in define mode
622 *    check that old attribute put works with target in data mode
623 *    check that changing type and length of an attribute work OK
624 *    try with same cdfid for source and target, different variables
625 *    try with same cdfid for source and target, same variable
626 *    try with nonexisting attribute, check error
627 *    try with bad source or target netCDF handles, check error
628 *    try with bad source or target variable handle, check error
629 */
630int
631test_ncattcopy(path1path2)
632     const char *path1; /* name of input netcdf file to open */
633     const char *path2; /* name of output netcdf file to create */
634{
635    int nerrs = 0;
636    static char pname[] = "test_ncattcopy";
637    int cdfidcdfid2; /* netcdf id */
638    int id; /* dimension id */
639    int tt_id; /* variable id */
640    static struct cdfvar tt = /* new variable for source netcdf */
641      {"tt", NC_LONG, 1, ___, 0};
642    int tu_idtu2_id; /* variable ids */
643    static struct cdfvar tu = /* new variable for target netcdf */
644      {"tu", NC_DOUBLE, 2, ___, 0};
645    static double double_vals[] = {-1., -2.};
646    static float float_vals[] = {-1., -2.};
647    static struct cdfatt att =  /* attribute */
648  {___, "att", NC_DOUBLELEN_OF(double_vals), (void *) double_vals};
649    static struct cdfatt att2 = /* attribute */
650  {___, "att", NC_FLOATLEN_OF(float_vals), (void *) float_vals};
651    static struct cdfatt tmp;  /* attribute */
652
653    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
654
655    if ((cdfid = ncopen(path1NC_WRITE)) == -1) {
656 error("%s: ncopen failed", pname);
657 return ++nerrs;
658    }
659    /* opened OK, enter define mode */
660    if (ncredef(cdfid) == -1) {
661 error("%s: ncredef failed on source", pname);
662 ncclose(cdfid); return ++nerrs;
663    }
664    /* in define mode, add a global attribute, a variable and an attribute */
665    if (ncattput(cdfidNC_GLOBALatt.nameatt.typeatt.lenatt.val) == -1) {
666 error("%s: ncattput failed", pname);
667 ncclose(cdfid); return ++nerrs;
668    }
669    add_att(&testNC_GLOBAL, &att); /* keep in-memory netcdf consistent */
670    tt.dims = (int *) emalloc(sizeof(int) * tt.ndims);
671    for (id=0; id < tt.ndimsid++)
672      tt.dims[0] = id;
673    if ((tt_id=ncvardef(cdfidtt.namett.typett.ndimstt.dims)) == -1) {
674 error("%s: ncvardef failed", pname);
675 ncclose(cdfid); return ++nerrs;
676    }
677    add_var(&test, &tt); /* keep in-memory netcdf consistent */
678    if (ncattput(cdfidtt_idatt.nameatt.typeatt.lenatt.val) == -1) {
679 error("%s: ncattput failed", pname);
680 ncclose(cdfid); return ++nerrs;
681    }
682    add_att(&testtt_id, &att); /* keep in-memory netcdf consistent */
683
684    tu.dims = (int *) emalloc(sizeof(int) * tu.ndims);
685    for (id = 0; id < tu.ndimsid++)
686 tu.dims[id] = id;
687    if ((tu_id=ncvardef(cdfidtu.nametu.typetu.ndimstu.dims)) == -1) {
688 error("%s: ncvardef failed", pname);
689 ncclose(cdfid); return ++nerrs;
690    }
691    add_var(&test, &tu); /* keep in-memory netcdf consistent */
692    if (ncattput(cdfidtu_idatt.nameatt.typeatt.lenatt.val) == -1) {
693 error("%s: ncattput failed", pname);
694 ncclose(cdfid); return ++nerrs;
695    }
696    add_att(&testtu_id, &att); /* keep in-memory netcdf consistent */
697    if (ncendef (cdfid) == -1) {
698 error("%s: ncendef failed", pname);
699 ncclose(cdfid); return ++nerrs;
700    }
701if(strcmp(path1, "nctest_netcdf4.nc")==0) {
702int x=0;
703}
704    /* first (source) netcdf is in data mode */
705    /* create second netCDF to copy attributes to */
706    if ((cdfid2 = nccreate(path2NC_CLOBBER)) == -1) {
707 error("%s: nccreate failed", pname);
708 return ++nerrs;
709    }
710    /* create dimensions and variable in second netcdf */
711    for (id = 0; id < tu.ndimsid++) { /* copy dimensions from source */
712 if ((tu.dims[id] =ncdimdef(cdfid2test.dims[id].name,
713     test.dims[id].size)) == -1) {
714     error("%s: ncdimdef failed", pname);
715     ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
716 }
717    }
718    if ((tu2_id=ncvardef(cdfid2tu.nametu.typetu.ndimstu.dims)) == -1) {
719 error("%s: ncvardef failed", pname);
720 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
721    }
722    /* try copying NC_GLOBAL attribute from source to target */
723    if (ncattcopy(cdfidNC_GLOBALatt.namecdfid2NC_GLOBAL) == -1) {
724 error("%s: ncattcopy on NC_GLOBAL attribute '%s' failed",
725       pnameatt.name);
726 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
727    }
728    /* check that copy worked with ncattinq and ncattget */
729    if (ncattinq(cdfid2NC_GLOBALatt.name, &tmp.type, &tmp.len) == -1) {
730 error("%s: ncattinq of NC_GLOBAL attribute failed", pname);
731 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
732    }
733    if (att.type != tmp.type || att.len != tmp.len) {
734 error("%s: NC_GLOBAL ncattinq got unexpected type or len", pname);
735 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
736    }
737    /* allocate space to hold the attribute value to be retrieved */
738    tmp.val = emalloc(att.len * nctypelen(att.type));
739    if (ncattget(cdfid2NC_GLOBALatt.nametmp.val) == -1) {
740 error("%s: ncattget of variable attribute failed", pname);
741 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
742    }
743    if (val_cmp(tmp.typetmp.lentmp.valatt.val) != 0) {
744 error("%s: ncattget got bad values after put of NC_GLOBAL attrs",
745       pname);
746 nerrs++;
747    }
748    free (tmp.val);
749    /* try copying variable attribute from source to target */
750    if (ncattcopy(cdfidtt_idatt.namecdfid2tu2_id) == -1) {
751 error("%s: ncattcopy failed", pname);
752 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
753    }
754    /* check that copy worked with ncattinq and ncattget */
755    if (ncattinq(cdfid2tu2_idatt.name, &tmp.type, &tmp.len) == -1) {
756 error("%s: ncattinq of variable attribute failed", pname);
757 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
758    }
759    if (att.type != tmp.type || att.len != tmp.len) {
760 error("%s: variable ncattinq got unexpected type or len", pname);
761 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
762    }
763    /* allocate space to hold the attribute value to be retrieved */
764    tmp.val = emalloc(att.len * nctypelen(att.type));
765    if (ncattget(cdfid2tu2_idatt.nametmp.val) == -1) {
766 error("%s: ncattget of variable attribute failed", pname);
767 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
768    }
769    if (val_cmp(tmp.typetmp.lentmp.valatt.val) != 0) {
770 error("%s: ncattget got bad values after copy of variable attrs",
771       pname);
772 nerrs++;
773    }
774    free (tmp.val);
775
776    /*
777     * check that old attribute put works with target in data mode,
778     * also checks that changing type and length of an attribute works OK
779     */
780    if (ncendef (cdfid2) == -1) {
781 error("%s: ncendef failed", pname);
782 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
783    }
784    /* change attribute to shorter attribute */
785    if (ncattput(cdfidNC_GLOBALatt2.nameatt2.typeatt2.lenatt2.val)
786 == -1) {
787 error("%s: ncattput of shorter NC_GLOBAL attribute failed", pname);
788 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
789    }
790    add_att(&testNC_GLOBAL, &att2); /* keep in-memory netcdf consistent */
791    /* copy shorter attribute on existing attribute */
792    if (ncattcopy(cdfidNC_GLOBALatt2.namecdfid2tu2_id) == -1) {
793 error("%s: ncattcopy of shorter attribute on old attribute failed",
794       pname);
795 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
796    }
797    /* check that copy worked with ncattinq and ncattget */
798    if (ncattinq(cdfid2tu2_idatt2.name, &tmp.type, &tmp.len) == -1) {
799 error("%s: ncattinq of variable attribute failed", pname);
800 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
801    }
802    if (att2.type != tmp.type || att2.len != tmp.len) {
803 error("%s: variable ncattinq got unexpected type or len", pname);
804 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
805    }
806    /* allocate space to hold the attribute value to be retrieved */
807    tmp.val = emalloc(att2.len * nctypelen(att2.type));
808    if (ncattget(cdfid2tu2_idatt2.nametmp.val) == -1) {
809 error("%s: ncattget of variable attribute failed", pname);
810 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
811    }
812    if (val_cmp(tmp.typetmp.lentmp.valatt2.val) != 0) {
813 error("%s: ncattget got bad values after copy of variable attrs",
814       pname);
815 nerrs++;
816    }
817    free (tmp.val);
818
819    /* try copying with same source and target netcdf, different variables */
820    /* copy shorter attribute on existing attribute */
821    if (ncattcopy(cdfidNC_GLOBALatt2.namecdfidtu_id) == -1) {
822 error("%s: ncattcopy of shorter NC_GLOBAL attribute failed", pname);
823 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
824    }
825    add_att(&testtu_id, &att2); /* keep in-memory netcdf consistent */
826    /* check that copy worked with ncattinq and ncattget */
827    if (ncattinq(cdfidtu_idatt2.name, &tmp.type, &tmp.len) == -1) {
828 error("%s: ncattinq of variable attribute failed", pname);
829 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
830    }
831    if (att2.type != tmp.type || att2.len != tmp.len) {
832 error("%s: variable ncattinq got unexpected type or len", pname);
833 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
834    }
835    /* allocate space to hold the attribute value to be retrieved */
836    tmp.val = emalloc(att2.len * nctypelen(att2.type));
837    if (ncattget(cdfidtu_idatt2.nametmp.val) == -1) {
838 error("%s: ncattget of variable attribute failed", pname);
839 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
840    }
841    if (val_cmp(tmp.typetmp.lentmp.valatt2.val) != 0) {
842 error("%s: ncattget got bad values after copy of variable attrs",
843       pname);
844 nerrs++;
845    }
846    free (tmp.val);
847
848    /* try with same cdfid for source and target, same variable */
849    if (ncattcopy(cdfidtu_idatt.namecdfidtu_id) == -1) {
850 error("%s: ncattcopy failed with identical source and target",
851       pname);
852 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
853    }
854    /* try with nonexisting attribute, check error */
855    if (ncattcopy(cdfidtt_id, "nonesuch", cdfidtu_id) != -1) {
856 error("%s: ncattcopy should fail with bad attribute name",
857       pname);
858 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
859    }
860    /* try with bad source or target variable handle, check error */
861    if (ncattcopy(cdfidtest.nvarsatt.namecdfidtu_id) != -1) {
862 error("%s: ncattcopy should fail with bad source variable id",
863       pname);
864 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
865    }
866    if (ncattcopy(cdfidtt_idatt.namecdfid, 2) != -1) {
867 error("%s: ncattcopy should fail with bad target variable id",
868       pname);
869 ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
870    }
871    if (ncclose (cdfid2) == -1) {
872 error("%s: ncclose failed", pname);
873 ncclose(cdfid); return ++nerrs;
874    }
875    /* try with bad source or target netCDF handles, check error */
876    if (ncattcopy(cdfidtt_idatt.namecdfid2tu_id) != -1) {
877 error("%s: ncattcopy should fail with bad target netcdf id",
878       pname);
879 ncclose(cdfid); return ++nerrs;
880    }
881    if (ncclose (cdfid) == -1) {
882 error("%s: ncclose failed", pname);
883 return ++nerrs;
884    }
885    if (ncattcopy(cdfidtt_idatt.namecdfid2tu_id) != -1) {
886 error("%s: ncattcopy should fail with bad netcdf id", pname);
887 nerrs++;
888    }
889    if (nerrs > 0)
890      (void) fprintf(stderr,"FAILED! ***\n");
891    else
892      (void) fprintf(stderr,"ok ***\n");
893
894    free(tt.dims);
895    free(tu.dims);
896
897    return nerrs;
898}
899
900
901/*
902 * Test ncattname
903 *    check that NC_GLOBAL variable id works
904 *    check in both modes
905 *    check that proper call worked after ncattput
906 *    try with bad netCDF handle, check error
907 *    try with bad variable handle, check error
908 *    try with bad attribute number, check error
909 */
910int
911test_ncattname(path)
912     const char *path; /* name of writable netcdf file to open */
913{
914    int nerrs = 0;
915    static char pname[] = "test_ncattname";
916    int cdfid; /* netcdf id */
917    struct cdfatt tmp; /* attributes */
918    int iaib; /* attribute numbers */
919    int iv; /* variable id */
920    static short short_vals[] = {3, 4, 5};
921    static struct cdfatt att =  /* attribute */
922  {______NC_SHORTLEN_OF(short_vals), (void *) short_vals};
923
924    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
925
926    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
927 error("%s: ncopen failed", pname);
928 return ++nerrs;
929    }
930    /* opened OK, enter define mode */
931    if (ncredef(cdfid) == -1) {
932 error("%s: ncredef failed", pname);
933 ncclose(cdfid); return ++nerrs;
934    }
935    /* for each NC_GLOBAL attribute, get name and compare with expected name */
936    att.name = (char *) emalloc(MAX_NC_NAME);
937    ib = 0;
938    for (ia = 0; ia < test.ngattsia++) {
939 if (ncattname(cdfidNC_GLOBALiaatt.name) == -1) {
940     error("%s: ncattname failed on global attribute", pname);
941     ncclose(cdfid); return ++nerrs;
942 }
943 /* find number of next global attribute */
944 while (ib < test.natts && test.atts[ib].var != NC_GLOBAL)
945   ib++;
946 if (ib >= test.natts) {
947     error("%s: test problem, expected global attribute not found",
948   pname);
949     ncclose(cdfid); return ++nerrs;
950 }
951 if (strcmp(att.nametest.atts[ib].name) != 0) {
952     error("%s: NC_GLOBAL attribute name `%s' instead of expected `%s'",
953   pnameatt.nametest.atts[ib].name);
954     nerrs++;
955 }
956 ib++;
957    }
958    /* for each variable attribute, get name and compare with expected name */
959    for (iv = 0; iv < test.nvarsiv++) {
960 ib = 0;
961 for (ia = 0; ia < test.vars[iv].nattsia++) {
962     if (ncattname(cdfidiviaatt.name) == -1) {
963 error("%s: ncattname failed on variable attribute", pname);
964 ncclose(cdfid); return ++nerrs;
965     }
966     /* find number of next attribute */
967     while (ib < test.natts && test.atts[ib].var != iv)
968       ib++;
969     if (ib >= test.natts) {
970 error("%s: problem  in test, expected attribute not found",
971       pname);
972 ncclose(cdfid); return ++nerrs;
973     }
974     if (strcmp(att.nametest.atts[ib].name) != 0) {
975 error("%s: variable '%s' name `%s' instead of expected `%s'",
976       pnametest.vars[iv].nameatt.nametest.atts[ib].name);
977 nerrs++;
978     }
979     ib++;
980 }
981    }
982    /* in define mode, add a global attribute */
983    (void) strcpy(att.name,"attx");
984    if (ncattput(cdfidNC_GLOBALatt.nameatt.typeatt.lenatt.val)
985 == -1) {
986 error("%s: ncattput failed", pname);
987 ncclose(cdfid); return ++nerrs;
988    }
989    add_att(&testNC_GLOBAL, &att); /* keep in-memory netcdf consistent */
990    /* test that ncattname works immediately after ncattput */
991    tmp.name = (char *) emalloc(MAX_NC_NAME);
992    if (ncattname(cdfidNC_GLOBALtest.ngatts-1, tmp.name) == -1) {
993 error("%s: ncattname failed on variable attribute", pname);
994 ncclose(cdfid); return ++nerrs;
995    }
996    if (strcmp(att.nametmp.name) != 0) {
997 error("%s: immediate NC_GLOBAL name `%s' instead of expected `%s'",
998       pnametmp.nameatt.name);
999 nerrs++;
1000    }
1001    if (ncendef (cdfid) == -1) {
1002 error("%s: ncendef failed", pname);
1003 ncclose(cdfid); return ++nerrs;
1004    }
1005    /* in data mode */
1006    /* for each NC_GLOBAL attribute, get name and compare with expected name */
1007    ib = 0;
1008    for (ia = 0; ia < test.ngattsia++) {
1009 if (ncattname(cdfidNC_GLOBALiaatt.name) == -1) {
1010     error("%s: ncattname failed on global attribute", pname);
1011     ncclose(cdfid); return ++nerrs;
1012 }
1013 /* find number of next global attribute */
1014 while (ib < test.natts && test.atts[ib].var != NC_GLOBAL)
1015   ib++;
1016 if (ib >= test.natts) {
1017     error("%s: test problem, expected global attribute not found",
1018   pname);
1019     ncclose(cdfid); return ++nerrs;
1020 }
1021 if (strcmp(att.nametest.atts[ib].name) != 0) {
1022     error("%s: NC_GLOBAL attribute name `%s' instead of expected `%s'",
1023   pnameatt.nametest.atts[ib].name);
1024     nerrs++;
1025 }
1026 ib++;
1027    }
1028    /* for each variable attribute, get name and compare with expected name */
1029    for (iv = 0; iv < test.nvarsiv++) {
1030 ib = 0;
1031 for (ia = 0; ia < test.vars[iv].nattsia++) {
1032     if (ncattname(cdfidiviaatt.name) == -1) {
1033 error("%s: ncattname failed on variable attribute", pname);
1034 ncclose(cdfid); return ++nerrs;
1035     }
1036     /* find number of next attribute */
1037     while (ib < test.natts && test.atts[ib].var != iv)
1038       ib++;
1039     if (ib >= test.natts) {
1040 error("%s: problem  in test, expected attribute not found",
1041       pname);
1042 ncclose(cdfid); return ++nerrs;
1043     }
1044     if (strcmp(att.nametest.atts[ib].name) != 0) {
1045 error("%s: variable '%s' name `%s' instead of expected `%s'",
1046       pnametest.vars[iv].nameatt.nametest.atts[ib].name);
1047 nerrs++;
1048     }
1049     ib++;
1050 }
1051    }
1052    /* try with bad variable handle, check error */
1053    if (ncattname(cdfidtest.nvars, 0, att.name) != -1) {
1054 error("%s: ncattname should fail with bad variable handle", pname);
1055 ncclose(cdfid); return ++nerrs;
1056    }
1057    /* try with bad attribute number, check error */
1058    if (ncattname(cdfidNC_GLOBAL, -1, att.name) != -1) {
1059 error("%s: ncattname should fail with negative number", pname);
1060 ncclose(cdfid); return ++nerrs;
1061    }
1062    if (ncattname(cdfidNC_GLOBALtest.ngattsatt.name) != -1) {
1063 error("%s: ncattname should fail with too-high number", pname);
1064 ncclose(cdfid); return ++nerrs;
1065    }
1066    if (ncclose (cdfid) == -1) {
1067 error("%s: ncclose failed", pname);
1068 nerrs++;
1069 return ++nerrs;
1070    }
1071    /* try with bad netCDF handle, check error */
1072    if (ncattname(cdfidNC_GLOBAL, 0, att.name) != -1) {
1073 error("%s: ncattname shoul fail with bad cdfid", pname);
1074 nerrs++;
1075    }
1076    free (tmp.name);
1077    free (att.name);
1078    if (nerrs > 0)
1079      (void) fprintf(stderr,"FAILED! ***\n");
1080    else
1081      (void) fprintf(stderr,"ok ***\n");
1082
1083    return nerrs;
1084}
1085
1086
1087/*
1088 * Test ncattrename
1089 *    check that proper rename worked with ncattinq, ncattget
1090 *    try renaming to existing attribute name, check error
1091 *    try with nonexisting attribute, check error
1092 *    try with bad variable handle, check error
1093 *    try in data mode, check error
1094 *    try with bad netCDF handle, check error
1095 */
1096int
1097test_ncattrename(path)
1098     const char *path; /* name of writable netcdf file to open */
1099{
1100    int nerrs = 0;
1101    static char pname[] = "test_ncattrename";
1102    int cdfid; /* netcdf id */
1103    static char newname[] = "shorter";
1104    static char longername[] = "longer_name";
1105    struct cdfatt tmp; /* attributes */
1106    static short short_vals[] = {3, 4, 5};
1107    static struct cdfatt atty = /* attribute */
1108  {___, "long_name", NC_SHORTLEN_OF(short_vals), (void *) short_vals};
1109    static struct cdfatt attz = /* attribute */
1110  {___, "arggh", NC_SHORTLEN_OF(short_vals), (void *) short_vals};
1111    int ynum; /* attribute number */
1112
1113    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
1114
1115    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
1116 error("%s: ncopen failed", pname);
1117 return ++nerrs;
1118    }
1119    /* opened OK, enter define mode */
1120    if (ncredef(cdfid) == -1) {
1121 error("%s: cdredef failed", pname);
1122 ncclose(cdfid); return ++nerrs;
1123    }
1124    /* in define mode, add two attributes */
1125    if (ncattput(cdfidNC_GLOBALatty.nameatty.typeatty.len,
1126   atty.val) == -1) {
1127 error("%s: ncattput failed", pname);
1128 ncclose(cdfid); return ++nerrs;
1129    }
1130    add_att(&testNC_GLOBAL, &atty); /* keep in-memory netcdf in sync */
1131    ynum = test.natts-1; /* number of attribute just put */
1132    if (ncattput(cdfidNC_GLOBALattz.nameattz.typeattz.len,
1133   attz.val) == -1) {
1134 error("%s: ncattput failed", pname);
1135 ncclose(cdfid); return ++nerrs;
1136    }
1137    add_att(&testNC_GLOBAL, &attz); /* keep in-memory netcdf in sync */
1138
1139    /* rename first attribute to shorter name */
1140    if (ncattrename(cdfidNC_GLOBALatty.namenewname) == -1) {
1141 error("%s: ncattrename failed", pname);
1142 ncclose(cdfid); return ++nerrs;
1143    }
1144    (void) strcpy(test.atts[ynum].namenewname); /* keep test consistent */
1145    /* check new name with ncattinq */
1146    if (ncattinq(cdfidNC_GLOBALnewname, &tmp.type, &tmp.len) == -1) {
1147 error("%s: ncattinq of renamed attribute failed", pname);
1148 ncclose(cdfid); return ++nerrs;
1149    }
1150    if (atty.type != tmp.type || atty.len != tmp.len) {
1151 error("%s: NC_GLOBAL ncattinq got unexpected type or len", pname);
1152 ncclose(cdfid); return ++nerrs;
1153    }
1154    /* allocate space to hold the attribute value to be retrieved */
1155    tmp.val = emalloc(atty.len * nctypelen(atty.type));
1156    if (ncattget(cdfidNC_GLOBALnewnametmp.val) == -1) {
1157 error("%s: ncattget of variable attribute failed", pname);
1158 ncclose(cdfid); return ++nerrs;
1159    }
1160    if (val_cmp(tmp.typetmp.lentmp.valatty.val) != 0) {
1161 error("%s: ncattget got bad values after rename attrs", pname);
1162 nerrs++;
1163 return ++nerrs;
1164    }
1165    if (ncattinq(cdfidNC_GLOBALatty.name, &tmp.type, &tmp.len) != -1) {
1166 error("%s: ncattrename left attribute with old name", pname);
1167 ncclose(cdfid); return ++nerrs;
1168    }
1169    /* try to rename second attribute same as first, should fail */
1170    if (ncattrename(cdfidNC_GLOBALattz.namenewname) != -1) {
1171 error("%s: ncattrename should have failed with used name", pname);
1172 ncclose(cdfid); return ++nerrs;
1173    }
1174    /* try to rename second attribute with a longer name */
1175    if (ncattrename(cdfidNC_GLOBALattz.namelongername) == -1) {
1176 error("%s: ncattrename failed with longer name", pname);
1177 ncclose(cdfid); return ++nerrs;
1178    }
1179    /* try with bad variable handle, check for failure */
1180    if (ncattrename(cdfidtest.nvarsnewnameatty.name) != -1) {
1181 error("%s: ncattrename should have failed on bad variable id", pname);
1182 ncclose(cdfid); return ++nerrs;
1183    }
1184    /* try with bad attribute name, check for failure */
1185    if (ncattrename(cdfidNC_GLOBAL, "nonesuch", newname) != -1) {
1186 error("%s: ncattrename should have failed on bad attribute name",
1187       pname);
1188 ncclose(cdfid); return ++nerrs;
1189    }
1190    if (ncendef (cdfid) == -1) {
1191 error("%s: ncendef failed", pname);
1192 ncclose(cdfid); return ++nerrs;
1193    }
1194    /* in data mode change name to even shorter and check value */
1195    if (ncattrename(cdfidNC_GLOBALnewname, "short") == -1) {
1196 error("%s: ncattrename to shorter name failed in data mode", pname);
1197 ncclose(cdfid); return ++nerrs;
1198    }
1199    if (ncattrename(cdfidNC_GLOBAL, "short", "plugh") == -1) {
1200 error("%s: ncattrename to same length failed in data mode", pname);
1201 ncclose(cdfid); return ++nerrs;
1202    }
1203    if (ncattget(cdfidNC_GLOBAL, "plugh", tmp.val) == -1) {
1204 error("%s: ncgetatt of renamed attribute failed in data mode", pname);
1205 ncclose(cdfid); return ++nerrs;
1206    }
1207    if (val_cmp(tmp.typetmp.lentmp.valatty.val) != 0) {
1208 error("%s: ncattget got bad values after data mode rename", pname);
1209 nerrs++;
1210 return ++nerrs;
1211    }
1212    free (tmp.val);
1213    if (ncclose (cdfid) == -1) {
1214 error("%s: ncclose failed", pname);
1215 return ++nerrs;
1216    }
1217    /* should fail, since bad handle */
1218    if (ncattrename(cdfidNC_GLOBALnewnameatty.name) != -1) {
1219 error("%s: ncattrename should fail with bad cdfid", pname);
1220 ncclose(cdfid); return ++nerrs;
1221    }
1222    if (nerrs > 0)
1223      (void) fprintf(stderr,"FAILED! ***\n");
1224    else
1225      (void) fprintf(stderr,"ok ***\n");
1226
1227    return nerrs;
1228}
1229
1230
1231/*
1232 * Test ncattdel
1233 *    check that proper delete worked
1234 *    try with bad netCDF handle, check error
1235 *    try with bad variable handle, check error
1236 *    try with nonexisting attribute, check error
1237 *    try in data mode, check error
1238 */
1239int
1240test_ncattdel(path)
1241     const char *path; /* name of writable netcdf file to open */
1242{
1243    int nerrs = 0;
1244    static char pname[] = "test_ncattdel";
1245    int cdfid; /* netcdf id */
1246    static short short_vals[] = {-1, -2, -3 };
1247    static struct cdfatt yaa = /* attribute */
1248  {___, "yet_another_attribute", NC_SHORTLEN_OF(short_vals),
1249    (void *) short_vals};
1250    int id; /* dimension id */
1251    int yav_id; /* variable id */
1252    static struct cdfvar yav = /* new variable for target netcdf */
1253      {"yet_another_variable", NC_DOUBLE, 2, ___, 0};
1254    struct cdfvar vtmp; /* variable */
1255    struct cdfatt atmp; /* attribute */
1256    int ndims; /* number of dimensions */
1257    int nvars; /* number of variables */
1258    int ngatts1ngatts2; /* number of global attributes */
1259    int natts; /* number of variable attributes */
1260    int xdimid; /* id of unlimited dimension */
1261
1262    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
1263
1264    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
1265 error("%s: ncopen failed", pname);
1266 return ++nerrs;
1267    }
1268    /* opened OK, enter define mode */
1269    if (ncredef(cdfid) == -1) {
1270 error("%s: cdredef failed", pname);
1271 ncclose(cdfid); return ++nerrs;
1272    }
1273    /* in define mode, add global attribute, variable, variable attribute */
1274    if (ncattput(cdfidNC_GLOBALyaa.nameyaa.typeyaa.lenyaa.val) == -1) {
1275 error("%s: ncattput failed", pname);
1276 ncclose(cdfid); return ++nerrs;
1277    }
1278    add_att(&testNC_GLOBAL, &yaa); /* keep in-memory netcdf in sync */
1279    yav.dims = (int *) emalloc(sizeof(int) * yav.ndims);
1280    for (id = 0; id < yav.ndimsid++)
1281 yav.dims[id] = id;
1282    if ((yav_id=ncvardef(cdfidyav.nameyav.typeyav.ndimsyav.dims))
1283 == -1) {
1284 error("%s: ncvardef failed", pname);
1285 ncclose(cdfid); return ++nerrs;
1286    }
1287    add_var(&test, &yav); /* keep in-memory netcdf consistent */
1288    if (ncattput(cdfidyav_idyaa.nameyaa.typeyaa.lenyaa.val) == -1) {
1289 error("%s: ncattput failed", pname);
1290 ncclose(cdfid); return ++nerrs;
1291    }
1292    add_att(&testyav_id, &yaa); /* keep in-memory netcdf consistent */
1293
1294    /* get number of global attributes, number of attributes for variable */
1295    if (ncinquire(cdfid, &ndims, &nvars, &ngatts1, &xdimid) == -1) {
1296 error("%s: ncinquire in data mode failed", pname);
1297 ncclose(cdfid); return ++nerrs;
1298    }
1299    vtmp.dims = (int *) emalloc(sizeof(int) * NC_MAX_VAR_DIMS);
1300    vtmp.name = (char *) emalloc(MAX_NC_NAME);
1301    if (ncvarinq(cdfidyav_idvtmp.name, &vtmp.type, &vtmp.ndimsvtmp.dims,
1302   &natts) == -1) {
1303 error("%s: ncvarinq failed", pname);
1304 ncclose(cdfid); return ++nerrs;
1305    }
1306
1307    /* delete global attribute and check that it's gone */
1308    if (ncattdel(cdfidNC_GLOBALyaa.name) == -1) {
1309 error("%s: ncattdel failed", pname);
1310 ncclose(cdfid); return ++nerrs;
1311    }
1312    del_att(&testNC_GLOBAL, &yaa); /* keep in-memory netcdf consistent */
1313    if (ncinquire(cdfid, &ndims, &nvars, &ngatts2, &xdimid) == -1) {
1314 error("%s: ncinquire failed", pname);
1315 ncclose(cdfid); return ++nerrs;
1316    }
1317    if (ngatts2 != ngatts1 - 1) {
1318 error("%s: NC_GLOBAL attribute deleted, but ngatts did not decrement",
1319       pname);
1320 ncclose(cdfid); return ++nerrs;
1321    }
1322    if (ncattinq(cdfidNC_GLOBALyaa.name, &atmp.type, &atmp.len) != -1) {
1323 error("%s: ncattinq on deleted NC_GLOBAL attribute should fail", pname);
1324 ncclose(cdfid); return ++nerrs;
1325    }
1326
1327    /* delete variable attribute and check that it's gone */
1328    if (ncattdel(cdfidyav_idyaa.name) == -1) {
1329 error("%s: ncattdel failed", pname);
1330 ncclose(cdfid); return ++nerrs;
1331    }
1332    del_att(&testyav_id, &yaa); /* keep in-memory netcdf consistent */
1333    if (ncvarinq(cdfidyav_idvtmp.name, &vtmp.type, &vtmp.ndims,
1334   vtmp.dims, &vtmp.natts) == -1) {
1335 error("%s: ncvarinq failed", pname);
1336 ncclose(cdfid); return ++nerrs;
1337    }
1338    if (vtmp.natts != natts - 1) {
1339 error("%s: NC_GLOBAL attribute deleted, but ngatts did not decrement",
1340       pname);
1341 ncclose(cdfid); return ++nerrs;
1342    }
1343    if (ncattinq(cdfidyav_idyaa.name, &atmp.type, &atmp.len) != -1) {
1344 error("%s: ncattinq on deleted variable attribute should fail",
1345       pname);
1346 ncclose(cdfid); return ++nerrs;
1347    }
1348    /* re-add global attribute, variable, variable attribute */
1349    if (ncattput(cdfidNC_GLOBALyaa.nameyaa.typeyaa.lenyaa.val) == -1) {
1350 error("%s: ncattput failed", pname);
1351 ncclose(cdfid); return ++nerrs;
1352    }
1353    add_att(&testNC_GLOBAL, &yaa); /* keep in-memory netcdf in sync */
1354    if (ncattput(cdfidyav_idyaa.nameyaa.typeyaa.lenyaa.val) == -1) {
1355 error("%s: ncattput failed", pname);
1356 ncclose(cdfid); return ++nerrs;
1357    }
1358    add_att(&testyav_id, &yaa); /* keep in-memory netcdf consistent */
1359    /* try on nonexistent attribute, should fail */
1360    if (ncattdel(cdfidyav_id, "nonesuch") != -1) {
1361 error("%s: ncattdel should fail on bogus attribute", pname);
1362 ncclose(cdfid); return ++nerrs;
1363    }
1364    /* try on bad variable id, should fail */
1365    if (ncattdel(cdfidtest.nvarsyaa.name) != -1) {
1366 error("%s: ncattdel should fail on bad variable id", pname);
1367 ncclose(cdfid); return ++nerrs;
1368    }
1369    if (ncendef (cdfid) == -1) {
1370 error("%s: ncendef failed", pname);
1371 ncclose(cdfid); return ++nerrs;
1372    }
1373    /* in data mode, should fail */
1374    if (ncattdel(cdfidNC_GLOBALyaa.name) != -1) {
1375 error("%s: ncattdel in data mode should fail", pname);
1376 ncclose(cdfid); return ++nerrs;
1377    }
1378    if (ncclose (cdfid) == -1) {
1379 error("%s: ncclose failed", pname);
1380 return ++nerrs;
1381    }
1382    /* try on bad netcdf handle, should fail */
1383    if (ncattdel(cdfidyav_idyaa.name) != -1) {
1384 error("%s: ncattdel should fail on bad netcdf id", pname);
1385 nerrs++;
1386    }
1387    free(vtmp.dims);
1388    free(vtmp.name);
1389    free(yav.dims);
1390    if (nerrs > 0)
1391      (void) fprintf(stderr,"FAILED! ***\n");
1392    else
1393      (void) fprintf(stderr,"ok ***\n");
1394
1395    return nerrs;
1396}


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