1dnl This is m4 source.
2dnl Process using m4 to produce 'C' language file.
3dnl
4dnl This file is supposed to be the same as PnetCDF's test_write.m4
5dnl
6dnl If you see this line, you can ignore the next one.
7/* Do not edit this file. It is produced from the corresponding .m4 source */
8dnl
9/*
10 *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
11 *  See COPYRIGHT notice in top-level directory.
12 */
13/* $Id: test_write.m4 2687 2016-12-08 18:32:13Z wkliao $ */
14
15dnl
16dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
17dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
18dnl (MPI_Offset vs. size_t), and function name substrings for external data
19dnl types.
20dnl
21
22#if defined (_WIN32) || defined (_WIN64)
23#include <io.h>
24#endif
25
26#include <sys/types.h>  /* open() */
27#include <sys/stat.h>   /* open() */
28#include <fcntl.h>      /* open() */
29#ifdef _MSC_VER
30#include <io.h>
31#else
32#include <unistd.h>     /* read() */
33#endif
34
35#include "tests.h"
36#include "config.h"
37#include "math.h"
38
39define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
40
41define(`IntType', `ifdef(`PNETCDF',`MPI_Offset',`size_t')')dnl
42define(`PTRDType',`ifdef(`PNETCDF',`MPI_Offset',`ptrdiff_t')')dnl
43define(`TestFunc',`ifdef(`PNETCDF',`test_ncmpi_$1',`test_nc_$1')')dnl
44define(`APIFunc', `ifdef(`PNETCDF',`ncmpi_$1',`nc_$1')')dnl
45
46define(`FileOpen', `ifdef(`PNETCDF',`ncmpi_open(comm, $1, $2, info, $3)', `file_open($1, $2, $3)')')dnl
47define(`FileCreate',`ifdef(`PNETCDF',`ncmpi_create(comm, $1, $2, info, $3)', `file_create($1, $2, $3)')')dnl
48define(`FileDelete',`ifdef(`PNETCDF',`ncmpi_delete($1,$2)',`nc_delete($1)')')dnl
49
50define(`Def_Vars',  `ifdef(`PNETCDF',`def_vars($1,$2)',`def_vars($1)')')dnl
51define(`Put_Atts',  `ifdef(`PNETCDF',`put_atts($1,$2,$3)',`put_atts($1)')')dnl
52define(`Put_Vars',  `ifdef(`PNETCDF',`put_vars($1,$2)',`put_vars($1)')')dnl
53define(`Check_File',`ifdef(`PNETCDF',`check_file($1,$2,$3)',`check_file($1)')')dnl
54define(`Check_Atts',`ifdef(`PNETCDF',`check_atts($1,$2,$3)',`check_atts($1)')')dnl
55define(`Check_Vars',`ifdef(`PNETCDF',`check_vars($1,$2)',`check_vars($1)')')dnl
56define(`VarArgs',   `ifdef(`PNETCDF',`int numVars',`void')')dnl
57define(`AttVarArgs',`ifdef(`PNETCDF',`int numGatts, int numVars',`void')')dnl
58
59define(`GetVar1TYPE',`ifdef(`PNETCDF',`ncmpi_get_var1_$1_all',`nc_get_var1_$1')')dnl
60define(`PutVar1TYPE',`ifdef(`PNETCDF',`ncmpi_put_var1_$1_all',`nc_put_var1_$1')')dnl
61
62define(`PutVar1', `ifdef(`PNETCDF',`ncmpi_put_var1_all($1,$2,$3,$4,$5,$6)',          `nc_put_var1($1,$2,$3,$4)')')dnl
63define(`PutVar',  `ifdef(`PNETCDF',`ncmpi_put_var_all( $1,$2,$3,$4,$5)',             `nc_put_var( $1,$2,$3)')')dnl
64define(`PutVara', `ifdef(`PNETCDF',`ncmpi_put_vara_all($1,$2,$3,$4,$5,$6,$7)',       `nc_put_vara($1,$2,$3,$4,$5)')')dnl
65define(`PutVars', `ifdef(`PNETCDF',`ncmpi_put_vars_all($1,$2,$3,$4,$5,$6,$7,$8)',    `nc_put_vars($1,$2,$3,$4,$5,$6)')')dnl
66define(`PutVarm', `ifdef(`PNETCDF',`ncmpi_put_varm_all($1,$2,$3,$4,$5,$6,$7,$8,$9)', `nc_put_varm($1,$2,$3,$4,$5,$6,$7)')')dnl
67
68
69/*
70 * Test APIFunc(create)
71 *    For mode in NC_NOCLOBBER, NC_CLOBBER do:
72 *       create netcdf file 'scratch.nc' with no data, close it
73 *       test that it can be opened, do APIFunc(inq) to check nvars = 0, etc.
74 *    Try again in NC_NOCLOBBER mode, check error return
75 * On exit, delete this file
76 */
77int
78TestFunc(create)(void)
79{
80    int clobber; /* 0 for NC_NOCLOBBER, 1 for NC_CLOBBER */
81    int err;
82    int ncid;
83    int ndims;   /* number of dimensions */
84    int nvars;   /* number of variables */
85    int ngatts;  /* number of global attributes */
86    int recdim;  /* id of unlimited dimension */
87    int nok=0;
88
89    for (clobber = 0; clobber < 2; clobber++) {
90        err = FileCreate(scratch, clobber ? NC_CLOBBER : NC_NOCLOBBER, &ncid);
91        IF (err != NC_NOERR)
92            error("create: %s", APIFunc(strerror)(err));
93        ELSE_NOK
94        err = APIFunc(close)(ncid);
95        IF (err != NC_NOERR)
96            error("close: %s", APIFunc(strerror)(err));
97        err = FileOpen(scratch, NC_NOWRITE, &ncid);
98        IF (err != NC_NOERR)
99            error("open: %s", APIFunc(strerror)(err));
100        err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, &recdim);
101        IF (err != NC_NOERR)
102            error("inq: %s", APIFunc(strerror)(err));
103        else IF (ndims != 0)
104            error("inq: wrong number of dimensions returned, %d", ndims);
105        else IF (nvars != 0)
106            error("inq: wrong number of variables returned, %d", nvars);
107        else IF (ngatts != 0)
108            error("inq: wrong number of global atts returned, %d", ngatts);
109        else IF (recdim != -1)
110            error("inq: wrong record dimension ID returned, %d", recdim);
111        ELSE_NOK
112        err = APIFunc(close)(ncid);
113        IF (err != NC_NOERR)
114            error("close: %s", APIFunc(strerror)(err));
115    }
116
117    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
118    IF (err != NC_EEXIST)
119        error("expecting NC_EEXIST but got %s", nc_err_code_name(err));
120    ELSE_NOK
121
122    err = FileDelete(scratch, info);
123    IF (err != NC_NOERR)
124        error("remove of %s failed", scratch);
125    return nok;
126}
127
128
129/*
130 * Test APIFunc(redef)
131 * (In fact also tests APIFunc(enddef) - called from TestFunc(enddef))
132 *    BAD_ID
133 *    attempt redef (error) & enddef on read-only file
134 *    create file, define dims & vars.
135 *    attempt put var (error)
136 *    attempt redef (error) & enddef.
137 *    put vars
138 *    attempt def new dims (error)
139 *    redef
140 *    def new dims, vars.
141 *    put atts
142 *    enddef
143 *    put vars
144 *    close
145 *    check file: vars & atts
146 *    check reopening with NC_WRITE and adding new dims, atts, vars
147 */
148int
149TestFunc(redef)(AttVarArgs)
150{
151    int ncid;          /* netcdf id */
152    /* used to force effective test of ncio->move() in redef */
153    IntType sizehint = 8192;
154    int dimid;         /* dimension id */
155    int varid;         /* variable id */
156    int varid1;        /* variable id */
157    int nok=0, err;
158    const char * title = "Not funny";
159    double var;
160    char name[NC_MAX_NAME];
161    IntType length;
162    int fmt_variant1, fmt_variant2;
163
164    /* BAD_ID tests */
165    err = APIFunc(redef)(BAD_ID);
166    IF (err != NC_EBADID)
167        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
168    ELSE_NOK
169    err = APIFunc(enddef)(BAD_ID);
170    IF (err != NC_EBADID)
171        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
172    ELSE_NOK
173
174    /* read-only tests */
175    err = FileOpen(testfile, NC_NOWRITE, &ncid);
176    IF (err != NC_NOERR)
177        error("open: %s", APIFunc(strerror)(err));
178    err = APIFunc(redef)(ncid);
179    IF (err != NC_EPERM)
180        error("expecting NC_EPERM but got %s", nc_err_code_name(err));
181    ELSE_NOK
182    err = APIFunc(enddef)(ncid);
183    IF (err != NC_ENOTINDEFINE)
184        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
185    ELSE_NOK
186    err = APIFunc(close)(ncid);
187    IF (err != NC_NOERR)
188        error("close: %s", APIFunc(strerror)(err));
189
190    /* tests using scratch file */
191ifdef(`PNETCDF',`dnl
192    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);',`dnl
193    err = file__create(scratch, NC_NOCLOBBER, 0, &sizehint, &ncid);')
194    IF (err != NC_NOERR) {
195        error("create: %s", APIFunc(strerror)(err));
196        return nok;
197    }
198ifdef(`PNETCDF',,`dnl
199    /* limit for ncio implementations which have infinite chunksize */
200    if(sizehint > 32768) sizehint = 16384;')
201    def_dims(ncid);
202    Def_Vars(ncid, numVars);
203    Put_Atts(ncid, numGatts, numVars);
204    err = APIFunc(inq_varid)(ncid, "d", &varid);
205    IF (err != NC_NOERR)
206        error("inq_varid: %s", APIFunc(strerror)(err));
207    var = 1.0;
208
209ifdef(`PNETCDF', `
210    err = ncmpi_begin_indep_data(ncid);
211    IF (err != NC_EINDEFINE)
212        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));')dnl
213
214    err = PutVar1TYPE(double)(ncid, varid, NULL, &var);
215    IF (err != NC_EINDEFINE)
216        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));
217
218ifdef(`PNETCDF', `
219    err = ncmpi_end_indep_data(ncid);
220    IF (err != NC_ENOTINDEP)
221        error("expecting NC_ENOTINDEP but got %s", nc_err_code_name(err));')dnl
222
223    err = APIFunc(redef)(ncid);
224    IF (err != NC_EINDEFINE)
225        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));
226    ELSE_NOK
227    err = APIFunc(enddef)(ncid);
228    IF (err != NC_NOERR)
229        error("enddef: %s", APIFunc(strerror)(err));
230    ELSE_NOK
231    Put_Vars(ncid, numVars);
232    err = APIFunc(def_dim)(ncid, "abc", sizehint, &dimid);
233    IF (err != NC_ENOTINDEFINE)
234        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
235    err = APIFunc(redef)(ncid);
236    IF (err != NC_NOERR)
237        error("redef: %s", APIFunc(strerror)(err));
238    ELSE_NOK
239
240    err = APIFunc(set_fill)(ncid, NC_NOFILL, NULL);
241    IF (err != NC_NOERR)
242        error("set_fill: %s", APIFunc(strerror)(err));
243
244    err = APIFunc(def_dim)(ncid, "abc", sizehint, &dimid);
245    IF (err != NC_NOERR)
246        error("def_dim: %s", APIFunc(strerror)(err));
247    err = APIFunc(def_var)(ncid, "abcScalar", NC_INT, 0, NULL, &varid);
248    IF (err != NC_NOERR)
249        error("def_var: %s", APIFunc(strerror)(err));
250    err = APIFunc(def_var)(ncid, "abc", NC_INT, 1, &dimid, &varid1);
251    IF (err != NC_NOERR)
252        error("def_var: %s", APIFunc(strerror)(err));
253    {
254        int dimids[NDIMS +1];
255        int ii = 0;
256        for(ii = 0; ii < NDIMS; ii++) dimids[ii] = ii;
257        dimids[NDIMS] = dimid;
258        err = APIFunc(def_var)(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1);
259        IF (err != NC_NOERR)
260            error("def_var: %s", APIFunc(strerror)(err));
261    }
262    err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "title", 1+strlen(title), title);
263    IF (err != NC_NOERR)
264        error("put_att_text: %s", APIFunc(strerror)(err));
265    err = APIFunc(enddef)(ncid);
266    IF (err != NC_NOERR)
267        error("enddef: %s", APIFunc(strerror)(err));
268    ELSE_NOK
269    var = 1.0;
270
271ifdef(`PNETCDF', `
272    err = ncmpi_end_indep_data(ncid);
273    IF (err != NC_ENOTINDEP)
274        error("expecting NC_ENOTINDEP but got %s", nc_err_code_name(err));')dnl
275
276    err = PutVar1TYPE(double)(ncid, varid, NULL, &var);
277    IF (err != NC_NOERR)
278        error("put_var1_double: %s", APIFunc(strerror)(err));
279    err = APIFunc(inq_format)(ncid, &fmt_variant1);
280    IF (err)
281        error("inq_format: %s", APIFunc(strerror)(err));
282    err = APIFunc(close)(ncid);
283    IF (err != NC_NOERR)
284        error("close: %s", APIFunc(strerror)(err));
285
286    /* check scratch file written as expected */
287    Check_File(scratch, numGatts, numVars); /* checks all except "abc" stuff added above */
288
289    IF ((err = FileOpen(scratch, NC_NOWRITE, &ncid)))
290        error("open: %s", APIFunc(strerror)(err));
291    IF ((err = APIFunc(inq_dim)(ncid, dimid, name, &length)))
292        error("inq_dim: %s", APIFunc(strerror)(err));
293    IF (strcmp(name, "abc") != 0)
294        error("Unexpected dim name");
295    IF (length != sizehint)
296        error("Unexpected dim length");
297    IF ((err = GetVar1TYPE(double)(ncid, varid, NULL, &var)))
298        error("get_var1_double: %s", APIFunc(strerror)(err));
299    IF (var != 1.0)
300        error("get_var1_double: unexpected value");
301    IF ((err = APIFunc(close)(ncid)))
302        error("close: %s", APIFunc(strerror)(err));
303
304    /* open scratch file for writing, add another dim, var, att, then check */
305    IF ((err = FileOpen(scratch, NC_WRITE, &ncid)))
306        error("open: %s", APIFunc(strerror)(err));
307    IF ((err = APIFunc(redef)(ncid)))
308        error("redef: %s", APIFunc(strerror)(err));
309    IF ((err = APIFunc(def_dim)(ncid, "def", sizehint, &dimid)))
310        error("def_dim: %s", APIFunc(strerror)(err));
311    IF ((err = APIFunc(def_var)(ncid, "defScalar", NC_INT, 0, NULL, &varid)))
312        error("def_var: %s", APIFunc(strerror)(err));
313    IF ((err = APIFunc(def_var)(ncid, "def", NC_INT, 1, &dimid, &varid1)))
314        error("def_var: %s", APIFunc(strerror)(err));
315    IF ((err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "Credits", 1+strlen("Thanks!"), "Thanks!")))
316        error("put_att_text: %s", APIFunc(strerror)(err));
317    IF ((err = APIFunc(enddef)(ncid)))
318        error("enddef: %s", APIFunc(strerror)(err));
319    var = 2.0;
320    IF ((err = PutVar1TYPE(double)(ncid, varid, NULL, &var)))
321        error("put_var1_double: %s", APIFunc(strerror)(err));
322    IF ((err = APIFunc(close)(ncid)))
323        error("close: %s", APIFunc(strerror)(err));
324
325    /* check scratch file written as expected */
326    Check_File(scratch, numGatts, numVars);
327
328    err = FileOpen(scratch, NC_NOWRITE, &ncid);
329    IF (err)
330        error("open: %s", APIFunc(strerror)(err));
331    err = APIFunc(inq_dim)(ncid, dimid, name, &length);
332    IF (err)
333        error("inq_dim: %s", APIFunc(strerror)(err));
334    IF (strcmp(name, "def") != 0)
335        error("Unexpected dim name");
336    IF (length != sizehint)
337        error("Unexpected dim length");
338    err = GetVar1TYPE(double)(ncid, varid, NULL, &var);
339    IF (err)
340        error("get_var1_double: %s", APIFunc(strerror)(err));
341    IF (var != 2.0)
342        error("get_var1_double: unexpected value");
343    /* make sure format variant hasn't changed from when created */
344    err = APIFunc(inq_format)(ncid, &fmt_variant2);
345    IF (err)
346        error("inq_format: %s", APIFunc(strerror)(err));
347    IF (fmt_variant1 != fmt_variant2)
348        error("enddef changed format variant");
349    err = APIFunc(close)(ncid);
350    IF (err)
351        error("close: %s", APIFunc(strerror)(err));
352
353    err = FileDelete(scratch, info);
354    IF (err != NC_NOERR)
355        error("remove of %s failed", scratch);
356    return nok;
357}
358
359
360/*
361 * Test APIFunc(enddef)
362 * Simply calls TestFunc(redef) which tests both APIFunc(redef) & APIFunc(enddef)
363 */
364int
365TestFunc(enddef)(AttVarArgs)
366{
367    ifdef(`PNETCDF',
368    `return test_ncmpi_redef(numGatts, numVars);',
369    `return test_nc_redef();')
370}
371
372
373/*
374 * Test APIFunc(sync)
375 *    try with bad handle, check error
376 *    try in define mode, check error
377 *    try writing with one handle, reading with another on same netCDF
378 */
379int
380TestFunc(sync)(AttVarArgs)
381{
382    int ncidw;         /* netcdf id for writing */
383    int ncidr;         /* netcdf id for reading */
384    int nok=0, err;
385
386    /* BAD_ID test */
387    err = APIFunc(sync)(BAD_ID);
388    IF (err != NC_EBADID)
389        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
390    ELSE_NOK
391
392    /* create scratch file & try APIFunc(sync) in define mode */
393    err = FileCreate(scratch, NC_NOCLOBBER, &ncidw);
394    IF (err != NC_NOERR) {
395        error("create: %s", APIFunc(strerror)(err));
396        return nok;
397    }
398    err = APIFunc(sync)(ncidw);
399    IF (err != NC_EINDEFINE)
400        error("expecting NC_EINDEFINE but got %s", nc_err_code_name(err));
401    ELSE_NOK
402
403    /* write using same handle */
404    def_dims(ncidw);
405    Def_Vars(ncidw, numVars);
406    Put_Atts(ncidw, numGatts, numVars);
407    err = APIFunc(enddef)(ncidw);
408    IF (err != NC_NOERR)
409        error("enddef: %s", APIFunc(strerror)(err));
410    Put_Vars(ncidw, numVars);
411    err = APIFunc(sync)(ncidw);
412    IF (err != NC_NOERR)
413        error("sync of ncidw failed: %s", APIFunc(strerror)(err));
414    ELSE_NOK
415
416    /* open another handle, APIFunc(sync), read (check) */
417    err = FileOpen(scratch, NC_NOWRITE, &ncidr);
418    IF (err != NC_NOERR)
419        error("open: %s", APIFunc(strerror)(err));
420    err = APIFunc(sync)(ncidr);
421    IF (err != NC_NOERR)
422        error("sync of ncidr failed: %s", APIFunc(strerror)(err));
423    ELSE_NOK
424    check_dims(ncidr);
425    Check_Atts(ncidr, numGatts, numVars);
426    Check_Vars(ncidr, numVars);
427
428    /* close both handles */
429    err = APIFunc(close)(ncidr);
430    IF (err != NC_NOERR)
431        error("close: %s", APIFunc(strerror)(err));
432    err = APIFunc(close)(ncidw);
433    IF (err != NC_NOERR)
434        error("close: %s", APIFunc(strerror)(err));
435
436    err = FileDelete(scratch, info);
437    IF (err != NC_NOERR)
438        error("remove of %s failed", scratch);
439    return nok;
440}
441
442
443/*
444 * Test APIFunc(abort)
445 *    try with bad handle, check error
446 *    try in define mode before anything written, check that file was deleted
447 *    try after APIFunc(enddef), APIFunc(redef), define new dims, vars, atts
448 *    try after writing variable
449 */
450int
451TestFunc(abort)(AttVarArgs)
452{
453    int ncid;          /* netcdf id */
454    int err;
455    int ndims;
456    int nvars;
457    int ngatts;
458    int nok=0;
459
460    /* BAD_ID test */
461    err = APIFunc(abort)(BAD_ID);
462    IF (err != NC_EBADID)
463        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
464    ELSE_NOK
465
466    /* create scratch file & try APIFunc(abort) in define mode */
467    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
468    IF (err != NC_NOERR) {
469        error("create: %s", APIFunc(strerror)(err));
470        return nok;
471    }
472    def_dims(ncid);
473    Def_Vars(ncid, numVars);
474    Put_Atts(ncid, numGatts, numVars);
475    err = APIFunc(abort)(ncid);
476    IF (err != NC_NOERR)
477        error("abort of ncid failed: %s", APIFunc(strerror)(err));
478    ELSE_NOK
479    err = APIFunc(close)(ncid);        /* should already be closed */
480    IF (err != NC_EBADID)
481        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
482    err = FileDelete(scratch, info);        /* should already be deleted */
483ifdef(`PNETCDF',
484    `IF (err != NC_ENOENT && err != NC_EFILE)
485        error("expecting NC_ENOENT or NC_EFILE but got %s", nc_err_code_name(err));',
486    `IF (err != ENOENT && err != NC_EIO)
487        error("expecting ENOENT or NC_EIO but got %s", nc_err_code_name(err));')dnl
488
489    /*
490     * create scratch file
491     * do APIFunc(enddef) & APIFunc(redef)
492     * define new dims, vars, atts
493     * try APIFunc(abort): should restore previous state (no dims, vars, atts)
494     */
495    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
496    IF (err != NC_NOERR) {
497        error("create: %s", APIFunc(strerror)(err));
498        return nok;
499    }
500    err = APIFunc(enddef)(ncid);
501    IF (err != NC_NOERR)
502        error("enddef: %s", APIFunc(strerror)(err));
503    err = APIFunc(redef)(ncid);
504    IF (err != NC_NOERR)
505        error("redef: %s", APIFunc(strerror)(err));
506    def_dims(ncid);
507    Def_Vars(ncid, numVars);
508    Put_Atts(ncid, numGatts, numVars);
509    err = APIFunc(abort)(ncid);
510    IF (err != NC_NOERR)
511        error("abort of ncid failed: %s", APIFunc(strerror)(err));
512    ELSE_NOK
513    err = APIFunc(close)(ncid);        /* should already be closed */
514    IF (err != NC_EBADID)
515        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
516    err = FileOpen(scratch, NC_NOWRITE, &ncid);
517    IF (err != NC_NOERR)
518        error("open: %s", APIFunc(strerror)(err));
519    err = APIFunc(inq)(ncid, &ndims, &nvars, &ngatts, NULL);
520    IF (err != NC_NOERR)
521        error("inq: %s", APIFunc(strerror)(err));
522    IF (ndims != 0)
523        error("ndims should be 0");
524    IF (nvars != 0)
525        error("nvars should be 0");
526    IF (ngatts != 0)
527        error("ngatts should be 0");
528    err = APIFunc(close)(ncid);
529    IF (err != NC_NOERR)
530        error("close: %s", APIFunc(strerror)(err));
531
532    /* try APIFunc(abort) in data mode - should just close */
533    err = FileCreate(scratch, NC_CLOBBER, &ncid);
534    IF (err != NC_NOERR) {
535        error("create: %s", APIFunc(strerror)(err));
536        return nok;
537    }
538    def_dims(ncid);
539    Def_Vars(ncid, numVars);
540    Put_Atts(ncid, numGatts, numVars);
541    err = APIFunc(enddef)(ncid);
542    IF (err != NC_NOERR)
543        error("enddef: %s", APIFunc(strerror)(err));
544    Put_Vars(ncid, numVars);
545    err = APIFunc(abort)(ncid);
546    IF (err != NC_NOERR)
547        error("abort of ncid failed: %s", APIFunc(strerror)(err));
548    ELSE_NOK
549    err = APIFunc(close)(ncid);       /* should already be closed */
550    IF (err != NC_EBADID)
551        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
552    Check_File(scratch, numGatts, numVars);
553    err = FileDelete(scratch, info);
554    IF (err != NC_NOERR)
555        error("remove of %s failed", scratch);
556    return nok;
557}
558
559
560/*
561 * Test APIFunc(def_dim)
562 *    try with bad netCDF handle, check error
563 *    try in data mode, check error
564 *    check that returned id is one more than previous id
565 *    try adding same dimension twice, check error
566 *    try with illegal sizes, check error
567 *    make sure unlimited size works, shows up in APIFunc(inq_unlimdim)
568 *    try to define a second unlimited dimension, check error
569 */
570int
571TestFunc(def_dim)(VarArgs)
572{
573    int ncid;
574    int  err;           /* status */
575    int  i, nok=0;
576    int  dimid;         /* dimension id */
577    IntType length;
578
579    /* BAD_ID test */
580    err = APIFunc(def_dim)(BAD_ID, "abc", 8, &dimid);
581    IF (err != NC_EBADID)
582        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
583    ELSE_NOK
584
585    /* data mode test */
586    err = FileCreate(scratch, NC_CLOBBER, &ncid);
587    IF (err != NC_NOERR) {
588        error("create: %s", APIFunc(strerror)(err));
589        return nok;
590    }
591    err = APIFunc(enddef)(ncid);
592    IF (err != NC_NOERR)
593        error("enddef: %s", APIFunc(strerror)(err));
594    err = APIFunc(def_dim)(ncid, "abc", 8, &dimid);
595    IF (err != NC_ENOTINDEFINE)
596        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
597    ELSE_NOK
598
599    /* define-mode tests: unlimited dim */
600    err = APIFunc(redef)(ncid);
601    IF (err != NC_NOERR)
602        error("redef: %s", APIFunc(strerror)(err));
603    err = APIFunc(def_dim)(ncid, dim_name[0], NC_UNLIMITED, &dimid);
604    IF (err != NC_NOERR)
605        error("def_dim: %s", APIFunc(strerror)(err));
606    ELSE_NOK
607    IF (dimid != 0)
608        error("Unexpected dimid");
609    ELSE_NOK
610    err = APIFunc(inq_unlimdim)(ncid, &dimid);
611    IF (err != NC_NOERR)
612        error("inq_unlimdim: %s", APIFunc(strerror)(err));
613    IF (dimid != 0)
614        error("Unexpected recdim");
615    err = APIFunc(inq_dimlen)(ncid, dimid, &length);
616    IF (length != 0)
617        error("Unexpected length");
618    err = APIFunc(def_dim)(ncid, "abc", NC_UNLIMITED, &dimid);
619    IF (err != NC_EUNLIMIT)
620        error("expecting NC_EUNLIMIT but got %s", nc_err_code_name(err));
621    ELSE_NOK
622
623    /* define-mode tests: remaining dims */
624    for (i = 1; i < NDIMS; i++) {
625        err = APIFunc(def_dim)(ncid, dim_name[i-1], dim_len[i], &dimid);
626        IF (err != NC_ENAMEINUSE)
627            error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
628        ELSE_NOK
629        err = APIFunc(def_dim)(ncid, BAD_NAME, dim_len[i], &dimid);
630        IF (err != NC_EBADNAME)
631            error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
632        ELSE_NOK
633ifdef(`PNETCDF', ,`if(sizeof(long) > 4) /* Fix: dmh 11/4/2011: works only if sizeof(long) > 4 */')
634        {
635            err = APIFunc(def_dim)(ncid, dim_name[i], (IntType)(NC_UNLIMITED-1), &dimid);
636            IF (err != NC_EDIMSIZE)
637                error("expecting NC_EDIMSIZE but got %s", nc_err_code_name(err));
638            ELSE_NOK
639        }
640        err = APIFunc(def_dim)(ncid, dim_name[i], dim_len[i], &dimid);
641        IF (err != NC_NOERR)
642            error("def_dim: %s", APIFunc(strerror)(err));
643        ELSE_NOK
644        IF (dimid != i)
645            error("Unexpected dimid");
646    }
647
648    /* Following just to expand unlimited dim */
649    Def_Vars(ncid, numVars);
650    err = APIFunc(enddef)(ncid);
651    IF (err != NC_NOERR)
652        error("enddef: %s", APIFunc(strerror)(err));
653    Put_Vars(ncid, numVars);
654
655    /* Check all dims */
656    check_dims(ncid);
657
658    err = APIFunc(close)(ncid);
659    IF (err != NC_NOERR)
660        error("close: %s", APIFunc(strerror)(err));
661    err = FileDelete(scratch, info);
662    IF (err != NC_NOERR)
663        error("remove of %s failed", scratch);
664    return nok;
665}
666
667
668/*
669 * Test APIFunc(rename_dim)
670 *    try with bad netCDF handle, check error
671 *    check that proper rename worked with APIFunc(inq_dim)
672 *    try renaming to existing dimension name, check error
673 *    try with bad dimension handle, check error
674 */
675int
676TestFunc(rename_dim)(void)
677{
678    int ncid;
679    int  err, nok=0;             /* status */
680    char name[NC_MAX_NAME];
681
682    /* BAD_ID test */
683    err = APIFunc(rename_dim)(BAD_ID, 0, "abc");
684    IF (err != NC_EBADID)
685        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
686    ELSE_NOK
687
688    /* main tests */
689    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
690    IF (err != NC_NOERR) {
691        error("create: %s", APIFunc(strerror)(err));
692        return nok;
693    }
694    def_dims(ncid);
695    err = APIFunc(rename_dim)(ncid, BAD_DIMID, "abc");
696    IF (err != NC_EBADDIM)
697        error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
698    ELSE_NOK
699    err = APIFunc(rename_dim)(ncid, 2, "abc");
700    IF (err != NC_NOERR)
701        error("rename_dim: %s", APIFunc(strerror)(err));
702    ELSE_NOK
703    err = APIFunc(inq_dimname)(ncid, 2, name);
704    IF (strcmp(name, "abc") != 0)
705        error("Unexpected name: %s", name);
706    err = APIFunc(rename_dim)(ncid, 0, "abc");
707    IF (err != NC_ENAMEINUSE)
708        error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
709    ELSE_NOK
710
711    err = APIFunc(close)(ncid);
712    IF (err != NC_NOERR)
713        error("close: %s", APIFunc(strerror)(err));
714    err = FileDelete(scratch, info);
715    IF (err != NC_NOERR)
716        error("remove of %s failed", scratch);
717    return nok;
718}
719
720
721/*
722 * Test APIFunc(def_var)
723 *    try with bad netCDF handle, check error
724 *    try with bad name, check error
725 *    scalar tests:
726 *      check that proper define worked with APIFunc(inq_var)
727 *      try redefining an existing variable, check error
728 *      try with bad datatype, check error
729 *      try with bad number of dimensions, check error
730 *      try in data mode, check error
731 *    check that returned id is one more than previous id
732 *    try with bad dimension ids, check error
733 */
734int
735TestFunc(def_var)(VarArgs)
736{
737    int  ncid;
738    int  varid;
739    int  err, nok=0;             /* status */
740    int  i;
741    int  ndims;
742    int  natts;
743    char name[NC_MAX_NAME];
744    int dimids[MAX_RANK];
745    nc_type datatype;
746
747    /* BAD_ID test */
748    err = APIFunc(def_var)(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid);
749    IF (err != NC_EBADID)
750        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
751    ELSE_NOK
752
753    /* scalar tests */
754    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
755    IF (err != NC_NOERR) {
756        error("create: %s", APIFunc(strerror)(err));
757        return nok;
758    }
759    err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 0, NULL, &varid);
760    IF (err != NC_NOERR)
761        error("def_var: %s", APIFunc(strerror)(err));
762    ELSE_NOK
763    err = APIFunc(inq_var)(ncid, varid, name, &datatype, &ndims, dimids, &natts);
764    IF (err != NC_NOERR)
765        error("inq_var: %s", APIFunc(strerror)(err));
766    IF (strcmp(name, "abc") != 0)
767        error("Unexpected name: %s", name);
768    IF (datatype != NC_SHORT)
769        error("Unexpected datatype");
770    IF (ndims != 0)
771        error("Unexpected rank");
772    err = APIFunc(def_var)(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid);
773    IF (err != NC_EBADNAME)
774        error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
775    ELSE_NOK
776    err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 0, NULL, &varid);
777    IF (err != NC_ENAMEINUSE)
778        error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
779    ELSE_NOK
780    err = APIFunc(def_var)(ncid, "ABC", BAD_TYPE, -1, dimids, &varid);
781    IF (err != NC_EBADTYPE)
782        error("expecting NC_EBADTYPE but got %s", nc_err_code_name(err));
783    ELSE_NOK
784    err = APIFunc(def_var)(ncid, "ABC", NC_SHORT, -1, dimids, &varid);
785    IF (err != NC_EINVAL)
786        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
787    ELSE_NOK
788    err = APIFunc(enddef)(ncid);
789    IF (err != NC_NOERR)
790        error("enddef: %s", APIFunc(strerror)(err));
791    err = APIFunc(def_var)(ncid, "ABC", NC_SHORT, 0, dimids, &varid);
792    IF (err != NC_ENOTINDEFINE)
793        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
794    ELSE_NOK
795    err = APIFunc(close)(ncid);
796    IF (err != NC_NOERR)
797        error("close: %s", APIFunc(strerror)(err));
798    err = FileDelete(scratch, info);
799    IF (err != NC_NOERR)
800        error("remove of %s failed", scratch);
801
802    /* general tests using global vars */
803    err = FileCreate(scratch, NC_CLOBBER, &ncid);
804    IF (err != NC_NOERR) {
805        error("create: %s", APIFunc(strerror)(err));
806        return nok;
807    }
808    def_dims(ncid);
809    for (i = 0; i < numVars; i++) {
810        err = APIFunc(def_var)(ncid, var_name[i], var_type[i], var_rank[i],
811            var_dimid[i], &varid);
812        IF (err != NC_NOERR)
813            error("def_var: %s", APIFunc(strerror)(err));
814        ELSE_NOK
815        IF (varid != i)
816            error("Unexpected varid");
817        ELSE_NOK
818    }
819
820    /* try bad dim ids */
821    dimids[0] = BAD_DIMID;
822    err = APIFunc(def_var)(ncid, "abc", NC_SHORT, 1, dimids, &varid);
823    IF (err != NC_EBADDIM)
824        error("expecting NC_EBADDIM but got %s", nc_err_code_name(err));
825    ELSE_NOK
826    err = APIFunc(close)(ncid);
827    IF (err != NC_NOERR)
828        error("close: %s", APIFunc(strerror)(err));
829
830    err = FileDelete(scratch, info);
831    IF (err != NC_NOERR)
832        error("remove of %s failed", scratch);
833    return nok;
834}
835
836
837/*
838 * Test PutVar1
839 */
840int
841TestFunc(put_var1)(VarArgs)
842{
843    int i, err, ncid, nok=0;
844    IntType j, index[MAX_RANK];
845    double value[1];
846    double buf[1];                /* (void *) buffer */
847    ifdef(`PNETCDF', `MPI_Datatype datatype;')
848
849    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
850    IF (err != NC_NOERR) {
851        error("create: %s", APIFunc(strerror)(err));
852        return nok;
853    }
854
855    def_dims(ncid);
856    Def_Vars(ncid, numVars);
857
858    err = APIFunc(enddef)(ncid);
859    IF (err != NC_NOERR)
860        error("enddef: %s", APIFunc(strerror)(err));
861
862    /* check if can detect a bad file ID */
863    err = PutVar1(BAD_ID, 0, NULL, NULL, 1, MPI_DATATYPE_NULL);
864    IF (err != NC_EBADID)
865        EXPECT_ERR(NC_EBADID, err)
866    ELSE_NOK
867
868    /* check if can detect a bad variable ID */
869    err = PutVar1(ncid, BAD_VARID, NULL, NULL, 1, MPI_DATATYPE_NULL);
870    IF (err != NC_ENOTVAR)
871        EXPECT_ERR(NC_ENOTVAR, err)
872    ELSE_NOK
873
874    for (i = 0; i < numVars; i++) {
875        assert(var_rank[i] <= MAX_RANK);
876        assert(var_nels[i] <= MAX_NELS);
877
878        value[0] = 5;  /* reset to a value within bounds */
879
880        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
881
882ifdef(`PNETCDF',`dnl
883        /* for non-scalar variables, argument start cannot be NULL */
884        err = PutVar1(ncid, i, NULL, value, 1, datatype);
885        if (var_rank[i] == 0) { /* scalar variable */
886            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
887        }
888        else IF (err != NC_EINVALCOORDS) {
889            EXPECT_ERR(NC_EINVALCOORDS, err)
890        }
891        ELSE_NOK
892')dnl
893
894        /* test NC_EINVALCOORDS */
895        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
896
897        for (j = 0; j < var_rank[i]; j++) {
898            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
899            index[j] = var_shape[i][j]; /* out of boundary check */
900            err = PutVar1(ncid, i, index, value, 1, datatype);
901            IF (err != NC_EINVALCOORDS)
902                EXPECT_ERR(NC_EINVALCOORDS, err)
903            ELSE_NOK
904            index[j] = 0;
905        }
906
907        for (j = 0; j < var_nels[i]; j++) {
908            err = toMixedBase(j, var_rank[i], var_shape[i], index);
909            IF (err != 0) error("error in toMixedBase");
910            value[0] = hash(var_type[i], var_rank[i], index);
911            if (inRange(value[0], var_type[i])) {
912                err = dbl2nc(value[0], var_type[i], buf);
913                IF (err != NC_NOERR)
914                    error("error in dbl2nc var:%s type:%s",
915                          var_name[i],s_nc_type(var_type[i]));
916                err = PutVar1(ncid, i, index, buf, 1, datatype);
917                IF (err != NC_NOERR)
918                    EXPECT_ERR(NC_NOERR, err)
919                ELSE_NOK
920            }
921        }
922    }
923
924    Check_Vars(ncid, numVars);
925    err = APIFunc(close)(ncid);
926    IF (err != NC_NOERR)
927        error("close: %s", APIFunc(strerror)(err));
928
929    err = FileDelete(scratch, info);
930    IF (err != NC_NOERR)
931        error("remove of %s failed", scratch);
932    return nok;
933}
934
935
936/*
937 * Test PutVara
938 * Choose a random point dividing each dim into 2 parts
939 * Put 2^rank (nslabs) slabs so defined
940 * Redefine buffer for each put.
941 * At end check all variables using Check_Vars
942 */
943int
944TestFunc(put_vara)(VarArgs)
945{
946    int d, i, k, err, nslabs, ncid, nok=0;
947    IntType j, nels;
948    IntType start[MAX_RANK];
949    IntType edge[MAX_RANK];
950    IntType index[MAX_RANK];
951    IntType mid[MAX_RANK];
952    double buf[MAX_NELS];         /* (void *) buffer */
953    char *p;                      /* (void *) pointer */
954    double value;
955    ifdef(`PNETCDF', `MPI_Datatype datatype;')
956
957    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
958    IF (err != NC_NOERR) {
959        error("create: %s", APIFunc(strerror)(err));
960        return nok;
961    }
962
963    def_dims(ncid);
964    Def_Vars(ncid, numVars);
965
966    err = APIFunc(enddef)(ncid);
967    IF (err != NC_NOERR)
968        error("enddef: %s", APIFunc(strerror)(err));
969
970    /* check if can detect a bad file ID */
971    err = PutVara(BAD_ID, 0, start, edge, buf, 1, MPI_DATATYPE_NULL);
972    IF (err != NC_EBADID)
973        EXPECT_ERR(NC_EBADID, err)
974    ELSE_NOK
975
976    /* check if can detect a bad variable ID */
977    err = PutVara(ncid, BAD_VARID, start, edge, buf, 1, MPI_DATATYPE_NULL);
978    IF (err != NC_ENOTVAR)
979        EXPECT_ERR(NC_ENOTVAR, err)
980    ELSE_NOK
981
982    for (i = 0; i < numVars; i++) {
983        assert(var_rank[i] <= MAX_RANK);
984        assert(var_nels[i] <= MAX_NELS);
985
986        buf[0] = 5;  /* reset to a value within bounds */
987
988        /* check if can detect a bad file ID */
989        err = PutVara(BAD_ID, i, start, edge, buf, 1, MPI_DATATYPE_NULL);
990        IF (err != NC_EBADID)
991            EXPECT_ERR(NC_EBADID, err)
992        ELSE_NOK
993
994        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
995
996        for (j = 0; j < var_rank[i]; j++) {
997            start[j] = 0;
998            edge[j] = 1;
999        }
1000
1001ifdef(`PNETCDF',`dnl
1002        /* for non-scalar variables, argument start cannot be NULL */
1003        err = PutVara(ncid, i, NULL, NULL, buf, 1, datatype);
1004        if (var_rank[i] == 0) { /* scalar variable */
1005            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1006        }
1007        else IF (err != NC_EINVALCOORDS) {
1008            EXPECT_ERR(NC_EINVALCOORDS, err)
1009        }
1010        ELSE_NOK
1011
1012        /* for non-scalar variables, argument count cannot be NULL */
1013        err = PutVara(ncid, i, start, NULL, buf, 1, datatype);
1014        if (var_rank[i] == 0) {
1015            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1016        }
1017        else IF (err != NC_EEDGE) {
1018            EXPECT_ERR(NC_EEDGE, err)
1019        }
1020        ELSE_NOK
1021')dnl
1022
1023        /* first test when edge[*] > 0 */
1024        for (j = 0; j < var_rank[i]; j++) {
1025            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
1026            start[j] = var_shape[i][j];
1027            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
1028            IF (err != NC_EINVALCOORDS)
1029                EXPECT_ERR(NC_EINVALCOORDS, err)
1030            ELSE_NOK
1031            start[j] = 0;
1032            edge[j] = var_shape[i][j] + 1;
1033            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
1034            IF (err != NC_EEDGE)
1035                EXPECT_ERR(NC_EEDG, err)
1036            ELSE_NOK
1037            edge[j] = 1;
1038        }
1039        /* Check correct error returned when nothing to put, when edge[*]==0 */
1040        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
1041
1042        for (j = 0; j < var_rank[i]; j++) {
1043            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
1044            start[j] = var_shape[i][j];
1045            err = PutVara(ncid, i, start, edge, buf, 0, datatype);
1046#ifdef RELAX_COORD_BOUND
1047            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
1048                EXPECT_ERR(NC_NOERR, err)
1049#else
1050            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
1051                EXPECT_ERR(NC_EINVALCOORDS, err)
1052#endif
1053            ELSE_NOK
1054            start[j] = var_shape[i][j]+1; /* out of boundary check */
1055            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
1056            IF (err != NC_EINVALCOORDS)
1057                EXPECT_ERR(NC_EINVALCOORDS, err)
1058            ELSE_NOK
1059            start[j] = 0;
1060        }
1061        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
1062
1063        /* Choose a random point dividing each dim into 2 parts */
1064        /* put 2^rank (nslabs) slabs so defined */
1065        nslabs = 1;
1066        for (j = 0; j < var_rank[i]; j++) {
1067            mid[j] = roll( var_shape[i][j] );
1068            nslabs *= 2;
1069        }
1070        /* bits of k determine whether to put lower or upper part of dim */
1071        for (k = 0; k < nslabs; k++) {
1072            nels = 1;
1073            for (j = 0; j < var_rank[i]; j++) {
1074                if ((k >> j) & 1) {
1075                    start[j] = 0;
1076                    edge[j] = mid[j];
1077                }else{
1078                    start[j] = mid[j];
1079                    edge[j] = var_shape[i][j] - mid[j];
1080                }
1081                nels *= edge[j];
1082            }
1083            p = (char *) buf;
1084            for (j = 0; j < nels; j++) {
1085                err = toMixedBase(j, var_rank[i], edge, index);
1086                IF (err != 0) error("error in toMixedBase");
1087                for (d = 0; d < var_rank[i]; d++)
1088                    index[d] += start[d];
1089                value = hash(var_type[i], var_rank[i], index);
1090                if (!inRange(value, var_type[i]))
1091                    value = 0;
1092                err = dbl2nc(value, var_type[i], p);
1093                IF (err != NC_NOERR)
1094                    error("error in dbl2nc");
1095                p += nctypelen(var_type[i]);
1096            }
1097            err = PutVara(ncid, i, start, edge, buf, nels, datatype);
1098            IF (err != NC_NOERR)
1099                error("%s", APIFunc(strerror)(err));
1100            ELSE_NOK
1101        }
1102    }
1103
1104    Check_Vars(ncid, numVars);
1105    err = APIFunc(close)(ncid);
1106    IF (err != NC_NOERR)
1107        error("close: %s", APIFunc(strerror)(err));
1108
1109    err = FileDelete(scratch, info);
1110    IF (err != NC_NOERR)
1111        error("remove of %s failed", scratch);
1112    return nok;
1113}
1114
1115
1116/*
1117 * Test PutVars
1118 * Choose a random point dividing each dim into 2 parts
1119 * Put 2^rank (nslabs) slabs so defined
1120 * Choose random stride from 1 to edge
1121 * Redefine buffer for each put.
1122 * At end check all variables using Check_Vars
1123 */
1124int
1125TestFunc(put_vars)(VarArgs)
1126{
1127    int ncid, d, i, k, err, nslabs, nok=0;
1128    PTRDType nstarts;        /* number of different starts */
1129    IntType j, m, nels;
1130    IntType start[MAX_RANK];
1131    IntType edge[MAX_RANK];
1132    IntType index[MAX_RANK];
1133    IntType index2[MAX_RANK];
1134    IntType mid[MAX_RANK];
1135    IntType count[MAX_RANK];
1136    IntType sstride[MAX_RANK];
1137    PTRDType stride[MAX_RANK];
1138    double buf[MAX_NELS]; /* (void *) buffer */
1139    char *p;              /* (void *) pointer */
1140    double value;
1141    ifdef(`PNETCDF', `MPI_Datatype datatype;')
1142
1143    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1144    IF (err != NC_NOERR) {
1145        error("create: %s", APIFunc(strerror)(err));
1146        return nok;
1147    }
1148
1149    def_dims(ncid);
1150    Def_Vars(ncid, numVars);
1151
1152    err = APIFunc(enddef)(ncid);
1153    IF (err != NC_NOERR)
1154        error("enddef: %s", APIFunc(strerror)(err));
1155
1156    /* check if can detect a bad file ID */
1157    err = PutVars(BAD_ID, 0, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1158    IF (err != NC_EBADID)
1159        EXPECT_ERR(NC_EBADID, err)
1160    ELSE_NOK
1161
1162    /* check if can detect a bad variable ID */
1163    err = PutVars(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1164    IF (err != NC_ENOTVAR)
1165        EXPECT_ERR(NC_ENOTVAR, err)
1166    ELSE_NOK
1167
1168    for (i = 0; i < numVars; i++) {
1169        assert(var_rank[i] <= MAX_RANK);
1170        assert(var_nels[i] <= MAX_NELS);
1171
1172        buf[0] = 5;  /* reset to a value within bounds */
1173
1174        /* check if can detect a bad file ID */
1175        err = PutVars(BAD_ID, i, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
1176        IF (err != NC_EBADID)
1177            EXPECT_ERR(NC_EBADID, err)
1178        ELSE_NOK
1179
1180        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
1181
1182        for (j = 0; j < var_rank[i]; j++) {
1183            start[j] = 0;
1184            edge[j] = 1;
1185            stride[j] = 1;
1186        }
1187
1188ifdef(`PNETCDF',`dnl
1189        /* for non-scalar variables, argument start cannot be NULL */
1190        err = PutVars(ncid, i, NULL, NULL, NULL, buf, 1, datatype);
1191        if (var_rank[i] == 0) { /* scalar variable */
1192            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1193        }
1194        else IF (err != NC_EINVALCOORDS) {
1195            EXPECT_ERR(NC_EINVALCOORDS, err)
1196        }
1197        ELSE_NOK
1198
1199        /* for non-scalar variables, argument count cannot be NULL */
1200        err = PutVars(ncid, i, start, NULL, NULL, buf, 1, datatype);
1201        if (var_rank[i] == 0) {
1202            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1203        }
1204        else IF (err != NC_EEDGE) {
1205            EXPECT_ERR(NC_EEDGE, err)
1206        }
1207        ELSE_NOK
1208')dnl
1209
1210        /* first test when edge[*] > 0 */
1211        for (j = 0; j < var_rank[i]; j++) {
1212            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1213            start[j] = var_shape[i][j];
1214            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1215            IF (err != NC_EINVALCOORDS)
1216                EXPECT_ERR(NC_EINVALCOORDS, err)
1217            ELSE_NOK
1218            start[j] = 0;
1219            edge[j] = var_shape[i][j] + 1;  /* edge error check */
1220            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1221            IF (err != NC_EEDGE)
1222                EXPECT_ERR(NC_EEDG, err)
1223            ELSE_NOK
1224            edge[j] = 1;
1225            stride[j] = 0;  /* strided edge error check */
1226            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1227            IF (err != NC_ESTRIDE)
1228                EXPECT_ERR(NC_ESTRIDE, err)
1229            ELSE_NOK
1230            stride[j] = 1;
1231        }
1232        /* Check correct error returned even when nothing to put */
1233        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
1234
1235        for (j = 0; j < var_rank[i]; j++) {
1236            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1237            start[j] = var_shape[i][j];
1238            err = PutVars(ncid, i, start, edge, stride, buf, 0, datatype);
1239#ifdef RELAX_COORD_BOUND
1240            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
1241                EXPECT_ERR(NC_NOERR, err)
1242#else
1243            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
1244                EXPECT_ERR(NC_EINVALCOORDS, err)
1245#endif
1246            ELSE_NOK
1247            start[j] = var_shape[i][j]+1; /* out of boundary check */
1248            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1249            IF (err != NC_EINVALCOORDS)
1250                EXPECT_ERR(NC_EINVALCOORDS, err)
1251            ELSE_NOK
1252            start[j] = 0;
1253        }
1254        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
1255
1256        /* Choose a random point dividing each dim into 2 parts */
1257        /* put 2^rank (nslabs) slabs so defined */
1258        nslabs = 1;
1259        for (j = 0; j < var_rank[i]; j++) {
1260            mid[j] = roll( var_shape[i][j] );
1261            nslabs *= 2;
1262        }
1263        /* bits of k determine whether to put lower or upper part of dim */
1264        /* choose random stride from 1 to edge */
1265        for (k = 0; k < nslabs; k++) {
1266            nstarts = 1;
1267            for (j = 0; j < var_rank[i]; j++) {
1268                if ((k >> j) & 1) {
1269                    start[j] = 0;
1270                    edge[j] = mid[j];
1271                }else{
1272                    start[j] = mid[j];
1273                    edge[j] = var_shape[i][j] - mid[j];
1274                }
1275                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
1276                stride[j] = (PTRDType)sstride[j];
1277                nstarts *= stride[j];
1278            }
1279            for (m = 0; m < nstarts; m++) {
1280                err = toMixedBase(m, var_rank[i], sstride, index);
1281                IF (err != 0) error("error in toMixedBase");
1282                nels = 1;
1283                for (j = 0; j < var_rank[i]; j++) {
1284                    count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
1285                    nels *= count[j];
1286                    index[j] += start[j];
1287                }
1288                /* Random choice of forward or backward */
1289/* TODO
1290                if ( roll(2) ) {
1291                    for (j = 0; j < var_rank[i]; j++) {
1292                        index[j] += (count[j] - 1) * (IntType)stride[j];
1293                        stride[j] = -stride[j];
1294                    }
1295                }
1296 */
1297                p = (char *) buf;
1298                for (j = 0; j < nels; j++) {
1299                    err = toMixedBase(j, var_rank[i], count, index2);
1300                    IF (err != 0) error("error in toMixedBase");
1301                    for (d = 0; d < var_rank[i]; d++)
1302                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
1303                    value = hash(var_type[i], var_rank[i], index2);
1304                    if (!inRange(value, var_type[i]))
1305                        value = 0;
1306                    err = dbl2nc(value, var_type[i], p);
1307                    IF (err != NC_NOERR)
1308                        error("error in dbl2nc");
1309                    p += nctypelen(var_type[i]);
1310                }
1311                err = PutVars(ncid, i, index, count, stride, buf, nels, datatype);
1312                IF (err != NC_NOERR)
1313                    EXPECT_ERR(NC_NOERR, err)
1314                ELSE_NOK
1315            }
1316        }
1317    }
1318
1319    Check_Vars(ncid, numVars);
1320    err = APIFunc(close)(ncid);
1321    IF (err != NC_NOERR)
1322        error("close: %s", APIFunc(strerror)(err));
1323
1324    err = FileDelete(scratch, info);
1325    IF (err != NC_NOERR)
1326        error("remove of %s failed", scratch);
1327    return nok;
1328}
1329
1330
1331/*
1332 * Test PutVarm
1333 * Choose a random point dividing each dim into 2 parts
1334 * Put 2^rank (nslabs) slabs so defined
1335 * Choose random stride from 1 to edge
1336 * Buffer is bit image of whole external variable.
1337 * So all puts for a variable put different elements of buffer
1338 * At end check all variables using Check_Vars
1339 */
1340int
1341TestFunc(put_varm)(VarArgs)
1342{
1343    int ncid, nok=0;
1344    int i;
1345    int k;
1346    int err;
1347    int nslabs;
1348    IntType j, m;
1349    PTRDType nstarts;        /* number of different starts */
1350    IntType start[MAX_RANK];
1351    IntType edge[MAX_RANK];
1352    IntType index[MAX_RANK];
1353    IntType mid[MAX_RANK];
1354    IntType count[MAX_RANK];
1355    IntType sstride[MAX_RANK];
1356    PTRDType stride[MAX_RANK];
1357    PTRDType imap[MAX_RANK];
1358    PTRDType imap2[MAX_RANK];
1359    ifdef(`PNETCDF', `IntType bufcount;')
1360    double buf[MAX_NELS];       /* (void *) buffer */
1361    char *p;                    /* (void *) pointer */
1362    double value;
1363    ifdef(`PNETCDF', `MPI_Datatype datatype;')
1364
1365    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1366    IF (err != NC_NOERR) {
1367        error("create: %s", APIFunc(strerror)(err));
1368        return nok;
1369    }
1370
1371    def_dims(ncid);
1372    Def_Vars(ncid, numVars);
1373
1374    err = APIFunc(enddef)(ncid);
1375    IF (err != NC_NOERR)
1376        error("enddef: %s", APIFunc(strerror)(err));
1377
1378    /* check if can detect a bad file ID */
1379    err = PutVarm(NC_EBADID, 0, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1380    IF (err != NC_EBADID)
1381        EXPECT_ERR(NC_EBADID, err)
1382    ELSE_NOK
1383
1384    /* check if can detect a bad variable ID */
1385    err = PutVarm(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1386    IF (err != NC_ENOTVAR)
1387        EXPECT_ERR(NC_ENOTVAR, err)
1388    ELSE_NOK
1389
1390    for (i = 0; i < numVars; i++) {
1391        assert(var_rank[i] <= MAX_RANK);
1392        assert(var_nels[i] <= MAX_NELS);
1393
1394        buf[0] = 5;  /* reset to a value within bounds */
1395
1396        /* check if can detect a bad file ID */
1397        err = PutVarm(BAD_ID, i, NULL, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
1398        IF (err != NC_EBADID)
1399            EXPECT_ERR(NC_EBADID, err)
1400        ELSE_NOK
1401
1402        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
1403
1404        for (j = 0; j < var_rank[i]; j++) {
1405            start[j] = 0;
1406            edge[j] = 1;
1407            stride[j] = 1;
1408            imap[j] = 1;
1409        }
1410
1411ifdef(`PNETCDF',`dnl
1412        /* for non-scalar variables, argument start cannot be NULL */
1413        err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
1414        if (var_rank[i] == 0) { /* scalar variable */
1415            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1416        }
1417        else IF (err != NC_EINVALCOORDS) {
1418            EXPECT_ERR(NC_EINVALCOORDS, err)
1419        }
1420        ELSE_NOK
1421
1422        /* for non-scalar variables, argument count cannot be NULL */
1423        err = PutVarm(ncid, i, start, NULL, NULL, NULL, buf, 1, datatype);
1424        if (var_rank[i] == 0) {
1425            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1426        }
1427        else IF (err != NC_EEDGE) {
1428            EXPECT_ERR(NC_EEDGE, err)
1429        }
1430        ELSE_NOK
1431')dnl
1432
1433        /* first test when edge[*] > 0 */
1434        for (j = 0; j < var_rank[i]; j++) {
1435            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1436            start[j] = var_shape[i][j];
1437            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1438            IF (err != NC_EINVALCOORDS)
1439                EXPECT_ERR(NC_EINVALCOORDS, err)
1440            ELSE_NOK
1441            start[j] = 0;
1442            edge[j] = var_shape[i][j] + 1;  /* edge error check */
1443            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1444            IF (err != NC_EEDGE)
1445                EXPECT_ERR(NC_EEDG, err)
1446            ELSE_NOK
1447            edge[j] = 1;
1448            stride[j] = 0;  /* strided edge error check */
1449            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1450            IF (err != NC_ESTRIDE)
1451                EXPECT_ERR(NC_ESTRIDE, err)
1452            ELSE_NOK
1453            stride[j] = 1;
1454        }
1455        /* Check correct error returned even when nothing to put */
1456        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
1457
1458        for (j = 0; j < var_rank[i]; j++) {
1459            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1460            start[j] = var_shape[i][j];
1461            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 0, datatype);
1462#ifdef RELAX_COORD_BOUND
1463            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
1464                EXPECT_ERR(NC_NOERR, err)
1465#else
1466            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
1467                EXPECT_ERR(NC_EINVALCOORDS, err)
1468#endif
1469            ELSE_NOK
1470            start[j] = var_shape[i][j]+1; /* out of boundary check */
1471            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1472            IF (err != NC_EINVALCOORDS)
1473                EXPECT_ERR(NC_EINVALCOORDS, err)
1474            ELSE_NOK
1475            start[j] = 0;
1476        }
1477        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
1478
1479        if (var_rank[i] > 0) {
1480            int jj = var_rank[i] - 1;
1481            imap[jj] = nctypelen(var_type[i]); /*  netCDF considers imap in bytes */
1482            imap[jj] = 1;                      /* PnetCDF considers imap in elements */
1483            for (; jj > 0; jj--)
1484                imap[jj-1] = imap[jj] * (PTRDType)var_shape[i][jj];
1485        }
1486        p = (char *) buf;
1487        for (j = 0; j < var_nels[i]; j++) {
1488            err = toMixedBase(j, var_rank[i], var_shape[i], index);
1489            IF (err != 0) error("error in toMixedBase");
1490            value = hash(var_type[i], var_rank[i], index);
1491            if (!inRange(value, var_type[i]))
1492                value = 0;
1493            err = dbl2nc(value, var_type[i], p);
1494            IF (err != NC_NOERR)
1495                error("error in dbl2nc");
1496            p += nctypelen(var_type[i]);
1497        }
1498
1499        /* Choose a random point dividing each dim into 2 parts */
1500        /* put 2^rank (nslabs) slabs so defined */
1501        nslabs = 1;
1502        for (j = 0; j < var_rank[i]; j++) {
1503            mid[j] = roll( var_shape[i][j] );
1504            nslabs *= 2;
1505        }
1506        /* bits of k determine whether to put lower or upper part of dim */
1507        /* choose random stride from 1 to edge */
1508        for (k = 0; k < nslabs; k++) {
1509            nstarts = 1;
1510            for (j = 0; j < var_rank[i]; j++) {
1511                if ((k >> j) & 1) {
1512                    start[j] = 0;
1513                    edge[j] = mid[j];
1514                }else{
1515                    start[j] = mid[j];
1516                    edge[j] = var_shape[i][j] - mid[j];
1517                }
1518                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
1519                stride[j] = (PTRDType)sstride[j];
1520                imap2[j] = imap[j] * (PTRDType)sstride[j];
1521                nstarts *= stride[j];
1522            }
1523            for (m = 0; m < nstarts; m++) {
1524                if (var_rank[i] == 0 && i%2 == 0) {
1525                    err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
1526                } else {
1527                    err = toMixedBase(m, var_rank[i], sstride, index);
1528                    IF (err != 0) error("error in toMixedBase");
1529                    for (j = 0; j < var_rank[i]; j++) {
1530                        count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
1531                        index[j] += start[j];
1532                    }
1533                    /* Random choice of forward or backward */
1534/* TODO
1535                    if ( roll(2) ) {
1536                        for (j = 0; j < var_rank[i]; j++) {
1537                            index[j] += (count[j] - 1) * (IntType)stride[j];
1538                            stride[j] = -stride[j];
1539                        }
1540                    }
1541 */
1542                    j = fromMixedBase(var_rank[i], index, var_shape[i]);
1543                    p = (char *) buf + (int)j * nctypelen(var_type[i]);
1544                    ifdef(`PNETCDF', `for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];')
1545                    err = PutVarm(ncid, i, index, count, stride, imap2, p, bufcount, datatype);
1546                }
1547                IF (err != NC_NOERR)
1548                    EXPECT_ERR(NC_NOERR, err)
1549                ELSE_NOK
1550            }
1551        }
1552    }
1553
1554    Check_Vars(ncid, numVars);
1555    err = APIFunc(close)(ncid);
1556    IF (err != NC_NOERR)
1557        error("close: %s", APIFunc(strerror)(err));
1558
1559    err = FileDelete(scratch, info);
1560    IF (err != NC_NOERR)
1561        error("remove of %s failed", scratch);
1562    return nok;
1563}
1564
1565
1566/*
1567 * Test APIFunc(rename_var)
1568 *    try with bad netCDF handle, check error
1569 *    try with bad variable handle, check error
1570 *    try renaming to existing variable name, check error
1571 *    check that proper rename worked with APIFunc(inq_varid)
1572 *    try in data mode, check error
1573 */
1574int
1575TestFunc(rename_var)(VarArgs)
1576{
1577    int ncid;
1578    int varid;
1579    int err, nok=0;
1580    int i;
1581    char name[NC_MAX_NAME];
1582
1583    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1584    IF (err != NC_NOERR) {
1585        error("create: %s", APIFunc(strerror)(err));
1586        return nok;
1587    }
1588    err = APIFunc(rename_var)(ncid, BAD_VARID, "newName");
1589    IF (err != NC_ENOTVAR)
1590        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1591    ELSE_NOK
1592    def_dims(ncid);
1593    Def_Vars(ncid, numVars);
1594
1595    /* Prefix "new_" to each name */
1596    for (i = 0; i < numVars; i++) {
1597        err = APIFunc(rename_var)(BAD_ID, i, "newName");
1598        IF (err != NC_EBADID)
1599            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1600        ELSE_NOK
1601        err = APIFunc(rename_var)(ncid, i, var_name[numVars-1]);
1602        IF (err != NC_ENAMEINUSE)
1603            error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
1604        ELSE_NOK
1605        strcpy(name, "new_");
1606        strcat(name, var_name[i]);
1607        err = APIFunc(rename_var)(ncid, i, name);
1608        IF (err != NC_NOERR)
1609            error("rename_var: %s", APIFunc(strerror)(err));
1610        ELSE_NOK
1611        err = APIFunc(inq_varid)(ncid, name, &varid);
1612        IF (err != NC_NOERR)
1613            error("inq_varid: %s", APIFunc(strerror)(err));
1614        IF (varid != i)
1615            error("Unexpected varid");
1616    }
1617
1618    /* Change to data mode */
1619    /* Try making names even longer. Then restore original names */
1620    err = APIFunc(enddef)(ncid);
1621    IF (err != NC_NOERR)
1622        error("enddef: %s", APIFunc(strerror)(err));
1623    for (i = 0; i < numVars; i++) {
1624        strcpy(name, "even_longer_");
1625        strcat(name, var_name[i]);
1626        err = APIFunc(rename_var)(ncid, i, name);
1627        IF (err != NC_ENOTINDEFINE)
1628            error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
1629        ELSE_NOK
1630        err = APIFunc(rename_var)(ncid, i, var_name[i]);
1631        IF (err != NC_NOERR)
1632            error("rename_var: %s", APIFunc(strerror)(err));
1633        ELSE_NOK
1634        err = APIFunc(inq_varid)(ncid, var_name[i], &varid);
1635        IF (err != NC_NOERR)
1636            error("inq_varid: %s", APIFunc(strerror)(err));
1637        IF (varid != i)
1638            error("Unexpected varid");
1639    }
1640
1641    Put_Vars(ncid, numVars);
1642    Check_Vars(ncid, numVars);
1643
1644    err = APIFunc(close)(ncid);
1645    IF (err != NC_NOERR)
1646        error("close: %s", APIFunc(strerror)(err));
1647
1648    err = FileDelete(scratch, info);
1649    IF (err != NC_NOERR)
1650        error("remove of %s failed", scratch);
1651    return nok;
1652}
1653
1654
1655int
1656TestFunc(put_att)(AttVarArgs)
1657{
1658    int ncid, nok=0;
1659    int varid;
1660    int i;
1661    int j;
1662    IntType k, ndx[1];
1663    int err;
1664    double buf[MAX_NELS];       /* (void *) buffer */
1665    char *p;                    /* (void *) pointer */
1666    char *name;                 /* of att */
1667    nc_type datatype;           /* of att */
1668    IntType length;             /* of att */
1669    double value;
1670
1671    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1672    IF (err != NC_NOERR) {
1673        error("create: %s", APIFunc(strerror)(err));
1674        return nok;
1675    }
1676    def_dims(ncid);
1677    Def_Vars(ncid, numVars);
1678
1679    for (i = -1; i < numVars; i++) {
1680        varid = VARID(i);
1681        for (j = 0; j < NATTS(i); j++) {
1682            name = ATT_NAME(i,j);
1683            datatype = ATT_TYPE(i,j);
1684            length = ATT_LEN(i,j);
1685            err = APIFunc(put_att)(BAD_ID, varid, name, datatype, length, buf);
1686            IF (err != NC_EBADID)
1687                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1688            ELSE_NOK
1689            err = APIFunc(put_att)(ncid, varid, BAD_NAME, datatype, length, buf);
1690            IF (err != NC_EBADNAME)
1691                error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
1692            ELSE_NOK
1693            err = APIFunc(put_att)(ncid, BAD_VARID, name, datatype, length, buf);
1694            IF (err != NC_ENOTVAR)
1695                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1696            ELSE_NOK
1697            err = APIFunc(put_att)(ncid, varid, name, BAD_TYPE, length, buf);
1698            IF (err != NC_EBADTYPE)
1699                error("expecting NC_EBADTYPE but got %s", nc_err_code_name(err));
1700            ELSE_NOK
1701            p = (char *) buf;
1702            for (k=0; k<length; k++) {
1703                ndx[0] = k;
1704                value = hash(datatype, -1, ndx);
1705                if (!inRange(value, datatype))
1706                    value = 0;
1707                err = dbl2nc(value, datatype, p);
1708                IF (err != NC_NOERR)
1709                    error("error in dbl2nc");
1710                p += nctypelen(datatype);
1711            }
1712            err = APIFunc(put_att)(ncid, varid, name, datatype, length, buf);
1713            IF (err != NC_NOERR)
1714                error("%s", APIFunc(strerror)(err));
1715            ELSE_NOK
1716        }
1717    }
1718
1719    Check_Atts(ncid, numGatts, numVars);
1720    err = APIFunc(close)(ncid);
1721    IF (err != NC_NOERR)
1722        error("close: %s", APIFunc(strerror)(err));
1723
1724    err = FileDelete(scratch, info);
1725    IF (err != NC_NOERR)
1726        error("remove of %s failed", scratch);
1727    return nok;
1728}
1729
1730
1731/*
1732 * Test APIFunc(copy_att)
1733 *    try with bad source or target netCDF handles, check error
1734 *    try with bad source or target variable handle, check error
1735 *    try with nonexisting attribute, check error
1736 *    check that NC_GLOBAL variable for source or target works
1737 *    check that new attribute put works with target in define mode
1738 *    check that old attribute put works with target in data mode
1739 *    check that changing type and length of an attribute work OK
1740 *    try with same ncid for source and target, different variables
1741 *    try with same ncid for source and target, same variable
1742 */
1743int
1744TestFunc(copy_att)(AttVarArgs)
1745{
1746    int ncid_in;
1747    int ncid_out;
1748    int varid;
1749    int err, nok=0;
1750    int i;
1751    int j=0;
1752    char *name;                 /* of att */
1753    nc_type datatype;           /* of att */
1754    IntType length;             /* of att */
1755    char  value;
1756
1757    err = FileOpen(testfile, NC_NOWRITE, &ncid_in);
1758    IF (err != NC_NOERR)
1759        error("open: %s", APIFunc(strerror)(err));
1760    err = FileCreate(scratch, NC_NOCLOBBER, &ncid_out);
1761    IF (err != NC_NOERR) {
1762        error("create: %s", APIFunc(strerror)(err));
1763        return nok;
1764    }
1765    def_dims(ncid_out);
1766    Def_Vars(ncid_out, numVars);
1767
1768    for (i = -1; i < numVars; i++) {
1769        varid = VARID(i);
1770        for (j = 0; j < NATTS(i); j++) {
1771            name = ATT_NAME(i,j);
1772            err = APIFunc(copy_att)(ncid_in, BAD_VARID, name, ncid_out, varid);
1773            IF (err != NC_ENOTVAR)
1774                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1775            ELSE_NOK
1776            err = APIFunc(copy_att)(ncid_in, varid, name, ncid_out, BAD_VARID);
1777            IF (err != NC_ENOTVAR)
1778                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1779            ELSE_NOK
1780            err = APIFunc(copy_att)(BAD_ID, varid, name, ncid_out, varid);
1781            IF (err != NC_EBADID)
1782                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1783            ELSE_NOK
1784            err = APIFunc(copy_att)(ncid_in, varid, name, BAD_ID, varid);
1785            IF (err != NC_EBADID)
1786                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1787            ELSE_NOK
1788            err = APIFunc(copy_att)(ncid_in, varid, "noSuch", ncid_out, varid);
1789            IF (err != NC_ENOTATT)
1790                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
1791            ELSE_NOK
1792            err = APIFunc(copy_att)(ncid_in, varid, name, ncid_out, varid);
1793            IF (err != NC_NOERR)
1794                error("copy_att: %s", APIFunc(strerror)(err));
1795            ELSE_NOK
1796            err = APIFunc(copy_att)(ncid_out, varid, name, ncid_out, varid);
1797            IF (err != NC_NOERR)
1798                error("source = target: %s", APIFunc(strerror)(err));
1799            ELSE_NOK
1800        }
1801    }
1802
1803    err = APIFunc(close)(ncid_in);
1804    IF (err != NC_NOERR)
1805        error("close: %s", APIFunc(strerror)(err));
1806
1807    /* Close scratch. Reopen & check attributes */
1808    err = APIFunc(close)(ncid_out);
1809    IF (err != NC_NOERR)
1810        error("close: %s", APIFunc(strerror)(err));
1811    err = FileOpen(scratch, NC_WRITE, &ncid_out);
1812    IF (err != NC_NOERR)
1813        error("open: %s", APIFunc(strerror)(err));
1814    Check_Atts(ncid_out, numGatts, numVars);
1815
1816   /*
1817    * change to define mode
1818    * define single char. global att. ':a' with value 'A'
1819    * This will be used as source for following copies
1820    */
1821    err = APIFunc(redef)(ncid_out);
1822    IF (err != NC_NOERR)
1823        error("redef: %s", APIFunc(strerror)(err));
1824    err = APIFunc(put_att_text)(ncid_out, NC_GLOBAL, "a", 1, "A");
1825    IF (err != NC_NOERR)
1826        error("put_att_text: %s", APIFunc(strerror)(err));
1827
1828   /*
1829    * change to data mode
1830    * Use scratch as both source & dest.
1831    * try copy to existing att. change type & decrease length
1832    * rename 1st existing att of each var (if any) 'a'
1833    * if this att. exists them copy ':a' to it
1834    */
1835    err = APIFunc(enddef)(ncid_out);
1836    IF (err != NC_NOERR)
1837        error("enddef: %s", APIFunc(strerror)(err));
1838    for (i = 0; i < numVars; i++) {
1839        if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
1840            err = APIFunc(rename_att)(ncid_out, i, att_name[i][0], "a");
1841            IF (err != NC_NOERR)
1842                error("rename_att: %s", APIFunc(strerror)(err));
1843            err = APIFunc(copy_att)(ncid_out, NC_GLOBAL, "a", ncid_out, i);
1844            IF (err != NC_NOERR)
1845                error("copy_att: %s", APIFunc(strerror)(err));
1846            ELSE_NOK
1847        }
1848    }
1849    err = APIFunc(close)(ncid_out);
1850    IF (err != NC_NOERR)
1851        error("close: %s", APIFunc(strerror)(err));
1852
1853    /* Reopen & check */
1854    err = FileOpen(scratch, NC_WRITE, &ncid_out);
1855    IF (err != NC_NOERR)
1856        error("open: %s", APIFunc(strerror)(err));
1857    for (i = 0; i < numVars; i++) {
1858        if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
1859            err = APIFunc(inq_att)(ncid_out, i, "a", &datatype, &length);
1860            IF (err != NC_NOERR)
1861                error("inq_att: %s", APIFunc(strerror)(err));
1862            IF (datatype != NC_CHAR)
1863                error("Unexpected type");
1864            IF (length != 1)
1865                error("Unexpected length");
1866            err = APIFunc(get_att_text)(ncid_out, i, "a", &value);
1867            IF (err != NC_NOERR)
1868                error("get_att_text: %s", APIFunc(strerror)(err));
1869            IF (value != 'A')
1870                error("Unexpected value");
1871        }
1872    }
1873
1874    err = APIFunc(close)(ncid_out);
1875    IF (err != NC_NOERR)
1876        error("close: %s", APIFunc(strerror)(err));
1877    err = FileDelete(scratch, info);
1878    IF (err != NC_NOERR)
1879        error("remove of %s failed", scratch);
1880    return nok;
1881}
1882
1883
1884/*
1885 * Test APIFunc(rename_att)
1886 *    try with bad netCDF handle, check error
1887 *    try with bad variable handle, check error
1888 *    try with nonexisting att name, check error
1889 *    try renaming to existing att name, check error
1890 *    check that proper rename worked with APIFunc(inq_attid)
1891 *    try in data mode, check error
1892 */
1893int
1894TestFunc(rename_att)(AttVarArgs)
1895{
1896    int ncid;
1897    int varid;
1898    int err;
1899    int i;
1900    int j;
1901    IntType k, ndx[1];
1902    int attnum;
1903    char *attname;
1904    char name[NC_MAX_NAME];
1905    char oldname[NC_MAX_NAME];
1906    char newname[NC_MAX_NAME];
1907    int nok = 0;      /* count of valid comparisons */
1908    nc_type datatype;
1909    nc_type atttype;
1910    IntType length;
1911    IntType attlength;
1912    char  text[MAX_NELS];
1913    double value[MAX_NELS];
1914    double expect;
1915
1916    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1917    IF (err != NC_NOERR) {
1918        error("create: %s", APIFunc(strerror)(err));
1919        return nok;
1920    }
1921    err = APIFunc(rename_att)(ncid, BAD_VARID, "abc", "newName");
1922    IF (err != NC_ENOTVAR)
1923        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1924    ELSE_NOK
1925    def_dims(ncid);
1926    Def_Vars(ncid, numVars);
1927    Put_Atts(ncid, numGatts, numVars);
1928
1929    for (i = -1; i < numVars; i++) {
1930        varid = VARID(i);
1931        for (j = 0; j < NATTS(i); j++) {
1932            attname = ATT_NAME(i,j);
1933            err = APIFunc(rename_att)(BAD_ID, varid, attname, "newName");
1934            IF (err != NC_EBADID)
1935                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1936            ELSE_NOK
1937            err = APIFunc(rename_att)(ncid, varid, "noSuch", "newName");
1938            IF (err != NC_ENOTATT)
1939                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
1940            ELSE_NOK
1941            strcpy(newname, "new_");
1942            strcat(newname, attname);
1943            err = APIFunc(rename_att)(ncid, varid, attname, newname);
1944            IF (err != NC_NOERR)
1945                error("rename_att: %s", APIFunc(strerror)(err));
1946            ELSE_NOK
1947            err = APIFunc(inq_attid)(ncid, varid, newname, &attnum);
1948            IF (err != NC_NOERR)
1949                error("inq_attid: %s", APIFunc(strerror)(err));
1950            IF (attnum != j)
1951                error("Unexpected attnum");
1952        }
1953    }
1954
1955    /* Close. Reopen & check */
1956    err = APIFunc(close)(ncid);
1957    IF (err != NC_NOERR)
1958        error("close: %s", APIFunc(strerror)(err));
1959    err = FileOpen(scratch, NC_WRITE, &ncid);
1960    IF (err != NC_NOERR)
1961        error("open: %s", APIFunc(strerror)(err));
1962
1963    for (i = -1; i < numVars; i++) {
1964        varid = VARID(i);
1965        for (j = 0; j < NATTS(i); j++) {
1966            attname = ATT_NAME(i,j);
1967            atttype = ATT_TYPE(i,j);
1968            attlength = ATT_LEN(i,j);
1969            strcpy(newname, "new_");
1970            strcat(newname, attname);
1971            err = APIFunc(inq_attname)(ncid, varid, j, name);
1972            IF (err != NC_NOERR)
1973                error("inq_attname: %s", APIFunc(strerror)(err));
1974            IF (strcmp(name, newname) != 0)
1975                error("inq_attname: unexpected name");
1976            err = APIFunc(inq_att)(ncid, varid, name, &datatype, &length);
1977            IF (err != NC_NOERR)
1978                error("inq_att: %s", APIFunc(strerror)(err));
1979            IF (datatype != atttype)
1980                error("inq_att: unexpected type");
1981            IF (length != attlength)
1982                error("inq_att: unexpected length");
1983            if (datatype == NC_CHAR) {
1984                err = APIFunc(get_att_text)(ncid, varid, name, text);
1985                IF (err != NC_NOERR)
1986                    error("get_att_text: %s", APIFunc(strerror)(err));
1987                for (k = 0; k < attlength; k++) {
1988                    ndx[0] = k;
1989                    expect = hash(datatype, -1, ndx);
1990                    IF (text[k] != (char)expect)
1991                        error("get_att_text: unexpected value");
1992                }
1993            } else {
1994                err = APIFunc(get_att_double)(ncid, varid, name, value);
1995                IF (err != NC_NOERR)
1996                    error("get_att_double: %s", APIFunc(strerror)(err));
1997                for (k = 0; k < attlength; k++) {
1998                    ndx[0] = k;
1999                    expect = hash(datatype, -1, ndx);
2000                    if (inRange(expect, datatype)) {
2001                        IF (!equal(value[k],expect,datatype,NCT_DOUBLE))
2002                            error("get_att_double: unexpected value");
2003                    }
2004                }
2005            }
2006        }
2007    }
2008
2009    /* Now in data mode */
2010    /* Try making names even longer. Then restore original names */
2011
2012    for (i = -1; i < numVars; i++) {
2013        varid = VARID(i);
2014        for (j = 0; j < NATTS(i); j++) {
2015            attname = ATT_NAME(i,j);
2016            strcpy(oldname, "new_");
2017            strcat(oldname, attname);
2018            strcpy(newname, "even_longer_");
2019            strcat(newname, attname);
2020            err = APIFunc(rename_att)(ncid, varid, oldname, newname);
2021            IF (err != NC_ENOTINDEFINE)
2022                error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
2023            ELSE_NOK
2024            err = APIFunc(rename_att)(ncid, varid, oldname, attname);
2025            IF (err != NC_NOERR)
2026                error("rename_att: %s", APIFunc(strerror)(err));
2027            ELSE_NOK
2028            err = APIFunc(inq_attid)(ncid, varid, attname, &attnum);
2029            IF (err != NC_NOERR)
2030                error("inq_attid: %s", APIFunc(strerror)(err));
2031            IF (attnum != j)
2032                error("Unexpected attnum");
2033        }
2034    }
2035
2036    err = APIFunc(close)(ncid);
2037    IF (err != NC_NOERR)
2038        error("close: %s", APIFunc(strerror)(err));
2039
2040    err = FileDelete(scratch, info);
2041    IF (err != NC_NOERR)
2042        error("remove of %s failed", scratch);
2043    return nok;
2044}
2045
2046
2047/*
2048 * Test APIFunc(del_att)
2049 *    try with bad netCDF handle, check error
2050 *    try with bad variable handle, check error
2051 *    try with nonexisting att name, check error
2052 *    check that proper delete worked using:
2053 *      APIFunc(inq_attid), APIFunc(inq_natts), APIFunc(inq_varnatts)
2054 */
2055int
2056TestFunc(del_att)(AttVarArgs)
2057{
2058    int ncid;
2059    int err, nok=0;
2060    int i;
2061    int j;
2062    int attnum;
2063    int natts;
2064    int numatts;
2065    int varid;
2066    char *name;                 /* of att */
2067
2068    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
2069    IF (err != NC_NOERR) {
2070        error("create: %s", APIFunc(strerror)(err));
2071        return nok;
2072    }
2073    err = APIFunc(del_att)(ncid, BAD_VARID, "abc");
2074    IF (err != NC_ENOTVAR)
2075        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
2076    ELSE_NOK
2077    def_dims(ncid);
2078    Def_Vars(ncid, numVars);
2079    Put_Atts(ncid, numGatts, numVars);
2080
2081    for (i = -1; i < numVars; i++) {
2082        varid = VARID(i);
2083        numatts = NATTS(i);
2084        for (j = 0; j < numatts; j++) {
2085            name = ATT_NAME(i,j);
2086            err = APIFunc(del_att)(BAD_ID, varid, name);
2087            IF (err != NC_EBADID)
2088                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
2089            ELSE_NOK
2090            err = APIFunc(del_att)(ncid, varid, "noSuch");
2091            IF (err != NC_ENOTATT)
2092                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
2093            ELSE_NOK
2094            err = APIFunc(del_att)(ncid, varid, name);
2095            IF (err != NC_NOERR)
2096                error("del_att: %s", APIFunc(strerror)(err));
2097            ELSE_NOK
2098            err = APIFunc(inq_attid)(ncid, varid, name, &attnum);
2099            IF (err != NC_ENOTATT)
2100                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
2101            if (i < 0) {
2102                err = APIFunc(inq_natts)(ncid, &natts);
2103                IF (err != NC_NOERR)
2104                    error("inq_natts: %s", APIFunc(strerror)(err));
2105                IF (natts != numatts-j-1)
2106                    error("natts: expected %d, got %d", numatts-j-1, natts);
2107            }
2108            err = APIFunc(inq_varnatts)(ncid, varid, &natts);
2109            IF (err != NC_NOERR)
2110                error("inq_natts: %s", APIFunc(strerror)(err));
2111            IF (natts != numatts-j-1)
2112                error("natts: expected %d, got %d", numatts-j-1, natts);
2113        }
2114    }
2115
2116    /* Close. Reopen & check no attributes left */
2117    err = APIFunc(close)(ncid);
2118    IF (err != NC_NOERR)
2119        error("close: %s", APIFunc(strerror)(err));
2120    err = FileOpen(scratch, NC_WRITE, &ncid);
2121    IF (err != NC_NOERR)
2122        error("open: %s", APIFunc(strerror)(err));
2123    err = APIFunc(inq_natts)(ncid, &natts);
2124    IF (err != NC_NOERR)
2125        error("inq_natts: %s", APIFunc(strerror)(err));
2126    IF (natts != 0)
2127        error("natts: expected %d, got %d", 0, natts);
2128    for (i = -1; i < numVars; i++) {
2129        varid = VARID(i);
2130        err = APIFunc(inq_varnatts)(ncid, varid, &natts);
2131        IF (err != NC_NOERR)
2132            error("inq_natts: %s", APIFunc(strerror)(err));
2133        IF (natts != 0)
2134            error("natts: expected %d, got %d", 0, natts);
2135    }
2136
2137    /* restore attributes. change to data mode. try to delete */
2138    err = APIFunc(redef)(ncid);
2139    IF (err != NC_NOERR)
2140        error("redef: %s", APIFunc(strerror)(err));
2141    Put_Atts(ncid, numGatts, numVars);
2142    err = APIFunc(enddef)(ncid);
2143    IF (err != NC_NOERR)
2144        error("enddef: %s", APIFunc(strerror)(err));
2145
2146    for (i = -1; i < numVars; i++) {
2147        varid = VARID(i);
2148        numatts = NATTS(i);
2149        for (j = 0; j < numatts; j++) {
2150            name = ATT_NAME(i,j);
2151            err = APIFunc(del_att)(ncid, varid, name);
2152            IF (err != NC_ENOTINDEFINE)
2153                error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
2154            ELSE_NOK
2155        }
2156    }
2157
2158    err = APIFunc(close)(ncid);
2159    IF (err != NC_NOERR)
2160        error("close: %s", APIFunc(strerror)(err));
2161    err = FileDelete(scratch, info);
2162    IF (err != NC_NOERR)
2163        error("remove of %s failed", scratch);
2164    return nok;
2165}
2166
2167
2168/*
2169 * Test APIFunc(set_fill)
2170 *    try with bad netCDF handle, check error
2171 *    try in read-only mode, check error
2172 *    try with bad new_fillmode, check error
2173 *    try in data mode, check error
2174 *    check that proper set to NC_FILL works for record & non-record variables
2175 *    (note that it is not possible to test NC_NOFILL mode!)
2176 *    close file & create again for test using attribute _FillValue
2177 */
2178int
2179TestFunc(set_fill)(VarArgs)
2180{
2181    int ncid;
2182    int varid;
2183    int err;
2184    int i;
2185    IntType j;
2186    int old_fillmode;
2187    int nok = 0;      /* count of valid comparisons */
2188    char text = 0;
2189    double value = 0;
2190    double fill;
2191    IntType index[MAX_RANK];
2192
2193    /* bad ncid */
2194    err = APIFunc(set_fill)(BAD_ID, NC_NOFILL, &old_fillmode);
2195    IF (err != NC_EBADID)
2196        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
2197
2198    /* try in read-only mode */
2199    err = FileOpen(testfile, NC_NOWRITE, &ncid);
2200    IF (err != NC_NOERR)
2201        error("open: %s", APIFunc(strerror)(err));
2202    err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode);
2203    IF (err != NC_EPERM)
2204        error("expecting NC_EPERM but got %s", nc_err_code_name(err));
2205    err = APIFunc(close)(ncid);
2206    IF (err != NC_NOERR)
2207        error("close: %s", APIFunc(strerror)(err));
2208
2209    /* create scratch */
2210    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
2211    IF (err != NC_NOERR) {
2212        error("create: %s", APIFunc(strerror)(err));
2213        return nok;
2214    }
2215
2216    /* BAD_FILLMODE */
2217    err = APIFunc(set_fill)(ncid, BAD_FILLMODE, &old_fillmode);
2218    IF (err != NC_EINVAL)
2219        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
2220
2221    /* proper calls */
2222    err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode);
2223    IF (err != NC_NOERR)
2224        error("set_fill: %s", APIFunc(strerror)(err));
2225    IF (old_fillmode != NC_NOFILL)
2226        error("Unexpected old fill mode: %d", old_fillmode);
2227    err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode);
2228    IF (err != NC_NOERR)
2229        error("set_fill: %s", APIFunc(strerror)(err));
2230    IF (old_fillmode != NC_NOFILL)
2231        error("Unexpected old fill mode: %d", old_fillmode);
2232
2233    /* define dims & vars */
2234    def_dims(ncid);
2235    Def_Vars(ncid, numVars);
2236
2237    /* Change to data mode. Set fillmode again */
2238    err = APIFunc(enddef)(ncid);
2239    IF (err != NC_NOERR)
2240        error("enddef: %s", APIFunc(strerror)(err));
2241    err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode);
2242ifdef(`PNETCDF',
2243    `IF (err != NC_ENOTINDEFINE)
2244        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));',
2245    `IF (err)
2246        error("nc_set_fill: %s", nc_strerror(err));
2247    IF (old_fillmode != NC_FILL)
2248        error("Unexpected old fill mode: %d", old_fillmode);')dnl
2249
2250    /* Write record number NRECS to force writing of preceding records */
2251    /* Assumes variable cr is char vector with UNLIMITED dimension */
2252    err = APIFunc(inq_varid)(ncid, "cr", &varid);
2253    IF (err != NC_NOERR)
2254        error("inq_varid: %s", APIFunc(strerror)(err));
2255    index[0] = NRECS;
2256
2257ifdef(`PNETCDF', `
2258    for (i=0; i<=index[0]; i++)
2259        err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl
2260
2261    err = PutVar1TYPE(text)(ncid, varid, index, &text);
2262    IF (err != NC_NOERR)
2263        error("put_var1_text_all: %s", APIFunc(strerror)(err));
2264
2265    /* get all variables & check all values equal default fill */
2266    for (i = 0; i < numVars; i++) {
2267        ifdef(`PNETCDF', `if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */')
2268        switch (var_type[i]) {
2269            case NC_CHAR:   fill = (double)NC_FILL_CHAR;   break;
2270            case NC_BYTE:   fill = (double)NC_FILL_BYTE;   break;
2271            case NC_SHORT:  fill = (double)NC_FILL_SHORT;  break;
2272            case NC_INT:    fill = (double)NC_FILL_INT;    break;
2273            case NC_FLOAT:  fill = (double)NC_FILL_FLOAT;  break;
2274            case NC_DOUBLE: fill = (double)NC_FILL_DOUBLE; break;
2275            case NC_UBYTE:  fill = (double)NC_FILL_UBYTE;  break;
2276            case NC_USHORT: fill = (double)NC_FILL_USHORT; break;
2277            case NC_UINT:   fill = (double)NC_FILL_UINT;   break;
2278            case NC_INT64:  fill = (double)NC_FILL_INT64;  break;
2279            case NC_UINT64: fill = (double)NC_FILL_UINT64; break;
2280            default: assert(0);
2281        }
2282        for (j = 0; j < var_nels[i]; j++) {
2283            err = toMixedBase(j, var_rank[i], var_shape[i], index);
2284            IF (err != 0) error("error in toMixedBase");
2285            if (var_type[i] == NC_CHAR) {
2286                err = GetVar1TYPE(text)(ncid, i, index, &text);
2287                IF (err != NC_NOERR)
2288                    error("get_var1_text_all failed: %s", APIFunc(strerror)(err));
2289                value = text;
2290            } else {
2291                err = GetVar1TYPE(double)(ncid, i, index, &value);
2292                IF (err != NC_NOERR)
2293                    error("get_var1_double_all failed: %s", APIFunc(strerror)(err));
2294            }
2295            IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
2296                error("\n\t\t%s Value expected: %-23.17e,\n\t\t          read: %-23.17e\n",
2297                        var_name[i],fill, value);
2298            ELSE_NOK
2299        }
2300    }
2301
2302    /* close scratch & create again for test using attribute _FillValue */
2303    err = APIFunc(close)(ncid);
2304    IF (err != NC_NOERR)
2305        error("close: %s", APIFunc(strerror)(err));
2306    err = FileCreate(scratch, NC_CLOBBER, &ncid);
2307    IF (err != NC_NOERR) {
2308        error("create: %s", APIFunc(strerror)(err));
2309        return nok;
2310    }
2311    def_dims(ncid);
2312    Def_Vars(ncid, numVars);
2313
2314    /* set _FillValue = 42 for all vars */
2315    fill = 42;
2316    text = 42;
2317    for (i = 0; i < numVars; i++) {
2318        if (var_type[i] == NC_CHAR) {
2319            err = APIFunc(put_att_text)(ncid, i, "_FillValue", 1, &text);
2320            IF (err != NC_NOERR)
2321                error("put_att_text: %s", APIFunc(strerror)(err));
2322        } else {
2323            err = APIFunc(put_att_double)(ncid, i, "_FillValue",var_type[i],1,&fill);
2324            IF (err != NC_NOERR)
2325                error("put_att_double: %s", APIFunc(strerror)(err));
2326        }
2327    }
2328
2329    /* data mode. write records */
2330    err = APIFunc(enddef)(ncid);
2331    IF (err != NC_NOERR)
2332        error("enddef: %s", APIFunc(strerror)(err));
2333    index[0] = NRECS;
2334
2335ifdef(`PNETCDF', `
2336    for (i=0; i<=index[0]; i++)
2337        err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl
2338
2339    err = PutVar1TYPE(text)(ncid, varid, index, &text);
2340    IF (err != NC_NOERR)
2341        error("put_var1_text_all: %s", APIFunc(strerror)(err));
2342
2343    /* get all variables & check all values equal 42 */
2344    for (i = 0; i < numVars; i++) {
2345        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
2346        for (j = 0; j < var_nels[i]; j++) {
2347            err = toMixedBase(j, var_rank[i], var_shape[i], index);
2348            IF (err != 0) error("error in toMixedBase");
2349            if (var_type[i] == NC_CHAR) {
2350                err = GetVar1TYPE(text)(ncid, i, index, &text);
2351                IF (err != NC_NOERR)
2352                    error("get_var1_text_all failed: %s", APIFunc(strerror)(err));
2353                value = text;
2354            } else {
2355                err = GetVar1TYPE(double)(ncid, i, index, &value);
2356                IF (err != NC_NOERR)
2357                    error("get_var1_double_all failed: %s", APIFunc(strerror)(err));
2358            }
2359            IF (value != fill)
2360                error(" %s Value expected: %g, read: %g\n", var_name[i],fill, value);
2361            ELSE_NOK
2362        }
2363    }
2364
2365    /* enter redef mode and add a new variable, check NC_ELATEFILL */
2366    err = APIFunc(redef)(ncid);
2367    IF (err != NC_NOERR)
2368        error("redef: %s", APIFunc(strerror)(err));
2369
2370    /* it is not allowed to define fill value when variable already exists */
2371    err = APIFunc(def_var_fill)(ncid, 0, 0, &value);
2372    IF (err != NC_ELATEFILL)
2373        error("redef: expect NC_ELATEFILL but got %s", nc_err_code_name(err));
2374    err = APIFunc(def_var)(ncid, "new_var", NC_INT, 0, NULL, &varid);
2375    IF (err != NC_NOERR)
2376        error("redef: %s", APIFunc(strerror)(err));
2377    err = APIFunc(def_var_fill)(ncid, varid, 0, &value);
2378    IF (err != NC_NOERR)
2379        error("def_var_fill: %s", APIFunc(strerror)(err));
2380
2381    err = APIFunc(close)(ncid);
2382    IF (err != NC_NOERR)
2383        error("close: %s", APIFunc(strerror)(err));
2384    err = FileDelete(scratch, info);
2385    IF (err != NC_NOERR)
2386        error("remove of %s failed", scratch);
2387
2388    return nok;
2389}
2390
2391
2392/* This function gets the version of a netCDF file, 1 is for netCDF
2393   classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format,
2394   5 for 64-bit data format (CDF-5).
2395*/
2396#define MAGIC_NUM_LEN 4
2397static
2398int
2399APIFunc(get_file_version)(char *path, int *version)
2400{
2401   int fd;
2402   ssize_t read_len;
2403   char magic[MAGIC_NUM_LEN];
2404
2405   /* Need two valid pointers - check for NULL. */
2406   if (!version || !path)
2407      return NC_EINVAL;
2408
2409   /* Figure out if this is a netcdf or hdf5 file. */
2410   fd = open(path, O_RDONLY, 0600);
2411   if (fd == -1) return errno;
2412
2413   read_len = read(fd, magic, MAGIC_NUM_LEN);
2414   if (-1 == close(fd)) return errno;
2415
2416   if (read_len == -1)
2417       return errno;
2418
2419   if (read_len != MAGIC_NUM_LEN) {
2420       printf("Error: reading NC magic string unexpected short read\n");
2421       return 0;
2422   }
2423
2424   if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0) {
2425      if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC ||
2426          magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET
2427#ifdef ENABLE_CDF5
2428          || magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5
2429#endif
2430)
2431         *version = magic[MAGIC_NUM_LEN-1];
2432      else
2433        return NC_ENOTNC;
2434   }
2435   /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
2436       away! */
2437   /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
2438      *version = 3;*/
2439   return NC_NOERR;
2440}
2441
2442/*
2443 * Test APIFunc(set_default_format)
2444 *    try with bad default format
2445 *    try with NULL old_formatp
2446 *    try in data mode, check error
2447 *    check that proper set to NC_FILL works for record & non-record variables
2448 *    (note that it is not possible to test NC_NOFILL mode!)
2449 *    close file & create again for test using attribute _FillValue
2450 */
2451int
2452TestFunc(set_default_format)(void)
2453{
2454    int ncid, nok=0;
2455    int err;
2456    int i;
2457    int version=1;
2458    int old_format;
2459
2460    /* bad format */
2461    err = APIFunc(set_default_format)(BAD_DEFAULT_FORMAT, &old_format);
2462    IF (err != NC_EINVAL)
2463        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
2464    ELSE_NOK
2465
2466    /* NULL old_formatp */
2467    err = APIFunc(set_default_format)(NC_FORMAT_64BIT_OFFSET, NULL);
2468    IF (err != NC_NOERR)
2469       error("null old_fortmatp: status = %d", err);
2470    ELSE_NOK
2471
2472    /* Cycle through available formats. */
2473
2474    for(i=NC_FORMAT_CLASSIC; i<NC_FORMAT_64BIT_DATA; i++) {
2475       if (i == NC_FORMAT_NETCDF4 || i == NC_FORMAT_NETCDF4_CLASSIC)
2476           continue; /* test classic formats only */
2477       if ((err = APIFunc(set_default_format)(i, NULL)))
2478           error("setting classic format: status = %d", err);
2479       ELSE_NOK
2480       err = FileCreate(scratch, NC_CLOBBER, &ncid);
2481       if (err != NC_NOERR)
2482           error("bad nc_create: status = %d", err);
2483       err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "testatt", sizeof("blah"), "blah");
2484       if (err != NC_NOERR)
2485           error("bad put_att: status = %d", err);
2486       err = APIFunc(close)(ncid);
2487       if (err != NC_NOERR)
2488           error("bad close: status = %d", err);
2489       err = APIFunc(get_file_version)(scratch, &version);
2490       if (err != NC_NOERR)
2491           error("bad file version = %d", err);
2492       if (version != i) {
2493#if 0
2494          if (i == 4) {
2495              if (version == 3) continue;
2496              printf("expect version 3 but got %d (file=%s)",version,scratch);
2497              continue;
2498          }
2499#endif
2500          printf("expect version %d but got %d (file=%s)",i,version,scratch);
2501          error("bad file version = %d", version);
2502        }
2503    }
2504
2505    /* Remove the left-over file. */
2506    err = FileDelete(scratch, info);
2507    IF (err != NC_NOERR)
2508        error("remove of %s failed", scratch);
2509
2510    return nok;
2511}
2512
2513
2514
2515
2516/*
2517 * Test FileDelete
2518 *         create netcdf file 'scratch.nc' with no data, close it
2519 *         delete the file
2520 */
2521int
2522TestFunc(delete)(void)
2523{
2524    int err, nok=0;
2525    int ncid;
2526
2527    err = FileCreate(scratch, NC_CLOBBER, &ncid);
2528    IF (err != NC_NOERR)
2529        error("error creating scratch file %s, status = %d\n", scratch,err);
2530    err = APIFunc(close)(ncid);
2531    IF (err != NC_NOERR)
2532        error("close: %s", APIFunc(strerror)(err));
2533    err = FileDelete(scratch, info);
2534    IF (err != NC_NOERR)
2535        error("remove of %s failed", scratch);
2536    ELSE_NOK
2537    return nok;
2538}
2539