ncdf4a13/nc_test/test_write.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  *   Copyright 1996, UCAR/Unidata
00003  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
00004  *   $Id: test_write.c,v 1.32 2006/01/06 01:22:15 ed Exp $
00005  *********************************************************************/
00006 
00007 #include "tests.h"
00008 #include "math.h"
00009 #include <stdio.h> /* For FILE stuff. */
00010 
00011 /*
00012  * Test nc_create
00013  *    For mode in NC_NOCLOBBER, NC_CLOBBER do:
00014  *       create netcdf file 'scratch.nc' with no data, close it
00015  *       test that it can be opened, do nc_inq to check nvars = 0, etc.
00016  *    Try again in NC_NOCLOBBER mode, check error return
00017  * On exit, delete this file
00018  */
00019 void
00020 test_nc_create(void)
00021 {
00022     int clobber;                /* 0 for NC_NOCLOBBER, 1 for NC_CLOBBER */
00023     int err;
00024     int ncid;
00025     int ndims;                  /* number of dimensions */
00026     int nvars;                  /* number of variables */
00027     int ngatts;                 /* number of global attributes */
00028     int recdim;                 /* id of unlimited dimension */
00029 
00030     for (clobber = 0; clobber < 2; clobber++) {
00031         err = nc_create(scratch, clobber ? NC_CLOBBER : NC_NOCLOBBER, &ncid);
00032         IF (err)
00033             error("nc_create: %s", nc_strerror(err));
00034         err = nc_close(ncid);
00035         IF (err)
00036             error("nc_close: %s", nc_strerror(err));
00037         err = nc_open(scratch, NC_NOWRITE, &ncid);
00038         IF (err)
00039             error("nc_open: %s", nc_strerror(err));
00040         err = nc_inq(ncid, &ndims, &nvars, &ngatts, &recdim);
00041         IF (err)
00042             error("nc_inq: %s", nc_strerror(err));
00043         else IF (ndims != 0)
00044             error("nc_inq: wrong number of dimensions returned, %d", ndims);
00045         else IF (nvars != 0)
00046             error("nc_inq: wrong number of variables returned, %d", nvars);
00047         else IF (ngatts != 0)
00048             error("nc_inq: wrong number of global atts returned, %d", ngatts);
00049         else IF (recdim != -1)
00050             error("nc_inq: wrong record dimension ID returned, %d", recdim);
00051         err = nc_close(ncid);
00052         IF (err)
00053             error("nc_close: %s", nc_strerror(err));
00054     }
00055 
00056     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00057     IF (err != NC_EEXIST)
00058         error("attempt to overwrite file: status = %d", err);
00059     err = remove(scratch);
00060     IF (err)
00061         error("remove of %s failed", scratch);
00062 }
00063 
00064 
00065 /*
00066  * Test nc_redef 
00067  * (In fact also tests nc_enddef - called from test_nc_enddef)
00068  *    BAD_ID
00069  *    attempt redef (error) & enddef on read-only file
00070  *    create file, define dims & vars. 
00071  *    attempt put var (error)
00072  *    attempt redef (error) & enddef.
00073  *    put vars
00074  *    attempt def new dims (error)
00075  *    redef
00076  *    def new dims, vars.
00077  *    put atts
00078  *    enddef
00079  *    put vars
00080  *    close
00081  *    check file: vars & atts
00082  *    check reopening with NC_WRITE and adding new dims, atts, vars
00083  */
00084 void
00085 test_nc_redef(void)
00086 {
00087     int ncid;                   /* netcdf id */
00088     /* used to force effective test of ncio->move() in redef */
00089     size_t sizehint = 8192;
00090     int dimid;         /* dimension id */
00091     int varid;         /* variable id */
00092     int varid1;        /* variable id */
00093     int err;
00094     const char * title = "Not funny";
00095     double var;
00096     char name[NC_MAX_NAME];
00097     size_t length;
00098     int fmt_variant1, fmt_variant2;
00099 
00100         /* BAD_ID tests */
00101     err = nc_redef(BAD_ID);
00102     IF (err != NC_EBADID)
00103         error("bad ncid: status = %d", err);
00104     err = nc_enddef(BAD_ID);
00105     IF (err != NC_EBADID)
00106         error("bad ncid: status = %d", err);
00107 
00108         /* read-only tests */
00109     err = nc_open(testfile, NC_NOWRITE, &ncid);
00110     IF (err)
00111         error("nc_open: %s", nc_strerror(err));
00112     err = nc_redef(ncid);
00113     IF (err != NC_EPERM)
00114         error("nc_redef in NC_NOWRITE mode: status = %d", err);
00115     err = nc_enddef(ncid);
00116     IF (err != NC_ENOTINDEFINE)
00117         error("nc_redef in NC_NOWRITE mode: status = %d", err);
00118     err = nc_close(ncid);
00119     IF (err) 
00120         error("nc_close: %s", nc_strerror(err));
00121 
00122         /* tests using scratch file */
00123     err = nc__create(scratch, NC_NOCLOBBER, 0, &sizehint, &ncid);
00124     IF (err) {
00125         error("nc_create: %s", nc_strerror(err));
00126         return;
00127     }
00128     /* limit for ncio implementations which have infinite chunksize */
00129     if(sizehint > 32768)
00130         sizehint = 16384;
00131     def_dims(ncid);
00132     def_vars(ncid);
00133     put_atts(ncid);
00134     err = nc_inq_varid(ncid, "d", &varid);
00135     IF (err) 
00136         error("nc_inq_varid: %s", nc_strerror(err));
00137     var = 1.0;
00138     err = nc_put_var1_double(ncid, varid, NULL, &var);
00139     IF (err != NC_EINDEFINE)
00140         error("nc_put_var... in define mode: status = %d", err);
00141     err = nc_redef(ncid);
00142     IF (err != NC_EINDEFINE)
00143         error("nc_redef in define mode: status = %d", err);
00144     err = nc_enddef(ncid);
00145     IF (err)
00146         error("nc_enddef: %s", nc_strerror(err));
00147     put_vars(ncid);
00148     err = nc_def_dim(ncid, "abc", sizehint, &dimid);
00149     IF (err != NC_ENOTINDEFINE)
00150         error("nc_def_dim in define mode: status = %d", err);
00151     err = nc_redef(ncid);
00152     IF (err)
00153         error("nc_redef: %s", nc_strerror(err));
00154 #if 0
00155     err = nc_set_fill(ncid, NC_NOFILL, NULL);
00156     IF (err)
00157         error("nc_set_fill: %s", nc_strerror(err));
00158 #endif
00159     err = nc_def_dim(ncid, "abc", sizehint, &dimid);
00160     IF (err)
00161         error("nc_def_dim: %s", nc_strerror(err));
00162     err = nc_def_var(ncid, "abcScalar", NC_INT, 0, NULL, &varid);
00163     IF (err)
00164         error("nc_def_var: %s", nc_strerror(err));
00165     err = nc_def_var(ncid, "abc", NC_INT, 1, &dimid, &varid1);
00166     IF (err)
00167         error("nc_def_var: %s", nc_strerror(err));
00168     {
00169         int dimids[NDIMS +1];
00170         int ii = 0;
00171         for(ii = 0; ii < NDIMS; ii++)
00172                 dimids[ii] = ii;
00173         dimids[NDIMS] = dimid;
00174         err = nc_def_var(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1);
00175         IF (err)
00176                 error("nc_def_var: %s", nc_strerror(err));
00177     }
00178     err = nc_put_att_text(ncid, NC_GLOBAL, "title", 1+strlen(title), title);
00179     IF (err)
00180         error("nc_put_att_text: %s", nc_strerror(err));
00181     err = nc_enddef(ncid);
00182     IF (err)
00183         error("nc_enddef: %s", nc_strerror(err));
00184     var = 1.0;
00185     err = nc_put_var1_double(ncid, varid, NULL, &var);
00186     IF (err)
00187         error("nc_put_var1_double: %s", nc_strerror(err));
00188     err = nc_inq_format(ncid, &fmt_variant1);
00189     IF (err)
00190         error("nc_inq_format: %s", nc_strerror(err));
00191     err = nc_close(ncid);
00192     IF (err) 
00193         error("nc_close: %s", nc_strerror(err));
00194 
00195     /* check scratch file written as expected */
00196     check_file(scratch);  /* checks all except "abc" stuff added above */
00197     err = nc_open(scratch, NC_NOWRITE, &ncid);
00198     IF (err)
00199         error("nc_open: %s", nc_strerror(err));
00200     err = nc_inq_dim(ncid, dimid, name, &length);
00201     IF (err) 
00202         error("nc_inq_dim: %s", nc_strerror(err));
00203     IF (strcmp(name, "abc") != 0) 
00204         error("Unexpected dim name");
00205     IF (length != sizehint) 
00206         error("Unexpected dim length");
00207     err = nc_get_var1_double(ncid, varid, NULL, &var);
00208     IF (err)
00209         error("nc_get_var1_double: %s", nc_strerror(err));
00210     IF (var != 1.0)
00211         error("nc_get_var1_double: unexpected value");
00212     err = nc_close(ncid);
00213     IF (err)
00214         error("nc_close: %s", nc_strerror(err));
00215 
00216     /* open scratch file for writing, add another dim, var, att, then check */
00217     err = nc_open(scratch, NC_WRITE, &ncid);
00218     IF (err)
00219         error("nc_open: %s", nc_strerror(err));
00220     err = nc_redef(ncid);
00221     IF (err)
00222         error("nc_redef: %s", nc_strerror(err));
00223     err = nc_def_dim(ncid, "def", sizehint, &dimid);
00224     IF (err)
00225         error("nc_def_dim: %s", nc_strerror(err));
00226     err = nc_def_var(ncid, "defScalar", NC_INT, 0, NULL, &varid);
00227     IF (err)
00228         error("nc_def_var: %s", nc_strerror(err));
00229     err = nc_def_var(ncid, "def", NC_INT, 1, &dimid, &varid1);
00230     IF (err)
00231         error("nc_def_var: %s", nc_strerror(err));
00232     err = nc_put_att_text(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), 
00233                           "Thanks!");
00234     IF (err)
00235         error("nc_put_att_text: %s", nc_strerror(err));
00236     err = nc_enddef(ncid);
00237     IF (err)
00238         error("nc_enddef: %s", nc_strerror(err));
00239     var = 2.0;
00240     err = nc_put_var1_double(ncid, varid, NULL, &var);
00241     IF (err)
00242         error("nc_put_var1_double: %s", nc_strerror(err));
00243     err = nc_close(ncid);
00244     IF (err) 
00245         error("nc_close: %s", nc_strerror(err));
00246 
00247     check_file(scratch);
00248     err = nc_open(scratch, NC_NOWRITE, &ncid);
00249     IF (err)
00250         error("nc_open: %s", nc_strerror(err));
00251     err = nc_inq_dim(ncid, dimid, name, &length);
00252     IF (err) 
00253         error("nc_inq_dim: %s", nc_strerror(err));
00254     IF (strcmp(name, "def") != 0) 
00255         error("Unexpected dim name");
00256     IF (length != sizehint) 
00257         error("Unexpected dim length");
00258     err = nc_get_var1_double(ncid, varid, NULL, &var);
00259     IF (err)
00260         error("nc_get_var1_double: %s", nc_strerror(err));
00261     IF (var != 2.0)
00262         error("nc_get_var1_double: unexpected value");
00263     /* make sure format variant hasn't changed from when created */
00264     err = nc_inq_format(ncid, &fmt_variant2);
00265     IF (err)
00266         error("nc_inq_format: %s", nc_strerror(err));
00267     IF (fmt_variant1 != fmt_variant2)
00268         error("nc_enddef changed format variant");
00269     err = nc_close(ncid);
00270     IF (err)
00271         error("nc_close: %s", nc_strerror(err));
00272     err = remove(scratch);
00273     IF (err)
00274         error("remove of %s failed", scratch);
00275 }
00276 
00277 
00278 /*
00279  * Test nc_enddef 
00280  * Simply calls test_nc_redef which tests both nc_redef & nc_enddef
00281  */
00282 void
00283 test_nc_enddef(void)
00284 {
00285     test_nc_redef();
00286 }
00287 
00288 
00289 /*
00290  * Test nc_sync
00291  *    try with bad handle, check error
00292  *    try in define mode, check error
00293  *    try writing with one handle, reading with another on same netCDF
00294  */
00295 void
00296 test_nc_sync(void)
00297 {
00298     int ncidw;         /* netcdf id for writing */
00299     int ncidr;         /* netcdf id for reading */
00300     int err;
00301 
00302         /* BAD_ID test */
00303     err = nc_sync(BAD_ID);
00304     IF (err != NC_EBADID)
00305         error("bad ncid: status = %d", err);
00306 
00307         /* create scratch file & try nc_sync in define mode */
00308     err = nc_create(scratch, NC_NOCLOBBER, &ncidw);
00309     IF (err) {
00310         error("nc_create: %s", nc_strerror(err));
00311         return;
00312     }
00313     err = nc_sync(ncidw);
00314     IF (err != NC_EINDEFINE)
00315         error("nc_sync called in define mode: status = %d", err);
00316 
00317         /* write using same handle */
00318     def_dims(ncidw);
00319     def_vars(ncidw);
00320     put_atts(ncidw);
00321     err = nc_enddef(ncidw);
00322     IF (err)
00323         error("nc_enddef: %s", nc_strerror(err));
00324     put_vars(ncidw);
00325     err = nc_sync(ncidw);
00326     IF (err)
00327         error("nc_sync of ncidw failed: %s", nc_strerror(err));
00328 
00329         /* open another handle, nc_sync, read (check) */
00330     err = nc_open(scratch, NC_NOWRITE, &ncidr);
00331     IF (err)
00332         error("nc_open: %s", nc_strerror(err));
00333     err = nc_sync(ncidr);
00334     IF (err)
00335         error("nc_sync of ncidr failed: %s", nc_strerror(err));
00336     check_dims(ncidr);
00337     check_atts(ncidr);
00338     check_vars(ncidr);
00339 
00340         /* close both handles */
00341     err = nc_close(ncidr);
00342     IF (err)
00343         error("nc_close: %s", nc_strerror(err));
00344     err = nc_close(ncidw);
00345     IF (err)
00346         error("nc_close: %s", nc_strerror(err));
00347 
00348     err = remove(scratch);
00349     IF (err)
00350         error("remove of %s failed", scratch);
00351 }
00352 
00353 
00354 /*
00355  * Test nc_abort
00356  *    try with bad handle, check error
00357  *    try in define mode before anything written, check that file was deleted
00358  *    try after nc_enddef, nc_redef, define new dims, vars, atts
00359  *    try after writing variable
00360  */
00361 void
00362 test_nc_abort(void)
00363 {
00364     int ncid;          /* netcdf id */
00365     int err;
00366     int ndims;
00367     int nvars;
00368     int ngatts;
00369 
00370         /* BAD_ID test */
00371     err = nc_abort(BAD_ID);
00372     IF (err != NC_EBADID)
00373         error("bad ncid: status = %d", err);
00374 
00375         /* create scratch file & try nc_abort in define mode */
00376     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00377     IF (err) {
00378         error("nc_create: %s", nc_strerror(err));
00379         return;
00380     }
00381     def_dims(ncid);
00382     def_vars(ncid);
00383     put_atts(ncid);
00384     err = nc_abort(ncid);
00385     IF (err)
00386         error("nc_abort of ncid failed: %s", nc_strerror(err));
00387     err = nc_close(ncid);       /* should already be closed */
00388     IF (err != NC_EBADID)
00389         error("bad ncid: status = %d", err);
00390     err = remove(scratch);      /* should already be deleted */
00391     IF (!err)
00392         error("file %s should not exist", scratch);
00393 
00394         /* 
00395          * create scratch file
00396          * do nc_enddef & nc_redef
00397          * define new dims, vars, atts
00398          * try nc_abort: should restore previous state (no dims, vars, atts)
00399          */ 
00400     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00401     IF (err) {
00402         error("nc_create: %s", nc_strerror(err));
00403         return;
00404     }
00405     err = nc_enddef(ncid);
00406     IF (err)
00407         error("nc_enddef: %s", nc_strerror(err));
00408     err = nc_redef(ncid);
00409     IF (err)
00410         error("nc_redef: %s", nc_strerror(err));
00411     def_dims(ncid);
00412     def_vars(ncid);
00413     put_atts(ncid);
00414     err = nc_abort(ncid);
00415     IF (err)
00416         error("nc_abort of ncid failed: %s", nc_strerror(err));
00417     err = nc_close(ncid);       /* should already be closed */
00418     IF (err != NC_EBADID)
00419         error("bad ncid: status = %d", err);
00420     err = nc_open(scratch, NC_NOWRITE, &ncid);
00421     IF (err)
00422         error("nc_open: %s", nc_strerror(err));
00423     err = nc_inq (ncid, &ndims, &nvars, &ngatts, NULL);
00424     IF (err)
00425         error("nc_inq: %s", nc_strerror(err));
00426     IF (ndims != 0)
00427         error("ndims should be 0");
00428     IF (nvars != 0)
00429         error("nvars should be 0");
00430     IF (ngatts != 0)
00431         error("ngatts should be 0");
00432     err = nc_close (ncid);
00433     IF (err)
00434         error("nc_close: %s", nc_strerror(err));
00435 
00436         /* try nc_abort in data mode - should just close */
00437     err = nc_create(scratch, NC_CLOBBER, &ncid);
00438     IF (err) {
00439         error("nc_create: %s", nc_strerror(err));
00440         return;
00441     }
00442     def_dims(ncid);
00443     def_vars(ncid);
00444     put_atts(ncid);
00445     err = nc_enddef(ncid);
00446     IF (err)
00447         error("nc_enddef: %s", nc_strerror(err));
00448     put_vars(ncid);
00449     err = nc_abort(ncid);
00450     IF (err)
00451         error("nc_abort of ncid failed: %s", nc_strerror(err));
00452     err = nc_close(ncid);       /* should already be closed */
00453     IF (err != NC_EBADID)
00454         error("bad ncid: status = %d", err);
00455     check_file(scratch);
00456     err = remove(scratch);
00457     IF (err)
00458         error("remove of %s failed", scratch);
00459 }
00460 
00461 
00462 /*
00463  * Test nc_def_dim
00464  *    try with bad netCDF handle, check error
00465  *    try in data mode, check error
00466  *    check that returned id is one more than previous id
00467  *    try adding same dimension twice, check error
00468  *    try with illegal sizes, check error
00469  *    make sure unlimited size works, shows up in nc_inq_unlimdim
00470  *    try to define a second unlimited dimension, check error
00471  */
00472 void
00473 test_nc_def_dim(void)
00474 {
00475     int ncid;
00476     int  err;             /* status */
00477     int  i;
00478     int  dimid;         /* dimension id */
00479     size_t length;
00480 
00481         /* BAD_ID test */
00482     err = nc_def_dim(BAD_ID, "abc", 8, &dimid);
00483     IF (err != NC_EBADID)
00484         error("bad ncid: status = %d", err);
00485 
00486         /* data mode test */
00487     err = nc_create(scratch, NC_CLOBBER, &ncid);
00488     IF (err) {
00489         error("nc_create: %s", nc_strerror(err));
00490         return;
00491     }
00492     err = nc_enddef(ncid);
00493     IF (err)
00494         error("nc_enddef: %s", nc_strerror(err));
00495     err = nc_def_dim(ncid, "abc", 8, &dimid);
00496     IF (err != NC_ENOTINDEFINE)
00497         error("bad ncid: status = %d", err);
00498 
00499         /* define-mode tests: unlimited dim */
00500     err = nc_redef(ncid);
00501     IF (err)
00502         error("nc_redef: %s", nc_strerror(err));
00503     err = nc_def_dim(ncid, dim_name[0], NC_UNLIMITED, &dimid);
00504     IF (err) 
00505         error("nc_def_dim: %s", nc_strerror(err));
00506     IF (dimid != 0) 
00507         error("Unexpected dimid");
00508     err = nc_inq_unlimdim(ncid, &dimid);
00509     IF (err) 
00510         error("nc_inq_unlimdim: %s", nc_strerror(err));
00511     IF (dimid != 0) 
00512         error("Unexpected recdim");
00513     err = nc_inq_dimlen(ncid, dimid, &length);
00514     IF (length != 0) 
00515         error("Unexpected length");
00516     err = nc_def_dim(ncid, "abc", NC_UNLIMITED, &dimid);
00517     IF (err != NC_EUNLIMIT)
00518         error("2nd unlimited dimension: status = %d", err);
00519 
00520         /* define-mode tests: remaining dims */
00521     for (i = 1; i < NDIMS; i++) {
00522         err = nc_def_dim(ncid, dim_name[i-1], dim_len[i], &dimid);
00523         IF (err != NC_ENAMEINUSE)
00524             error("duplicate name: status = %d", err);
00525         err = nc_def_dim(ncid, BAD_NAME, dim_len[i], &dimid);
00526         IF (err != NC_EBADNAME)
00527             error("bad name: status = %d", err);
00528         err = nc_def_dim(ncid, dim_name[i], NC_UNLIMITED-1, &dimid);
00529         IF (err != NC_EDIMSIZE)
00530             error("bad size: status = %d", err);
00531         err = nc_def_dim(ncid, dim_name[i], dim_len[i], &dimid);
00532         IF (err) 
00533             error("nc_def_dim: %s", nc_strerror(err));
00534         IF (dimid != i) 
00535             error("Unexpected dimid");
00536     }
00537 
00538         /* Following just to expand unlimited dim */
00539     def_vars(ncid);
00540     err = nc_enddef(ncid);
00541     IF (err)
00542         error("nc_enddef: %s", nc_strerror(err));
00543     put_vars(ncid);
00544 
00545         /* Check all dims */
00546     check_dims(ncid);
00547 
00548     err = nc_close(ncid);
00549     IF (err)
00550         error("nc_close: %s", nc_strerror(err));
00551     err = remove(scratch);
00552     IF (err)
00553         error("remove of %s failed", scratch);
00554 }
00555 
00556 
00557 /*
00558  * Test nc_rename_dim
00559  *    try with bad netCDF handle, check error
00560  *    check that proper rename worked with nc_inq_dim
00561  *    try renaming to existing dimension name, check error
00562  *    try with bad dimension handle, check error
00563  */
00564 void
00565 test_nc_rename_dim(void)
00566 {
00567     int ncid;
00568     int  err;             /* status */
00569     char name[NC_MAX_NAME];
00570 
00571         /* BAD_ID test */
00572     err = nc_rename_dim(BAD_ID, 0, "abc");
00573     IF (err != NC_EBADID)
00574         error("bad ncid: status = %d", err);
00575 
00576         /* main tests */
00577     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00578     IF (err) {
00579         error("nc_create: %s", nc_strerror(err));
00580         return;
00581     }
00582     def_dims(ncid);
00583     err = nc_rename_dim(ncid, BAD_DIMID, "abc");
00584     IF (err != NC_EBADDIM)
00585         error("bad dimid: status = %d", err);
00586     err = nc_rename_dim(ncid, 2, "abc");
00587     IF (err)
00588         error("nc_rename_dim: %s", nc_strerror(err));
00589     err = nc_inq_dimname(ncid, 2, name);
00590     IF (strcmp(name, "abc") != 0)
00591         error("Unexpected name: %s", name);
00592     err = nc_rename_dim(ncid, 0, "abc");
00593     IF (err != NC_ENAMEINUSE)
00594         error("duplicate name: status = %d", err);
00595 
00596     err = nc_close(ncid);
00597     IF (err)
00598         error("nc_close: %s", nc_strerror(err));
00599     err = remove(scratch);
00600     IF (err)
00601         error("remove of %s failed", scratch);
00602 }
00603 
00604 
00605 /*
00606  * Test nc_def_var
00607  *    try with bad netCDF handle, check error
00608  *    try with bad name, check error
00609  *    scalar tests:
00610  *      check that proper define worked with nc_inq_var
00611  *      try redefining an existing variable, check error
00612  *      try with bad datatype, check error
00613  *      try with bad number of dimensions, check error
00614  *      try in data mode, check error
00615  *    check that returned id is one more than previous id
00616  *    try with bad dimension ids, check error
00617  */
00618 void
00619 test_nc_def_var(void)
00620 {
00621     int  ncid;
00622     int  varid;
00623     int  err;             /* status */
00624     int  i;
00625     int  ndims;
00626     int  natts;
00627     char name[NC_MAX_NAME];
00628     int dimids[MAX_RANK];
00629     nc_type datatype;
00630 
00631         /* BAD_ID test */
00632     err = nc_def_var(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid);
00633     IF (err != NC_EBADID)
00634         error("bad ncid: status = %d", err);
00635 
00636         /* scalar tests */
00637     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00638     IF (err) {
00639         error("nc_create: %s", nc_strerror(err));
00640         return;
00641     }
00642     err = nc_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
00643     IF (err)
00644         error("nc_def_var: %s", nc_strerror(err));
00645     err = nc_inq_var(ncid, varid, name, &datatype, &ndims, dimids, &natts);
00646     IF (err)
00647         error("nc_inq_var: %s", nc_strerror(err));
00648     IF (strcmp(name, "abc") != 0)
00649         error("Unexpected name: %s", name);
00650     IF (datatype != NC_SHORT)
00651         error("Unexpected datatype");
00652     IF (ndims != 0)
00653         error("Unexpected rank");
00654     err = nc_def_var(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid);
00655     IF (err != NC_EBADNAME)
00656         error("bad name: status = %d", err);
00657     err = nc_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
00658     IF (err != NC_ENAMEINUSE)
00659         error("duplicate name: status = %d", err);
00660     err = nc_def_var(ncid, "ABC", BAD_TYPE, -1, dimids, &varid);
00661     IF (err != NC_EBADTYPE)
00662         error("bad type: status = %d", err);
00663     err = nc_def_var(ncid, "ABC", NC_SHORT, -1, dimids, &varid);
00664     IF (err != NC_EINVAL)
00665         error("bad rank: status = %d", err);
00666     err = nc_enddef(ncid);
00667     IF (err)
00668         error("nc_enddef: %s", nc_strerror(err));
00669     err = nc_def_var(ncid, "ABC", NC_SHORT, 0, dimids, &varid);
00670     IF (err != NC_ENOTINDEFINE)
00671         error("nc_def_var called in data mode: status = %d", err);
00672     err = nc_close(ncid);
00673     IF (err)
00674         error("nc_close: %s", nc_strerror(err));
00675     err = remove(scratch);
00676     IF (err)
00677         error("remove of %s failed", scratch);
00678 
00679         /* general tests using global vars */
00680     err = nc_create(scratch, NC_CLOBBER, &ncid);
00681     IF (err) {
00682         error("nc_create: %s", nc_strerror(err));
00683         return;
00684     }
00685     def_dims(ncid);
00686     for (i = 0; i < NVARS; i++) {
00687         err = nc_def_var(ncid, var_name[i], var_type[i], var_rank[i],
00688             var_dimid[i], &varid);
00689         IF (err) 
00690             error("nc_def_var: %s", nc_strerror(err));
00691         IF (varid != i)
00692             error("Unexpected varid");
00693     }
00694 
00695         /* try bad dim ids */
00696     dimids[0] = BAD_DIMID;
00697     err = nc_def_var(ncid, "abc", NC_SHORT, 1, dimids, &varid);
00698     IF (err != NC_EBADDIM)
00699         error("bad dim ids: status = %d", err);
00700     err = nc_close(ncid);
00701     IF (err)
00702         error("nc_close: %s", nc_strerror(err));
00703 
00704     err = remove(scratch);
00705     IF (err)
00706         error("remove of %s failed", scratch);
00707 }
00708 
00709 
00710 /*
00711  * Test nc_put_var1
00712  */
00713 void
00714 test_nc_put_var1(void)
00715 {
00716     int ncid;
00717     int i;
00718     int j;
00719     int err;
00720     size_t index[MAX_RANK];
00721     double value;
00722     double buf[1];              /* (void *) buffer */
00723 
00724     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00725     IF (err) {
00726         error("nc_create: %s", nc_strerror(err));
00727         return;
00728     }
00729     def_dims(ncid);
00730     def_vars(ncid);
00731     err = nc_enddef(ncid);
00732     IF (err)
00733         error("nc_enddef: %s", nc_strerror(err));
00734 
00735     for (i = 0; i < NVARS; i++) {
00736         for (j = 0; j < var_rank[i]; j++)
00737             index[j] = 0;
00738         err = nc_put_var1(BAD_ID, i, index, buf);
00739         IF (err != NC_EBADID)
00740             error("bad ncid: status = %d", err);
00741         err = nc_put_var1(ncid, BAD_VARID, index, buf);
00742         IF (err != NC_ENOTVAR)
00743             error("bad var id: status = %d", err);
00744         for (j = 0; j < var_rank[i]; j++) {
00745             if (var_dimid[i][j] > 0) {          /* skip record dim */
00746                 index[j] = var_shape[i][j];
00747                 err = nc_put_var1(ncid, i, index, buf);
00748                 IF (err != NC_EINVALCOORDS)
00749                     error("bad index: status = %d", err);
00750                 index[j] = 0;
00751             }
00752         }
00753         for (j = 0; j < var_nels[i]; j++) {
00754             err = toMixedBase(j, var_rank[i], var_shape[i], index);
00755             IF (err)
00756                 error("error in toMixedBase");
00757             value = hash( var_type[i], var_rank[i], index);
00758             if (inRange(value, var_type[i])) {
00759                 err = dbl2nc(value, var_type[i], buf);
00760                 IF (err)
00761                     error("error in dbl2nc");
00762                 if (var_rank[i] == 0 && i%2 == 0)
00763                     err = nc_put_var1(ncid, i, NULL, buf);
00764                 else
00765                     err = nc_put_var1(ncid, i, index, buf);
00766                 IF (err)
00767                     error("%s", nc_strerror(err));
00768             }
00769         }
00770     }
00771 
00772     check_vars(ncid);
00773     err = nc_close(ncid);
00774     IF (err)
00775         error("nc_close: %s", nc_strerror(err));
00776 
00777     err = remove(scratch);
00778     IF (err)
00779         error("remove of %s failed", scratch);
00780 }
00781 
00782 
00783 /*
00784  * Test nc_put_vara
00785  * Choose a random point dividing each dim into 2 parts
00786  * Put 2^rank (nslabs) slabs so defined
00787  * Redefine buffer for each put.
00788  * At end check all variables using check_vars
00789  */
00790 void
00791 test_nc_put_vara(void)
00792 {
00793     int ncid;
00794     int d;
00795     int i;
00796     int j;
00797     int k;
00798     int err;
00799     int nels;
00800     int nslabs;
00801     size_t start[MAX_RANK];
00802     size_t edge[MAX_RANK];
00803     size_t index[MAX_RANK];
00804     size_t mid[MAX_RANK];
00805     double buf[MAX_NELS];       /* (void *) buffer */
00806     char *p;                    /* (void *) pointer */
00807     double value;
00808 
00809     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00810     IF (err) {
00811         error("nc_create: %s", nc_strerror(err));
00812         return;
00813     }
00814     def_dims(ncid);
00815     def_vars(ncid);
00816     err = nc_enddef(ncid);
00817     IF (err)
00818         error("nc_enddef: %s", nc_strerror(err));
00819 
00820     for (i = 0; i < NVARS; i++) {
00821         assert(var_rank[i] <= MAX_RANK);
00822         assert(var_nels[i] <= MAX_NELS);
00823         for (j = 0; j < var_rank[i]; j++) {
00824             start[j] = 0;
00825             edge[j] = 1;
00826         }
00827         err = nc_put_vara(BAD_ID, i, start, edge, buf);
00828         IF (err != NC_EBADID)
00829             error("bad ncid: status = %d", err);
00830         err = nc_put_vara(ncid, BAD_VARID, start, edge, buf);
00831         IF (err != NC_ENOTVAR)
00832             error("bad var id: status = %d", err);
00833         for (j = 0; j < var_rank[i]; j++) {
00834             if (var_dimid[i][j] > 0) {          /* skip record dim */
00835                 start[j] = var_shape[i][j];
00836                 err = nc_put_vara(ncid, i, start, edge, buf);
00837                 IF (err != NC_EINVALCOORDS)
00838                     error("bad index: status = %d", err);
00839                 start[j] = 0;
00840                 edge[j] = var_shape[i][j] + 1;
00841                 err = nc_put_vara(ncid, i, start, edge, buf);
00842                 IF (err != NC_EEDGE)
00843                     error("bad edge: status = %d", err);
00844                 edge[j] = 1;
00845             }
00846         }
00847             /* Choose a random point dividing each dim into 2 parts */
00848             /* put 2^rank (nslabs) slabs so defined */
00849         nslabs = 1;
00850         for (j = 0; j < var_rank[i]; j++) {
00851             mid[j] = roll( var_shape[i][j] );
00852             nslabs *= 2;
00853         }
00854             /* bits of k determine whether to put lower or upper part of dim */
00855         for (k = 0; k < nslabs; k++) {
00856             nels = 1;
00857             for (j = 0; j < var_rank[i]; j++) {
00858                 if ((k >> j) & 1) {
00859                     start[j] = 0;
00860                     edge[j] = mid[j];
00861                 }else{
00862                     start[j] = mid[j];
00863                     edge[j] = var_shape[i][j] - mid[j];
00864                 }
00865                 nels *= edge[j];
00866             }
00867             p = (char *) buf;
00868             for (j = 0; j < nels; j++) {
00869                 err = toMixedBase(j, var_rank[i], edge, index);
00870                 IF (err)
00871                     error("error in toMixedBase");
00872                 for (d = 0; d < var_rank[i]; d++)
00873                     index[d] += start[d];
00874                 value = hash( var_type[i], var_rank[i], index);
00875                 if (!inRange(value, var_type[i]))
00876                     value = 0;
00877                 err = dbl2nc(value, var_type[i], p);
00878                 IF (err)
00879                     error("error in dbl2nc");
00880                 p += nctypelen(var_type[i]);
00881             }
00882             if (var_rank[i] == 0 && i%2 == 0)
00883                 err = nc_put_vara(ncid, i, NULL, NULL, buf);
00884             else
00885                 err = nc_put_vara(ncid, i, start, edge, buf);
00886             IF (err) {
00887                 error("%s", nc_strerror(err));
00888             }
00889         }
00890     }
00891 
00892     check_vars(ncid);
00893     err = nc_close(ncid);
00894     IF (err)
00895         error("nc_close: %s", nc_strerror(err));
00896 
00897     err = remove(scratch);
00898     IF (err)
00899         error("remove of %s failed", scratch);
00900 }
00901 
00902 
00903 /*
00904  * Test nc_put_vars
00905  * Choose a random point dividing each dim into 2 parts
00906  * Put 2^rank (nslabs) slabs so defined
00907  * Choose random stride from 1 to edge
00908  * Redefine buffer for each put.
00909  * At end check all variables using check_vars
00910  */
00911 void
00912 test_nc_put_vars(void)
00913 {
00914     int ncid;
00915     int d;
00916     int i;
00917     int j;
00918     int k;
00919     int m;
00920     int err;
00921     int nels;
00922     int nslabs;
00923     int nstarts;        /* number of different starts */
00924     size_t start[MAX_RANK];
00925     size_t edge[MAX_RANK];
00926     size_t index[MAX_RANK];
00927     size_t index2[MAX_RANK];
00928     size_t mid[MAX_RANK];
00929     size_t count[MAX_RANK];
00930     size_t sstride[MAX_RANK];
00931     ptrdiff_t stride[MAX_RANK];
00932     double buf[MAX_NELS]; /* (void *) buffer */
00933     char *p;                    /* (void *) pointer */
00934     double value;
00935 
00936     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
00937     IF (err) {
00938         error("nc_create: %s", nc_strerror(err));
00939         return;
00940     }
00941     def_dims(ncid);
00942     def_vars(ncid);
00943     err = nc_enddef(ncid);
00944     IF (err)
00945         error("nc_enddef: %s", nc_strerror(err));
00946 
00947     for (i = 0; i < NVARS; i++) {
00948         assert(var_rank[i] <= MAX_RANK);
00949         assert(var_nels[i] <= MAX_NELS);
00950         for (j = 0; j < var_rank[i]; j++) {
00951             start[j] = 0;
00952             edge[j] = 1;
00953             stride[j] = 1;
00954         }
00955         err = nc_put_vars(BAD_ID, i, start, edge, stride, buf);
00956         IF (err != NC_EBADID)
00957             error("bad ncid: status = %d", err);
00958         err = nc_put_vars(ncid, BAD_VARID, start, edge, stride, buf);
00959         IF (err != NC_ENOTVAR)
00960             error("bad var id: status = %d", err);
00961         for (j = 0; j < var_rank[i]; j++) {
00962             if (var_dimid[i][j] > 0) {          /* skip record dim */
00963                 start[j] = var_shape[i][j];
00964                 err = nc_put_vars(ncid, i, start, edge, stride, buf);
00965                 IF (err != NC_EINVALCOORDS && err != NC_EEDGE)
00966                     error("bad index: status = %d", err);
00967                 start[j] = 0;
00968                 edge[j] = var_shape[i][j] + 1;
00969                 err = nc_put_vars(ncid, i, start, edge, stride, buf);
00970                 IF (err != NC_EEDGE)
00971                     error("bad edge: status = %d", err);
00972                 edge[j] = 1;
00973                 stride[j] = 0;
00974                 err = nc_put_vars(ncid, i, start, edge, stride, buf);
00975                 IF (err != NC_ESTRIDE)
00976                     error("bad stride: status = %d", err);
00977                 stride[j] = 1;
00978             }
00979         }
00980             /* Choose a random point dividing each dim into 2 parts */
00981             /* put 2^rank (nslabs) slabs so defined */
00982         nslabs = 1;
00983         for (j = 0; j < var_rank[i]; j++) {
00984             mid[j] = roll( var_shape[i][j] );
00985             nslabs *= 2;
00986         }
00987             /* bits of k determine whether to put lower or upper part of dim */
00988             /* choose random stride from 1 to edge */
00989         for (k = 0; k < nslabs; k++) {
00990             nstarts = 1;
00991             for (j = 0; j < var_rank[i]; j++) {
00992                 if ((k >> j) & 1) {
00993                     start[j] = 0;
00994                     edge[j] = mid[j];
00995                 }else{
00996                     start[j] = mid[j];
00997                     edge[j] = var_shape[i][j] - mid[j];
00998                 }
00999                 sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
01000                 nstarts *= stride[j];
01001             }
01002             for (m = 0; m < nstarts; m++) {
01003                 err = toMixedBase(m, var_rank[i], sstride, index);
01004                 IF (err)
01005                     error("error in toMixedBase");
01006                 nels = 1;
01007                 for (j = 0; j < var_rank[i]; j++) {
01008                     count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
01009                     nels *= count[j];
01010                     index[j] += start[j];
01011                 }
01012                         /* Random choice of forward or backward */
01013 /* TODO
01014                 if ( roll(2) ) {
01015                     for (j = 0; j < var_rank[i]; j++) {
01016                         index[j] += (count[j] - 1) * stride[j];
01017                         stride[j] = -stride[j];
01018                     }
01019                 }
01020  */
01021                 p = (char *) buf;
01022                 for (j = 0; j < nels; j++) {
01023                     err = toMixedBase(j, var_rank[i], count, index2);
01024                     IF (err)
01025                         error("error in toMixedBase");
01026                     for (d = 0; d < var_rank[i]; d++)
01027                         index2[d] = index[d] + index2[d] * stride[d];
01028                     value = hash( var_type[i], var_rank[i], index2);
01029                     if (!inRange(value, var_type[i]))
01030                         value = 0;
01031                     err = dbl2nc(value, var_type[i], p);
01032                     IF (err)
01033                         error("error in dbl2nc");
01034                     p += nctypelen(var_type[i]);
01035                 }
01036                 if (var_rank[i] == 0 && i%2 == 0)
01037                     err = nc_put_vars(ncid, i, NULL, NULL, NULL, buf);
01038                 else
01039                     err = nc_put_vars(ncid, i, index, count, stride, buf);
01040                 IF (err) {
01041                     error("%s", nc_strerror(err));
01042                 }
01043             }
01044         }
01045     }
01046 
01047     check_vars(ncid);
01048     err = nc_close(ncid);
01049     IF (err)
01050         error("nc_close: %s", nc_strerror(err));
01051 
01052     err = remove(scratch);
01053     IF (err)
01054         error("remove of %s failed", scratch);
01055 }
01056 
01057 
01058 /*
01059  * Test nc_put_varm
01060  * Choose a random point dividing each dim into 2 parts
01061  * Put 2^rank (nslabs) slabs so defined
01062  * Choose random stride from 1 to edge
01063  * Buffer is bit image of whole external variable.
01064  * So all puts for a variable put different elements of buffer
01065  * At end check all variables using check_vars
01066  */
01067 void
01068 test_nc_put_varm(void)
01069 {
01070     int ncid;
01071     int i;
01072     int j;
01073     int k;
01074     int m;
01075     int err;
01076     int nslabs;
01077     int nstarts;        /* number of different starts */
01078     size_t start[MAX_RANK];
01079     size_t edge[MAX_RANK];
01080     size_t index[MAX_RANK];
01081     size_t mid[MAX_RANK];
01082     size_t count[MAX_RANK];
01083     size_t sstride[MAX_RANK];
01084     ptrdiff_t stride[MAX_RANK];
01085     ptrdiff_t imap[MAX_RANK];
01086     ptrdiff_t imap2[MAX_RANK];
01087     double buf[MAX_NELS];       /* (void *) buffer */
01088     char *p;                    /* (void *) pointer */
01089     double value;
01090 
01091     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
01092     IF (err) {
01093         error("nc_create: %s", nc_strerror(err));
01094         return;
01095     }
01096     def_dims(ncid);
01097     def_vars(ncid);
01098     err = nc_enddef(ncid);
01099     IF (err)
01100         error("nc_enddef: %s", nc_strerror(err));
01101 
01102     for (i = 0; i < NVARS; i++) {
01103         assert(var_rank[i] <= MAX_RANK);
01104         assert(var_nels[i] <= MAX_NELS);
01105         for (j = 0; j < var_rank[i]; j++) {
01106             start[j] = 0;
01107             edge[j] = 1;
01108             stride[j] = 1;
01109         }
01110         if (var_rank[i] > 0) {
01111             j = var_rank[i] - 1; 
01112             imap[j] = nctypelen(var_type[i]);
01113             for (; j > 0; j--)
01114                 imap[j-1] = imap[j] * var_shape[i][j];
01115         }
01116         p = (char *) buf;
01117         for (j = 0; j < var_nels[i]; j++) {
01118             err = toMixedBase(j, var_rank[i], var_shape[i], index);
01119             IF (err)
01120                 error("error in toMixedBase");
01121             value = hash( var_type[i], var_rank[i], index);
01122             if (!inRange(value, var_type[i]))
01123                 value = 0;
01124             err = dbl2nc(value, var_type[i], p);
01125             IF (err)
01126                 error("error in dbl2nc");
01127             p += nctypelen(var_type[i]);
01128         }
01129         err = nc_put_varm(BAD_ID, i, start, edge, stride, imap, buf);
01130         IF (err != NC_EBADID)
01131             error("bad ncid: status = %d", err);
01132         err = nc_put_varm(ncid, BAD_VARID, start, edge, stride, imap, buf);
01133         IF (err != NC_ENOTVAR)
01134             error("bad var id: status = %d", err);
01135         for (j = 0; j < var_rank[i]; j++) {
01136             if (var_dimid[i][j] > 0) {          /* skip record dim */
01137                 start[j] = var_shape[i][j];
01138                 err = nc_put_varm(ncid, i, start, edge, stride, imap, buf);
01139                 IF (err != NC_EINVALCOORDS && err != NC_EEDGE)
01140                     error("bad index: status = %d", err);
01141                 start[j] = 0;
01142                 edge[j] = var_shape[i][j] + 1;
01143                 err = nc_put_varm(ncid, i, start, edge, stride, imap, buf);
01144                 IF (err != NC_EEDGE)
01145                     error("bad edge: status = %d", err);
01146                 edge[j] = 1;
01147                 stride[j] = 0;
01148                 err = nc_put_varm(ncid, i, start, edge, stride, imap, buf);
01149                 IF (err != NC_ESTRIDE)
01150                     error("bad stride: status = %d", err);
01151                 stride[j] = 1;
01152             }
01153         }
01154             /* Choose a random point dividing each dim into 2 parts */
01155             /* put 2^rank (nslabs) slabs so defined */
01156         nslabs = 1;
01157         for (j = 0; j < var_rank[i]; j++) {
01158             mid[j] = roll( var_shape[i][j] );
01159             nslabs *= 2;
01160         }
01161             /* bits of k determine whether to put lower or upper part of dim */
01162             /* choose random stride from 1 to edge */
01163         for (k = 0; k < nslabs; k++) {
01164             nstarts = 1;
01165             for (j = 0; j < var_rank[i]; j++) {
01166                 if ((k >> j) & 1) {
01167                     start[j] = 0;
01168                     edge[j] = mid[j];
01169                 }else{
01170                     start[j] = mid[j];
01171                     edge[j] = var_shape[i][j] - mid[j];
01172                 }
01173                 sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
01174                 imap2[j] = imap[j] * sstride[j];
01175                 nstarts *= stride[j];
01176             }
01177             for (m = 0; m < nstarts; m++) {
01178                 if (var_rank[i] == 0 && i%2 == 0) {
01179                     err = nc_put_varm(ncid, i, NULL, NULL, NULL, NULL, buf);
01180                 } else {
01181                     err = toMixedBase(m, var_rank[i], sstride, index);
01182                     IF (err)
01183                         error("error in toMixedBase");
01184                     for (j = 0; j < var_rank[i]; j++) {
01185                         count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
01186                         index[j] += start[j];
01187                     }
01188                             /* Random choice of forward or backward */
01189 /* TODO
01190                     if ( roll(2) ) {
01191                         for (j = 0; j < var_rank[i]; j++) {
01192                             index[j] += (count[j] - 1) * stride[j];
01193                             stride[j] = -stride[j];
01194                         }
01195                     }
01196  */
01197                     j = fromMixedBase(var_rank[i], index, var_shape[i]);
01198                     p = (char *) buf + j * nctypelen(var_type[i]);
01199                     err = nc_put_varm(ncid, i, index, count, stride, imap2, p);
01200                 }
01201                 IF (err) {
01202                     error("%s", nc_strerror(err));
01203                 }
01204             }
01205         }
01206     }
01207 
01208     check_vars(ncid);
01209     err = nc_close(ncid);
01210     IF (err)
01211         error("nc_close: %s", nc_strerror(err));
01212 
01213     err = remove(scratch);
01214     IF (err)
01215         error("remove of %s failed", scratch);
01216 }
01217 
01218 
01219 /*
01220  * Test nc_rename_var
01221  *    try with bad netCDF handle, check error
01222  *    try with bad variable handle, check error
01223  *    try renaming to existing variable name, check error
01224  *    check that proper rename worked with nc_inq_varid
01225  *    try in data mode, check error
01226  */
01227 void
01228 test_nc_rename_var(void)
01229 {
01230     int ncid;
01231     int varid;
01232     int err;
01233     int i;
01234     char name[NC_MAX_NAME];
01235 
01236     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
01237     IF (err) {
01238         error("nc_create: %s", nc_strerror(err));
01239         return;
01240     }
01241     err = nc_rename_var(ncid, BAD_VARID, "newName");
01242     IF (err != NC_ENOTVAR)
01243         error("bad var id: status = %d", err);
01244     def_dims(ncid);
01245     def_vars(ncid);
01246 
01247         /* Prefix "new_" to each name */
01248     for (i = 0; i < NVARS; i++) {
01249         err = nc_rename_var(BAD_ID, i, "newName");
01250         IF (err != NC_EBADID)
01251             error("bad ncid: status = %d", err);
01252         err = nc_rename_var(ncid, i, var_name[NVARS-1]);
01253         IF (err != NC_ENAMEINUSE)
01254             error("duplicate name: status = %d", err);
01255         (void) strcpy(name, "new_");
01256         (void) strcat(name, var_name[i]);
01257         err = nc_rename_var(ncid, i, name);
01258         IF (err)
01259             error("nc_rename_var: %s", nc_strerror(err));
01260         err = nc_inq_varid(ncid, name, &varid);
01261         IF (err)
01262             error("nc_inq_varid: %s", nc_strerror(err));
01263         IF (varid != i)
01264             error("Unexpected varid");
01265     }
01266 
01267         /* Change to data mode */
01268         /* Try making names even longer. Then restore original names */
01269     err = nc_enddef(ncid);
01270     IF (err)
01271         error("nc_enddef: %s", nc_strerror(err));
01272     for (i = 0; i < NVARS; i++) {
01273         (void) strcpy(name, "even_longer_");
01274         (void) strcat(name, var_name[i]);
01275         err = nc_rename_var(ncid, i, name);
01276         IF (err != NC_ENOTINDEFINE)
01277             error("longer name in data mode: status = %d", err);
01278         err = nc_rename_var(ncid, i, var_name[i]);
01279         IF (err)
01280             error("nc_rename_var: %s", nc_strerror(err));
01281         err = nc_inq_varid(ncid, var_name[i], &varid);
01282         IF (err)
01283             error("nc_inq_varid: %s", nc_strerror(err));
01284         IF (varid != i)
01285             error("Unexpected varid");
01286     }
01287 
01288     put_vars(ncid);
01289     check_vars(ncid);
01290 
01291     err = nc_close(ncid);
01292     IF (err)
01293         error("nc_close: %s", nc_strerror(err));
01294 
01295     err = remove(scratch);
01296     IF (err)
01297         error("remove of %s failed", scratch);
01298 }
01299 
01300 
01301 void
01302 test_nc_put_att(void)
01303 {
01304     int ncid;
01305     int varid;
01306     int i;
01307     int j;
01308     size_t k;
01309     int err;
01310     double buf[MAX_NELS];       /* (void *) buffer */
01311     char *p;                    /* (void *) pointer */
01312     char *name;                 /* of att */
01313     nc_type datatype;           /* of att */
01314     size_t length;              /* of att */
01315     double value;
01316 
01317     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
01318     IF (err) {
01319         error("nc_create: %s", nc_strerror(err));
01320         return;
01321     }
01322     def_dims(ncid);
01323     def_vars(ncid);
01324 
01325     for (i = -1; i < NVARS; i++) {
01326         varid = VARID(i);
01327         for (j = 0; j < NATTS(i); j++) {
01328             name = ATT_NAME(i,j);
01329             datatype = ATT_TYPE(i,j);
01330             length = ATT_LEN(i,j);
01331             err = nc_put_att(BAD_ID, varid, name, datatype, length, buf);
01332             IF (err != NC_EBADID)
01333                 error("bad ncid: status = %d", err);
01334             err = nc_put_att(ncid, varid, BAD_NAME, datatype, length, buf);
01335             IF (err != NC_EBADNAME)
01336                 error("bad name: status = %d", err);
01337             err = nc_put_att(ncid, BAD_VARID, name, datatype, length, buf);
01338             IF (err != NC_ENOTVAR)
01339                 error("bad var id: status = %d", err);
01340             err = nc_put_att(ncid, varid, name, BAD_TYPE, length, buf);
01341             IF (err != NC_EBADTYPE)
01342                 error("bad type: status = %d", err);
01343             p = (char *) buf;
01344             for (k = 0; k < length; k++) {
01345                 value = hash(datatype, -1, &k );
01346                 if (!inRange(value, datatype))
01347                     value = 0;
01348                 err = dbl2nc(value, datatype, p);
01349                 IF (err)
01350                     error("error in dbl2nc");
01351                 p += nctypelen(datatype);
01352             }
01353             err = nc_put_att(ncid, varid, name, datatype, length, buf);
01354             IF (err) {
01355                 error("%s", nc_strerror(err));
01356             }
01357         }
01358     }
01359 
01360     check_atts(ncid);
01361     err = nc_close(ncid);
01362     IF (err)
01363         error("nc_close: %s", nc_strerror(err));
01364 
01365     err = remove(scratch);
01366     IF (err)
01367         error("remove of %s failed", scratch);
01368 }
01369 
01370 
01371 /*
01372  * Test nc_copy_att
01373  *    try with bad source or target netCDF handles, check error
01374  *    try with bad source or target variable handle, check error
01375  *    try with nonexisting attribute, check error
01376  *    check that NC_GLOBAL variable for source or target works
01377  *    check that new attribute put works with target in define mode
01378  *    check that old attribute put works with target in data mode
01379  *    check that changing type and length of an attribute work OK
01380  *    try with same ncid for source and target, different variables
01381  *    try with same ncid for source and target, same variable
01382  */
01383 void
01384 test_nc_copy_att(void)
01385 {
01386     int ncid_in;
01387     int ncid_out;
01388     int varid;
01389     int err;
01390     int i;
01391     int j;
01392     char *name;                 /* of att */
01393     nc_type datatype;           /* of att */
01394     size_t length;              /* of att */
01395     char  value;
01396 
01397     err = nc_open(testfile, NC_NOWRITE, &ncid_in);
01398     IF (err)
01399         error("nc_open: %s", nc_strerror(err));
01400     err = nc_create(scratch, NC_NOCLOBBER, &ncid_out);
01401     IF (err) {
01402         error("nc_create: %s", nc_strerror(err));
01403         return;
01404     }
01405     def_dims(ncid_out);
01406     def_vars(ncid_out);
01407 
01408     for (i = -1; i < NVARS; i++) {
01409         varid = VARID(i);
01410         for (j = 0; j < NATTS(i); j++) {
01411             name = ATT_NAME(i,j);
01412             err = nc_copy_att(ncid_in, BAD_VARID, name, ncid_out, varid);
01413             IF (err != NC_ENOTVAR)
01414                 error("bad var id: status = %d", err);
01415             err = nc_copy_att(ncid_in, varid, name, ncid_out, BAD_VARID);
01416             IF (err != NC_ENOTVAR)
01417                 error("bad var id: status = %d", err);
01418             err = nc_copy_att(BAD_ID, varid, name, ncid_out, varid);
01419             IF (err != NC_EBADID)
01420                 error("bad ncid: status = %d", err);
01421             err = nc_copy_att(ncid_in, varid, name, BAD_ID, varid);
01422             IF (err != NC_EBADID)
01423                 error("bad ncid: status = %d", err);
01424             err = nc_copy_att(ncid_in, varid, "noSuch", ncid_out, varid);
01425             IF (err != NC_ENOTATT)
01426                 error("bad attname: status = %d", err);
01427             err = nc_copy_att(ncid_in, varid, name, ncid_out, varid);
01428             IF (err)
01429                 error("nc_copy_att: %s", nc_strerror(err));
01430             err = nc_copy_att(ncid_out, varid, name, ncid_out, varid);
01431             IF (err)
01432                 error("source = target: %s", nc_strerror(err));
01433         }
01434     }
01435 
01436     err = nc_close(ncid_in);
01437     IF (err)
01438         error("nc_close: %s", nc_strerror(err));
01439 
01440         /* Close scratch. Reopen & check attributes */
01441     err = nc_close(ncid_out);
01442     IF (err)
01443         error("nc_close: %s", nc_strerror(err));
01444     err = nc_open(scratch, NC_WRITE, &ncid_out);
01445     IF (err)
01446         error("nc_open: %s", nc_strerror(err));
01447     check_atts(ncid_out);
01448 
01449        /* 
01450         * change to define mode
01451         * define single char. global att. ':a' with value 'A'
01452         * This will be used as source for following copies
01453         */
01454     err = nc_redef(ncid_out);
01455     IF (err)
01456         error("nc_redef: %s", nc_strerror(err));
01457     err = nc_put_att_text(ncid_out, NC_GLOBAL, "a", 1, "A");
01458     IF (err)
01459         error("nc_put_att_text: %s", nc_strerror(err));
01460 
01461        /* 
01462         * change to data mode
01463         * Use scratch as both source & dest.
01464         * try copy to existing att. change type & decrease length
01465         * rename 1st existing att of each var (if any) 'a'
01466         * if this att. exists them copy ':a' to it
01467         */
01468     err = nc_enddef(ncid_out);
01469     IF (err)
01470         error("nc_enddef: %s", nc_strerror(err));
01471     for (i = 0; i < NVARS; i++) {
01472         if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
01473             err = nc_rename_att(ncid_out, i, att_name[i][0], "a");
01474             IF (err)
01475                 error("nc_rename_att: %s", nc_strerror(err));
01476             err = nc_copy_att(ncid_out, NC_GLOBAL, "a", ncid_out, i);
01477             IF (err)
01478                 error("nc_copy_att: %s", nc_strerror(err));
01479         }
01480     }
01481     err = nc_close(ncid_out);
01482     IF (err)
01483         error("nc_close: %s", nc_strerror(err));
01484 
01485         /* Reopen & check */
01486     err = nc_open(scratch, NC_WRITE, &ncid_out);
01487     IF (err)
01488         error("nc_open: %s", nc_strerror(err));
01489     for (i = 0; i < NVARS; i++) {
01490         if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
01491             err = nc_inq_att(ncid_out, i, "a", &datatype, &length);
01492             IF (err)
01493                 error("nc_inq_att: %s", nc_strerror(err));
01494             IF (datatype != NC_CHAR)
01495                 error("Unexpected type");
01496             IF (length != 1)
01497                 error("Unexpected length");
01498             err = nc_get_att_text(ncid_out, i, "a", &value);
01499             IF (err)
01500                 error("nc_get_att_text: %s", nc_strerror(err));
01501             IF (value != 'A')
01502                 error("Unexpected value");
01503         }                                                   
01504     }                                                   
01505 
01506     err = nc_close(ncid_out);
01507     IF (err)
01508         error("nc_close: %s", nc_strerror(err));
01509     err = remove(scratch);
01510     IF (err)
01511         error("remove of %s failed", scratch);
01512 }
01513 
01514 
01515 /*
01516  * Test nc_rename_att
01517  *    try with bad netCDF handle, check error
01518  *    try with bad variable handle, check error
01519  *    try with nonexisting att name, check error
01520  *    try renaming to existing att name, check error
01521  *    check that proper rename worked with nc_inq_attid
01522  *    try in data mode, check error
01523  */
01524 void
01525 test_nc_rename_att(void)
01526 {
01527     int ncid;
01528     int varid;
01529     int err;
01530     int i;
01531     int j;
01532     size_t  k;
01533     int attnum;
01534     char *attname;
01535     char name[NC_MAX_NAME];
01536     char oldname[NC_MAX_NAME];
01537     char newname[NC_MAX_NAME];
01538     int nok = 0;      /* count of valid comparisons */
01539     nc_type datatype;
01540     nc_type atttype;
01541     size_t length;
01542     size_t attlength;
01543     char  text[MAX_NELS];
01544     double value[MAX_NELS];
01545     double expect;
01546 
01547     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
01548     IF (err) {
01549         error("nc_create: %s", nc_strerror(err));
01550         return;
01551     }
01552     err = nc_rename_att(ncid, BAD_VARID, "abc", "newName");
01553     IF (err != NC_ENOTVAR)
01554         error("bad var id: status = %d", err);
01555     def_dims(ncid);
01556     def_vars(ncid);
01557     put_atts(ncid);
01558 
01559     for (i = -1; i < NVARS; i++) {
01560         varid = VARID(i);
01561         for (j = 0; j < NATTS(i); j++) {
01562             attname = ATT_NAME(i,j);
01563             err = nc_rename_att(BAD_ID, varid, attname, "newName");
01564             IF (err != NC_EBADID)
01565                 error("bad ncid: status = %d", err);
01566             err = nc_rename_att(ncid, varid, "noSuch", "newName");
01567             IF (err != NC_ENOTATT)
01568                 error("bad attname: status = %d", err);
01569             (void) strcpy(newname, "new_");
01570             (void) strcat(newname, attname);
01571             err = nc_rename_att(ncid, varid, attname, newname);
01572             IF (err)
01573                 error("nc_rename_att: %s", nc_strerror(err));
01574             err = nc_inq_attid(ncid, varid, newname, &attnum);
01575             IF (err)
01576                 error("nc_inq_attid: %s", nc_strerror(err));
01577             IF (attnum != j)
01578                 error("Unexpected attnum");
01579         }
01580     }
01581 
01582         /* Close. Reopen & check */
01583     err = nc_close(ncid);
01584     IF (err)
01585         error("nc_close: %s", nc_strerror(err));
01586     err = nc_open(scratch, NC_WRITE, &ncid);
01587     IF (err)
01588         error("nc_open: %s", nc_strerror(err));
01589 
01590     for (i = -1; i < NVARS; i++) {
01591         varid = VARID(i);
01592         for (j = 0; j < NATTS(i); j++) {
01593             attname = ATT_NAME(i,j);
01594             atttype = ATT_TYPE(i,j);
01595             attlength = ATT_LEN(i,j);
01596             (void) strcpy(newname, "new_");
01597             (void) strcat(newname, attname);
01598             err = nc_inq_attname(ncid, varid, j, name);
01599             IF (err)
01600                 error("nc_inq_attname: %s", nc_strerror(err));
01601             IF (strcmp(name, newname) != 0)
01602                 error("nc_inq_attname: unexpected name");
01603             err = nc_inq_att(ncid, varid, name, &datatype, &length);
01604             IF (err)
01605                 error("nc_inq_att: %s", nc_strerror(err));
01606             IF (datatype != atttype)
01607                 error("nc_inq_att: unexpected type");
01608             IF (length != attlength)
01609                 error("nc_inq_att: unexpected length");
01610             if (datatype == NC_CHAR) {
01611                 err = nc_get_att_text(ncid, varid, name, text);
01612                 IF (err)
01613                     error("nc_get_att_text: %s", nc_strerror(err));
01614                 for (k = 0; k < attlength; k++) {
01615                     expect = hash(datatype, -1, &k);
01616                     IF (text[k] != expect) {
01617                         error("nc_get_att_text: unexpected value");
01618                     } else {
01619                         nok++;
01620                     }
01621                 }
01622             } else {
01623                 err = nc_get_att_double(ncid, varid, name, value);
01624                 IF (err)
01625                     error("nc_get_att_double: %s", nc_strerror(err));
01626                 for (k = 0; k < attlength; k++) {
01627                     expect = hash(datatype, -1, &k);
01628                     if (inRange(expect, datatype)) {
01629                         IF (!equal(value[k],expect,datatype,NCT_DOUBLE)) {
01630                             error("nc_get_att_double: unexpected value");
01631                         } else {
01632                             nok++;
01633                         }
01634                     }
01635                 }
01636             }
01637         }
01638     }
01639     print_nok(nok);
01640 
01641         /* Now in data mode */
01642         /* Try making names even longer. Then restore original names */
01643 
01644     for (i = -1; i < NVARS; i++) {
01645         varid = VARID(i);
01646         for (j = 0; j < NATTS(i); j++) {
01647             attname = ATT_NAME(i,j);
01648             (void) strcpy(oldname, "new_");
01649             (void) strcat(oldname, attname);
01650             (void) strcpy(newname, "even_longer_");
01651             (void) strcat(newname, attname);
01652             err = nc_rename_att(ncid, varid, oldname, newname);
01653             IF (err != NC_ENOTINDEFINE)
01654                 error("longer name in data mode: status = %d", err);
01655             err = nc_rename_att(ncid, varid, oldname, attname);
01656             IF (err)
01657                 error("nc_rename_att: %s", nc_strerror(err));
01658             err = nc_inq_attid(ncid, varid, attname, &attnum);
01659             IF (err)
01660                 error("nc_inq_attid: %s", nc_strerror(err));
01661             IF (attnum != j)
01662                 error("Unexpected attnum");
01663         }
01664     }
01665 
01666     err = nc_close(ncid);
01667     IF (err)
01668         error("nc_close: %s", nc_strerror(err));
01669 
01670     err = remove(scratch);
01671     IF (err)
01672         error("remove of %s failed", scratch);
01673 }
01674 
01675 
01676 /*
01677  * Test nc_del_att
01678  *    try with bad netCDF handle, check error
01679  *    try with bad variable handle, check error
01680  *    try with nonexisting att name, check error
01681  *    check that proper delete worked using:
01682  *      nc_inq_attid, nc_inq_natts, nc_inq_varnatts
01683  */
01684 void
01685 test_nc_del_att(void)
01686 {
01687     int ncid;
01688     int err;
01689     int i;
01690     int j;
01691     int attnum;
01692     int natts;
01693     int numatts;
01694     int varid;
01695     char *name;                 /* of att */
01696 
01697     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
01698     IF (err) {
01699         error("nc_create: %s", nc_strerror(err));
01700         return;
01701     }
01702     err = nc_del_att(ncid, BAD_VARID, "abc");
01703     IF (err != NC_ENOTVAR)
01704         error("bad var id: status = %d", err);
01705     def_dims(ncid);
01706     def_vars(ncid);
01707     put_atts(ncid);
01708 
01709     for (i = -1; i < NVARS; i++) {
01710         varid = VARID(i);
01711         numatts = NATTS(i);
01712         for (j = 0; j < numatts; j++) {
01713             name = ATT_NAME(i,j);
01714             err = nc_del_att(BAD_ID, varid, name);
01715             IF (err != NC_EBADID)
01716                 error("bad ncid: status = %d", err);
01717             err = nc_del_att(ncid, varid, "noSuch");
01718             IF (err != NC_ENOTATT)
01719                 error("bad attname: status = %d", err);
01720             err = nc_del_att(ncid, varid, name);
01721             IF (err)
01722                 error("nc_del_att: %s", nc_strerror(err));
01723             err = nc_inq_attid(ncid, varid, name, &attnum);
01724             IF (err != NC_ENOTATT)
01725                 error("bad attname: status = %d", err);
01726             if (i < 0) {
01727                 err = nc_inq_natts(ncid, &natts);
01728                 IF (err)
01729                     error("nc_inq_natts: %s", nc_strerror(err));
01730                 IF (natts != numatts-j-1)
01731                     error("natts: expected %d, got %d", numatts-j-1, natts);
01732             }
01733             err = nc_inq_varnatts(ncid, varid, &natts);
01734             IF (err)
01735                 error("nc_inq_varnatts: %s", nc_strerror(err));
01736             IF (natts != numatts-j-1)
01737                 error("natts: expected %d, got %d", numatts-j-1, natts);
01738         }
01739     }
01740 
01741         /* Close. Reopen & check no attributes left */
01742     err = nc_close(ncid);
01743     IF (err)
01744         error("nc_close: %s", nc_strerror(err));
01745     err = nc_open(scratch, NC_WRITE, &ncid);
01746     IF (err)
01747         error("nc_open: %s", nc_strerror(err));
01748     err = nc_inq_natts(ncid, &natts);
01749     IF (err)
01750         error("nc_inq_natts: %s", nc_strerror(err));
01751     IF (natts != 0)
01752         error("natts: expected %d, got %d", 0, natts);
01753     for (i = -1; i < NVARS; i++) {
01754         varid = VARID(i);
01755         err = nc_inq_varnatts(ncid, varid, &natts);
01756         IF (err)
01757             error("nc_inq_natts: %s", nc_strerror(err));
01758         IF (natts != 0)
01759             error("natts: expected %d, got %d", 0, natts);
01760     }
01761 
01762         /* restore attributes. change to data mode. try to delete */
01763     err = nc_redef(ncid);
01764     IF (err)
01765         error("nc_redef: %s", nc_strerror(err));
01766     put_atts(ncid);
01767     err = nc_enddef(ncid);
01768     IF (err)
01769         error("nc_enddef: %s", nc_strerror(err));
01770 
01771     for (i = -1; i < NVARS; i++) {
01772         varid = VARID(i);
01773         numatts = NATTS(i);
01774         for (j = 0; j < numatts; j++) {
01775             name = ATT_NAME(i,j);
01776             err = nc_del_att(ncid, varid, name);
01777             IF (err != NC_ENOTINDEFINE)
01778                 error("in data mode: status = %d", err);
01779         }
01780     }
01781 
01782     err = nc_close(ncid);
01783     IF (err)
01784         error("nc_close: %s", nc_strerror(err));
01785     err = remove(scratch);
01786     IF (err)
01787         error("remove of %s failed", scratch);
01788 }
01789 
01790 
01791 /*
01792  * Test nc_set_fill
01793  *    try with bad netCDF handle, check error
01794  *    try in read-only mode, check error
01795  *    try with bad new_fillmode, check error
01796  *    try in data mode, check error
01797  *    check that proper set to NC_FILL works for record & non-record variables
01798  *    (note that it is not possible to test NC_NOFILL mode!)
01799  *    close file & create again for test using attribute _FillValue
01800  */
01801 void
01802 test_nc_set_fill(void)
01803 {
01804     int ncid;
01805     int varid;
01806     int err;
01807     int i;
01808     int j;
01809     int old_fillmode;
01810     int nok = 0;      /* count of valid comparisons */
01811     char text = 0;
01812     double value = 0;
01813     double fill;
01814     size_t index[MAX_RANK];
01815 
01816         /* bad ncid */
01817     err = nc_set_fill(BAD_ID, NC_NOFILL, &old_fillmode);
01818     IF (err != NC_EBADID)
01819         error("bad ncid: status = %d", err);
01820 
01821         /* try in read-only mode */
01822     err = nc_open(testfile, NC_NOWRITE, &ncid);
01823     IF (err)
01824         error("nc_open: %s", nc_strerror(err));
01825     err = nc_set_fill(ncid, NC_NOFILL, &old_fillmode);
01826     IF (err != NC_EPERM)
01827         error("read-only: status = %d", err);
01828     err = nc_close(ncid);
01829     IF (err)
01830         error("nc_close: %s", nc_strerror(err));
01831 
01832         /* create scratch */
01833     err = nc_create(scratch, NC_NOCLOBBER, &ncid);
01834     IF (err) {
01835         error("nc_create: %s", nc_strerror(err));
01836         return;
01837     }
01838 
01839         /* BAD_FILLMODE */
01840     err = nc_set_fill(ncid, BAD_FILLMODE, &old_fillmode);
01841     IF (err != NC_EINVAL)
01842         error("bad fillmode: status = %d", err);
01843 
01844         /* proper calls */
01845     err = nc_set_fill(ncid, NC_NOFILL, &old_fillmode);
01846     IF (err)
01847         error("nc_set_fill: %s", nc_strerror(err));
01848     IF (old_fillmode != NC_FILL)
01849         error("Unexpected old fill mode: %d", old_fillmode);
01850     err = nc_set_fill(ncid, NC_FILL, &old_fillmode);
01851     IF (err)
01852         error("nc_set_fill: %s", nc_strerror(err));
01853     IF (old_fillmode != NC_NOFILL)
01854         error("Unexpected old fill mode: %d", old_fillmode);
01855 
01856         /* define dims & vars */
01857     def_dims(ncid);
01858     def_vars(ncid);
01859 
01860         /* Change to data mode. Set fillmode again */
01861     err = nc_enddef(ncid);
01862     IF (err)
01863         error("nc_enddef: %s", nc_strerror(err));
01864     err = nc_set_fill(ncid, NC_FILL, &old_fillmode);
01865     IF (err)
01866         error("nc_set_fill: %s", nc_strerror(err));
01867     IF (old_fillmode != NC_FILL)
01868         error("Unexpected old fill mode: %d", old_fillmode);
01869 
01870         /* Write record number NRECS to force writing of preceding records */
01871         /* Assumes variable cr is char vector with UNLIMITED dimension */
01872     err = nc_inq_varid(ncid, "cr", &varid);
01873     IF (err)
01874         error("nc_inq_varid: %s", nc_strerror(err));
01875     index[0] = NRECS;
01876     err = nc_put_var1_text(ncid, varid, index, &text);
01877     IF (err)
01878         error("nc_put_var1_text: %s", nc_strerror(err));
01879 
01880         /* get all variables & check all values equal default fill */
01881     for (i = 0; i < NVARS; i++) {
01882         switch (var_type[i]) {
01883             case NC_CHAR:   fill = NC_FILL_CHAR; break;
01884             case NC_BYTE:   fill = NC_FILL_BYTE; break;
01885             case NC_SHORT:  fill = NC_FILL_SHORT; break;
01886             case NC_INT:   fill = NC_FILL_INT; break;
01887             case NC_FLOAT:  fill = NC_FILL_FLOAT; break;
01888             case NC_DOUBLE: fill = NC_FILL_DOUBLE; break;
01889             default: assert(0);
01890         }
01891         for (j = 0; j < var_nels[i]; j++) {
01892             err = toMixedBase(j, var_rank[i], var_shape[i], index);
01893             IF (err)
01894                 error("error in toMixedBase");
01895             if (var_type[i] == NC_CHAR) {
01896                 err = nc_get_var1_text(ncid, i, index, &text);
01897                 IF (err)
01898                     error("nc_get_var1_text failed: %s", nc_strerror(err));
01899                 value = text;
01900             } else {
01901                 err = nc_get_var1_double(ncid, i, index, &value);
01902                 IF (err)
01903                     error("nc_get_var1_double failed: %s", nc_strerror(err));
01904             }
01905             IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
01906                 error("\n\t\tValue expected: %-23.17e,\n\t\t          read: %-23.17e\n",
01907                         fill, value);
01908             else
01909                 nok++;
01910         }
01911     }
01912 
01913         /* close scratch & create again for test using attribute _FillValue */
01914     err = nc_close(ncid);
01915     IF (err)
01916         error("nc_close: %s", nc_strerror(err));
01917     err = nc_create(scratch, NC_CLOBBER, &ncid);
01918     IF (err) {
01919         error("nc_create: %s", nc_strerror(err));
01920         return;
01921     }
01922     def_dims(ncid);
01923     def_vars(ncid);
01924 
01925         /* set _FillValue = 42 for all vars */
01926     text = fill = 42;
01927     for (i = 0; i < NVARS; i++) {
01928         if (var_type[i] == NC_CHAR) {
01929             err = nc_put_att_text(ncid, i, "_FillValue", 1, &text);
01930             IF (err)
01931                 error("nc_put_att_text: %s", nc_strerror(err));
01932         } else {
01933             err = nc_put_att_double(ncid, i, "_FillValue",var_type[i],1,&fill);
01934             IF (err)
01935                 error("nc_put_att_double: %s", nc_strerror(err));
01936         }
01937     }
01938 
01939         /* data mode. write records */
01940     err = nc_enddef(ncid);
01941     IF (err)
01942         error("nc_enddef: %s", nc_strerror(err));
01943     index[0] = NRECS;
01944     err = nc_put_var1_text(ncid, varid, index, &text);
01945     IF (err)
01946         error("nc_put_var1_text: %s", nc_strerror(err));
01947 
01948         /* get all variables & check all values equal 42 */
01949     for (i = 0; i < NVARS; i++) {
01950         for (j = 0; j < var_nels[i]; j++) {
01951             err = toMixedBase(j, var_rank[i], var_shape[i], index);
01952             IF (err)
01953                 error("error in toMixedBase");
01954             if (var_type[i] == NC_CHAR) {
01955                 err = nc_get_var1_text(ncid, i, index, &text);
01956                 IF (err)
01957                     error("nc_get_var1_text failed: %s", nc_strerror(err));
01958                 value = text;
01959             } else {
01960                 err = nc_get_var1_double(ncid, i, index, &value);
01961                 IF (err)
01962                     error("nc_get_var1_double failed: %s", nc_strerror(err));
01963             }
01964             IF (value != fill)
01965                 error(" Value expected: %g, read: %g\n", fill, value);
01966             else
01967                 nok++;
01968         }
01969     }
01970     print_nok(nok);
01971 
01972     err = nc_close(ncid);
01973     IF (err)
01974         error("nc_close: %s", nc_strerror(err));
01975     err = remove(scratch);
01976     IF (err)
01977         error("remove of %s failed", scratch);
01978 }
01979 
01980 /* This function gets the version of a netCDF file, 1 is for netCDF
01981    classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format.
01982 */
01983 #define MAGIC_NUM_LEN 4
01984 static
01985 int
01986 nc_get_file_version(char *path, int *version)
01987 {
01988    FILE *fp;
01989    char magic[MAGIC_NUM_LEN];
01990 
01991    /* Need two valid pointers - check for NULL. */
01992    if (!version || !path)
01993       return NC_EINVAL;
01994 
01995    /* Figure out if this is a netcdf or hdf5 file. */
01996    if (!(fp = fopen(path, "r")) ||
01997        fread(magic, MAGIC_NUM_LEN, 1, fp) != 1)
01998       return errno;
01999    fclose(fp);
02000    if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0)
02001    {
02002       if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC || 
02003           magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT)
02004          *version = magic[MAGIC_NUM_LEN-1];
02005       else
02006          return NC_ENOTNC;
02007    }
02008    /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
02009         away! */
02010    /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
02011       *version = 3;*/
02012    return NC_NOERR;
02013 }
02014 
02015 /*
02016  * Test nc_set_default_format
02017  *    try with bad default format
02018  *    try with NULL old_formatp
02019  *    try in data mode, check error
02020  *    check that proper set to NC_FILL works for record & non-record variables
02021  *    (note that it is not possible to test NC_NOFILL mode!)
02022  *    close file & create again for test using attribute _FillValue
02023  */
02024 void
02025 test_nc_set_default_format(void)
02026 {
02027     int ncid;
02028     int err;
02029     int i;
02030     int version;
02031     int old_format;
02032 
02033     /* bad format */
02034     err = nc_set_default_format(BAD_DEFAULT_FORMAT, &old_format);
02035     IF (err != NC_EINVAL)
02036         error("bad default format: status = %d", err);
02037 
02038     /* NULL old_formatp */
02039     err = nc_set_default_format(NC_FORMAT_64BIT, NULL);
02040     IF (err)
02041         error("null old_fortmatp: status = %d", err);
02042 
02043     /* Cycle through available formats. */
02044     for(i=1; i<3; i++)
02045     {
02046        if ((err = nc_set_default_format(i, NULL)))
02047           error("setting classic format: status = %d", err);
02048        if ((err=nc_create(scratch, NC_CLOBBER, &ncid)))
02049           error("bad nc_create: status = %d", err);
02050        if ((err=nc_put_att_text(ncid, NC_GLOBAL, "testatt", 
02051                                 sizeof("blah"), "blah")))
02052           error("bad put_att: status = %d", err);
02053        if ((err=nc_close(ncid)))
02054           error("bad close: status = %d", err);
02055        if ((err = nc_get_file_version(scratch, &version)))
02056           error("bad file version = %d", err);
02057        if (version != i)
02058           error("bad file version = %d", err);
02059     }
02060 
02061     /* Remove the left-over file. */
02062     if ((err = remove(scratch)))
02063        error("remove of %s failed", scratch);
02064 }

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