1/*********************************************************************
2 *   Copyright 1996, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Id: test_write.c 2796 2014-10-28 03:40:29Z wkliao $
5 *********************************************************************/
6
7#include "tests.h"
8#include "math.h"
9#include <stdio.h> /* For FILE stuff. */
10
11/*
12 * Test nc_create
13 *    For mode in NC_NOCLOBBER, NC_CLOBBER do:
14 *       create netcdf file 'scratch.nc' with no data, close it
15 *       test that it can be opened, do nc_inq to check nvars = 0, etc.
16 *    Try again in NC_NOCLOBBER mode, check error return
17 * On exit, delete this file
18 */
19void
20test_nc_create(void)
21{
22    int clobber; /* 0 for NC_NOCLOBBER, 1 for NC_CLOBBER */
23    int err;
24    int ncid;
25    int ndims;                  /* number of dimensions */
26    int nvars;                  /* number of variables */
27    int ngatts;                 /* number of global attributes */
28    int recdim;                 /* id of unlimited dimension */
29
30    for (clobber = 0; clobber < 2; clobber++) {
31        int cmode = clobber ? NC_CLOBBER : NC_NOCLOBBER;
32 err = file_create(scratchcmode, &ncid);
33 IF (err)
34     error("nc_create: %s", nc_strerror(err));
35 err = nc_close(ncid);
36 IF (err)
37     error("nc_close: %s", nc_strerror(err));
38 err = file_open(scratchNC_NOWRITE, &ncid);
39 IF (err)
40     error("nc_open: %s", nc_strerror(err));
41 err = nc_inq(ncid, &ndims, &nvars, &ngatts, &recdim);
42 IF (err)
43     error("nc_inq: %s", nc_strerror(err));
44 else IF (ndims != 0)
45     error("nc_inq: wrong number of dimensions returned, %d", ndims);
46 else IF (nvars != 0)
47     error("nc_inq: wrong number of variables returned, %d", nvars);
48 else IF (ngatts != 0)
49     error("nc_inq: wrong number of global atts returned, %d", ngatts);
50 else IF (recdim != -1)
51     error("nc_inq: wrong record dimension ID returned, %d", recdim);
52 err = nc_close(ncid);
53 IF (err)
54     error("nc_close: %s", nc_strerror(err));
55    }
56
57    err = file_create(scratchNC_NOCLOBBER, &ncid);
58    IF (err != NC_EEXIST)
59 error("attempt to overwrite file: status = %d", err);
60    err = remove(scratch);
61    IF (err)
62 error("remove of %s failed", scratch);
63}
64
65
66/*
67 * Test nc_redef
68 * (In fact also tests nc_enddef - called from test_nc_enddef)
69 *    BAD_ID
70 *    attempt redef (error) & enddef on read-only file
71 *    create file, define dims & vars.
72 *    attempt put var (error)
73 *    attempt redef (error) & enddef.
74 *    put vars
75 *    attempt def new dims (error)
76 *    redef
77 *    def new dims, vars.
78 *    put atts
79 *    enddef
80 *    put vars
81 *    close
82 *    check file: vars & atts
83 *    check reopening with NC_WRITE and adding new dims, atts, vars
84 */
85void
86test_nc_redef(void)
87{
88    int ncid;                   /* netcdf id */
89    /* used to force effective test of ncio->move() in redef */
90    size_t sizehint = 8192;
91    int dimid;         /* dimension id */
92    int varid;         /* variable id */
93    int varid1;        /* variable id */
94    int err;
95    const char * title = "Not funny";
96    double var;
97    char name[NC_MAX_NAME];
98    size_t length;
99    int fmt_variant1fmt_variant2;
100
101 /* BAD_ID tests */
102    err = nc_redef(BAD_ID);
103    IF (err != NC_EBADID)
104 error("bad ncid: status = %d", err);
105    err = nc_enddef(BAD_ID);
106    IF (err != NC_EBADID)
107 error("bad ncid: status = %d", err);
108
109 /* read-only tests */
110    err = file_open(testfileNC_NOWRITE, &ncid);
111    IF (err)
112        error("nc_open: %s", nc_strerror(err));
113    err = nc_redef(ncid);
114    IF (err != NC_EPERM)
115 error("nc_redef in NC_NOWRITE mode: status = %d", err);
116    err = nc_enddef(ncid);
117    IF (err != NC_ENOTINDEFINE)
118 error("nc_redef in NC_NOWRITE mode: status = %d", err);
119    err = nc_close(ncid);
120    IF (err)
121 error("nc_close: %s", nc_strerror(err));
122
123 /* tests using scratch file */
124    err = file_create(scratchNC_NOCLOBBER, &ncid);
125    IF (err) {
126        error("nc_create: %s", nc_strerror(err));
127        return;
128    }
129    /* limit for ncio implementations which have infinite chunksize */
130    if(sizehint > 32768)
131 sizehint = 16384;
132    def_dims(ncid);
133    def_vars(ncid);
134    put_atts(ncid);
135    err = nc_inq_varid(ncid, "d", &varid);
136    IF (err)
137 error("nc_inq_varid: %s", nc_strerror(err));
138    var = 1.0;
139    err = nc_put_var1_double(ncidvaridNULL, &var);
140    IF (err != NC_EINDEFINE)
141        error("nc_put_var... in define mode: status = %d", err);
142    err = nc_redef(ncid);
143    IF (err != NC_EINDEFINE)
144        error("nc_redef in define mode: status = %d", err);
145    err = nc_enddef(ncid);
146    IF (err)
147        error("nc_enddef: %s", nc_strerror(err));
148    put_vars(ncid);
149    err = nc_def_dim(ncid, "abc", sizehint, &dimid);
150    IF (err != NC_ENOTINDEFINE)
151        error("nc_def_dim in define mode: status = %d", err);
152    err = nc_redef(ncid);
153    IF (err)
154        error("nc_redef: %s", nc_strerror(err));
155#if 0
156    err = nc_set_fill(ncidNC_NOFILLNULL);
157    IF (err)
158        error("nc_set_fill: %s", nc_strerror(err));
159#endif
160    err = nc_def_dim(ncid, "abc", sizehint, &dimid);
161    IF (err)
162        error("nc_def_dim: %s", nc_strerror(err));
163    err = nc_def_var(ncid, "abcScalar", NC_INT, 0, NULL, &varid);
164    IF (err)
165        error("nc_def_var: %s", nc_strerror(err));
166    err = nc_def_var(ncid, "abc", NC_INT, 1, &dimid, &varid1);
167    IF (err)
168        error("nc_def_var: %s", nc_strerror(err));
169    {
170 int dimids[NDIMS +1];
171 int ii = 0;
172 for(ii = 0; ii < NDIMSii++)
173 dimids[ii] = ii;
174 dimids[NDIMS] = dimid;
175     err = nc_def_var(ncid, "abcRec", NC_INTNDIMSdimids, &varid1);
176     IF (err)
177         error("nc_def_var: %s", nc_strerror(err));
178    }
179    err = nc_put_att_text(ncidNC_GLOBAL, "title", 1+strlen(title), title);
180    IF (err)
181        error("nc_put_att_text: %s", nc_strerror(err));
182    err = nc_enddef(ncid);
183    IF (err)
184        error("nc_enddef: %s", nc_strerror(err));
185    var = 1.0;
186    err = nc_put_var1_double(ncidvaridNULL, &var);
187    IF (err)
188        error("nc_put_var1_double: %s", nc_strerror(err));
189    err = nc_inq_format(ncid, &fmt_variant1);
190    IF (err)
191 error("nc_inq_format: %s", nc_strerror(err));
192    err = nc_close(ncid);
193    IF (err)
194 error("nc_close: %s", nc_strerror(err));
195
196    /* check scratch file written as expected */
197    check_file(scratch);  /* checks all except "abc" stuff added above */
198
199    IF ((err = file_open(scratchNC_NOWRITE, &ncid)))
200        error("nc_open: %s", nc_strerror(err));
201    IF ((err = nc_inq_dim(nciddimidname, &length)))
202 error("nc_inq_dim: %s", nc_strerror(err));
203    IF (strcmp(name, "abc") != 0)
204 error("Unexpected dim name");
205    IF (length != sizehint)
206 error("Unexpected dim length");
207    IF ((err = nc_get_var1_double(ncidvaridNULL, &var)))
208        error("nc_get_var1_double: %s", nc_strerror(err));
209    IF (var != 1.0)
210        error("nc_get_var1_double: unexpected value");
211    IF ((err = nc_close(ncid)))
212        error("nc_close: %s", nc_strerror(err));
213
214    /* open scratch file for writing, add another dim, var, att, then check */
215    IF ((err = file_open(scratchNC_WRITE, &ncid)))
216        error("nc_open: %s", nc_strerror(err));
217    IF ((err = nc_redef(ncid)))
218        error("nc_redef: %s", nc_strerror(err));
219    IF ((err = nc_def_dim(ncid, "def", sizehint, &dimid)))
220        error("nc_def_dim: %s", nc_strerror(err));
221    IF ((err = nc_def_var(ncid, "defScalar", NC_INT, 0, NULL, &varid)))
222        error("nc_def_var: %s", nc_strerror(err));
223    IF ((err = nc_def_var(ncid, "def", NC_INT, 1, &dimid, &varid1)))
224        error("nc_def_var: %s", nc_strerror(err));
225    IF ((err = nc_put_att_text(ncidNC_GLOBAL, "Credits", 1+strlen("Thanks!"), "Thanks!")))
226        error("nc_put_att_text: %s", nc_strerror(err));
227    IF ((err = nc_enddef(ncid)))
228        error("nc_enddef: %s", nc_strerror(err));
229    var = 2.0;
230    IF ((err = nc_put_var1_double(ncidvaridNULL, &var)))
231        error("nc_put_var1_double: %s", nc_strerror(err));
232    IF ((err = nc_close(ncid)))
233 error("nc_close: %s", nc_strerror(err));
234
235    /* check scratch file written as expected */
236    check_file(scratch);
237
238        err = file_open(scratchNC_NOWRITE, &ncid);
239    IF (err)
240        error("nc_open: %s", nc_strerror(err));
241    err = nc_inq_dim(nciddimidname, &length);
242    IF (err)
243 error("nc_inq_dim: %s", nc_strerror(err));
244    IF (strcmp(name, "def") != 0)
245 error("Unexpected dim name");
246    IF (length != sizehint)
247 error("Unexpected dim length");
248    err = nc_get_var1_double(ncidvaridNULL, &var);
249    IF (err)
250        error("nc_get_var1_double: %s", nc_strerror(err));
251    IF (var != 2.0)
252        error("nc_get_var1_double: unexpected value");
253    /* make sure format variant hasn't changed from when created */
254    err = nc_inq_format(ncid, &fmt_variant2);
255    IF (err)
256 error("nc_inq_format: %s", nc_strerror(err));
257    IF (fmt_variant1 != fmt_variant2)
258 error("nc_enddef changed format variant");
259    err = nc_close(ncid);
260    IF (err)
261        error("nc_close: %s", nc_strerror(err));
262    err = remove(scratch);
263    IF (err)
264        error("remove of %s failed", scratch);
265}
266
267
268/*
269 * Test nc_enddef
270 * Simply calls test_nc_redef which tests both nc_redef & nc_enddef
271 */
272void
273test_nc_enddef(void)
274{
275    test_nc_redef();
276}
277
278
279/*
280 * Test nc_sync
281 *    try with bad handle, check error
282 *    try in define mode, check error
283 *    try writing with one handle, reading with another on same netCDF
284 */
285void
286test_nc_sync(void)
287{
288    int ncidw;         /* netcdf id for writing */
289    int ncidr;         /* netcdf id for reading */
290    int err;
291
292        /* BAD_ID test */
293    err = nc_sync(BAD_ID);
294    IF (err != NC_EBADID)
295        error("bad ncid: status = %d", err);
296
297        /* create scratch file & try nc_sync in define mode */
298    err = file_create(scratchNC_NOCLOBBER, &ncidw);
299    IF (err) {
300        error("nc_create: %s", nc_strerror(err));
301 return;
302    }
303    err = nc_sync(ncidw);
304    IF (err != NC_EINDEFINE)
305        error("nc_sync called in define mode: status = %d", err);
306
307        /* write using same handle */
308    def_dims(ncidw);
309    def_vars(ncidw);
310    put_atts(ncidw);
311    err = nc_enddef(ncidw);
312    IF (err)
313        error("nc_enddef: %s", nc_strerror(err));
314    put_vars(ncidw);
315    err = nc_sync(ncidw);
316    IF (err)
317        error("nc_sync of ncidw failed: %s", nc_strerror(err));
318
319        /* open another handle, nc_sync, read (check) */
320        err = file_open(scratchNC_NOWRITE, &ncidr);
321    IF (err)
322        error("nc_open: %s", nc_strerror(err));
323    err = nc_sync(ncidr);
324    IF (err)
325        error("nc_sync of ncidr failed: %s", nc_strerror(err));
326    check_dims(ncidr);
327    check_atts(ncidr);
328    check_vars(ncidr);
329
330        /* close both handles */
331    err = nc_close(ncidr);
332    IF (err)
333        error("nc_close: %s", nc_strerror(err));
334    err = nc_close(ncidw);
335    IF (err)
336        error("nc_close: %s", nc_strerror(err));
337
338    err = remove(scratch);
339    IF (err)
340        error("remove of %s failed", scratch);
341}
342
343
344/*
345 * Test nc_abort
346 *    try with bad handle, check error
347 *    try in define mode before anything written, check that file was deleted
348 *    try after nc_enddef, nc_redef, define new dims, vars, atts
349 *    try after writing variable
350 */
351void
352test_nc_abort(void)
353{
354    int ncid;          /* netcdf id */
355    int err;
356    int ndims;
357    int nvars;
358    int ngatts;
359
360        /* BAD_ID test */
361    err = nc_abort(BAD_ID);
362    IF (err != NC_EBADID)
363        error("bad ncid: status = %d", err);
364
365        /* create scratch file & try nc_abort in define mode */
366    err = file_create(scratchNC_NOCLOBBER, &ncid);
367    IF (err) {
368        error("nc_create: %s", nc_strerror(err));
369        return;
370    }
371    def_dims(ncid);
372    def_vars(ncid);
373    put_atts(ncid);
374    err = nc_abort(ncid);
375    IF (err)
376        error("nc_abort of ncid failed: %s", nc_strerror(err));
377    err = nc_close(ncid); /* should already be closed */
378    IF (err != NC_EBADID)
379        error("bad ncid: status = %d", err);
380    err = remove(scratch); /* should already be deleted */
381    IF (!err)
382        error("file %s should not exist", scratch);
383
384        /*
385         * create scratch file
386  * do nc_enddef & nc_redef
387  * define new dims, vars, atts
388  * try nc_abort: should restore previous state (no dims, vars, atts)
389  */
390    err = file_create(scratchNC_NOCLOBBER, &ncid);
391    IF (err) {
392        error("nc_create: %s", nc_strerror(err));
393        return;
394    }
395    err = nc_enddef(ncid);
396    IF (err)
397        error("nc_enddef: %s", nc_strerror(err));
398    err = nc_redef(ncid);
399    IF (err)
400        error("nc_redef: %s", nc_strerror(err));
401    def_dims(ncid);
402    def_vars(ncid);
403    put_atts(ncid);
404    err = nc_abort(ncid);
405    IF (err)
406        error("nc_abort of ncid failed: %s", nc_strerror(err));
407    err = nc_close(ncid); /* should already be closed */
408    IF (err != NC_EBADID)
409        error("bad ncid: status = %d", err);
410        err = file_open(scratchNC_NOWRITE, &ncid);
411    IF (err)
412        error("nc_open: %s", nc_strerror(err));
413    err = nc_inq (ncid, &ndims, &nvars, &ngattsNULL);
414    IF (err)
415        error("nc_inq: %s", nc_strerror(err));
416    IF (ndims != 0)
417        error("ndims should be 0");
418    IF (nvars != 0)
419        error("nvars should be 0");
420    IF (ngatts != 0)
421        error("ngatts should be 0");
422    err = nc_close (ncid);
423    IF (err)
424        error("nc_close: %s", nc_strerror(err));
425
426        /* try nc_abort in data mode - should just close */
427    err = file_create(scratchNC_CLOBBER, &ncid);
428    IF (err) {
429        error("nc_create: %s", nc_strerror(err));
430        return;
431    }
432    def_dims(ncid);
433    def_vars(ncid);
434    put_atts(ncid);
435    err = nc_enddef(ncid);
436    IF (err)
437        error("nc_enddef: %s", nc_strerror(err));
438    put_vars(ncid);
439    err = nc_abort(ncid);
440    IF (err)
441        error("nc_abort of ncid failed: %s", nc_strerror(err));
442    err = nc_close(ncid);       /* should already be closed */
443    IF (err != NC_EBADID)
444        error("bad ncid: status = %d", err);
445    check_file(scratch);
446    err = remove(scratch);
447    IF (err)
448        error("remove of %s failed", scratch);
449}
450
451
452/*
453 * Test nc_def_dim
454 *    try with bad netCDF handle, check error
455 *    try in data mode, check error
456 *    check that returned id is one more than previous id
457 *    try adding same dimension twice, check error
458 *    try with illegal sizes, check error
459 *    make sure unlimited size works, shows up in nc_inq_unlimdim
460 *    try to define a second unlimited dimension, check error
461 */
462void
463test_nc_def_dim(void)
464{
465    int ncid;
466    int  err;             /* status */
467    int  i;
468    int  dimid;         /* dimension id */
469    size_t length;
470
471        /* BAD_ID test */
472    err = nc_def_dim(BAD_ID, "abc", 8, &dimid);
473    IF (err != NC_EBADID)
474        error("bad ncid: status = %d", err);
475
476        /* data mode test */
477    err = file_create(scratchNC_CLOBBER, &ncid);
478    IF (err) {
479        error("nc_create: %s", nc_strerror(err));
480        return;
481    }
482    err = nc_enddef(ncid);
483    IF (err)
484        error("nc_enddef: %s", nc_strerror(err));
485    err = nc_def_dim(ncid, "abc", 8, &dimid);
486    IF (err != NC_ENOTINDEFINE)
487        error("bad ncid: status = %d", err);
488
489        /* define-mode tests: unlimited dim */
490    err = nc_redef(ncid);
491    IF (err)
492        error("nc_redef: %s", nc_strerror(err));
493    err = nc_def_dim(nciddim_name[0], NC_UNLIMITED, &dimid);
494    IF (err)
495 error("nc_def_dim: %s", nc_strerror(err));
496    IF (dimid != 0)
497 error("Unexpected dimid");
498    err = nc_inq_unlimdim(ncid, &dimid);
499    IF (err)
500 error("nc_inq_unlimdim: %s", nc_strerror(err));
501    IF (dimid != 0)
502 error("Unexpected recdim");
503    err = nc_inq_dimlen(nciddimid, &length);
504    IF (err)
505 error("nc_inq_dimlen: %s", nc_strerror(err));
506    IF (length != 0)
507 error("Unexpected length");
508    err = nc_def_dim(ncid, "abc", NC_UNLIMITED, &dimid);
509    IF (err != NC_EUNLIMIT)
510        error("2nd unlimited dimension: status = %d", err);
511    /* define-mode tests: remaining dims */
512    for (i = 1; i < NDIMSi++) {
513        err = nc_def_dim(nciddim_name[i-1], dim_len[i], &dimid);
514 IF (err != NC_ENAMEINUSE)
515     error("duplicate name: status = %d", err);
516 err = nc_def_dim(ncidBAD_NAMEdim_len[i], &dimid);
517 IF (err != NC_EBADNAME)
518     error("bad name: status = %d", err);
519 /* Fix: dmh 11/4/2011: works only if sizeof(long) > 4 */
520 if(sizeof(long) > 4) {
521            err = nc_def_dim(nciddim_name[i], NC_UNLIMITED-1, &dimid);
522         IF (err != NC_EDIMSIZE)
523         error("bad size: status = %d", err);
524 }
525        err = nc_def_dim(nciddim_name[i], dim_len[i], &dimid);
526        IF (err)
527     error("nc_def_dim: %s", nc_strerror(err));
528 IF (dimid != i)
529     error("Unexpected dimid");
530    }
531
532        /* Following just to expand unlimited dim */
533    def_vars(ncid);
534    err = nc_enddef(ncid);
535    IF (err)
536        error("nc_enddef: %s", nc_strerror(err));
537    put_vars(ncid);
538
539        /* Check all dims */
540    check_dims(ncid);
541
542    err = nc_close(ncid);
543    IF (err)
544 error("nc_close: %s", nc_strerror(err));
545    err = remove(scratch);
546    IF (err)
547        error("remove of %s failed", scratch);
548}
549
550
551/*
552 * Test nc_rename_dim
553 *    try with bad netCDF handle, check error
554 *    check that proper rename worked with nc_inq_dim
555 *    try renaming to existing dimension name, check error
556 *    try with bad dimension handle, check error
557 */
558void
559test_nc_rename_dim(void)
560{
561    int ncid;
562    int  err;             /* status */
563    char name[NC_MAX_NAME];
564
565        /* BAD_ID test */
566    err = nc_rename_dim(BAD_ID, 0, "abc");
567    IF (err != NC_EBADID)
568        error("bad ncid: status = %d", err);
569
570        /* main tests */
571    err = file_create(scratchNC_NOCLOBBER, &ncid);
572    IF (err) {
573        error("nc_create: %s", nc_strerror(err));
574        return;
575    }
576    def_dims(ncid);
577    err = nc_rename_dim(ncidBAD_DIMID, "abc");
578    IF (err != NC_EBADDIM)
579        error("bad dimid: status = %d", err);
580    err = nc_rename_dim(ncid, 2, "abc");
581    IF (err)
582        error("nc_rename_dim: %s", nc_strerror(err));
583    err = nc_inq_dimname(ncid, 2, name);
584    IF (err)
585        error("nc_inq_dimname: %s", nc_strerror(err));
586    IF (strcmp(name, "abc") != 0)
587        error("Unexpected name: %s", name);
588    err = nc_rename_dim(ncid, 0, "abc");
589    IF (err != NC_ENAMEINUSE)
590        error("duplicate name: status = %d", err);
591
592    err = nc_close(ncid);
593    IF (err)
594        error("nc_close: %s", nc_strerror(err));
595    err = remove(scratch);
596    IF (err)
597        error("remove of %s failed", scratch);
598}
599
600
601/*
602 * Test nc_def_var
603 *    try with bad netCDF handle, check error
604 *    try with bad name, check error
605 *    scalar tests:
606 *      check that proper define worked with nc_inq_var
607 *      try redefining an existing variable, check error
608 *      try with bad datatype, check error
609 *      try with bad number of dimensions, check error
610 *      try in data mode, check error
611 *    check that returned id is one more than previous id
612 *    try with bad dimension ids, check error
613 */
614void
615test_nc_def_var(void)
616{
617    int  ncid;
618    int  varid;
619    int  err;             /* status */
620    int  i;
621    int  ndims;
622    int  natts;
623    char name[NC_MAX_NAME];
624    int dimids[MAX_RANK];
625    nc_type datatype;
626
627        /* BAD_ID test */
628    err = nc_def_var(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid);
629    IF (err != NC_EBADID)
630        error("bad ncid: status = %d", err);
631
632        /* scalar tests */
633    err = file_create(scratchNC_NOCLOBBER, &ncid);
634    IF (err) {
635        error("nc_create: %s", nc_strerror(err));
636        return;
637    }
638    err = nc_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
639    IF (err)
640        error("nc_def_var: %s", nc_strerror(err));
641    err = nc_inq_var(ncidvaridname, &datatype, &ndimsdimids, &natts);
642    IF (err)
643        error("nc_inq_var: %s", nc_strerror(err));
644    IF (strcmp(name, "abc") != 0)
645        error("Unexpected name: %s", name);
646    IF (datatype != NC_SHORT)
647        error("Unexpected datatype");
648    IF (ndims != 0)
649        error("Unexpected rank");
650    err = nc_def_var(ncidBAD_NAMENC_SHORT, 0, NULL, &varid);
651    IF (err != NC_EBADNAME)
652        error("bad name: status = %d", err);
653    err = nc_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
654    IF (err != NC_ENAMEINUSE)
655        error("duplicate name: status = %d", err);
656    err = nc_def_var(ncid, "ABC", BAD_TYPE, -1, dimids, &varid);
657    IF (err != NC_EBADTYPE)
658        error("bad type: status = %d", err);
659    err = nc_def_var(ncid, "ABC", NC_SHORT, -1, dimids, &varid);
660    IF (err != NC_EINVAL)
661        error("bad rank: status = %d", err);
662    err = nc_enddef(ncid);
663    IF (err)
664 error("nc_enddef: %s", nc_strerror(err));
665    err = nc_def_var(ncid, "ABC", NC_SHORT, 0, dimids, &varid);
666    IF (err != NC_ENOTINDEFINE)
667        error("nc_def_var called in data mode: status = %d", err);
668    err = nc_close(ncid);
669    IF (err)
670        error("nc_close: %s", nc_strerror(err));
671    err = remove(scratch);
672    IF (err)
673        error("remove of %s failed", scratch);
674
675        /* general tests using global vars */
676    err = file_create(scratchNC_CLOBBER, &ncid);
677    IF (err) {
678        error("nc_create: %s", nc_strerror(err));
679        return;
680    }
681    def_dims(ncid);
682    for (i = 0; i < numVarsi++) {
683        err = nc_def_var(ncidvar_name[i], var_type[i], var_rank[i],
684            var_dimid[i], &varid);
685        IF (err)
686     error("nc_def_var: %s", nc_strerror(err));
687 IF (varid != i)
688     error("Unexpected varid");
689    }
690
691        /* try bad dim ids */
692    dimids[0] = BAD_DIMID;
693    err = nc_def_var(ncid, "abc", NC_SHORT, 1, dimids, &varid);
694    IF (err != NC_EBADDIM)
695        error("bad dim ids: status = %d", err);
696    err = nc_close(ncid);
697    IF (err)
698        error("nc_close: %s", nc_strerror(err));
699
700    err = remove(scratch);
701    IF (err)
702        error("remove of %s failed", scratch);
703}
704
705
706/*
707 * Test nc_put_var1
708 */
709void
710test_nc_put_var1(void)
711{
712    int ncid;
713    int i;
714    int j;
715    int err;
716    size_t index[MAX_RANK];
717    double value;
718    double buf[1]; /* (void *) buffer */
719
720    err = file_create(scratchNC_NOCLOBBER, &ncid);
721    IF (err) {
722        error("nc_create: %s", nc_strerror(err));
723        return;
724    }
725    def_dims(ncid);
726    def_vars(ncid);
727    err = nc_enddef(ncid);
728    IF (err)
729        error("nc_enddef: %s", nc_strerror(err));
730
731    for (i = 0; i < numVarsi++) {
732        for (j = 0; j < var_rank[i]; j++)
733            index[j] = 0;
734        err = nc_put_var1(BAD_IDiindexbuf);
735        IF (err != NC_EBADID)
736            error("bad ncid: status = %d", err);
737        err = nc_put_var1(ncidBAD_VARIDindexbuf);
738        IF (err != NC_ENOTVAR)
739            error("bad var id: status = %d", err);
740        for (j = 0; j < var_rank[i]; j++) {
741            if (var_dimid[i][j] > 0) {          /* skip record dim */
742                index[j] = var_shape[i][j];
743                err = nc_put_var1(ncidiindexbuf);
744                IF (err != NC_EINVALCOORDS)
745                    error("bad index: status = %d", err);
746                index[j] = 0;
747            }
748        }
749        for (j = 0; j < var_nels[i]; j++) {
750            err = toMixedBase(jvar_rank[i], var_shape[i], index);
751            IF (err)
752                error("error in toMixedBase");
753            value = hashvar_type[i], var_rank[i], index);
754     if (inRange(valuevar_type[i])) {
755 err = dbl2nc(valuevar_type[i], buf);
756 IF (err)
757     error("error in dbl2nc");
758 if (var_rank[i] == 0 && i%2 == 0)
759     err = nc_put_var1(ncidiNULLbuf);
760 else
761     err = nc_put_var1(ncidiindexbuf);
762 IF (err)
763     error("%s", nc_strerror(err));
764     }
765        }
766    }
767
768    check_vars(ncid);
769    err = nc_close(ncid);
770    IF (err)
771        error("nc_close: %s", nc_strerror(err));
772
773    err = remove(scratch);
774    IF (err)
775        error("remove of %s failed", scratch);
776}
777
778
779/*
780 * Test nc_put_vara
781 * Choose a random point dividing each dim into 2 parts
782 * Put 2^rank (nslabs) slabs so defined
783 * Redefine buffer for each put.
784 * At end check all variables using check_vars
785 */
786void
787test_nc_put_vara(void)
788{
789    int ncid;
790    int d;
791    int i;
792    int j;
793    int k;
794    int err;
795    int nels;
796    int nslabs;
797    size_t start[MAX_RANK];
798    size_t edge[MAX_RANK];
799    size_t index[MAX_RANK];
800    size_t mid[MAX_RANK];
801    double buf[MAX_NELS];  /* (void *) buffer */
802    char *p; /* (void *) pointer */
803    double value;
804
805    err = file_create(scratchNC_NOCLOBBER, &ncid);
806    IF (err) {
807        error("nc_create: %s", nc_strerror(err));
808        return;
809    }
810    def_dims(ncid);
811    def_vars(ncid);
812    err = nc_enddef(ncid);
813    IF (err)
814        error("nc_enddef: %s", nc_strerror(err));
815
816    for (i = 0; i < numVarsi++) {
817        assert(var_rank[i] <= MAX_RANK);
818        assert(var_nels[i] <= MAX_NELS);
819        for (j = 0; j < var_rank[i]; j++) {
820            start[j] = 0;
821            edge[j] = 1;
822        }
823        err = nc_put_vara(BAD_IDistartedgebuf);
824        IF (err != NC_EBADID)
825            error("bad ncid: status = %d", err);
826        err = nc_put_vara(ncidBAD_VARIDstartedgebuf);
827        IF (err != NC_ENOTVAR)
828            error("bad var id: status = %d", err);
829        for (j = 0; j < var_rank[i]; j++) {
830            if (var_dimid[i][j] > 0) {          /* skip record dim */
831 start[j] = var_shape[i][j];
832 err = nc_put_vara(ncidistartedgebuf);
833 IF (err != NC_EINVALCOORDS)
834     error("bad index: status = %d", err);
835 start[j] = 0;
836 edge[j] = var_shape[i][j] + 1;
837 err = nc_put_vara(ncidistartedgebuf);
838 IF (err != NC_EEDGE)
839     error("bad edge: status = %d", err);
840 edge[j] = 1;
841     }
842        }
843            /* Choose a random point dividing each dim into 2 parts */
844            /* put 2^rank (nslabs) slabs so defined */
845        nslabs = 1;
846        for (j = 0; j < var_rank[i]; j++) {
847            mid[j] = rollvar_shape[i][j] );
848            nslabs *= 2;
849        }
850            /* bits of k determine whether to put lower or upper part of dim */
851        for (k = 0; k < nslabsk++) {
852            nels = 1;
853            for (j = 0; j < var_rank[i]; j++) {
854                if ((k >> j) & 1) {
855                    start[j] = 0;
856                    edge[j] = mid[j];
857                }else{
858                    start[j] = mid[j];
859                    edge[j] = var_shape[i][j] - mid[j];
860                }
861                nels *= edge[j];
862            }
863     p = (char *) buf;
864     for (j = 0; j < nelsj++) {
865 err = toMixedBase(jvar_rank[i], edgeindex);
866 IF (err)
867     error("error in toMixedBase");
868 for (d = 0; d < var_rank[i]; d++)
869     index[d] += start[d];
870 value = hashvar_type[i], var_rank[i], index);
871 if (!inRange(valuevar_type[i]))
872     value = 0;
873 err = dbl2nc(valuevar_type[i], p);
874 IF (err)
875     error("error in dbl2nc");
876 p += nctypelen(var_type[i]);
877            }
878            if (var_rank[i] == 0 && i%2 == 0)
879 err = nc_put_vara(ncidiNULLNULLbuf);
880            else
881 err = nc_put_vara(ncidistartedgebuf);
882            IF (err) {
883                error("%s", nc_strerror(err));
884            }
885        }
886    }
887
888    check_vars(ncid);
889    err = nc_close(ncid);
890    IF (err)
891        error("nc_close: %s", nc_strerror(err));
892
893    err = remove(scratch);
894    IF (err)
895        error("remove of %s failed", scratch);
896}
897
898
899/*
900 * Test nc_put_vars
901 * Choose a random point dividing each dim into 2 parts
902 * Put 2^rank (nslabs) slabs so defined
903 * Choose random stride from 1 to edge
904 * Redefine buffer for each put.
905 * At end check all variables using check_vars
906 */
907void
908test_nc_put_vars(void)
909{
910    int ncid;
911    int d;
912    int i;
913    int j;
914    int k;
915    int m;
916    int err;
917    int nels;
918    int nslabs;
919    int nstarts;        /* number of different starts */
920    size_t start[MAX_RANK];
921    size_t edge[MAX_RANK];
922    size_t index[MAX_RANK];
923    size_t index2[MAX_RANK];
924    size_t mid[MAX_RANK];
925    size_t count[MAX_RANK];
926    size_t sstride[MAX_RANK];
927    ptrdiff_t stride[MAX_RANK];
928    double buf[MAX_NELS]; /* (void *) buffer */
929    char *p; /* (void *) pointer */
930    double value;
931
932    err = file_create(scratchNC_NOCLOBBER, &ncid);
933    IF (err) {
934        error("nc_create: %s", nc_strerror(err));
935        return;
936    }
937    def_dims(ncid);
938    def_vars(ncid);
939    err = nc_enddef(ncid);
940    IF (err)
941        error("nc_enddef: %s", nc_strerror(err));
942
943    for (i = 0; i < numVarsi++) {
944        assert(var_rank[i] <= MAX_RANK);
945        assert(var_nels[i] <= MAX_NELS);
946        for (j = 0; j < var_rank[i]; j++) {
947            start[j] = 0;
948            edge[j] = 1;
949            stride[j] = 1;
950        }
951        err = nc_put_vars(BAD_IDistartedgestridebuf);
952        IF (err != NC_EBADID)
953            error("bad ncid: status = %d", err);
954        err = nc_put_vars(ncidBAD_VARIDstartedgestridebuf);
955        IF (err != NC_ENOTVAR)
956            error("bad var id: status = %d", err);
957        for (j = 0; j < var_rank[i]; j++) {
958            if (var_dimid[i][j] > 0) {          /* skip record dim */
959 start[j] = var_shape[i][j];
960 err = nc_put_vars(ncidistartedgestridebuf);
961 IF (err != NC_EINVALCOORDS && err != NC_EEDGE)
962     error("bad index: status = %d", err);
963 start[j] = 0;
964 edge[j] = var_shape[i][j] + 1;
965 err = nc_put_vars(ncidistartedgestridebuf);
966 IF (err != NC_EEDGE)
967     error("bad edge: status = %d", err);
968 edge[j] = 1;
969 stride[j] = 0;
970 err = nc_put_vars(ncidistartedgestridebuf);
971 IF (err != NC_ESTRIDE)
972     error("bad stride: status = %d", err);
973 stride[j] = 1;
974     }
975        }
976            /* Choose a random point dividing each dim into 2 parts */
977            /* put 2^rank (nslabs) slabs so defined */
978        nslabs = 1;
979        for (j = 0; j < var_rank[i]; j++) {
980            mid[j] = rollvar_shape[i][j] );
981            nslabs *= 2;
982        }
983            /* bits of k determine whether to put lower or upper part of dim */
984            /* choose random stride from 1 to edge */
985        for (k = 0; k < nslabsk++) {
986            nstarts = 1;
987            for (j = 0; j < var_rank[i]; j++) {
988                if ((k >> j) & 1) {
989                    start[j] = 0;
990                    edge[j] = mid[j];
991                }else{
992                    start[j] = mid[j];
993                    edge[j] = var_shape[i][j] - mid[j];
994                }
995                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
996                nstarts *= stride[j];
997            }
998            for (m = 0; m < nstartsm++) {
999                err = toMixedBase(mvar_rank[i], sstrideindex);
1000                IF (err)
1001                    error("error in toMixedBase");
1002                nels = 1;
1003                for (j = 0; j < var_rank[i]; j++) {
1004                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
1005                    nels *= count[j];
1006                    index[j] += start[j];
1007                }
1008                        /* Random choice of forward or backward */
1009/* TODO
1010                if ( roll(2) ) {
1011                    for (j = 0; j < var_rank[i]; j++) {
1012                        index[j] += (count[j] - 1) * stride[j];
1013                        stride[j] = -stride[j];
1014                    }
1015                }
1016 */
1017 p = (char *) buf;
1018 for (j = 0; j < nelsj++) {
1019     err = toMixedBase(jvar_rank[i], countindex2);
1020     IF (err)
1021 error("error in toMixedBase");
1022     for (d = 0; d < var_rank[i]; d++)
1023 index2[d] = index[d] + index2[d] * stride[d];
1024     value = hashvar_type[i], var_rank[i], index2);
1025     if (!inRange(valuevar_type[i]))
1026 value = 0;
1027     err = dbl2nc(valuevar_type[i], p);
1028     IF (err)
1029 error("error in dbl2nc");
1030     p += nctypelen(var_type[i]);
1031 }
1032 if (var_rank[i] == 0 && i%2 == 0)
1033     err = nc_put_vars(ncidiNULLNULLNULLbuf);
1034 else
1035     err = nc_put_vars(ncidiindexcountstridebuf);
1036 IF (err) {
1037     error("%s", nc_strerror(err));
1038 }
1039            }
1040        }
1041    }
1042
1043    check_vars(ncid);
1044    err = nc_close(ncid);
1045    IF (err)
1046        error("nc_close: %s", nc_strerror(err));
1047
1048    err = remove(scratch);
1049    IF (err)
1050        error("remove of %s failed", scratch);
1051}
1052
1053
1054/*
1055 * Test nc_put_varm
1056 * Choose a random point dividing each dim into 2 parts
1057 * Put 2^rank (nslabs) slabs so defined
1058 * Choose random stride from 1 to edge
1059 * Buffer is bit image of whole external variable.
1060 * So all puts for a variable put different elements of buffer
1061 * At end check all variables using check_vars
1062 */
1063void
1064test_nc_put_varm(void)
1065{
1066    int ncid;
1067    int i;
1068    int j;
1069    int k;
1070    int m;
1071    int err;
1072    int nslabs;
1073    int nstarts;        /* number of different starts */
1074    size_t start[MAX_RANK];
1075    size_t edge[MAX_RANK];
1076    size_t index[MAX_RANK];
1077    size_t mid[MAX_RANK];
1078    size_t count[MAX_RANK];
1079    size_t sstride[MAX_RANK];
1080    ptrdiff_t stride[MAX_RANK];
1081    ptrdiff_t imap[MAX_RANK];
1082    ptrdiff_t imap2[MAX_RANK];
1083    double buf[MAX_NELS];       /* (void *) buffer */
1084    char *p; /* (void *) pointer */
1085    double value;
1086
1087    err = file_create(scratchNC_NOCLOBBER, &ncid);
1088    IF (err) {
1089        error("nc_create: %s", nc_strerror(err));
1090        return;
1091    }
1092    def_dims(ncid);
1093    def_vars(ncid);
1094    err = nc_enddef(ncid);
1095    IF (err)
1096        error("nc_enddef: %s", nc_strerror(err));
1097
1098    for (i = 0; i < numVarsi++) {
1099        assert(var_rank[i] <= MAX_RANK);
1100        assert(var_nels[i] <= MAX_NELS);
1101        for (j = 0; j < var_rank[i]; j++) {
1102            start[j] = 0;
1103            edge[j] = 1;
1104            stride[j] = 1;
1105        }
1106 if (var_rank[i] > 0) {
1107     j = var_rank[i] - 1;
1108            // imap[j] = nctypelen(var_type[i]); /* in bytes */
1109            imap[j] = 1; /* in numbers of elements */
1110     for (; j > 0; j--)
1111 imap[j-1] = imap[j] * var_shape[i][j];
1112 }
1113 p = (char *) buf;
1114 for (j = 0; j < var_nels[i]; j++) {
1115     err = toMixedBase(jvar_rank[i], var_shape[i], index);
1116     IF (err)
1117 error("error in toMixedBase");
1118     value = hashvar_type[i], var_rank[i], index);
1119     if (!inRange(valuevar_type[i]))
1120 value = 0;
1121     err = dbl2nc(valuevar_type[i], p);
1122     IF (err)
1123 error("error in dbl2nc");
1124     p += nctypelen(var_type[i]);
1125 }
1126        err = nc_put_varm(BAD_IDistartedgestrideimapbuf);
1127        IF (err != NC_EBADID)
1128            error("bad ncid: status = %d", err);
1129        err = nc_put_varm(ncidBAD_VARIDstartedgestrideimapbuf);
1130        IF (err != NC_ENOTVAR)
1131            error("bad var id: status = %d", err);
1132        for (j = 0; j < var_rank[i]; j++) {
1133            if (var_dimid[i][j] > 0) {          /* skip record dim */
1134 start[j] = var_shape[i][j];
1135 err = nc_put_varm(ncidistartedgestrideimapbuf);
1136 IF (err != NC_EINVALCOORDS && err != NC_EEDGE)
1137     error("bad index: status = %d", err);
1138 start[j] = 0;
1139 edge[j] = var_shape[i][j] + 1;
1140 err = nc_put_varm(ncidistartedgestrideimapbuf);
1141 IF (err != NC_EEDGE)
1142     error("bad edge: status = %d", err);
1143 edge[j] = 1;
1144 stride[j] = 0;
1145 err = nc_put_varm(ncidistartedgestrideimapbuf);
1146 IF (err != NC_ESTRIDE)
1147     error("bad stride: status = %d", err);
1148 stride[j] = 1;
1149     }
1150        }
1151            /* Choose a random point dividing each dim into 2 parts */
1152            /* put 2^rank (nslabs) slabs so defined */
1153        nslabs = 1;
1154        for (j = 0; j < var_rank[i]; j++) {
1155            mid[j] = rollvar_shape[i][j] );
1156            nslabs *= 2;
1157        }
1158            /* bits of k determine whether to put lower or upper part of dim */
1159            /* choose random stride from 1 to edge */
1160        for (k = 0; k < nslabsk++) {
1161            nstarts = 1;
1162            for (j = 0; j < var_rank[i]; j++) {
1163                if ((k >> j) & 1) {
1164                    start[j] = 0;
1165                    edge[j] = mid[j];
1166                }else{
1167                    start[j] = mid[j];
1168                    edge[j] = var_shape[i][j] - mid[j];
1169                }
1170                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
1171                imap2[j] = imap[j] * sstride[j];
1172                nstarts *= stride[j];
1173            }
1174            for (m = 0; m < nstartsm++) {
1175 if (var_rank[i] == 0 && i%2 == 0) {
1176     err = nc_put_varm(ncidiNULLNULLNULLNULLbuf);
1177 } else {
1178     err = toMixedBase(mvar_rank[i], sstrideindex);
1179     IF (err)
1180 error("error in toMixedBase");
1181     for (j = 0; j < var_rank[i]; j++) {
1182 count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
1183 index[j] += start[j];
1184     }
1185     /* Random choice of forward or backward */
1186/* TODO
1187     if ( roll(2) ) {
1188 for (j = 0; j < var_rank[i]; j++) {
1189     index[j] += (count[j] - 1) * stride[j];
1190     stride[j] = -stride[j];
1191 }
1192     }
1193 */
1194     j = fromMixedBase(var_rank[i], indexvar_shape[i]);
1195                    p = (char *) buf + j * nctypelen(var_type[i]);
1196     err = nc_put_varm(ncidiindexcountstrideimap2p);
1197 }
1198 IF (err) {
1199     error("%s", nc_strerror(err));
1200 }
1201            }
1202        }
1203    }
1204
1205    check_vars(ncid);
1206    err = nc_close(ncid);
1207    IF (err)
1208        error("nc_close: %s", nc_strerror(err));
1209
1210    err = remove(scratch);
1211    IF (err)
1212        error("remove of %s failed", scratch);
1213}
1214
1215
1216/*
1217 * Test nc_rename_var
1218 *    try with bad netCDF handle, check error
1219 *    try with bad variable handle, check error
1220 *    try renaming to existing variable name, check error
1221 *    check that proper rename worked with nc_inq_varid
1222 *    try in data mode, check error
1223 */
1224void
1225test_nc_rename_var(void)
1226{
1227    int ncid;
1228    int varid;
1229    int err;
1230    int i;
1231    char name[NC_MAX_NAME];
1232
1233    err = file_create(scratchNC_NOCLOBBER, &ncid);
1234    IF (err) {
1235        error("nc_create: %s", nc_strerror(err));
1236        return;
1237    }
1238    err = nc_rename_var(ncidBAD_VARID, "newName");
1239    IF (err != NC_ENOTVAR)
1240 error("bad var id: status = %d", err);
1241    def_dims(ncid);
1242    def_vars(ncid);
1243
1244 /* Prefix "new_" to each name */
1245    for (i = 0; i < numVarsi++) {
1246        err = nc_rename_var(BAD_IDi, "newName");
1247        IF (err != NC_EBADID)
1248            error("bad ncid: status = %d", err);
1249        err = nc_rename_var(ncidivar_name[numVars-1]);
1250        IF (err != NC_ENAMEINUSE)
1251            error("duplicate name: status = %d", err);
1252 (void) strcpy(name, "new_");
1253 (void) strcat(namevar_name[i]);
1254        err = nc_rename_var(ncidiname);
1255        IF (err)
1256     error("nc_rename_var: %s", nc_strerror(err));
1257        err = nc_inq_varid(ncidname, &varid);
1258        IF (err)
1259     error("nc_inq_varid: %s", nc_strerror(err));
1260        IF (varid != i)
1261     error("Unexpected varid");
1262    }
1263
1264 /* Change to data mode */
1265 /* Try making names even longer. Then restore original names */
1266    err = nc_enddef(ncid);
1267    IF (err)
1268        error("nc_enddef: %s", nc_strerror(err));
1269    for (i = 0; i < numVarsi++) {
1270 (void) strcpy(name, "even_longer_");
1271 (void) strcat(namevar_name[i]);
1272        err = nc_rename_var(ncidiname);
1273        IF (err != NC_ENOTINDEFINE)
1274            error("longer name in data mode: status = %d", err);
1275        err = nc_rename_var(ncidivar_name[i]);
1276        IF (err)
1277     error("nc_rename_var: %s", nc_strerror(err));
1278        err = nc_inq_varid(ncidvar_name[i], &varid);
1279        IF (err)
1280     error("nc_inq_varid: %s", nc_strerror(err));
1281        IF (varid != i)
1282     error("Unexpected varid");
1283    }
1284
1285    put_vars(ncid);
1286    check_vars(ncid);
1287
1288    err = nc_close(ncid);
1289    IF (err)
1290        error("nc_close: %s", nc_strerror(err));
1291
1292    err = remove(scratch);
1293    IF (err)
1294        error("remove of %s failed", scratch);
1295}
1296
1297
1298void
1299test_nc_put_att(void)
1300{
1301    int ncid;
1302    int varid;
1303    int i;
1304    int j;
1305    size_t k;
1306    int err;
1307    double buf[MAX_NELS];       /* (void *) buffer */
1308    char *p;                    /* (void *) pointer */
1309    char *name; /* of att */
1310    nc_type datatype; /* of att */
1311    size_t length; /* of att */
1312    double value;
1313
1314    err = file_create(scratchNC_NOCLOBBER, &ncid);
1315    IF (err) {
1316        error("nc_create: %s", nc_strerror(err));
1317        return;
1318    }
1319    def_dims(ncid);
1320    def_vars(ncid);
1321
1322    for (i = -1; i < numVarsi++) {
1323 varid = VARID(i);
1324        for (j = 0; j < NATTS(i); j++) {
1325     name = ATT_NAME(i,j);
1326     datatype = ATT_TYPE(i,j);
1327     length = ATT_LEN(i,j);
1328            err = nc_put_att(BAD_IDvaridnamedatatypelengthbuf);
1329            IF (err != NC_EBADID)
1330                error("bad ncid: status = %d", err);
1331            err = nc_put_att(ncidvaridBAD_NAMEdatatypelengthbuf);
1332     IF (err != NC_EBADNAME)
1333 error("bad name: status = %d", err);
1334            err = nc_put_att(ncidBAD_VARIDnamedatatypelengthbuf);
1335            IF (err != NC_ENOTVAR)
1336                error("bad var id: status = %d", err);
1337     err = nc_put_att(ncidvaridnameBAD_TYPElengthbuf);
1338     IF (err != NC_EBADTYPE)
1339 error("bad type: status = %d", err);
1340     p = (char *) buf;
1341     for (k = 0; k < lengthk++) {
1342 value = hash(datatype, -1, &k );
1343 if (!inRange(valuedatatype))
1344     value = 0;
1345 err = dbl2nc(valuedatatypep);
1346 IF (err)
1347     error("error in dbl2nc");
1348 p += nctypelen(datatype);
1349     }
1350            err = nc_put_att(ncidvaridnamedatatypelengthbuf);
1351            IF (err) {
1352                error("%s", nc_strerror(err));
1353            }
1354        }
1355    }
1356
1357    check_atts(ncid);
1358    err = nc_close(ncid);
1359    IF (err)
1360        error("nc_close: %s", nc_strerror(err));
1361
1362    err = remove(scratch);
1363    IF (err)
1364        error("remove of %s failed", scratch);
1365}
1366
1367
1368/*
1369 * Test nc_copy_att
1370 *    try with bad source or target netCDF handles, check error
1371 *    try with bad source or target variable handle, check error
1372 *    try with nonexisting attribute, check error
1373 *    check that NC_GLOBAL variable for source or target works
1374 *    check that new attribute put works with target in define mode
1375 *    check that old attribute put works with target in data mode
1376 *    check that changing type and length of an attribute work OK
1377 *    try with same ncid for source and target, different variables
1378 *    try with same ncid for source and target, same variable
1379 */
1380void
1381test_nc_copy_att(void)
1382{
1383    int ncid_in;
1384    int ncid_out;
1385    int varid;
1386    int err;
1387    int i;
1388    int j;
1389    char *name;                 /* of att */
1390    nc_type datatype;           /* of att */
1391    size_t length;              /* of att */
1392    char  value;
1393
1394    err = file_open(testfileNC_NOWRITE, &ncid_in);
1395    IF (err)
1396        error("nc_open: %s", nc_strerror(err));
1397    err = file_create(scratchNC_NOCLOBBER, &ncid_out);
1398    IF (err) {
1399        error("nc_create: %s", nc_strerror(err));
1400        return;
1401    }
1402    def_dims(ncid_out);
1403    def_vars(ncid_out);
1404
1405    for (i = -1; i < numVarsi++) {
1406        varid = VARID(i);
1407        for (j = 0; j < NATTS(i); j++) {
1408            name = ATT_NAME(i,j);
1409     err = nc_copy_att(ncid_inBAD_VARIDnamencid_outvarid);
1410     IF (err != NC_ENOTVAR)
1411 error("bad var id: status = %d", err);
1412     err = nc_copy_att(ncid_invaridnamencid_outBAD_VARID);
1413     IF (err != NC_ENOTVAR)
1414 error("bad var id: status = %d", err);
1415     err = nc_copy_att(BAD_IDvaridnamencid_outvarid);
1416     IF (err != NC_EBADID)
1417 error("bad ncid: status = %d", err);
1418     err = nc_copy_att(ncid_invaridnameBAD_IDvarid);
1419     IF (err != NC_EBADID)
1420 error("bad ncid: status = %d", err);
1421     err = nc_copy_att(ncid_invarid, "noSuch", ncid_outvarid);
1422     IF (err != NC_ENOTATT)
1423 error("bad attname: status = %d", err);
1424     err = nc_copy_att(ncid_invaridnamencid_outvarid);
1425     IF (err)
1426 error("nc_copy_att: %s", nc_strerror(err));
1427     err = nc_copy_att(ncid_outvaridnamencid_outvarid);
1428     IF (err)
1429 error("source = target: %s", nc_strerror(err));
1430 }
1431    }
1432
1433    err = nc_close(ncid_in);
1434    IF (err)
1435        error("nc_close: %s", nc_strerror(err));
1436
1437        /* Close scratch. Reopen & check attributes */
1438    err = nc_close(ncid_out);
1439    IF (err)
1440        error("nc_close: %s", nc_strerror(err));
1441    err = file_open(scratchNC_WRITE, &ncid_out);
1442    IF (err)
1443        error("nc_open: %s", nc_strerror(err));
1444    check_atts(ncid_out);
1445
1446       /*
1447 * change to define mode
1448 * define single char. global att. ':a' with value 'A'
1449 * This will be used as source for following copies
1450 */
1451    err = nc_redef(ncid_out);
1452    IF (err)
1453        error("nc_redef: %s", nc_strerror(err));
1454    err = nc_put_att_text(ncid_outNC_GLOBAL, "a", 1, "A");
1455    IF (err)
1456 error("nc_put_att_text: %s", nc_strerror(err));
1457
1458       /*
1459 * change to data mode
1460 * Use scratch as both source & dest.
1461 * try copy to existing att. change type & decrease length
1462 * rename 1st existing att of each var (if any) 'a'
1463 * if this att. exists them copy ':a' to it
1464 */
1465    err = nc_enddef(ncid_out);
1466    IF (err)
1467        error("nc_enddef: %s", nc_strerror(err));
1468    for (i = 0; i < numVarsi++) {
1469 if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
1470     err = nc_rename_att(ncid_outiatt_name[i][0], "a");
1471     IF (err)
1472 error("nc_rename_att: %s", nc_strerror(err));
1473     err = nc_copy_att(ncid_outNC_GLOBAL, "a", ncid_outi);
1474     IF (err)
1475 error("nc_copy_att: %s", nc_strerror(err));
1476 }
1477    }
1478    err = nc_close(ncid_out);
1479    IF (err)
1480        error("nc_close: %s", nc_strerror(err));
1481
1482 /* Reopen & check */
1483    err = file_open(scratchNC_WRITE, &ncid_out);
1484    IF (err)
1485        error("nc_open: %s", nc_strerror(err));
1486    for (i = 0; i < numVarsi++) {
1487 if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
1488     err = nc_inq_att(ncid_outi, "a", &datatype, &length);
1489     IF (err)
1490 error("nc_inq_att: %s", nc_strerror(err));
1491     IF (datatype != NC_CHAR)
1492 error("Unexpected type");
1493     IF (length != 1)
1494 error("Unexpected length");
1495     err = nc_get_att_text(ncid_outi, "a", &value);
1496     IF (err)
1497 error("nc_get_att_text: %s", nc_strerror(err));
1498     IF (value != 'A')
1499 error("Unexpected value");
1500 }
1501    }
1502
1503    err = nc_close(ncid_out);
1504    IF (err)
1505        error("nc_close: %s", nc_strerror(err));
1506    err = remove(scratch);
1507    IF (err)
1508        error("remove of %s failed", scratch);
1509}
1510
1511
1512/*
1513 * Test nc_rename_att
1514 *    try with bad netCDF handle, check error
1515 *    try with bad variable handle, check error
1516 *    try with nonexisting att name, check error
1517 *    try renaming to existing att name, check error
1518 *    check that proper rename worked with nc_inq_attid
1519 *    try in data mode, check error
1520 */
1521void
1522test_nc_rename_att(void)
1523{
1524    int ncid;
1525    int varid;
1526    int err;
1527    int i;
1528    int j;
1529    size_t  k;
1530    int attnum;
1531    char *attname;
1532    char name[NC_MAX_NAME];
1533    char oldname[NC_MAX_NAME];
1534    char newname[NC_MAX_NAME];
1535    int nok = 0;      /* count of valid comparisons */
1536    nc_type datatype;
1537    nc_type atttype;
1538    size_t length;
1539    size_t attlength;
1540    signed char  text[MAX_NELS];
1541    double value[MAX_NELS];
1542    double expect;
1543
1544    err = file_create(scratchNC_NOCLOBBER, &ncid);
1545    IF (err) {
1546        error("nc_create: %s", nc_strerror(err));
1547        return;
1548    }
1549    err = nc_rename_att(ncidBAD_VARID, "abc", "newName");
1550    IF (err != NC_ENOTVAR)
1551 error("bad var id: status = %d", err);
1552    def_dims(ncid);
1553    def_vars(ncid);
1554    put_atts(ncid);
1555
1556    for (i = -1; i < numVarsi++) {
1557        varid = VARID(i);
1558        for (j = 0; j < NATTS(i); j++) {
1559     attname = ATT_NAME(i,j);
1560     err = nc_rename_att(BAD_IDvaridattname, "newName");
1561     IF (err != NC_EBADID)
1562 error("bad ncid: status = %d", err);
1563     err = nc_rename_att(ncidvarid, "noSuch", "newName");
1564     IF (err != NC_ENOTATT)
1565 error("bad attname: status = %d", err);
1566     (void) strcpy(newname, "new_");
1567     (void) strcat(newnameattname);
1568     err = nc_rename_att(ncidvaridattnamenewname);
1569     IF (err)
1570 error("nc_rename_att: %s", nc_strerror(err));
1571     err = nc_inq_attid(ncidvaridnewname, &attnum);
1572     IF (err)
1573 error("nc_inq_attid: %s", nc_strerror(err));
1574     IF (attnum != j)
1575 error("Unexpected attnum");
1576 }
1577    }
1578
1579        /* Close. Reopen & check */
1580    err = nc_close(ncid);
1581    IF (err)
1582        error("nc_close: %s", nc_strerror(err));
1583    err = file_open(scratchNC_WRITE, &ncid);
1584    IF (err)
1585        error("nc_open: %s", nc_strerror(err));
1586
1587    for (i = -1; i < numVarsi++) {
1588        varid = VARID(i);
1589        for (j = 0; j < NATTS(i); j++) {
1590     attname = ATT_NAME(i,j);
1591     atttype = ATT_TYPE(i,j);
1592     attlength = ATT_LEN(i,j);
1593            (void) strcpy(newname, "new_");
1594            (void) strcat(newnameattname);
1595            err = nc_inq_attname(ncidvaridjname);
1596            IF (err)
1597                error("nc_inq_attname: %s", nc_strerror(err));
1598            IF (strcmp(namenewname) != 0)
1599                error("nc_inq_attname: unexpected name");
1600            err = nc_inq_att(ncidvaridname, &datatype, &length);
1601            IF (err)
1602                error("nc_inq_att: %s", nc_strerror(err));
1603            IF (datatype != atttype)
1604                error("nc_inq_att: unexpected type");
1605            IF (length != attlength)
1606                error("nc_inq_att: unexpected length");
1607            if (datatype == NC_CHAR) {
1608                err = nc_get_att_text(ncidvaridnametext);
1609                IF (err)
1610                    error("nc_get_att_text: %s", nc_strerror(err));
1611                for (k = 0; k < attlengthk++) {
1612                    expect = hash(datatype, -1, &k);
1613                    IF (text[k] != expect) {
1614                        error("nc_get_att_text: unexpected value");
1615                    } else {
1616                        nok++;
1617                    }
1618                }
1619            } else {
1620                err = nc_get_att_double(ncidvaridnamevalue);
1621                IF (err)
1622                    error("nc_get_att_double: %s", nc_strerror(err));
1623                for (k = 0; k < attlengthk++) {
1624                    expect = hash(datatype, -1, &k);
1625     if (inRange(expectdatatype)) {
1626 IF (!equal(value[k],expect,datatype,NCT_DOUBLE)) {
1627     error("nc_get_att_double: unexpected value");
1628 } else {
1629     nok++;
1630 }
1631                    }
1632                }
1633            }
1634        }
1635    }
1636    print_nok(nok);
1637
1638 /* Now in data mode */
1639 /* Try making names even longer. Then restore original names */
1640
1641    for (i = -1; i < numVarsi++) {
1642        varid = VARID(i);
1643        for (j = 0; j < NATTS(i); j++) {
1644     attname = ATT_NAME(i,j);
1645     (void) strcpy(oldname, "new_");
1646     (void) strcat(oldnameattname);
1647     (void) strcpy(newname, "even_longer_");
1648     (void) strcat(newnameattname);
1649     err = nc_rename_att(ncidvaridoldnamenewname);
1650     IF (err != NC_ENOTINDEFINE)
1651 error("longer name in data mode: status = %d", err);
1652     err = nc_rename_att(ncidvaridoldnameattname);
1653     IF (err)
1654 error("nc_rename_att: %s", nc_strerror(err));
1655     err = nc_inq_attid(ncidvaridattname, &attnum);
1656     IF (err)
1657 error("nc_inq_attid: %s", nc_strerror(err));
1658     IF (attnum != j)
1659 error("Unexpected attnum");
1660 }
1661    }
1662
1663    err = nc_close(ncid);
1664    IF (err)
1665        error("nc_close: %s", nc_strerror(err));
1666
1667    err = remove(scratch);
1668    IF (err)
1669        error("remove of %s failed", scratch);
1670}
1671
1672
1673/*
1674 * Test nc_del_att
1675 *    try with bad netCDF handle, check error
1676 *    try with bad variable handle, check error
1677 *    try with nonexisting att name, check error
1678 *    check that proper delete worked using:
1679 *      nc_inq_attid, nc_inq_natts, nc_inq_varnatts
1680 */
1681void
1682test_nc_del_att(void)
1683{
1684    int ncid;
1685    int err;
1686    int i;
1687    int j;
1688    int attnum;
1689    int natts;
1690    int numatts;
1691    int varid;
1692    char *name;                 /* of att */
1693
1694    err = file_create(scratchNC_NOCLOBBER, &ncid);
1695    IF (err) {
1696        error("nc_create: %s", nc_strerror(err));
1697        return;
1698    }
1699    err = nc_del_att(ncidBAD_VARID, "abc");
1700    IF (err != NC_ENOTVAR)
1701 error("bad var id: status = %d", err);
1702    def_dims(ncid);
1703    def_vars(ncid);
1704    put_atts(ncid);
1705
1706    for (i = -1; i < numVarsi++) {
1707 varid = VARID(i);
1708 numatts = NATTS(i);
1709        for (j = 0; j < numattsj++) {
1710     name = ATT_NAME(i,j);
1711     err = nc_del_att(BAD_IDvaridname);
1712     IF (err != NC_EBADID)
1713 error("bad ncid: status = %d", err);
1714     err = nc_del_att(ncidvarid, "noSuch");
1715     IF (err != NC_ENOTATT)
1716 error("bad attname: status = %d", err);
1717     err = nc_del_att(ncidvaridname);
1718     IF (err)
1719 error("nc_del_att: %s", nc_strerror(err));
1720     err = nc_inq_attid(ncidvaridname, &attnum);
1721     IF (err != NC_ENOTATT)
1722 error("bad attname: status = %d", err);
1723     if (i < 0) {
1724 err = nc_inq_natts(ncid, &natts);
1725 IF (err)
1726     error("nc_inq_natts: %s", nc_strerror(err));
1727 IF (natts != numatts-j-1)
1728     error("natts: expected %d, got %d", numatts-j-1, natts);
1729     }
1730     err = nc_inq_varnatts(ncidvarid, &natts);
1731     IF (err)
1732 error("nc_inq_varnatts: %s", nc_strerror(err));
1733     IF (natts != numatts-j-1)
1734 error("natts: expected %d, got %d", numatts-j-1, natts);
1735 }
1736    }
1737
1738        /* Close. Reopen & check no attributes left */
1739    err = nc_close(ncid);
1740    IF (err)
1741        error("nc_close: %s", nc_strerror(err));
1742    err = file_open(scratchNC_WRITE, &ncid);
1743    IF (err)
1744        error("nc_open: %s", nc_strerror(err));
1745    err = nc_inq_natts(ncid, &natts);
1746    IF (err)
1747 error("nc_inq_natts: %s", nc_strerror(err));
1748    IF (natts != 0)
1749 error("natts: expected %d, got %d", 0, natts);
1750    for (i = -1; i < numVarsi++) {
1751 varid = VARID(i);
1752 err = nc_inq_varnatts(ncidvarid, &natts);
1753 IF (err)
1754     error("nc_inq_natts: %s", nc_strerror(err));
1755 IF (natts != 0)
1756     error("natts: expected %d, got %d", 0, natts);
1757    }
1758
1759 /* restore attributes. change to data mode. try to delete */
1760    err = nc_redef(ncid);
1761    IF (err)
1762        error("nc_redef: %s", nc_strerror(err));
1763    put_atts(ncid);
1764    err = nc_enddef(ncid);
1765    IF (err)
1766        error("nc_enddef: %s", nc_strerror(err));
1767
1768    for (i = -1; i < numVarsi++) {
1769 varid = VARID(i);
1770 numatts = NATTS(i);
1771        for (j = 0; j < numattsj++) {
1772     name = ATT_NAME(i,j);
1773     err = nc_del_att(ncidvaridname);
1774     IF (err != NC_ENOTINDEFINE)
1775 error("in data mode: status = %d", err);
1776 }
1777    }
1778
1779    err = nc_close(ncid);
1780    IF (err)
1781        error("nc_close: %s", nc_strerror(err));
1782    err = remove(scratch);
1783    IF (err)
1784        error("remove of %s failed", scratch);
1785}
1786
1787
1788/*
1789 * Test nc_set_fill
1790 *    try with bad netCDF handle, check error
1791 *    try in read-only mode, check error
1792 *    try with bad new_fillmode, check error
1793 *    try in data mode, check error
1794 *    check that proper set to NC_FILL works for record & non-record variables
1795 *    (note that it is not possible to test NC_NOFILL mode!)
1796 *    close file & create again for test using attribute _FillValue
1797 */
1798void
1799test_nc_set_fill(void)
1800{
1801    int ncid;
1802    int varid;
1803    int err;
1804    int i;
1805    int j;
1806    int old_fillmode;
1807    int nok = 0;      /* count of valid comparisons */
1808    char text = 0;
1809    double value = 0;
1810    double fill;
1811    size_t index[MAX_RANK];
1812
1813 /* bad ncid */
1814    err = nc_set_fill(BAD_IDNC_NOFILL, &old_fillmode);
1815    IF (err != NC_EBADID)
1816 error("bad ncid: status = %d", err);
1817
1818 /* try in read-only mode */
1819    err = file_open(testfileNC_NOWRITE, &ncid);
1820    IF (err)
1821        error("nc_open: %s", nc_strerror(err));
1822    err = nc_set_fill(ncidNC_NOFILL, &old_fillmode);
1823    IF (err != NC_EPERM)
1824 error("read-only: status = %d", err);
1825    err = nc_close(ncid);
1826    IF (err)
1827        error("nc_close: %s", nc_strerror(err));
1828
1829 /* create scratch */
1830    err = file_create(scratchNC_NOCLOBBER, &ncid);
1831    IF (err) {
1832        error("nc_create: %s", nc_strerror(err));
1833        return;
1834    }
1835
1836 /* BAD_FILLMODE */
1837    err = nc_set_fill(ncidBAD_FILLMODE, &old_fillmode);
1838    IF (err != NC_EINVAL)
1839        error("bad fillmode: status = %d", err);
1840
1841 /* proper calls */
1842    err = nc_set_fill(ncidNC_NOFILL, &old_fillmode);
1843    IF (err)
1844        error("nc_set_fill: %s", nc_strerror(err));
1845    IF (old_fillmode != NC_FILL)
1846        error("Unexpected old fill mode: %d", old_fillmode);
1847    err = nc_set_fill(ncidNC_FILL, &old_fillmode);
1848    IF (err)
1849        error("nc_set_fill: %s", nc_strerror(err));
1850    IF (old_fillmode != NC_NOFILL)
1851        error("Unexpected old fill mode: %d", old_fillmode);
1852
1853 /* define dims & vars */
1854    def_dims(ncid);
1855    def_vars(ncid);
1856
1857 /* Change to data mode. Set fillmode again */
1858    err = nc_enddef(ncid);
1859    IF (err)
1860        error("nc_enddef: %s", nc_strerror(err));
1861    err = nc_set_fill(ncidNC_FILL, &old_fillmode);
1862    IF (err)
1863        error("nc_set_fill: %s", nc_strerror(err));
1864    IF (old_fillmode != NC_FILL)
1865        error("Unexpected old fill mode: %d", old_fillmode);
1866
1867 /* Write record number NRECS to force writing of preceding records */
1868 /* Assumes variable cr is char vector with UNLIMITED dimension */
1869    err = nc_inq_varid(ncid, "cr", &varid);
1870    IF (err)
1871        error("nc_inq_varid: %s", nc_strerror(err));
1872    index[0] = NRECS;
1873    err = nc_put_var1_text(ncidvaridindex, &text);
1874    IF (err)
1875        error("nc_put_var1_text: %s", nc_strerror(err));
1876
1877 /* get all variables & check all values equal default fill */
1878    for (i = 0; i < numVarsi++) {
1879 switch (var_type[i]) {
1880     case NC_CHAR:   fill = NC_FILL_CHAR; break;
1881     case NC_BYTE:   fill = NC_FILL_BYTE; break;
1882     case NC_SHORT:  fill = NC_FILL_SHORT; break;
1883     case NC_INT:   fill = NC_FILL_INT; break;
1884     case NC_FLOAT:  fill = NC_FILL_FLOAT; break;
1885     case NC_DOUBLEfill = NC_FILL_DOUBLE; break;
1886     default: assert(0);
1887 }
1888 for (j = 0; j < var_nels[i]; j++) {
1889            err = toMixedBase(jvar_rank[i], var_shape[i], index);
1890            IF (err)
1891                error("error in toMixedBase");
1892     if (var_type[i] == NC_CHAR) {
1893 err = nc_get_var1_text(ncidiindex, &text);
1894 IF (err)
1895     error("nc_get_var1_text failed: %s", nc_strerror(err));
1896 value = text;
1897     } else {
1898 err = nc_get_var1_double(ncidiindex, &value);
1899 IF (err)
1900     error("nc_get_var1_double failed: %s", nc_strerror(err));
1901     }
1902     IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
1903 error("\n\t\tValue expected: %-23.17e,\n\t\t          read: %-23.17e\n",
1904 fillvalue);
1905     else
1906 nok++;
1907        }
1908    }
1909
1910 /* close scratch & create again for test using attribute _FillValue */
1911    err = nc_close(ncid);
1912    IF (err)
1913        error("nc_close: %s", nc_strerror(err));
1914    err = file_create(scratchNC_CLOBBER, &ncid);
1915    IF (err) {
1916        error("nc_create: %s", nc_strerror(err));
1917        return;
1918    }
1919    def_dims(ncid);
1920    def_vars(ncid);
1921
1922 /* set _FillValue = 42 for all vars */
1923    text = fill = 42;
1924    for (i = 0; i < numVarsi++) {
1925 if (var_type[i] == NC_CHAR) {
1926     err = nc_put_att_text(ncidi, "_FillValue", 1, &text);
1927     IF (err)
1928 error("nc_put_att_text: %s", nc_strerror(err));
1929 } else {
1930     err = nc_put_att_double(ncidi, "_FillValue",var_type[i],1,&fill);
1931     IF (err)
1932 error("nc_put_att_double: %s", nc_strerror(err));
1933 }
1934    }
1935
1936 /* data mode. write records */
1937    err = nc_enddef(ncid);
1938    IF (err)
1939        error("nc_enddef: %s", nc_strerror(err));
1940    index[0] = NRECS;
1941    err = nc_put_var1_text(ncidvaridindex, &text);
1942    IF (err)
1943        error("nc_put_var1_text: %s", nc_strerror(err));
1944
1945 /* get all variables & check all values equal 42 */
1946    for (i = 0; i < numVarsi++) {
1947 for (j = 0; j < var_nels[i]; j++) {
1948            err = toMixedBase(jvar_rank[i], var_shape[i], index);
1949            IF (err)
1950                error("error in toMixedBase");
1951     if (var_type[i] == NC_CHAR) {
1952 err = nc_get_var1_text(ncidiindex, &text);
1953 IF (err)
1954     error("nc_get_var1_text failed: %s", nc_strerror(err));
1955 value = text;
1956     } else {
1957 err = nc_get_var1_double(ncidiindex, &value);
1958 IF (err)
1959     error("nc_get_var1_double failed: %s", nc_strerror(err));
1960     }
1961     IF (value != fill)
1962 error(" Value expected: %g, read: %g\n", fillvalue);
1963     else
1964 nok++;
1965        }
1966    }
1967    print_nok(nok);
1968
1969    err = nc_close(ncid);
1970    IF (err)
1971        error("nc_close: %s", nc_strerror(err));
1972    err = remove(scratch);
1973    IF (err)
1974        error("remove of %s failed", scratch);
1975}
1976
1977/* This function gets the version of a netCDF file, 1 is for netCDF
1978   classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format,
1979   5 for 64-bit data format (CDF-5).
1980*/
1981#define MAGIC_NUM_LEN 4
1982static
1983int
1984nc_get_file_version(char *path, int *version)
1985{
1986   FILE *fp;
1987   char magic[MAGIC_NUM_LEN];
1988
1989   /* Need two valid pointers - check for NULL. */
1990   if (!version || !path)
1991      return NC_EINVAL;
1992
1993   /* Figure out if this is a netcdf or hdf5 file. */
1994   if (!(fp = fopen(path, "r")) ||
1995       fread(magicMAGIC_NUM_LEN, 1, fp) != 1) {
1996     fclose(fp);
1997     return errno;
1998   }
1999   fclose(fp);
2000   if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0)
2001   {
2002      if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC ||
2003   magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET ||
2004   magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5)
2005  *version = magic[MAGIC_NUM_LEN-1];
2006      else
2007  return NC_ENOTNC;
2008   }
2009   /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
2010 away! */
2011   /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
2012      *version = 3;*/
2013   return NC_NOERR;
2014}
2015
2016/*
2017 * Test nc_set_default_format
2018 *    try with bad default format
2019 *    try with NULL old_formatp
2020 *    try in data mode, check error
2021 *    check that proper set to NC_FILL works for record & non-record variables
2022 *    (note that it is not possible to test NC_NOFILL mode!)
2023 *    close file & create again for test using attribute _FillValue
2024 */
2025void
2026test_nc_set_default_format(void)
2027{
2028    int ncid;
2029    int err;
2030    int i;
2031    int version;
2032    int old_format;
2033
2034    /* bad format */
2035    err = nc_set_default_format(BAD_DEFAULT_FORMAT, &old_format);
2036    IF (err != NC_EINVAL)
2037 error("bad default format: status = %d", err);
2038
2039    /* NULL old_formatp */
2040    err = nc_set_default_format(NC_FORMAT_64BIT_OFFSETNULL);
2041    IF (err)
2042 error("null old_fortmatp: status = %d", err);
2043
2044    /* Cycle through available formats. */
2045    for(i=NC_FORMAT_CLASSICi<NC_FORMAT_64BIT_DATAi++)
2046    {
2047       if (i == NC_FORMAT_NETCDF4 || i == NC_FORMAT_NETCDF4_CLASSIC)
2048   continue; /* test classic formats only */
2049       if ((err = nc_set_default_format(iNULL)))
2050   error("setting classic format: status = %d", err);
2051       if ((file_create(scratchNC_CLOBBER, &ncid)))
2052   error("bad nc_create: status = %d", err);
2053       if ((err=nc_put_att_text(ncidNC_GLOBAL, "testatt",
2054 sizeof("blah"), "blah")))
2055   error("bad put_att: status = %d", err);
2056       if ((err=nc_close(ncid)))
2057   error("bad close: status = %d", err);
2058       if ((err = nc_get_file_version(scratch, &version)))
2059   error("bad file version = %d", version);
2060       if (version != i) {
2061#if 0
2062          if (i == 4) {
2063              if (version == 3) continue;
2064       printf("expect version 3 but got %d (file=%s)",version,scratch);
2065              continue;
2066          }
2067#endif
2068   printf("expect version %d but got %d (file=%s)",i,version,scratch);
2069   error("bad file version = %d", version);
2070 }
2071    }
2072
2073    /* Remove the left-over file. */
2074    if (remove(scratch))
2075       error("remove of %s failed", scratch);
2076}


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