ncdf4a13/nctest/atttests.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  *   Copyright 1993, UCAR/Unidata
00003  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
00004  *   $Header: /upc/share/CVS/netcdf-3/nctest/atttests.c,v 1.17 2005/03/17 14:59:19 ed Exp $
00005  *********************************************************************/
00006 
00007 #ifdef _MPW
00008 #define         __SEG__  toobig    /* under MPW on MacOS, makes it fit */
00009 #endif
00010 
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <stdlib.h>             /* for free() */
00014 #include "netcdf.h"
00015 #include "testcdf.h"            /* defines in-memory test cdf structure */
00016 #include "add.h"                /* functions to update in-memory netcdf */
00017 #include "error.h"
00018 #include "emalloc.h"
00019 #include "tests.h"
00020 #include "val.h"
00021 
00022 #define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
00023 
00024 
00025 /*
00026  * Test ncattput
00027  *    check that new attribute put works in define mode
00028  *    check that NC_GLOBAL variable id works
00029  *    check that changing type of existing attribute works in define mode
00030  *    check that increasing length of attribute works in define mode
00031  *    check that changing value of existing attribute works in define mode
00032  *    try with bad datatype, should fail
00033  *    try with negative length, should fail
00034  *    try increasing length of attribute in data mode, should fail
00035  *    try putting new attribute in data mode, should fail
00036  *    check that changing type of existing attribute works in data mode
00037  *    check that decreasing length of attribute works in data mode
00038  *    check that changing value of existing attribute works in data mode
00039  *    try with bad variable handle, should fail
00040  *    try with bad netCDF handle, check error
00041  */
00042 int
00043 test_ncattput(path)
00044      const char *path;          /* name of writable netcdf file to open */
00045 {
00046     int nerrs = 0;
00047     static char pname[] = "test_ncattput";
00048     int cdfid;                  /* netcdf id */
00049     int ndims;                  /* number of dimensions */
00050     int nvars;                  /* number of variables */
00051     int ngatts_prev, ngatts;    /* number of global attributes */
00052     int xdimid;                 /* id of unlimited dimension */
00053     int ia, id;
00054     static char byte_vals[] = {'a', 'b'};
00055     static char char_vals[] = "chars";
00056     static short short_vals[] = {-999, 0, 999};
00057     static nclong long_vals[] = {10, 20};
00058     static float float_vals[] = {1.5, 2.5, 3.5 };
00059     static double double_vals[] = {4.5, 5.5, 6.5, 7.5};
00060     /* 
00061      * test attributes; it is important for this test that the size 
00062      * required for the attribute values increases monotonically.
00063      */
00064     static struct cdfatt atts[] = {
00065         {___, "att0", NC_BYTE, LEN_OF(byte_vals), (void *) byte_vals},
00066         {___, "att1", NC_CHAR, LEN_OF(char_vals), (void *) char_vals},
00067         {___, "att2", NC_SHORT, LEN_OF(short_vals), (void *) short_vals},
00068         {___, "att3", NC_LONG, LEN_OF(long_vals), (void *) long_vals},
00069         {___, "att4", NC_FLOAT, LEN_OF(float_vals), (void *) float_vals},
00070         {___, "att5", NC_DOUBLE, LEN_OF(double_vals), (void *) double_vals}
00071     };
00072     int na = LEN_OF(atts);      /* number of test attributes */
00073     int ww_id;                  /* variable id */
00074     static struct cdfvar ww =   /* new variable */
00075       {"ww", NC_LONG, 1, ___, 0};
00076     static struct cdfatt tmp;   /* attribute */
00077 
00078     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
00079 
00080     if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
00081         error("%s: ncopen failed", pname);
00082         return ++nerrs;
00083     }
00084     /* enter define mode */
00085     if (ncredef(cdfid) == -1) {
00086         error("%s: cdredef failed", pname);
00087         ncclose(cdfid); return ++nerrs;
00088     }
00089     /* get count of global attributes */
00090     if (ncinquire(cdfid, &ndims, &nvars, &ngatts, &xdimid) == -1) {
00091         error("%s: ncinquire failed", pname);
00092         ncclose(cdfid); return ++nerrs;
00093     }
00094     ngatts_prev = ngatts;
00095     /* in define mode, add global attributes of every type */
00096     for (ia = 0; ia < na; ia++) {
00097         if (ncattput(cdfid, NC_GLOBAL, atts[ia].name, atts[ia].type,
00098                       atts[ia].len, atts[ia].val) == -1) {
00099             error("%s: ncattput of NC_GLOBAL attribute failed", pname);
00100             ncclose(cdfid); return ++nerrs;
00101         }
00102         add_att(&test, NC_GLOBAL, &atts[ia]); /* keep in-memory netcdf updated */
00103     }
00104     /* make sure count of global attributes has been updated */
00105     if (ncinquire(cdfid, &ndims, &nvars, &ngatts, &xdimid) == -1) {
00106         error("%s: ncinquire failed", pname);
00107         ncclose(cdfid); return ++nerrs;
00108     }
00109     if (ngatts != ngatts_prev + na) {
00110         error("%s: number of global = %d, expected %d",
00111               pname, ngatts, ngatts_prev + na);
00112         nerrs++;
00113     }
00114     /* check with ncattinq and ncattget that NC_GLOBAL attributes put OK */
00115     for (ia = 0; ia < na; ia++) {
00116         if (ncattinq(cdfid, NC_GLOBAL, atts[ia].name,
00117                       &tmp.type, &tmp.len) == -1) {
00118             error("%s: ncattinq of global attribute failed", pname);
00119             ncclose(cdfid); return ++nerrs;
00120         }
00121         if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
00122             error("%s: NC_GLOBAL ncattinq got unexpected type or len",
00123                   pname);
00124             ncclose(cdfid); return ++nerrs;
00125         }
00126         /* allocate space to hold the attribute value to be retrieved */
00127         tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
00128         if (ncattget(cdfid, NC_GLOBAL, atts[ia].name, tmp.val) == -1) {
00129             error("%s: ncattget of variable attribute failed", pname);
00130             ncclose(cdfid); return ++nerrs;
00131         }
00132         if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) {
00133             error("%s: ncattget got bad values after put of NC_GLOBAL attrs",
00134                   pname);
00135             nerrs++;
00136         }
00137         free (tmp.val);
00138     }
00139     /* add a variable, then variable attributes of every type */
00140     ww.dims = (int *) emalloc(sizeof(int) * ww.ndims);
00141     for (id = 0; id < ww.ndims; id++)
00142       ww.dims[id] = id;
00143     if ((ww_id = ncvardef(cdfid,
00144                            ww.name, ww.type, ww.ndims, ww.dims)) == -1) {
00145         error("%s: ncvardef failed", pname);
00146         ncclose(cdfid); return ++nerrs;
00147     }
00148     add_var(&test, &ww);        /* keep in-memory netcdf in sync */
00149     for (ia = 0; ia < na; ia++) {
00150         if (ncattput(cdfid, ww_id,
00151                       atts[ia].name, atts[ia].type, atts[ia].len, atts[ia].val)
00152             == -1) {
00153             error("%s: ncattput of variable attribute failed", pname);
00154             ncclose(cdfid); return ++nerrs;
00155         }
00156         add_att(&test, ww_id, &atts[ia]); /* keep in-memory netcdf updated */
00157     }
00158     /* check with ncattinq and ncattget that variable attributes put OK */
00159     for (ia = 0; ia < na; ia++) {
00160         if (ncattinq(cdfid, ww_id, atts[ia].name,
00161                       &tmp.type, &tmp.len) == -1) {
00162             error("%s: ncattinq of variable attribute failed", pname);
00163             ncclose(cdfid); return ++nerrs;
00164         }
00165         if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
00166             error("%s: ncattinq for new attribute got bad type or len",
00167                   pname);
00168             ncclose(cdfid); return ++nerrs;
00169         }
00170         /* allocate space to hold the attribute value to be retrieved */
00171         tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
00172         if (ncattget(cdfid, ww_id, atts[ia].name, tmp.val) == -1) {
00173             error("%s: ncattget of variable attribute failed", pname);
00174             ncclose(cdfid); return ++nerrs;
00175         }
00176         if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) {
00177             error("%s: ncattget got bad values after put of variable attrs",
00178                   pname);
00179             nerrs++;
00180         }
00181         free (tmp.val);
00182     }
00183     /*
00184      * check that changing type of existing attribute, increasing 
00185      * length of attribute, and changing value of existing attribute 
00186      * work OK in define mode.
00187      */
00188     tmp.name = (char *) emalloc(MAX_NC_NAME);
00189     for (ia = 1; ia < na; ia++) {
00190         if (ncattput(cdfid, ww_id, atts[ia-1].name, atts[ia].type,
00191                       atts[ia].len, atts[ia].val) == -1) {
00192             error("%s: ncattput of larger attribute failed", pname);
00193             ncclose(cdfid); return ++nerrs;
00194         }
00195         tmp.var = atts[ia].var;
00196         (void) strcpy (tmp.name, atts[ia-1].name);
00197         tmp.type = atts[ia].type;
00198         tmp.len = atts[ia].len;
00199         tmp.val = atts[ia].val;
00200         add_att(&test, ww_id, &tmp); /* keep in-memory netcdf updated */
00201     }
00202     /* check with ncattinq and ncattget that variable attributes put OK */
00203     for (ia = 1; ia < na; ia++) {
00204         if (ncattinq(cdfid, ww_id, atts[ia-1].name,
00205                       &tmp.type, &tmp.len) == -1) {
00206             error("%s: ncattinq of larger attribute failed", pname);
00207             ncclose(cdfid); return ++nerrs;
00208         }
00209         if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
00210             error("%s: ncattinq for larger attribute got bad type or len",
00211                   pname);
00212             ncclose(cdfid); return ++nerrs;
00213         }
00214         /* allocate space to hold the attribute value to be retrieved */
00215         tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
00216         if (ncattget(cdfid, ww_id, atts[ia-1].name, tmp.val) == -1) {
00217             error("%s: ncattget of variable attribute failed", pname);
00218             ncclose(cdfid); return ++nerrs;
00219         }
00220         if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) {
00221             error("%s: ncattget got bad values after put of larger attrs",
00222                   pname);
00223             nerrs++;
00224         }
00225         free (tmp.val);
00226     }
00227     /* try with bad datatype, should fail */
00228     if (ncattput(cdfid, ww_id, "bogus_att1", BAD_TYPE,
00229                   atts[0].len, atts[0].val) != -1) {
00230         error("%s: ncattput should fail with bad type", pname);
00231         nerrs++;
00232     }
00233     /* try with negative length, should fail */
00234     if (ncattput(cdfid, ww_id, "bogus_att2", atts[0].type,
00235                   -1, atts[0].val) != -1) {
00236         error("%s: ncattput should fail with bad length", pname);
00237         nerrs++;
00238     }
00239     if (ncendef (cdfid) == -1) {
00240         error("%s: ncendef failed", pname);
00241         ncclose(cdfid); return ++nerrs;
00242     }
00243     /* in data mode try increasing length of attribute, should fail */
00244     if (ncattput(cdfid, ww_id, atts[0].name, atts[0].type,
00245                   atts[0].len + 10, atts[0].val) != -1) {
00246         error("%s: ncattput should fail with increased length in data mode",
00247               pname);
00248         nerrs++;
00249         /* reset to correct length for later tests */
00250         if (ncattput(cdfid, ww_id, atts[0].name, atts[0].type,
00251                       atts[0].len, atts[0].val) != -1) {
00252             error("%s: ncattput failed to reset length in data mode", pname);
00253             nerrs++;
00254         }
00255     }
00256     /* try creating new attribute in data mode, should fail */
00257     if (ncattput(cdfid, ww_id, "new_name", atts[0].type,
00258                   atts[0].len, atts[0].val) != -1) {
00259         error("%s: ncattput of new attribute in data mode should fail",
00260               pname);
00261         ncclose(cdfid); return ++nerrs;
00262     }
00263     /* 
00264      * check that changing type of existing attribute, decreasing 
00265      * length of attribute, and changing value of existing attribute 
00266      * work OK in data mode
00267      */
00268     for (ia = 0; ia < na - 1; ia++) {
00269         if (ncattput(cdfid, ww_id, atts[ia+1].name, atts[ia].type,
00270                       atts[ia].len, atts[ia].val) == -1) {
00271             error("%s: ncattput of smaller attribute failed in data mode",
00272                   pname);
00273             ncclose(cdfid); return ++nerrs;
00274         }
00275         tmp.var = atts[ia].var;
00276         (void) strcpy (tmp.name, atts[ia+1].name);
00277         tmp.type = atts[ia].type;
00278         tmp.len = atts[ia].len;
00279         tmp.val = atts[ia].val;
00280         add_att(&test, ww_id, &tmp); /* keep in-memory netcdf updated */
00281     }
00282     /* check with ncattinq and ncattget that variable attributes put OK */
00283     for (ia = 0; ia < na - 1; ia++) {
00284         if (ncattinq(cdfid, ww_id, atts[ia+1].name, &tmp.type, &tmp.len)
00285             == -1) {
00286             error("%s: ncattinq of variable attribute failed in data mode",
00287                   pname);
00288             ncclose(cdfid); return ++nerrs;
00289         }
00290         if (atts[ia].type != tmp.type || atts[ia].len != tmp.len) {
00291             error("%s: VARIABLE ncattinq got bad type or len in data mode",
00292                   pname);
00293             ncclose(cdfid); return ++nerrs;
00294         }
00295         /* allocate space to hold the attribute value to be retrieved */
00296         tmp.val = emalloc(atts[ia].len * nctypelen(atts[ia].type));
00297         if (ncattget(cdfid, ww_id, atts[ia+1].name, tmp.val) == -1) {
00298             error("%s: ncattget of variable attribute failed in data mode",
00299                   pname);
00300             ncclose(cdfid); return ++nerrs;
00301         }
00302         if (val_cmp(tmp.type, tmp.len, tmp.val, atts[ia].val) != 0) {
00303             error("%s: ncattget got bad values in data mode", pname);
00304             nerrs++;
00305         }
00306         free (tmp.val);
00307     }
00308     /* try with bad variable handle, should fail */
00309     if (ncattput(cdfid, test.nvars, atts[0].name, atts[0].type, atts[0].len,
00310                   atts[0].val) != -1) {
00311         error("%s: ncattput should fail with bad variable handle", pname);
00312         ncclose(cdfid); return ++nerrs;
00313     }
00314     if (ncclose (cdfid) == -1) {
00315         error("%s: ncclose failed", pname);
00316         return ++nerrs;
00317     }
00318     /* try with bad netcdf handle, should fail */
00319     if (ncattput(cdfid, ww_id, atts[0].name, atts[0].type, atts[0].len,
00320                   atts[0].val) != -1) {
00321         error("%s: ncattput should fail with bad netcdf handle", pname);
00322         ncclose(cdfid); return ++nerrs;
00323     }
00324     free(tmp.name);
00325     if (nerrs > 0)
00326       (void) fprintf(stderr,"FAILED! ***\n");
00327     else
00328       (void) fprintf(stderr,"ok ***\n");
00329 
00330     return nerrs;
00331 }
00332 
00333 
00334 /*
00335  * Test ncattinq
00336  *    check returned values of properly created attributes
00337  *    try with nonexisting attribute, check error
00338  *    try with bad variable handle, check error
00339  *    try with bad netCDF handle, check error
00340  */
00341 int
00342 test_ncattinq(path)
00343      const char *path;          /* name of writable netcdf file to open */
00344 {
00345     int nerrs = 0;
00346     static char pname[] = "test_ncattinq";
00347     int cdfid;                  /* netcdf id */
00348     int ia, id;                 /* attribute number */
00349     nc_type type;
00350     int len;
00351     int vv_id;                  /* variable id */
00352     static struct cdfvar vv =   /* new variable */
00353       {"vv", NC_SHORT, 2, ___, 0};
00354 
00355     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
00356 
00357     if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
00358         error("%s: ncopen failed", pname);
00359         return ++nerrs;
00360     }
00361     /* in data mode, check all attributes against test netcdf */
00362     for (ia = 0; ia < test.natts; ia++) {
00363         if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name,
00364                       &type, &len) == -1) {
00365             error("%s: ncattinq failed", pname);
00366             ncclose(cdfid);
00367             return ++nerrs;
00368         }
00369         if (type != test.atts[ia].type) {
00370             error("%s: ncattinq returned wrong type", pname);
00371             ncclose(cdfid);
00372             return ++nerrs;
00373         }
00374         if (len != test.atts[ia].len) {
00375             error("%s: ncattinq returned wrong len", pname);
00376             ncclose(cdfid);
00377             return ++nerrs;
00378         }
00379     }
00380 
00381     /* enter define mode */
00382     if (ncredef(cdfid) == -1) {
00383         error("%s: cdredef failed", pname);
00384         ncclose(cdfid); return ++nerrs;
00385     }
00386     /* in define mode, add a variable */
00387     vv.dims = (int *) emalloc(sizeof(int) * vv.ndims);
00388     for (id = 0; id < vv.ndims; id++)
00389       vv.dims[id] = id;         /* assumes vv.ndims <= test.ndims */
00390     if ((vv_id = ncvardef(cdfid, vv.name, vv.type, vv.ndims, vv.dims))
00391         == -1) {
00392         error("%s: ncvardef failed", pname);
00393         ncclose(cdfid); return ++nerrs;
00394     }
00395     add_var(&test, &vv);        /* keep in-memory netcdf in sync */
00396 
00397     /* try with nonexisting attribute, should fail */
00398     if (ncattinq(cdfid, vv_id, "nonesuch", &type, &len) != -1) {
00399         error("%s: ncattinq should fail with nonexisting attribute", pname);
00400         ncclose(cdfid); return ++nerrs;
00401     }
00402     /* try with bad variable handle, should fail */
00403     if (ncattinq(cdfid, test.nvars, test.atts[0].name, &type, &len) != -1) {
00404         error("%s: ncattinq should fail with bad variable id", pname);
00405         ncclose(cdfid); return ++nerrs;
00406     }
00407     /* in define mode check all attributes against test netcdf */
00408     for (ia = 0; ia < test.natts; ia++) {
00409         if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name,
00410                       &type, &len) == -1) {
00411             error("%s: ncattinq in define mode failed", pname);
00412             ncclose(cdfid);
00413             return ++nerrs;
00414         }
00415         if (type != test.atts[ia].type) {
00416             error("%s: ncattinq in define mode returned wrong type", pname);
00417             ncclose(cdfid);
00418             return ++nerrs;
00419         }
00420         if (len != test.atts[ia].len) {
00421             error("%s: ncattinq in define mode returned wrong len", pname);
00422             ncclose(cdfid);
00423             return ++nerrs;
00424         }
00425     }
00426     if (ncendef (cdfid) == -1) {
00427         error("%s: ncendef failed", pname);
00428         ncclose(cdfid); return ++nerrs;
00429     }
00430     if (ncclose (cdfid) == -1) {
00431         error("%s: ncclose failed", pname);
00432         return ++nerrs;
00433     }
00434     if (ncattinq(cdfid, NC_GLOBAL, test.atts[0].name, &type, &len) != -1) {
00435         error("%s: ncattinq should fail with bad cdfid", pname);
00436         nerrs++;
00437     }
00438     if (nerrs > 0)
00439       (void) fprintf(stderr,"FAILED! ***\n");
00440     else
00441       (void) fprintf(stderr,"ok ***\n");
00442 
00443     return nerrs;
00444 }
00445 
00446 /*
00447  * Test ncattget
00448  *    check that NC_GLOBAL variable id works
00449  *    check in both modes
00450  *    check that proper call worked after ncattput
00451  *    try with bad variable handle, check error
00452  *    try with nonexisting attribute, check error
00453  *    try with bad netCDF handle, check error
00454  */
00455 int
00456 test_ncattget(path)
00457      const char *path;          /* name of writable netcdf file to open */
00458 {
00459     int nerrs = 0;
00460     int cdfid;                  /* netcdf id */
00461     int ia, id;
00462     static struct cdfatt tmp;   /* attribute */
00463     int uu_id;                  /* variable id */
00464     static struct cdfvar uu =   /* variable */
00465       {"uu", NC_LONG, 2, ___, 0};
00466     static nclong uumax = 1000; /* attribute value */
00467     static struct cdfatt vmax = /* attribute */
00468         {___, "valid_max", NC_LONG, 1, (void *) &uumax};
00469 
00470     static char pname[] = "test_ncattget";
00471 
00472     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
00473 
00474     if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
00475         error("%s: ncopen failed", pname);
00476         return ++nerrs;
00477     }
00478     /* enter define mode */
00479     if (ncredef(cdfid) == -1) {
00480         error("%s: cdredef failed", pname);
00481         ncclose(cdfid); return ++nerrs;
00482     }
00483     /* add a variable */
00484     uu.dims = (int *) emalloc(sizeof(int) * uu.ndims);
00485     for (id = 0; id < uu.ndims; id++)
00486       uu.dims[id] = id;
00487     if ((uu_id = ncvardef(cdfid,
00488                            uu.name, uu.type, uu.ndims, uu.dims)) == -1) {
00489         error("%s: ncvardef failed", pname);
00490         ncclose(cdfid); return ++nerrs;
00491     }
00492     add_var(&test, &uu);        /* keep in-memory netcdf in sync */
00493 
00494     /* add an attribute */
00495     if (ncattput(cdfid, uu_id,
00496                   vmax.name, vmax.type, vmax.len, vmax.val)
00497         == -1) {
00498         error("%s: ncattput of variable attribute failed", pname);
00499         ncclose(cdfid); return ++nerrs;
00500     }
00501     add_att(&test, uu_id, &vmax); /* keep in-memory netcdf updated */
00502 
00503     /* in define mode, check all attributes values against test netcdf */
00504     for (ia = 0; ia < test.natts; ia++) {
00505         if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name,
00506                       &tmp.type, &tmp.len) == -1) {
00507             error("%s: ncattinq in define mode failed", pname);
00508             ncclose(cdfid); return ++nerrs;
00509         }
00510         if (tmp.type != test.atts[ia].type) {
00511             error("%s: ncattinq in define mode returned wrong type", pname);
00512             ncclose(cdfid);
00513             return ++nerrs;
00514         }
00515         if (tmp.len != test.atts[ia].len) {
00516             error("%s: ncattinq in define mode returned wrong len", pname);
00517             ncclose(cdfid); return ++nerrs;
00518         }
00519         /* allocate space to hold the attribute value to be retrieved */
00520         tmp.val = emalloc(tmp.len * nctypelen(tmp.type));
00521         if (ncattget(cdfid, test.atts[ia].var, test.atts[ia].name, tmp.val)
00522             == -1) {
00523             error("%s: ncattget of variable attribute failed in define mode",
00524                   pname);
00525             ncclose(cdfid); return ++nerrs;
00526         }
00527         if (val_cmp(tmp.type, tmp.len, tmp.val, test.atts[ia].val) != 0) {
00528             error("%s: ncattget got bad values in define mode", pname);
00529             error("   cdfid=%d, varname=%s, attname=%s, type=%d, len=%d",
00530                   cdfid, test.vars[test.atts[ia].var].name,
00531                   test.atts[ia].name, test.atts[ia].type, test.atts[ia].len);
00532             (void)fprintf(stderr,"should have got:");
00533             val_out(test.atts[ia].type, test.atts[ia].len,
00534                            test.atts[ia].val);
00535             (void)fprintf(stderr,"    instead got:");
00536             val_out(tmp.type, tmp.len, tmp.val);
00537             nerrs++;
00538         }
00539         free (tmp.val);
00540     }
00541     if (ncendef (cdfid) == -1) {
00542         error("%s: ncendef failed", pname);
00543         ncclose(cdfid); return ++nerrs;
00544     }
00545 
00546     /* in data mode, check all attributes values against test netcdf */
00547     for (ia = 0; ia < test.natts; ia++) {
00548         if (ncattinq(cdfid, test.atts[ia].var, test.atts[ia].name,
00549                       &tmp.type, &tmp.len) == -1) {
00550             error("%s: ncattinq failed", pname);
00551             ncclose(cdfid);
00552             return ++nerrs;
00553         }
00554         if (tmp.type != test.atts[ia].type) {
00555             error("%s: ncattinq returned wrong type", pname);
00556             ncclose(cdfid);
00557             return ++nerrs;
00558         }
00559         if (tmp.len != test.atts[ia].len) {
00560             error("%s: ncattinq returned wrong len", pname);
00561             ncclose(cdfid);
00562             return ++nerrs;
00563         }
00564         /* allocate space to hold the attribute value to be retrieved */
00565         tmp.val = emalloc(tmp.len * nctypelen(tmp.type));
00566         if (ncattget(cdfid, test.atts[ia].var, test.atts[ia].name, tmp.val)
00567             == -1) {
00568             error("%s: ncattget of variable attribute failed in data mode",
00569                   pname);
00570             ncclose(cdfid); return ++nerrs;
00571         }
00572         if (val_cmp(tmp.type, tmp.len, tmp.val, test.atts[ia].val) != 0) {
00573             error("%s: ncattget got bad values in data mode", pname);
00574             error("   cdfid=%d, varname=%s, attname=%s, type=%d, len=%d",
00575                   cdfid, test.vars[test.atts[ia].var].name,
00576                   test.atts[ia].name, test.atts[ia].type, test.atts[ia].len);
00577             (void)fprintf(stderr,"should have got:");
00578             val_out(test.atts[ia].type, test.atts[ia].len,
00579                            test.atts[ia].val);
00580             (void)fprintf(stderr,"    instead got:");
00581             val_out(tmp.type, tmp.len, tmp.val);
00582             nerrs++;
00583         }
00584         free (tmp.val);
00585     }
00586     /* try with bad variable handle, should fail */
00587     if (ncattget(cdfid, test.nvars, vmax.name, vmax.val) != -1) {
00588         error("%s: ncattget should fail with bad variable handle", pname);
00589         ncclose(cdfid); return ++nerrs;
00590     }
00591     /* try getting non-existent attribute, should fail */
00592     if (ncattget(cdfid, uu_id, "nonesuch", vmax.val) != -1) {
00593         error("%s: ncattget should fail with nonexistant attribute", pname);
00594         ncclose(cdfid); return ++nerrs;
00595     }
00596     if (ncclose (cdfid) == -1) {
00597         error("%s: ncclose failed", pname);
00598         return ++nerrs;
00599     }
00600     /* try with bad netcdf handle, should fail */
00601     if (ncattget(cdfid, uu_id, vmax.name, vmax.val) != -1) {
00602         error("%s: ncattput should fail with bad netcdf handle", pname);
00603         ncclose(cdfid); return ++nerrs;
00604     }
00605     if (nerrs > 0)
00606       (void) fprintf(stderr,"FAILED! ***\n");
00607     else
00608       (void) fprintf(stderr,"ok ***\n");
00609 
00610     return nerrs;
00611 }
00612 
00613 
00614 /*
00615  * Test ncattcopy
00616  *    check that NC_GLOBAL variable for source or target works
00617  *    check that new attribute put works with target in define mode
00618  *    check that old attribute put works with target in data mode
00619  *    check that changing type and length of an attribute work OK
00620  *    try with same cdfid for source and target, different variables
00621  *    try with same cdfid for source and target, same variable
00622  *    try with nonexisting attribute, check error
00623  *    try with bad source or target netCDF handles, check error
00624  *    try with bad source or target variable handle, check error
00625  */
00626 int
00627 test_ncattcopy(path1, path2)
00628      const char *path1;         /* name of input netcdf file to open */
00629      const char *path2;         /* name of output netcdf file to create */
00630 {
00631     int nerrs = 0;
00632     static char pname[] = "test_ncattcopy";
00633     int cdfid, cdfid2;          /* netcdf id */
00634     int id;                     /* dimension id */
00635     int tt_id;                  /* variable id */
00636     static struct cdfvar tt =   /* new variable for source netcdf */
00637       {"tt", NC_LONG, 1, ___, 0};
00638     int tu_id, tu2_id;          /* variable ids */
00639     static struct cdfvar tu =   /* new variable for target netcdf */
00640       {"tu", NC_DOUBLE, 2, ___, 0};
00641     static double double_vals[] = {-1., -2.};
00642     static float float_vals[] = {-1., -2.};
00643     static struct cdfatt att =  /* attribute */
00644         {___, "att", NC_DOUBLE, LEN_OF(double_vals), (void *) double_vals};
00645     static struct cdfatt att2 = /* attribute */
00646         {___, "att", NC_FLOAT, LEN_OF(float_vals), (void *) float_vals};
00647     static struct cdfatt tmp;   /* attribute */
00648 
00649     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
00650 
00651     if ((cdfid = ncopen(path1, NC_WRITE)) == -1) {
00652         error("%s: ncopen failed", pname);
00653         return ++nerrs;
00654     }
00655     /* opened OK, enter define mode */
00656     if (ncredef(cdfid) == -1) {
00657         error("%s: ncredef failed on source", pname);
00658         ncclose(cdfid); return ++nerrs;
00659     }
00660     /* in define mode, add a global attribute, a variable and an attribute */
00661     if (ncattput(cdfid, NC_GLOBAL, att.name, att.type, att.len, att.val) == -1) {
00662         error("%s: ncattput failed", pname);
00663         ncclose(cdfid); return ++nerrs;
00664     }
00665     add_att(&test, NC_GLOBAL, &att); /* keep in-memory netcdf consistent */
00666     tt.dims = (int *) emalloc(sizeof(int) * tt.ndims);
00667     for (id=0; id < tt.ndims; id++)
00668       tt.dims[0] = id;
00669     if ((tt_id=ncvardef(cdfid, tt.name, tt.type, tt.ndims, tt.dims)) == -1) {
00670         error("%s: ncvardef failed", pname);
00671         ncclose(cdfid); return ++nerrs;
00672     }
00673     add_var(&test, &tt);        /* keep in-memory netcdf consistent */
00674     if (ncattput(cdfid, tt_id, att.name, att.type, att.len, att.val) == -1) {
00675         error("%s: ncattput failed", pname);
00676         ncclose(cdfid); return ++nerrs;
00677     }
00678     add_att(&test, tt_id, &att); /* keep in-memory netcdf consistent */
00679 
00680     tu.dims = (int *) emalloc(sizeof(int) * tu.ndims);
00681     for (id = 0; id < tu.ndims; id++)
00682         tu.dims[id] = id;
00683     if ((tu_id=ncvardef(cdfid, tu.name, tu.type, tu.ndims, tu.dims)) == -1) {
00684         error("%s: ncvardef failed", pname);
00685         ncclose(cdfid); return ++nerrs;
00686     }
00687     add_var(&test, &tu);        /* keep in-memory netcdf consistent */
00688     if (ncattput(cdfid, tu_id, att.name, att.type, att.len, att.val) == -1) {
00689         error("%s: ncattput failed", pname);
00690         ncclose(cdfid); return ++nerrs;
00691     }
00692     add_att(&test, tu_id, &att); /* keep in-memory netcdf consistent */
00693     if (ncendef (cdfid) == -1) {
00694         error("%s: ncendef failed", pname);
00695         ncclose(cdfid); return ++nerrs;
00696     }
00697     /* first (source) netcdf is in data mode */
00698     /* create second netCDF to copy attributes to */
00699     if ((cdfid2 = nccreate(path2, NC_CLOBBER)) == -1) {
00700         error("%s: nccreate failed", pname);
00701         return ++nerrs;
00702     }
00703     /* create dimensions and variable in second netcdf */
00704     for (id = 0; id < tu.ndims; id++)   { /* copy dimensions from source */
00705         if ((tu.dims[id] =ncdimdef(cdfid2, test.dims[id].name,
00706                                     test.dims[id].size)) == -1) {
00707             error("%s: ncdimdef failed", pname);
00708             ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00709         }
00710     }
00711     if ((tu2_id=ncvardef(cdfid2, tu.name, tu.type, tu.ndims, tu.dims)) == -1) {
00712         error("%s: ncvardef failed", pname);
00713         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00714     }
00715     /* try copying NC_GLOBAL attribute from source to target */
00716     if (ncattcopy(cdfid, NC_GLOBAL, att.name, cdfid2, NC_GLOBAL) == -1) {
00717         error("%s: ncattcopy on NC_GLOBAL attribute '%s' failed",
00718               pname, att.name);
00719         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00720     }
00721     /* check that copy worked with ncattinq and ncattget */
00722     if (ncattinq(cdfid2, NC_GLOBAL, att.name, &tmp.type, &tmp.len) == -1) {
00723         error("%s: ncattinq of NC_GLOBAL attribute failed", pname);
00724         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00725     }
00726     if (att.type != tmp.type || att.len != tmp.len) {
00727         error("%s: NC_GLOBAL ncattinq got unexpected type or len", pname);
00728         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00729     }
00730     /* allocate space to hold the attribute value to be retrieved */
00731     tmp.val = emalloc(att.len * nctypelen(att.type));
00732     if (ncattget(cdfid2, NC_GLOBAL, att.name, tmp.val) == -1) {
00733         error("%s: ncattget of variable attribute failed", pname);
00734         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00735     }
00736     if (val_cmp(tmp.type, tmp.len, tmp.val, att.val) != 0) {
00737         error("%s: ncattget got bad values after put of NC_GLOBAL attrs",
00738               pname);
00739         nerrs++;
00740     }
00741     free (tmp.val);
00742     /* try copying variable attribute from source to target */
00743     if (ncattcopy(cdfid, tt_id, att.name, cdfid2, tu2_id) == -1) {
00744         error("%s: ncattcopy failed", pname);
00745         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00746     }
00747     /* check that copy worked with ncattinq and ncattget */
00748     if (ncattinq(cdfid2, tu2_id, att.name, &tmp.type, &tmp.len) == -1) {
00749         error("%s: ncattinq of variable attribute failed", pname);
00750         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00751     }
00752     if (att.type != tmp.type || att.len != tmp.len) {
00753         error("%s: variable ncattinq got unexpected type or len", pname);
00754         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00755     }
00756     /* allocate space to hold the attribute value to be retrieved */
00757     tmp.val = emalloc(att.len * nctypelen(att.type));
00758     if (ncattget(cdfid2, tu2_id, att.name, tmp.val) == -1) {
00759         error("%s: ncattget of variable attribute failed", pname);
00760         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00761     }
00762     if (val_cmp(tmp.type, tmp.len, tmp.val, att.val) != 0) {
00763         error("%s: ncattget got bad values after copy of variable attrs",
00764               pname);
00765         nerrs++;
00766     }
00767     free (tmp.val);
00768 
00769     /* 
00770      * check that old attribute put works with target in data mode, 
00771      * also checks that changing type and length of an attribute works OK
00772      */
00773     if (ncendef (cdfid2) == -1) {
00774         error("%s: ncendef failed", pname);
00775         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00776     }
00777     /* change attribute to shorter attribute */
00778     if (ncattput(cdfid, NC_GLOBAL, att2.name, att2.type, att2.len, att2.val)
00779         == -1) {
00780         error("%s: ncattput of shorter NC_GLOBAL attribute failed", pname);
00781         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00782     }
00783     add_att(&test, NC_GLOBAL, &att2); /* keep in-memory netcdf consistent */
00784     /* copy shorter attribute on existing attribute */
00785     if (ncattcopy(cdfid, NC_GLOBAL, att2.name, cdfid2, tu2_id) == -1) {
00786         error("%s: ncattcopy of shorter attribute on old attribute failed",
00787               pname);
00788         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00789     }
00790     /* check that copy worked with ncattinq and ncattget */
00791     if (ncattinq(cdfid2, tu2_id, att2.name, &tmp.type, &tmp.len) == -1) {
00792         error("%s: ncattinq of variable attribute failed", pname);
00793         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00794     }
00795     if (att2.type != tmp.type || att2.len != tmp.len) {
00796         error("%s: variable ncattinq got unexpected type or len", pname);
00797         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00798     }
00799     /* allocate space to hold the attribute value to be retrieved */
00800     tmp.val = emalloc(att2.len * nctypelen(att2.type));
00801     if (ncattget(cdfid2, tu2_id, att2.name, tmp.val) == -1) {
00802         error("%s: ncattget of variable attribute failed", pname);
00803         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00804     }
00805     if (val_cmp(tmp.type, tmp.len, tmp.val, att2.val) != 0) {
00806         error("%s: ncattget got bad values after copy of variable attrs",
00807               pname);
00808         nerrs++;
00809     }
00810     free (tmp.val);
00811 
00812     /* try copying with same source and target netcdf, different variables */
00813     /* copy shorter attribute on existing attribute */
00814     if (ncattcopy(cdfid, NC_GLOBAL, att2.name, cdfid, tu_id) == -1) {
00815         error("%s: ncattcopy of shorter NC_GLOBAL attribute failed", pname);
00816         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00817     }
00818     add_att(&test, tu_id, &att2); /* keep in-memory netcdf consistent */
00819     /* check that copy worked with ncattinq and ncattget */
00820     if (ncattinq(cdfid, tu_id, att2.name, &tmp.type, &tmp.len) == -1) {
00821         error("%s: ncattinq of variable attribute failed", pname);
00822         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00823     }
00824     if (att2.type != tmp.type || att2.len != tmp.len) {
00825         error("%s: variable ncattinq got unexpected type or len", pname);
00826         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00827     }
00828     /* allocate space to hold the attribute value to be retrieved */
00829     tmp.val = emalloc(att2.len * nctypelen(att2.type));
00830     if (ncattget(cdfid, tu_id, att2.name, tmp.val) == -1) {
00831         error("%s: ncattget of variable attribute failed", pname);
00832         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00833     }
00834     if (val_cmp(tmp.type, tmp.len, tmp.val, att2.val) != 0) {
00835         error("%s: ncattget got bad values after copy of variable attrs",
00836               pname);
00837         nerrs++;
00838     }
00839     free (tmp.val);
00840 
00841     /* try with same cdfid for source and target, same variable */
00842     if (ncattcopy(cdfid, tu_id, att.name, cdfid, tu_id) == -1) {
00843         error("%s: ncattcopy failed with identical source and target",
00844               pname);
00845         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00846     }
00847     /* try with nonexisting attribute, check error */
00848     if (ncattcopy(cdfid, tt_id, "nonesuch", cdfid, tu_id) != -1) {
00849         error("%s: ncattcopy should fail with bad attribute name",
00850               pname);
00851         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00852     }
00853     /* try with bad source or target variable handle, check error */
00854     if (ncattcopy(cdfid, test.nvars, att.name, cdfid, tu_id) != -1) {
00855         error("%s: ncattcopy should fail with bad source variable id",
00856               pname);
00857         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00858     }
00859     if (ncattcopy(cdfid, tt_id, att.name, cdfid, 2) != -1) {
00860         error("%s: ncattcopy should fail with bad target variable id",
00861               pname);
00862         ncclose(cdfid); ncclose(cdfid2); return ++nerrs;
00863     }
00864     if (ncclose (cdfid2) == -1) {
00865         error("%s: ncclose failed", pname);
00866         ncclose(cdfid); return ++nerrs;
00867     }
00868     /* try with bad source or target netCDF handles, check error */
00869     if (ncattcopy(cdfid, tt_id, att.name, cdfid2, tu_id) != -1) {
00870         error("%s: ncattcopy should fail with bad target netcdf id",
00871               pname);
00872         ncclose(cdfid); return ++nerrs;
00873     }
00874     if (ncclose (cdfid) == -1) {
00875         error("%s: ncclose failed", pname);
00876         return ++nerrs;
00877     }
00878     if (ncattcopy(cdfid, tt_id, att.name, cdfid2, tu_id) != -1) {
00879         error("%s: ncattcopy should fail with bad netcdf id", pname);
00880         nerrs++;
00881     }
00882     if (nerrs > 0)
00883       (void) fprintf(stderr,"FAILED! ***\n");
00884     else
00885       (void) fprintf(stderr,"ok ***\n");
00886 
00887     return nerrs;
00888 }
00889 
00890 
00891 /*
00892  * Test ncattname
00893  *    check that NC_GLOBAL variable id works
00894  *    check in both modes
00895  *    check that proper call worked after ncattput
00896  *    try with bad netCDF handle, check error
00897  *    try with bad variable handle, check error
00898  *    try with bad attribute number, check error
00899  */
00900 int
00901 test_ncattname(path)
00902      const char *path;          /* name of writable netcdf file to open */
00903 {
00904     int nerrs = 0;
00905     static char pname[] = "test_ncattname";
00906     int cdfid;                  /* netcdf id */
00907     struct cdfatt tmp;          /* attributes */
00908     int ia, ib;                 /* attribute numbers */
00909     int iv;                     /* variable id */
00910     static short short_vals[] = {3, 4, 5};
00911     static struct cdfatt att =  /* attribute */
00912         {___, ___, NC_SHORT, LEN_OF(short_vals), (void *) short_vals};
00913 
00914     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
00915 
00916     if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
00917         error("%s: ncopen failed", pname);
00918         return ++nerrs;
00919     }
00920     /* opened OK, enter define mode */
00921     if (ncredef(cdfid) == -1) {
00922         error("%s: ncredef failed", pname);
00923         ncclose(cdfid); return ++nerrs;
00924     }
00925     /* for each NC_GLOBAL attribute, get name and compare with expected name */
00926     att.name = (char *) emalloc(MAX_NC_NAME);
00927     ib = 0;
00928     for (ia = 0; ia < test.ngatts; ia++) {
00929         if (ncattname(cdfid, NC_GLOBAL, ia, att.name) == -1) {
00930             error("%s: ncattname failed on global attribute", pname);
00931             ncclose(cdfid); return ++nerrs;
00932         }
00933         /* find number of next global attribute */
00934         while (ib < test.natts && test.atts[ib].var != NC_GLOBAL)
00935           ib++;
00936         if (ib >= test.natts) {
00937             error("%s: test problem, expected global attribute not found",
00938                   pname);
00939             ncclose(cdfid); return ++nerrs;
00940         }
00941         if (strcmp(att.name, test.atts[ib].name) != 0) {
00942             error("%s: NC_GLOBAL attribute name `%s' instead of expected `%s'",
00943                   pname, att.name, test.atts[ib].name);
00944             nerrs++;
00945         }
00946         ib++;
00947     }
00948     /* for each variable attribute, get name and compare with expected name */
00949     for (iv = 0; iv < test.nvars; iv++) {
00950         ib = 0;
00951         for (ia = 0; ia < test.vars[iv].natts; ia++) {
00952             if (ncattname(cdfid, iv, ia, att.name) == -1) {
00953                 error("%s: ncattname failed on variable attribute", pname);
00954                 ncclose(cdfid); return ++nerrs;
00955             }
00956             /* find number of next attribute */
00957             while (ib < test.natts && test.atts[ib].var != iv)
00958               ib++;
00959             if (ib >= test.natts) {
00960                 error("%s: problem  in test, expected attribute not found",
00961                       pname);
00962                 ncclose(cdfid); return ++nerrs;
00963             }
00964             if (strcmp(att.name, test.atts[ib].name) != 0) {
00965                 error("%s: variable '%s' name `%s' instead of expected `%s'",
00966                       pname, test.vars[iv].name, att.name, test.atts[ib].name);
00967                 nerrs++;
00968             }
00969             ib++;
00970         }
00971     }
00972     /* in define mode, add a global attribute */
00973     (void) strcpy(att.name,"attx");
00974     if (ncattput(cdfid, NC_GLOBAL, att.name, att.type, att.len, att.val)
00975         == -1) {
00976         error("%s: ncattput failed", pname);
00977         ncclose(cdfid); return ++nerrs;
00978     }
00979     add_att(&test, NC_GLOBAL, &att); /* keep in-memory netcdf consistent */
00980     /* test that ncattname works immediately after ncattput */
00981     tmp.name = (char *) emalloc(MAX_NC_NAME);
00982     if (ncattname(cdfid, NC_GLOBAL, test.ngatts-1, tmp.name) == -1) {
00983         error("%s: ncattname failed on variable attribute", pname);
00984         ncclose(cdfid); return ++nerrs;
00985     }
00986     if (strcmp(att.name, tmp.name) != 0) {
00987         error("%s: immediate NC_GLOBAL name `%s' instead of expected `%s'",
00988               pname, tmp.name, att.name);
00989         nerrs++;
00990     }
00991     if (ncendef (cdfid) == -1) {
00992         error("%s: ncendef failed", pname);
00993         ncclose(cdfid); return ++nerrs;
00994     }
00995     /* in data mode */
00996     /* for each NC_GLOBAL attribute, get name and compare with expected name */
00997     ib = 0;
00998     for (ia = 0; ia < test.ngatts; ia++) {
00999         if (ncattname(cdfid, NC_GLOBAL, ia, att.name) == -1) {
01000             error("%s: ncattname failed on global attribute", pname);
01001             ncclose(cdfid); return ++nerrs;
01002         }
01003         /* find number of next global attribute */
01004         while (ib < test.natts && test.atts[ib].var != NC_GLOBAL)
01005           ib++;
01006         if (ib >= test.natts) {
01007             error("%s: test problem, expected global attribute not found",
01008                   pname);
01009             ncclose(cdfid); return ++nerrs;
01010         }
01011         if (strcmp(att.name, test.atts[ib].name) != 0) {
01012             error("%s: NC_GLOBAL attribute name `%s' instead of expected `%s'",
01013                   pname, att.name, test.atts[ib].name);
01014             nerrs++;
01015         }
01016         ib++;
01017     }
01018     /* for each variable attribute, get name and compare with expected name */
01019     for (iv = 0; iv < test.nvars; iv++) {
01020         ib = 0;
01021         for (ia = 0; ia < test.vars[iv].natts; ia++) {
01022             if (ncattname(cdfid, iv, ia, att.name) == -1) {
01023                 error("%s: ncattname failed on variable attribute", pname);
01024                 ncclose(cdfid); return ++nerrs;
01025             }
01026             /* find number of next attribute */
01027             while (ib < test.natts && test.atts[ib].var != iv)
01028               ib++;
01029             if (ib >= test.natts) {
01030                 error("%s: problem  in test, expected attribute not found",
01031                       pname);
01032                 ncclose(cdfid); return ++nerrs;
01033             }
01034             if (strcmp(att.name, test.atts[ib].name) != 0) {
01035                 error("%s: variable '%s' name `%s' instead of expected `%s'",
01036                       pname, test.vars[iv].name, att.name, test.atts[ib].name);
01037                 nerrs++;
01038             }
01039             ib++;
01040         }
01041     }
01042     /* try with bad variable handle, check error */
01043     if (ncattname(cdfid, test.nvars, 0, att.name) != -1) {
01044         error("%s: ncattname should fail with bad variable handle", pname);
01045         ncclose(cdfid); return ++nerrs;
01046     }
01047     /* try with bad attribute number, check error */
01048     if (ncattname(cdfid, NC_GLOBAL, -1, att.name) != -1) {
01049         error("%s: ncattname should fail with negative number", pname);
01050         ncclose(cdfid); return ++nerrs;
01051     }
01052     if (ncattname(cdfid, NC_GLOBAL, test.ngatts, att.name) != -1) {
01053         error("%s: ncattname should fail with too-high number", pname);
01054         ncclose(cdfid); return ++nerrs;
01055     }
01056     if (ncclose (cdfid) == -1) {
01057         error("%s: ncclose failed", pname);
01058         nerrs++;
01059         return ++nerrs;
01060     }
01061     /* try with bad netCDF handle, check error */
01062     if (ncattname(cdfid, NC_GLOBAL, 0, att.name) != -1) {
01063         error("%s: ncattname shoul fail with bad cdfid", pname);
01064         nerrs++;
01065     }
01066     free (tmp.name);
01067     free (att.name);
01068     if (nerrs > 0)
01069       (void) fprintf(stderr,"FAILED! ***\n");
01070     else
01071       (void) fprintf(stderr,"ok ***\n");
01072     
01073     return nerrs;
01074 }
01075 
01076 
01077 /*
01078  * Test ncattrename
01079  *    check that proper rename worked with ncattinq, ncattget
01080  *    try renaming to existing attribute name, check error
01081  *    try with nonexisting attribute, check error
01082  *    try with bad variable handle, check error
01083  *    try in data mode, check error
01084  *    try with bad netCDF handle, check error
01085  */
01086 int
01087 test_ncattrename(path)
01088      const char *path;          /* name of writable netcdf file to open */
01089 {
01090     int nerrs = 0;
01091     static char pname[] = "test_ncattrename";
01092     int cdfid;                  /* netcdf id */
01093     static char newname[] = "shorter";
01094     static char longername[] = "longer_name";
01095     struct cdfatt tmp;          /* attributes */
01096     static short short_vals[] = {3, 4, 5};
01097     static struct cdfatt atty = /* attribute */
01098         {___, "long_name", NC_SHORT, LEN_OF(short_vals), (void *) short_vals};
01099     static struct cdfatt attz = /* attribute */
01100         {___, "arggh", NC_SHORT, LEN_OF(short_vals), (void *) short_vals};
01101     int ynum;                   /* attribute number */
01102 
01103     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
01104 
01105     if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
01106         error("%s: ncopen failed", pname);
01107         return ++nerrs;
01108     }
01109     /* opened OK, enter define mode */
01110     if (ncredef(cdfid) == -1) {
01111         error("%s: cdredef failed", pname);
01112         ncclose(cdfid); return ++nerrs;
01113     }
01114     /* in define mode, add two attributes */
01115     if (ncattput(cdfid, NC_GLOBAL, atty.name, atty.type, atty.len,
01116                   atty.val) == -1) {
01117         error("%s: ncattput failed", pname);
01118         ncclose(cdfid); return ++nerrs;
01119     }
01120     add_att(&test, NC_GLOBAL, &atty); /* keep in-memory netcdf in sync */
01121     ynum = test.natts-1;        /* number of attribute just put */
01122     if (ncattput(cdfid, NC_GLOBAL, attz.name, attz.type, attz.len,
01123                   attz.val) == -1) {
01124         error("%s: ncattput failed", pname);
01125         ncclose(cdfid); return ++nerrs;
01126     }
01127     add_att(&test, NC_GLOBAL, &attz); /* keep in-memory netcdf in sync */
01128 
01129     /* rename first attribute to shorter name */
01130     if (ncattrename(cdfid, NC_GLOBAL, atty.name, newname) == -1) {
01131         error("%s: ncattrename failed", pname);
01132         ncclose(cdfid); return ++nerrs;
01133     }
01134     (void) strcpy(test.atts[ynum].name, newname); /* keep test consistent */
01135     /* check new name with ncattinq */
01136     if (ncattinq(cdfid, NC_GLOBAL, newname, &tmp.type, &tmp.len) == -1) {
01137         error("%s: ncattinq of renamed attribute failed", pname);
01138         ncclose(cdfid); return ++nerrs;
01139     }
01140     if (atty.type != tmp.type || atty.len != tmp.len) {
01141         error("%s: NC_GLOBAL ncattinq got unexpected type or len", pname);
01142         ncclose(cdfid); return ++nerrs;
01143     }
01144     /* allocate space to hold the attribute value to be retrieved */
01145     tmp.val = emalloc(atty.len * nctypelen(atty.type));
01146     if (ncattget(cdfid, NC_GLOBAL, newname, tmp.val) == -1) {
01147         error("%s: ncattget of variable attribute failed", pname);
01148         ncclose(cdfid); return ++nerrs;
01149     }
01150     if (val_cmp(tmp.type, tmp.len, tmp.val, atty.val) != 0) {
01151         error("%s: ncattget got bad values after rename attrs", pname);
01152         nerrs++;
01153     }
01154     if (ncattinq(cdfid, NC_GLOBAL, atty.name, &tmp.type, &tmp.len) != -1) {
01155         error("%s: ncattrename left attribute with old name", pname);
01156         ncclose(cdfid); return ++nerrs;
01157     }
01158     /* try to rename second attribute same as first, should fail */
01159     if (ncattrename(cdfid, NC_GLOBAL, attz.name, newname) != -1) {
01160         error("%s: ncattrename should have failed with used name", pname);
01161         ncclose(cdfid); return ++nerrs;
01162     }
01163     /* try to rename second attribute with a longer name */
01164     if (ncattrename(cdfid, NC_GLOBAL, attz.name, longername) == -1) {
01165         error("%s: ncattrename failed with longer name", pname);
01166         ncclose(cdfid); return ++nerrs;
01167     }
01168     /* try with bad variable handle, check for failure */
01169     if (ncattrename(cdfid, test.nvars, newname, atty.name) != -1) {
01170         error("%s: ncattrename should have failed on bad variable id", pname);
01171         ncclose(cdfid); return ++nerrs;
01172     }
01173     /* try with bad attribute name, check for failure */
01174     if (ncattrename(cdfid, NC_GLOBAL, "nonesuch", newname) != -1) {
01175         error("%s: ncattrename should have failed on bad attribute name",
01176               pname);
01177         ncclose(cdfid); return ++nerrs;
01178     }
01179     if (ncendef (cdfid) == -1) {
01180         error("%s: ncendef failed", pname);
01181         ncclose(cdfid); return ++nerrs;
01182     }
01183     /* in data mode change name to even shorter and check value */
01184     if (ncattrename(cdfid, NC_GLOBAL, newname, "short") == -1) {
01185         error("%s: ncattrename to shorter name failed in data mode", pname);
01186         ncclose(cdfid); return ++nerrs;
01187     }
01188     if (ncattrename(cdfid, NC_GLOBAL, "short", "plugh") == -1) {
01189         error("%s: ncattrename to same length failed in data mode", pname);
01190         ncclose(cdfid); return ++nerrs;
01191     }
01192     if (ncattget(cdfid, NC_GLOBAL, "plugh", tmp.val) == -1) {
01193         error("%s: ncgetatt of renamed attribute failed in data mode", pname);
01194         ncclose(cdfid); return ++nerrs;
01195     }
01196     if (val_cmp(tmp.type, tmp.len, tmp.val, atty.val) != 0) {
01197         error("%s: ncattget got bad values after data mode rename", pname);
01198         nerrs++;
01199     }
01200     free (tmp.val);
01201     if (ncclose (cdfid) == -1) {
01202         error("%s: ncclose failed", pname);
01203         return ++nerrs;
01204     }
01205     /* should fail, since bad handle */
01206     if (ncattrename(cdfid, NC_GLOBAL, newname, atty.name) != -1) {
01207         error("%s: ncattrename should fail with bad cdfid", pname);
01208         ncclose(cdfid); return ++nerrs;
01209     }
01210     if (nerrs > 0)
01211       (void) fprintf(stderr,"FAILED! ***\n");
01212     else
01213       (void) fprintf(stderr,"ok ***\n");
01214 
01215     return nerrs;
01216 }
01217 
01218 
01219 /*
01220  * Test ncattdel
01221  *    check that proper delete worked   
01222  *    try with bad netCDF handle, check error
01223  *    try with bad variable handle, check error
01224  *    try with nonexisting attribute, check error
01225  *    try in data mode, check error
01226  */
01227 int
01228 test_ncattdel(path)
01229      const char *path;          /* name of writable netcdf file to open */
01230 {
01231     int nerrs = 0;
01232     static char pname[] = "test_ncattdel";
01233     int cdfid;                  /* netcdf id */
01234     static short short_vals[] = {-1, -2, -3 };
01235     static struct cdfatt yaa =  /* attribute */
01236         {___, "yet_another_attribute", NC_SHORT, LEN_OF(short_vals),
01237            (void *) short_vals};
01238     int id;                     /* dimension id */
01239     int yav_id;                 /* variable id */
01240     static struct cdfvar yav =  /* new variable for target netcdf */
01241       {"yet_another_variable", NC_DOUBLE, 2, ___, 0};
01242     struct cdfvar vtmp;         /* variable */
01243     struct cdfatt atmp;         /* attribute */
01244     int ndims;                  /* number of dimensions */
01245     int nvars;                  /* number of variables */
01246     int ngatts1, ngatts2;       /* number of global attributes */
01247     int natts;                  /* number of variable attributes */
01248     int xdimid;                 /* id of unlimited dimension */
01249 
01250     (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
01251 
01252     if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
01253         error("%s: ncopen failed", pname);
01254         return ++nerrs;
01255     }
01256     /* opened OK, enter define mode */
01257     if (ncredef(cdfid) == -1) {
01258         error("%s: cdredef failed", pname);
01259         ncclose(cdfid); return ++nerrs;
01260     }
01261     /* in define mode, add global attribute, variable, variable attribute */
01262     if (ncattput(cdfid, NC_GLOBAL, yaa.name, yaa.type, yaa.len, yaa.val) == -1) {
01263         error("%s: ncattput failed", pname);
01264         ncclose(cdfid); return ++nerrs;
01265     }
01266     add_att(&test, NC_GLOBAL, &yaa); /* keep in-memory netcdf in sync */
01267     yav.dims = (int *) emalloc(sizeof(int) * yav.ndims);
01268     for (id = 0; id < yav.ndims; id++)
01269         yav.dims[id] = id;
01270     if ((yav_id=ncvardef(cdfid, yav.name, yav.type, yav.ndims, yav.dims))
01271         == -1) {
01272         error("%s: ncvardef failed", pname);
01273         ncclose(cdfid); return ++nerrs;
01274     }
01275     add_var(&test, &yav);       /* keep in-memory netcdf consistent */
01276     if (ncattput(cdfid, yav_id, yaa.name, yaa.type, yaa.len, yaa.val) == -1) {
01277         error("%s: ncattput failed", pname);
01278         ncclose(cdfid); return ++nerrs;
01279     }
01280     add_att(&test, yav_id, &yaa); /* keep in-memory netcdf consistent */
01281 
01282     /* get number of global attributes, number of attributes for variable */
01283     if (ncinquire(cdfid, &ndims, &nvars, &ngatts1, &xdimid) == -1) {
01284         error("%s: ncinquire in data mode failed", pname);
01285         ncclose(cdfid); return ++nerrs;
01286     }
01287     vtmp.dims = (int *) emalloc(sizeof(int) * MAX_VAR_DIMS);
01288     vtmp.name = (char *) emalloc(MAX_NC_NAME);
01289     if (ncvarinq(cdfid, yav_id, vtmp.name, &vtmp.type, &vtmp.ndims, vtmp.dims,
01290                   &natts) == -1) {
01291         error("%s: ncvarinq failed", pname);
01292         ncclose(cdfid); return ++nerrs;
01293     }    
01294 
01295     /* delete global attribute and check that it's gone */
01296     if (ncattdel(cdfid, NC_GLOBAL, yaa.name) == -1) {
01297         error("%s: ncattdel failed", pname);
01298         ncclose(cdfid); return ++nerrs;
01299     }
01300     del_att(&test, NC_GLOBAL, &yaa); /* keep in-memory netcdf consistent */
01301     if (ncinquire(cdfid, &ndims, &nvars, &ngatts2, &xdimid) == -1) {
01302         error("%s: ncinquire failed", pname);
01303         ncclose(cdfid); return ++nerrs;
01304     }
01305     if (ngatts2 != ngatts1 - 1) {
01306         error("%s: NC_GLOBAL attribute deleted, but ngatts did not decrement",
01307               pname);
01308         ncclose(cdfid); return ++nerrs;
01309     }
01310     if (ncattinq(cdfid, NC_GLOBAL, yaa.name, &atmp.type, &atmp.len) != -1) {
01311         error("%s: ncattinq on deleted NC_GLOBAL attribute should fail", pname);
01312         ncclose(cdfid); return ++nerrs;
01313     }
01314 
01315     /* delete variable attribute and check that it's gone */
01316     if (ncattdel(cdfid, yav_id, yaa.name) == -1) {
01317         error("%s: ncattdel failed", pname);
01318         ncclose(cdfid); return ++nerrs;
01319     }
01320     del_att(&test, yav_id, &yaa); /* keep in-memory netcdf consistent */
01321     if (ncvarinq(cdfid, yav_id, vtmp.name, &vtmp.type, &vtmp.ndims,
01322                   vtmp.dims, &vtmp.natts) == -1) {
01323         error("%s: ncvarinq failed", pname);
01324         ncclose(cdfid); return ++nerrs;
01325     }
01326     if (vtmp.natts != natts - 1) {
01327         error("%s: NC_GLOBAL attribute deleted, but ngatts did not decrement",
01328               pname);
01329         ncclose(cdfid); return ++nerrs;
01330     }
01331     if (ncattinq(cdfid, yav_id, yaa.name, &atmp.type, &atmp.len) != -1) {
01332         error("%s: ncattinq on deleted variable attribute should fail",
01333               pname);
01334         ncclose(cdfid); return ++nerrs;
01335     }
01336     /* re-add global attribute, variable, variable attribute */
01337     if (ncattput(cdfid, NC_GLOBAL, yaa.name, yaa.type, yaa.len, yaa.val) == -1) {
01338         error("%s: ncattput failed", pname);
01339         ncclose(cdfid); return ++nerrs;
01340     }
01341     add_att(&test, NC_GLOBAL, &yaa); /* keep in-memory netcdf in sync */
01342     if (ncattput(cdfid, yav_id, yaa.name, yaa.type, yaa.len, yaa.val) == -1) {
01343         error("%s: ncattput failed", pname);
01344         ncclose(cdfid); return ++nerrs;
01345     }
01346     add_att(&test, yav_id, &yaa); /* keep in-memory netcdf consistent */
01347     /* try on nonexistent attribute, should fail */
01348     if (ncattdel(cdfid, yav_id, "nonesuch") != -1) {
01349         error("%s: ncattdel should fail on bogus attribute", pname);
01350         ncclose(cdfid); return ++nerrs;
01351     }
01352     /* try on bad variable id, should fail */
01353     if (ncattdel(cdfid, test.nvars, yaa.name) != -1) {
01354         error("%s: ncattdel should fail on bad variable id", pname);
01355         ncclose(cdfid); return ++nerrs;
01356     }
01357     if (ncendef (cdfid) == -1) {
01358         error("%s: ncendef failed", pname);
01359         ncclose(cdfid); return ++nerrs;
01360     }
01361     /* in data mode, should fail */
01362     if (ncattdel(cdfid, NC_GLOBAL, yaa.name) != -1) {
01363         error("%s: ncattdel in data mode should fail", pname);
01364         ncclose(cdfid); return ++nerrs;
01365     }
01366     if (ncclose (cdfid) == -1) {
01367         error("%s: ncclose failed", pname);
01368         return ++nerrs;
01369     }
01370     /* try on bad netcdf handle, should fail */
01371     if (ncattdel(cdfid, yav_id, yaa.name) != -1) {
01372         error("%s: ncattdel should fail on bad netcdf id", pname);
01373         nerrs++;
01374     }
01375     free(vtmp.dims);
01376     free(vtmp.name);
01377     free(yav.dims);
01378     if (nerrs > 0)
01379       (void) fprintf(stderr,"FAILED! ***\n");
01380     else
01381       (void) fprintf(stderr,"ok ***\n");
01382 
01383     return nerrs;
01384 }

Generated on Thu Mar 16 18:10:14 2006 for nco by  doxygen 1.4.4