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            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
1047                EXPECT_ERR(NC_NOERR, err)
1048            ELSE_NOK
1049            start[j] = var_shape[i][j]+1; /* out of boundary check */
1050            err = PutVara(ncid, i, start, edge, buf, 1, datatype);
1051            IF (err != NC_EINVALCOORDS)
1052                EXPECT_ERR(NC_EINVALCOORDS, err)
1053            ELSE_NOK
1054            start[j] = 0;
1055        }
1056        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
1057
1058        /* Choose a random point dividing each dim into 2 parts */
1059        /* put 2^rank (nslabs) slabs so defined */
1060        nslabs = 1;
1061        for (j = 0; j < var_rank[i]; j++) {
1062            mid[j] = roll( var_shape[i][j] );
1063            nslabs *= 2;
1064        }
1065        /* bits of k determine whether to put lower or upper part of dim */
1066        for (k = 0; k < nslabs; k++) {
1067            nels = 1;
1068            for (j = 0; j < var_rank[i]; j++) {
1069                if ((k >> j) & 1) {
1070                    start[j] = 0;
1071                    edge[j] = mid[j];
1072                }else{
1073                    start[j] = mid[j];
1074                    edge[j] = var_shape[i][j] - mid[j];
1075                }
1076                nels *= edge[j];
1077            }
1078            p = (char *) buf;
1079            for (j = 0; j < nels; j++) {
1080                err = toMixedBase(j, var_rank[i], edge, index);
1081                IF (err != 0) error("error in toMixedBase");
1082                for (d = 0; d < var_rank[i]; d++)
1083                    index[d] += start[d];
1084                value = hash(var_type[i], var_rank[i], index);
1085                if (!inRange(value, var_type[i]))
1086                    value = 0;
1087                err = dbl2nc(value, var_type[i], p);
1088                IF (err != NC_NOERR)
1089                    error("error in dbl2nc");
1090                p += nctypelen(var_type[i]);
1091            }
1092            err = PutVara(ncid, i, start, edge, buf, nels, datatype);
1093            IF (err != NC_NOERR)
1094                error("%s", APIFunc(strerror)(err));
1095            ELSE_NOK
1096        }
1097    }
1098
1099    Check_Vars(ncid, numVars);
1100    err = APIFunc(close)(ncid);
1101    IF (err != NC_NOERR)
1102        error("close: %s", APIFunc(strerror)(err));
1103
1104    err = FileDelete(scratch, info);
1105    IF (err != NC_NOERR)
1106        error("remove of %s failed", scratch);
1107    return nok;
1108}
1109
1110
1111/*
1112 * Test PutVars
1113 * Choose a random point dividing each dim into 2 parts
1114 * Put 2^rank (nslabs) slabs so defined
1115 * Choose random stride from 1 to edge
1116 * Redefine buffer for each put.
1117 * At end check all variables using Check_Vars
1118 */
1119int
1120TestFunc(put_vars)(VarArgs)
1121{
1122    int ncid, d, i, k, err, nslabs, nok=0;
1123    PTRDType nstarts;        /* number of different starts */
1124    IntType j, m, nels;
1125    IntType start[MAX_RANK];
1126    IntType edge[MAX_RANK];
1127    IntType index[MAX_RANK];
1128    IntType index2[MAX_RANK];
1129    IntType mid[MAX_RANK];
1130    IntType count[MAX_RANK];
1131    IntType sstride[MAX_RANK];
1132    PTRDType stride[MAX_RANK];
1133    double buf[MAX_NELS]; /* (void *) buffer */
1134    char *p;              /* (void *) pointer */
1135    double value;
1136    ifdef(`PNETCDF', `MPI_Datatype datatype;')
1137
1138    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1139    IF (err != NC_NOERR) {
1140        error("create: %s", APIFunc(strerror)(err));
1141        return nok;
1142    }
1143
1144    def_dims(ncid);
1145    Def_Vars(ncid, numVars);
1146
1147    err = APIFunc(enddef)(ncid);
1148    IF (err != NC_NOERR)
1149        error("enddef: %s", APIFunc(strerror)(err));
1150
1151    /* check if can detect a bad file ID */
1152    err = PutVars(BAD_ID, 0, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1153    IF (err != NC_EBADID)
1154        EXPECT_ERR(NC_EBADID, err)
1155    ELSE_NOK
1156
1157    /* check if can detect a bad variable ID */
1158    err = PutVars(ncid, BAD_VARID, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1159    IF (err != NC_ENOTVAR)
1160        EXPECT_ERR(NC_ENOTVAR, err)
1161    ELSE_NOK
1162
1163    for (i = 0; i < numVars; i++) {
1164        assert(var_rank[i] <= MAX_RANK);
1165        assert(var_nels[i] <= MAX_NELS);
1166
1167        buf[0] = 5;  /* reset to a value within bounds */
1168
1169        /* check if can detect a bad file ID */
1170        err = PutVars(BAD_ID, i, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
1171        IF (err != NC_EBADID)
1172            EXPECT_ERR(NC_EBADID, err)
1173        ELSE_NOK
1174
1175        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
1176
1177        for (j = 0; j < var_rank[i]; j++) {
1178            start[j] = 0;
1179            edge[j] = 1;
1180            stride[j] = 1;
1181        }
1182
1183ifdef(`PNETCDF',`dnl
1184        /* for non-scalar variables, argument start cannot be NULL */
1185        err = PutVars(ncid, i, NULL, NULL, NULL, buf, 1, datatype);
1186        if (var_rank[i] == 0) { /* scalar variable */
1187            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1188        }
1189        else IF (err != NC_EINVALCOORDS) {
1190            EXPECT_ERR(NC_EINVALCOORDS, err)
1191        }
1192        ELSE_NOK
1193
1194        /* for non-scalar variables, argument count cannot be NULL */
1195        err = PutVars(ncid, i, start, NULL, NULL, buf, 1, datatype);
1196        if (var_rank[i] == 0) {
1197            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1198        }
1199        else IF (err != NC_EEDGE) {
1200            EXPECT_ERR(NC_EEDGE, err)
1201        }
1202        ELSE_NOK
1203')dnl
1204
1205        /* first test when edge[*] > 0 */
1206        for (j = 0; j < var_rank[i]; j++) {
1207            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1208            start[j] = var_shape[i][j];
1209            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1210            IF (err != NC_EINVALCOORDS)
1211                EXPECT_ERR(NC_EINVALCOORDS, err)
1212            ELSE_NOK
1213            start[j] = 0;
1214            edge[j] = var_shape[i][j] + 1;  /* edge error check */
1215            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1216            IF (err != NC_EEDGE)
1217                EXPECT_ERR(NC_EEDG, err)
1218            ELSE_NOK
1219            edge[j] = 1;
1220            stride[j] = 0;  /* strided edge error check */
1221            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1222            IF (err != NC_ESTRIDE)
1223                EXPECT_ERR(NC_ESTRIDE, err)
1224            ELSE_NOK
1225            stride[j] = 1;
1226        }
1227        /* Check correct error returned even when nothing to put */
1228        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
1229
1230        for (j = 0; j < var_rank[i]; j++) {
1231            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1232            start[j] = var_shape[i][j];
1233            err = PutVars(ncid, i, start, edge, stride, buf, 0, datatype);
1234            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
1235                EXPECT_ERR(NC_NOERR, err)
1236            ELSE_NOK
1237            start[j] = var_shape[i][j]+1; /* out of boundary check */
1238            err = PutVars(ncid, i, start, edge, stride, buf, 1, datatype);
1239            IF (err != NC_EINVALCOORDS)
1240                EXPECT_ERR(NC_EINVALCOORDS, err)
1241            ELSE_NOK
1242            start[j] = 0;
1243        }
1244        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
1245
1246        /* Choose a random point dividing each dim into 2 parts */
1247        /* put 2^rank (nslabs) slabs so defined */
1248        nslabs = 1;
1249        for (j = 0; j < var_rank[i]; j++) {
1250            mid[j] = roll( var_shape[i][j] );
1251            nslabs *= 2;
1252        }
1253        /* bits of k determine whether to put lower or upper part of dim */
1254        /* choose random stride from 1 to edge */
1255        for (k = 0; k < nslabs; k++) {
1256            nstarts = 1;
1257            for (j = 0; j < var_rank[i]; j++) {
1258                if ((k >> j) & 1) {
1259                    start[j] = 0;
1260                    edge[j] = mid[j];
1261                }else{
1262                    start[j] = mid[j];
1263                    edge[j] = var_shape[i][j] - mid[j];
1264                }
1265                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
1266                stride[j] = (PTRDType)sstride[j];
1267                nstarts *= stride[j];
1268            }
1269            for (m = 0; m < nstarts; m++) {
1270                err = toMixedBase(m, var_rank[i], sstride, index);
1271                IF (err != 0) error("error in toMixedBase");
1272                nels = 1;
1273                for (j = 0; j < var_rank[i]; j++) {
1274                    count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
1275                    nels *= count[j];
1276                    index[j] += start[j];
1277                }
1278                /* Random choice of forward or backward */
1279/* TODO
1280                if ( roll(2) ) {
1281                    for (j = 0; j < var_rank[i]; j++) {
1282                        index[j] += (count[j] - 1) * (IntType)stride[j];
1283                        stride[j] = -stride[j];
1284                    }
1285                }
1286 */
1287                p = (char *) buf;
1288                for (j = 0; j < nels; j++) {
1289                    err = toMixedBase(j, var_rank[i], count, index2);
1290                    IF (err != 0) error("error in toMixedBase");
1291                    for (d = 0; d < var_rank[i]; d++)
1292                        index2[d] = index[d] + index2[d] * (IntType)stride[d];
1293                    value = hash(var_type[i], var_rank[i], index2);
1294                    if (!inRange(value, var_type[i]))
1295                        value = 0;
1296                    err = dbl2nc(value, var_type[i], p);
1297                    IF (err != NC_NOERR)
1298                        error("error in dbl2nc");
1299                    p += nctypelen(var_type[i]);
1300                }
1301                err = PutVars(ncid, i, index, count, stride, buf, nels, datatype);
1302                IF (err != NC_NOERR)
1303                    EXPECT_ERR(NC_NOERR, err)
1304                ELSE_NOK
1305            }
1306        }
1307    }
1308
1309    Check_Vars(ncid, numVars);
1310    err = APIFunc(close)(ncid);
1311    IF (err != NC_NOERR)
1312        error("close: %s", APIFunc(strerror)(err));
1313
1314    err = FileDelete(scratch, info);
1315    IF (err != NC_NOERR)
1316        error("remove of %s failed", scratch);
1317    return nok;
1318}
1319
1320
1321/*
1322 * Test PutVarm
1323 * Choose a random point dividing each dim into 2 parts
1324 * Put 2^rank (nslabs) slabs so defined
1325 * Choose random stride from 1 to edge
1326 * Buffer is bit image of whole external variable.
1327 * So all puts for a variable put different elements of buffer
1328 * At end check all variables using Check_Vars
1329 */
1330int
1331TestFunc(put_varm)(VarArgs)
1332{
1333    int ncid, nok=0;
1334    int i;
1335    int k;
1336    int err;
1337    int nslabs;
1338    IntType j, m;
1339    PTRDType nstarts;        /* number of different starts */
1340    IntType start[MAX_RANK];
1341    IntType edge[MAX_RANK];
1342    IntType index[MAX_RANK];
1343    IntType mid[MAX_RANK];
1344    IntType count[MAX_RANK];
1345    IntType sstride[MAX_RANK];
1346    PTRDType stride[MAX_RANK];
1347    PTRDType imap[MAX_RANK];
1348    PTRDType imap2[MAX_RANK];
1349    ifdef(`PNETCDF', `IntType bufcount;')
1350    double buf[MAX_NELS];       /* (void *) buffer */
1351    char *p;                    /* (void *) pointer */
1352    double value;
1353    ifdef(`PNETCDF', `MPI_Datatype datatype;')
1354
1355    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1356    IF (err != NC_NOERR) {
1357        error("create: %s", APIFunc(strerror)(err));
1358        return nok;
1359    }
1360
1361    def_dims(ncid);
1362    Def_Vars(ncid, numVars);
1363
1364    err = APIFunc(enddef)(ncid);
1365    IF (err != NC_NOERR)
1366        error("enddef: %s", APIFunc(strerror)(err));
1367
1368    /* check if can detect a bad file ID */
1369    err = PutVarm(NC_EBADID, 0, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1370    IF (err != NC_EBADID)
1371        EXPECT_ERR(NC_EBADID, err)
1372    ELSE_NOK
1373
1374    /* check if can detect a bad variable ID */
1375    err = PutVarm(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL, 1, MPI_DATATYPE_NULL);
1376    IF (err != NC_ENOTVAR)
1377        EXPECT_ERR(NC_ENOTVAR, err)
1378    ELSE_NOK
1379
1380    for (i = 0; i < numVars; i++) {
1381        assert(var_rank[i] <= MAX_RANK);
1382        assert(var_nels[i] <= MAX_NELS);
1383
1384        buf[0] = 5;  /* reset to a value within bounds */
1385
1386        /* check if can detect a bad file ID */
1387        err = PutVarm(BAD_ID, i, NULL, NULL, NULL, NULL, buf, 1, MPI_DATATYPE_NULL);
1388        IF (err != NC_EBADID)
1389            EXPECT_ERR(NC_EBADID, err)
1390        ELSE_NOK
1391
1392        ifdef(`PNETCDF', `datatype = nc_mpi_type(var_type[i]);')
1393
1394        for (j = 0; j < var_rank[i]; j++) {
1395            start[j] = 0;
1396            edge[j] = 1;
1397            stride[j] = 1;
1398            imap[j] = 1;
1399        }
1400
1401ifdef(`PNETCDF',`dnl
1402        /* for non-scalar variables, argument start cannot be NULL */
1403        err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
1404        if (var_rank[i] == 0) { /* scalar variable */
1405            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1406        }
1407        else IF (err != NC_EINVALCOORDS) {
1408            EXPECT_ERR(NC_EINVALCOORDS, err)
1409        }
1410        ELSE_NOK
1411
1412        /* for non-scalar variables, argument count cannot be NULL */
1413        err = PutVarm(ncid, i, start, NULL, NULL, NULL, buf, 1, datatype);
1414        if (var_rank[i] == 0) {
1415            IF (err != NC_NOERR) EXPECT_ERR(NC_NOERR, err)
1416        }
1417        else IF (err != NC_EEDGE) {
1418            EXPECT_ERR(NC_EEDGE, err)
1419        }
1420        ELSE_NOK
1421')dnl
1422
1423        /* first test when edge[*] > 0 */
1424        for (j = 0; j < var_rank[i]; j++) {
1425            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1426            start[j] = var_shape[i][j];
1427            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1428            IF (err != NC_EINVALCOORDS)
1429                EXPECT_ERR(NC_EINVALCOORDS, err)
1430            ELSE_NOK
1431            start[j] = 0;
1432            edge[j] = var_shape[i][j] + 1;  /* edge error check */
1433            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1434            IF (err != NC_EEDGE)
1435                EXPECT_ERR(NC_EEDG, err)
1436            ELSE_NOK
1437            edge[j] = 1;
1438            stride[j] = 0;  /* strided edge error check */
1439            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1440            IF (err != NC_ESTRIDE)
1441                EXPECT_ERR(NC_ESTRIDE, err)
1442            ELSE_NOK
1443            stride[j] = 1;
1444        }
1445        /* Check correct error returned even when nothing to put */
1446        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;
1447
1448        for (j = 0; j < var_rank[i]; j++) {
1449            if (var_dimid[i][j] == 0) continue; /* skip record dim */
1450            start[j] = var_shape[i][j];
1451            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 0, datatype);
1452            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
1453                EXPECT_ERR(NC_NOERR, err)
1454            ELSE_NOK
1455            start[j] = var_shape[i][j]+1; /* out of boundary check */
1456            err = PutVarm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
1457            IF (err != NC_EINVALCOORDS)
1458                EXPECT_ERR(NC_EINVALCOORDS, err)
1459            ELSE_NOK
1460            start[j] = 0;
1461        }
1462        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;
1463
1464        if (var_rank[i] > 0) {
1465            int jj = var_rank[i] - 1;
1466            imap[jj] = nctypelen(var_type[i]); /*  netCDF considers imap in bytes */
1467            imap[jj] = 1;                      /* PnetCDF considers imap in elements */
1468            for (; jj > 0; jj--)
1469                imap[jj-1] = imap[jj] * (PTRDType)var_shape[i][jj];
1470        }
1471        p = (char *) buf;
1472        for (j = 0; j < var_nels[i]; j++) {
1473            err = toMixedBase(j, var_rank[i], var_shape[i], index);
1474            IF (err != 0) error("error in toMixedBase");
1475            value = hash(var_type[i], var_rank[i], index);
1476            if (!inRange(value, var_type[i]))
1477                value = 0;
1478            err = dbl2nc(value, var_type[i], p);
1479            IF (err != NC_NOERR)
1480                error("error in dbl2nc");
1481            p += nctypelen(var_type[i]);
1482        }
1483
1484        /* Choose a random point dividing each dim into 2 parts */
1485        /* put 2^rank (nslabs) slabs so defined */
1486        nslabs = 1;
1487        for (j = 0; j < var_rank[i]; j++) {
1488            mid[j] = roll( var_shape[i][j] );
1489            nslabs *= 2;
1490        }
1491        /* bits of k determine whether to put lower or upper part of dim */
1492        /* choose random stride from 1 to edge */
1493        for (k = 0; k < nslabs; k++) {
1494            nstarts = 1;
1495            for (j = 0; j < var_rank[i]; j++) {
1496                if ((k >> j) & 1) {
1497                    start[j] = 0;
1498                    edge[j] = mid[j];
1499                }else{
1500                    start[j] = mid[j];
1501                    edge[j] = var_shape[i][j] - mid[j];
1502                }
1503                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
1504                stride[j] = (PTRDType)sstride[j];
1505                imap2[j] = imap[j] * (PTRDType)sstride[j];
1506                nstarts *= stride[j];
1507            }
1508            for (m = 0; m < nstarts; m++) {
1509                if (var_rank[i] == 0 && i%2 == 0) {
1510                    err = PutVarm(ncid, i, NULL, NULL, NULL, NULL, buf, 1, datatype);
1511                } else {
1512                    err = toMixedBase(m, var_rank[i], sstride, index);
1513                    IF (err != 0) error("error in toMixedBase");
1514                    for (j = 0; j < var_rank[i]; j++) {
1515                        count[j] = 1 + (edge[j] - index[j] - 1) / (IntType)stride[j];
1516                        index[j] += start[j];
1517                    }
1518                    /* Random choice of forward or backward */
1519/* TODO
1520                    if ( roll(2) ) {
1521                        for (j = 0; j < var_rank[i]; j++) {
1522                            index[j] += (count[j] - 1) * (IntType)stride[j];
1523                            stride[j] = -stride[j];
1524                        }
1525                    }
1526 */
1527                    j = fromMixedBase(var_rank[i], index, var_shape[i]);
1528                    p = (char *) buf + (int)j * nctypelen(var_type[i]);
1529                    ifdef(`PNETCDF', `for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];')
1530                    err = PutVarm(ncid, i, index, count, stride, imap2, p, bufcount, datatype);
1531                }
1532                IF (err != NC_NOERR)
1533                    EXPECT_ERR(NC_NOERR, err)
1534                ELSE_NOK
1535            }
1536        }
1537    }
1538
1539    Check_Vars(ncid, numVars);
1540    err = APIFunc(close)(ncid);
1541    IF (err != NC_NOERR)
1542        error("close: %s", APIFunc(strerror)(err));
1543
1544    err = FileDelete(scratch, info);
1545    IF (err != NC_NOERR)
1546        error("remove of %s failed", scratch);
1547    return nok;
1548}
1549
1550
1551/*
1552 * Test APIFunc(rename_var)
1553 *    try with bad netCDF handle, check error
1554 *    try with bad variable handle, check error
1555 *    try renaming to existing variable name, check error
1556 *    check that proper rename worked with APIFunc(inq_varid)
1557 *    try in data mode, check error
1558 */
1559int
1560TestFunc(rename_var)(VarArgs)
1561{
1562    int ncid;
1563    int varid;
1564    int err, nok=0;
1565    int i;
1566    char name[NC_MAX_NAME];
1567
1568    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1569    IF (err != NC_NOERR) {
1570        error("create: %s", APIFunc(strerror)(err));
1571        return nok;
1572    }
1573    err = APIFunc(rename_var)(ncid, BAD_VARID, "newName");
1574    IF (err != NC_ENOTVAR)
1575        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1576    ELSE_NOK
1577    def_dims(ncid);
1578    Def_Vars(ncid, numVars);
1579
1580    /* Prefix "new_" to each name */
1581    for (i = 0; i < numVars; i++) {
1582        err = APIFunc(rename_var)(BAD_ID, i, "newName");
1583        IF (err != NC_EBADID)
1584            error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1585        ELSE_NOK
1586        err = APIFunc(rename_var)(ncid, i, var_name[numVars-1]);
1587        IF (err != NC_ENAMEINUSE)
1588            error("expecting NC_ENAMEINUSE but got %s", nc_err_code_name(err));
1589        ELSE_NOK
1590        strcpy(name, "new_");
1591        strcat(name, var_name[i]);
1592        err = APIFunc(rename_var)(ncid, i, name);
1593        IF (err != NC_NOERR)
1594            error("rename_var: %s", APIFunc(strerror)(err));
1595        ELSE_NOK
1596        err = APIFunc(inq_varid)(ncid, name, &varid);
1597        IF (err != NC_NOERR)
1598            error("inq_varid: %s", APIFunc(strerror)(err));
1599        IF (varid != i)
1600            error("Unexpected varid");
1601    }
1602
1603    /* Change to data mode */
1604    /* Try making names even longer. Then restore original names */
1605    err = APIFunc(enddef)(ncid);
1606    IF (err != NC_NOERR)
1607        error("enddef: %s", APIFunc(strerror)(err));
1608    for (i = 0; i < numVars; i++) {
1609        strcpy(name, "even_longer_");
1610        strcat(name, var_name[i]);
1611        err = APIFunc(rename_var)(ncid, i, name);
1612        IF (err != NC_ENOTINDEFINE)
1613            error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
1614        ELSE_NOK
1615        err = APIFunc(rename_var)(ncid, i, var_name[i]);
1616        IF (err != NC_NOERR)
1617            error("rename_var: %s", APIFunc(strerror)(err));
1618        ELSE_NOK
1619        err = APIFunc(inq_varid)(ncid, var_name[i], &varid);
1620        IF (err != NC_NOERR)
1621            error("inq_varid: %s", APIFunc(strerror)(err));
1622        IF (varid != i)
1623            error("Unexpected varid");
1624    }
1625
1626    Put_Vars(ncid, numVars);
1627    Check_Vars(ncid, numVars);
1628
1629    err = APIFunc(close)(ncid);
1630    IF (err != NC_NOERR)
1631        error("close: %s", APIFunc(strerror)(err));
1632
1633    err = FileDelete(scratch, info);
1634    IF (err != NC_NOERR)
1635        error("remove of %s failed", scratch);
1636    return nok;
1637}
1638
1639
1640int
1641TestFunc(put_att)(AttVarArgs)
1642{
1643    int ncid, nok=0;
1644    int varid;
1645    int i;
1646    int j;
1647    IntType k, ndx[1];
1648    int err;
1649    double buf[MAX_NELS];       /* (void *) buffer */
1650    char *p;                    /* (void *) pointer */
1651    char *name;                 /* of att */
1652    nc_type datatype;           /* of att */
1653    IntType length;             /* of att */
1654    double value;
1655
1656    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1657    IF (err != NC_NOERR) {
1658        error("create: %s", APIFunc(strerror)(err));
1659        return nok;
1660    }
1661    def_dims(ncid);
1662    Def_Vars(ncid, numVars);
1663
1664    for (i = -1; i < numVars; i++) {
1665        varid = VARID(i);
1666        for (j = 0; j < NATTS(i); j++) {
1667            name = ATT_NAME(i,j);
1668            datatype = ATT_TYPE(i,j);
1669            length = ATT_LEN(i,j);
1670            err = APIFunc(put_att)(BAD_ID, varid, name, datatype, length, buf);
1671            IF (err != NC_EBADID)
1672                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1673            ELSE_NOK
1674            err = APIFunc(put_att)(ncid, varid, BAD_NAME, datatype, length, buf);
1675            IF (err != NC_EBADNAME)
1676                error("expecting NC_EBADNAME but got %s", nc_err_code_name(err));
1677            ELSE_NOK
1678            err = APIFunc(put_att)(ncid, BAD_VARID, name, datatype, length, buf);
1679            IF (err != NC_ENOTVAR)
1680                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1681            ELSE_NOK
1682            err = APIFunc(put_att)(ncid, varid, name, BAD_TYPE, length, buf);
1683            IF (err != NC_EBADTYPE)
1684                error("expecting NC_EBADTYPE but got %s", nc_err_code_name(err));
1685            ELSE_NOK
1686            p = (char *) buf;
1687            for (k=0; k<length; k++) {
1688                ndx[0] = k;
1689                value = hash(datatype, -1, ndx);
1690                if (!inRange(value, datatype))
1691                    value = 0;
1692                err = dbl2nc(value, datatype, p);
1693                IF (err != NC_NOERR)
1694                    error("error in dbl2nc");
1695                p += nctypelen(datatype);
1696            }
1697            err = APIFunc(put_att)(ncid, varid, name, datatype, length, buf);
1698            IF (err != NC_NOERR)
1699                error("%s", APIFunc(strerror)(err));
1700            ELSE_NOK
1701        }
1702    }
1703
1704    Check_Atts(ncid, numGatts, numVars);
1705    err = APIFunc(close)(ncid);
1706    IF (err != NC_NOERR)
1707        error("close: %s", APIFunc(strerror)(err));
1708
1709    err = FileDelete(scratch, info);
1710    IF (err != NC_NOERR)
1711        error("remove of %s failed", scratch);
1712    return nok;
1713}
1714
1715
1716/*
1717 * Test APIFunc(copy_att)
1718 *    try with bad source or target netCDF handles, check error
1719 *    try with bad source or target variable handle, check error
1720 *    try with nonexisting attribute, check error
1721 *    check that NC_GLOBAL variable for source or target works
1722 *    check that new attribute put works with target in define mode
1723 *    check that old attribute put works with target in data mode
1724 *    check that changing type and length of an attribute work OK
1725 *    try with same ncid for source and target, different variables
1726 *    try with same ncid for source and target, same variable
1727 */
1728int
1729TestFunc(copy_att)(AttVarArgs)
1730{
1731    int ncid_in;
1732    int ncid_out;
1733    int varid;
1734    int err, nok=0;
1735    int i;
1736    int j=0;
1737    char *name;                 /* of att */
1738    nc_type datatype;           /* of att */
1739    IntType length;             /* of att */
1740    char  value;
1741
1742    err = FileOpen(testfile, NC_NOWRITE, &ncid_in);
1743    IF (err != NC_NOERR)
1744        error("open: %s", APIFunc(strerror)(err));
1745    err = FileCreate(scratch, NC_NOCLOBBER, &ncid_out);
1746    IF (err != NC_NOERR) {
1747        error("create: %s", APIFunc(strerror)(err));
1748        return nok;
1749    }
1750    def_dims(ncid_out);
1751    Def_Vars(ncid_out, numVars);
1752
1753    for (i = -1; i < numVars; i++) {
1754        varid = VARID(i);
1755        for (j = 0; j < NATTS(i); j++) {
1756            name = ATT_NAME(i,j);
1757            err = APIFunc(copy_att)(ncid_in, BAD_VARID, name, ncid_out, varid);
1758            IF (err != NC_ENOTVAR)
1759                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1760            ELSE_NOK
1761            err = APIFunc(copy_att)(ncid_in, varid, name, ncid_out, BAD_VARID);
1762            IF (err != NC_ENOTVAR)
1763                error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1764            ELSE_NOK
1765            err = APIFunc(copy_att)(BAD_ID, varid, name, ncid_out, varid);
1766            IF (err != NC_EBADID)
1767                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1768            ELSE_NOK
1769            err = APIFunc(copy_att)(ncid_in, varid, name, BAD_ID, varid);
1770            IF (err != NC_EBADID)
1771                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1772            ELSE_NOK
1773            err = APIFunc(copy_att)(ncid_in, varid, "noSuch", ncid_out, varid);
1774            IF (err != NC_ENOTATT)
1775                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
1776            ELSE_NOK
1777            err = APIFunc(copy_att)(ncid_in, varid, name, ncid_out, varid);
1778            IF (err != NC_NOERR)
1779                error("copy_att: %s", APIFunc(strerror)(err));
1780            ELSE_NOK
1781            err = APIFunc(copy_att)(ncid_out, varid, name, ncid_out, varid);
1782            IF (err != NC_NOERR)
1783                error("source = target: %s", APIFunc(strerror)(err));
1784            ELSE_NOK
1785        }
1786    }
1787
1788    err = APIFunc(close)(ncid_in);
1789    IF (err != NC_NOERR)
1790        error("close: %s", APIFunc(strerror)(err));
1791
1792    /* Close scratch. Reopen & check attributes */
1793    err = APIFunc(close)(ncid_out);
1794    IF (err != NC_NOERR)
1795        error("close: %s", APIFunc(strerror)(err));
1796    err = FileOpen(scratch, NC_WRITE, &ncid_out);
1797    IF (err != NC_NOERR)
1798        error("open: %s", APIFunc(strerror)(err));
1799    Check_Atts(ncid_out, numGatts, numVars);
1800
1801   /*
1802    * change to define mode
1803    * define single char. global att. ':a' with value 'A'
1804    * This will be used as source for following copies
1805    */
1806    err = APIFunc(redef)(ncid_out);
1807    IF (err != NC_NOERR)
1808        error("redef: %s", APIFunc(strerror)(err));
1809    err = APIFunc(put_att_text)(ncid_out, NC_GLOBAL, "a", 1, "A");
1810    IF (err != NC_NOERR)
1811        error("put_att_text: %s", APIFunc(strerror)(err));
1812
1813   /*
1814    * change to data mode
1815    * Use scratch as both source & dest.
1816    * try copy to existing att. change type & decrease length
1817    * rename 1st existing att of each var (if any) 'a'
1818    * if this att. exists them copy ':a' to it
1819    */
1820    err = APIFunc(enddef)(ncid_out);
1821    IF (err != NC_NOERR)
1822        error("enddef: %s", APIFunc(strerror)(err));
1823    for (i = 0; i < numVars; i++) {
1824        if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
1825            err = APIFunc(rename_att)(ncid_out, i, att_name[i][0], "a");
1826            IF (err != NC_NOERR)
1827                error("rename_att: %s", APIFunc(strerror)(err));
1828            err = APIFunc(copy_att)(ncid_out, NC_GLOBAL, "a", ncid_out, i);
1829            IF (err != NC_NOERR)
1830                error("copy_att: %s", APIFunc(strerror)(err));
1831            ELSE_NOK
1832        }
1833    }
1834    err = APIFunc(close)(ncid_out);
1835    IF (err != NC_NOERR)
1836        error("close: %s", APIFunc(strerror)(err));
1837
1838    /* Reopen & check */
1839    err = FileOpen(scratch, NC_WRITE, &ncid_out);
1840    IF (err != NC_NOERR)
1841        error("open: %s", APIFunc(strerror)(err));
1842    for (i = 0; i < numVars; i++) {
1843        if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
1844            err = APIFunc(inq_att)(ncid_out, i, "a", &datatype, &length);
1845            IF (err != NC_NOERR)
1846                error("inq_att: %s", APIFunc(strerror)(err));
1847            IF (datatype != NC_CHAR)
1848                error("Unexpected type");
1849            IF (length != 1)
1850                error("Unexpected length");
1851            err = APIFunc(get_att_text)(ncid_out, i, "a", &value);
1852            IF (err != NC_NOERR)
1853                error("get_att_text: %s", APIFunc(strerror)(err));
1854            IF (value != 'A')
1855                error("Unexpected value");
1856        }
1857    }
1858
1859    err = APIFunc(close)(ncid_out);
1860    IF (err != NC_NOERR)
1861        error("close: %s", APIFunc(strerror)(err));
1862    err = FileDelete(scratch, info);
1863    IF (err != NC_NOERR)
1864        error("remove of %s failed", scratch);
1865    return nok;
1866}
1867
1868
1869/*
1870 * Test APIFunc(rename_att)
1871 *    try with bad netCDF handle, check error
1872 *    try with bad variable handle, check error
1873 *    try with nonexisting att name, check error
1874 *    try renaming to existing att name, check error
1875 *    check that proper rename worked with APIFunc(inq_attid)
1876 *    try in data mode, check error
1877 */
1878int
1879TestFunc(rename_att)(AttVarArgs)
1880{
1881    int ncid;
1882    int varid;
1883    int err;
1884    int i;
1885    int j;
1886    IntType k, ndx[1];
1887    int attnum;
1888    char *attname;
1889    char name[NC_MAX_NAME];
1890    char oldname[NC_MAX_NAME];
1891    char newname[NC_MAX_NAME];
1892    int nok = 0;      /* count of valid comparisons */
1893    nc_type datatype;
1894    nc_type atttype;
1895    IntType length;
1896    IntType attlength;
1897    char  text[MAX_NELS];
1898    double value[MAX_NELS];
1899    double expect;
1900
1901    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
1902    IF (err != NC_NOERR) {
1903        error("create: %s", APIFunc(strerror)(err));
1904        return nok;
1905    }
1906    err = APIFunc(rename_att)(ncid, BAD_VARID, "abc", "newName");
1907    IF (err != NC_ENOTVAR)
1908        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
1909    ELSE_NOK
1910    def_dims(ncid);
1911    Def_Vars(ncid, numVars);
1912    Put_Atts(ncid, numGatts, numVars);
1913
1914    for (i = -1; i < numVars; i++) {
1915        varid = VARID(i);
1916        for (j = 0; j < NATTS(i); j++) {
1917            attname = ATT_NAME(i,j);
1918            err = APIFunc(rename_att)(BAD_ID, varid, attname, "newName");
1919            IF (err != NC_EBADID)
1920                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
1921            ELSE_NOK
1922            err = APIFunc(rename_att)(ncid, varid, "noSuch", "newName");
1923            IF (err != NC_ENOTATT)
1924                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
1925            ELSE_NOK
1926            strcpy(newname, "new_");
1927            strcat(newname, attname);
1928            err = APIFunc(rename_att)(ncid, varid, attname, newname);
1929            IF (err != NC_NOERR)
1930                error("rename_att: %s", APIFunc(strerror)(err));
1931            ELSE_NOK
1932            err = APIFunc(inq_attid)(ncid, varid, newname, &attnum);
1933            IF (err != NC_NOERR)
1934                error("inq_attid: %s", APIFunc(strerror)(err));
1935            IF (attnum != j)
1936                error("Unexpected attnum");
1937        }
1938    }
1939
1940    /* Close. Reopen & check */
1941    err = APIFunc(close)(ncid);
1942    IF (err != NC_NOERR)
1943        error("close: %s", APIFunc(strerror)(err));
1944    err = FileOpen(scratch, NC_WRITE, &ncid);
1945    IF (err != NC_NOERR)
1946        error("open: %s", APIFunc(strerror)(err));
1947
1948    for (i = -1; i < numVars; i++) {
1949        varid = VARID(i);
1950        for (j = 0; j < NATTS(i); j++) {
1951            attname = ATT_NAME(i,j);
1952            atttype = ATT_TYPE(i,j);
1953            attlength = ATT_LEN(i,j);
1954            strcpy(newname, "new_");
1955            strcat(newname, attname);
1956            err = APIFunc(inq_attname)(ncid, varid, j, name);
1957            IF (err != NC_NOERR)
1958                error("inq_attname: %s", APIFunc(strerror)(err));
1959            IF (strcmp(name, newname) != 0)
1960                error("inq_attname: unexpected name");
1961            err = APIFunc(inq_att)(ncid, varid, name, &datatype, &length);
1962            IF (err != NC_NOERR)
1963                error("inq_att: %s", APIFunc(strerror)(err));
1964            IF (datatype != atttype)
1965                error("inq_att: unexpected type");
1966            IF (length != attlength)
1967                error("inq_att: unexpected length");
1968            if (datatype == NC_CHAR) {
1969                err = APIFunc(get_att_text)(ncid, varid, name, text);
1970                IF (err != NC_NOERR)
1971                    error("get_att_text: %s", APIFunc(strerror)(err));
1972                for (k = 0; k < attlength; k++) {
1973                    ndx[0] = k;
1974                    expect = hash(datatype, -1, ndx);
1975                    IF (text[k] != (char)expect)
1976                        error("get_att_text: unexpected value");
1977                }
1978            } else {
1979                err = APIFunc(get_att_double)(ncid, varid, name, value);
1980                IF (err != NC_NOERR)
1981                    error("get_att_double: %s", APIFunc(strerror)(err));
1982                for (k = 0; k < attlength; k++) {
1983                    ndx[0] = k;
1984                    expect = hash(datatype, -1, ndx);
1985                    if (inRange(expect, datatype)) {
1986                        IF (!equal(value[k],expect,datatype,NCT_DOUBLE))
1987                            error("get_att_double: unexpected value");
1988                    }
1989                }
1990            }
1991        }
1992    }
1993
1994    /* Now in data mode */
1995    /* Try making names even longer. Then restore original names */
1996
1997    for (i = -1; i < numVars; i++) {
1998        varid = VARID(i);
1999        for (j = 0; j < NATTS(i); j++) {
2000            attname = ATT_NAME(i,j);
2001            strcpy(oldname, "new_");
2002            strcat(oldname, attname);
2003            strcpy(newname, "even_longer_");
2004            strcat(newname, attname);
2005            err = APIFunc(rename_att)(ncid, varid, oldname, newname);
2006            IF (err != NC_ENOTINDEFINE)
2007                error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
2008            ELSE_NOK
2009            err = APIFunc(rename_att)(ncid, varid, oldname, attname);
2010            IF (err != NC_NOERR)
2011                error("rename_att: %s", APIFunc(strerror)(err));
2012            ELSE_NOK
2013            err = APIFunc(inq_attid)(ncid, varid, attname, &attnum);
2014            IF (err != NC_NOERR)
2015                error("inq_attid: %s", APIFunc(strerror)(err));
2016            IF (attnum != j)
2017                error("Unexpected attnum");
2018        }
2019    }
2020
2021    err = APIFunc(close)(ncid);
2022    IF (err != NC_NOERR)
2023        error("close: %s", APIFunc(strerror)(err));
2024
2025    err = FileDelete(scratch, info);
2026    IF (err != NC_NOERR)
2027        error("remove of %s failed", scratch);
2028    return nok;
2029}
2030
2031
2032/*
2033 * Test APIFunc(del_att)
2034 *    try with bad netCDF handle, check error
2035 *    try with bad variable handle, check error
2036 *    try with nonexisting att name, check error
2037 *    check that proper delete worked using:
2038 *      APIFunc(inq_attid), APIFunc(inq_natts), APIFunc(inq_varnatts)
2039 */
2040int
2041TestFunc(del_att)(AttVarArgs)
2042{
2043    int ncid;
2044    int err, nok=0;
2045    int i;
2046    int j;
2047    int attnum;
2048    int natts;
2049    int numatts;
2050    int varid;
2051    char *name;                 /* of att */
2052
2053    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
2054    IF (err != NC_NOERR) {
2055        error("create: %s", APIFunc(strerror)(err));
2056        return nok;
2057    }
2058    err = APIFunc(del_att)(ncid, BAD_VARID, "abc");
2059    IF (err != NC_ENOTVAR)
2060        error("expecting NC_ENOTVAR but got %s", nc_err_code_name(err));
2061    ELSE_NOK
2062    def_dims(ncid);
2063    Def_Vars(ncid, numVars);
2064    Put_Atts(ncid, numGatts, numVars);
2065
2066    for (i = -1; i < numVars; i++) {
2067        varid = VARID(i);
2068        numatts = NATTS(i);
2069        for (j = 0; j < numatts; j++) {
2070            name = ATT_NAME(i,j);
2071            err = APIFunc(del_att)(BAD_ID, varid, name);
2072            IF (err != NC_EBADID)
2073                error("expecting NC_EBADID but got %s", nc_err_code_name(err));
2074            ELSE_NOK
2075            err = APIFunc(del_att)(ncid, varid, "noSuch");
2076            IF (err != NC_ENOTATT)
2077                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
2078            ELSE_NOK
2079            err = APIFunc(del_att)(ncid, varid, name);
2080            IF (err != NC_NOERR)
2081                error("del_att: %s", APIFunc(strerror)(err));
2082            ELSE_NOK
2083            err = APIFunc(inq_attid)(ncid, varid, name, &attnum);
2084            IF (err != NC_ENOTATT)
2085                error("expecting NC_ENOTATT but got %s", nc_err_code_name(err));
2086            if (i < 0) {
2087                err = APIFunc(inq_natts)(ncid, &natts);
2088                IF (err != NC_NOERR)
2089                    error("inq_natts: %s", APIFunc(strerror)(err));
2090                IF (natts != numatts-j-1)
2091                    error("natts: expected %d, got %d", numatts-j-1, natts);
2092            }
2093            err = APIFunc(inq_varnatts)(ncid, varid, &natts);
2094            IF (err != NC_NOERR)
2095                error("inq_natts: %s", APIFunc(strerror)(err));
2096            IF (natts != numatts-j-1)
2097                error("natts: expected %d, got %d", numatts-j-1, natts);
2098        }
2099    }
2100
2101    /* Close. Reopen & check no attributes left */
2102    err = APIFunc(close)(ncid);
2103    IF (err != NC_NOERR)
2104        error("close: %s", APIFunc(strerror)(err));
2105    err = FileOpen(scratch, NC_WRITE, &ncid);
2106    IF (err != NC_NOERR)
2107        error("open: %s", APIFunc(strerror)(err));
2108    err = APIFunc(inq_natts)(ncid, &natts);
2109    IF (err != NC_NOERR)
2110        error("inq_natts: %s", APIFunc(strerror)(err));
2111    IF (natts != 0)
2112        error("natts: expected %d, got %d", 0, natts);
2113    for (i = -1; i < numVars; i++) {
2114        varid = VARID(i);
2115        err = APIFunc(inq_varnatts)(ncid, varid, &natts);
2116        IF (err != NC_NOERR)
2117            error("inq_natts: %s", APIFunc(strerror)(err));
2118        IF (natts != 0)
2119            error("natts: expected %d, got %d", 0, natts);
2120    }
2121
2122    /* restore attributes. change to data mode. try to delete */
2123    err = APIFunc(redef)(ncid);
2124    IF (err != NC_NOERR)
2125        error("redef: %s", APIFunc(strerror)(err));
2126    Put_Atts(ncid, numGatts, numVars);
2127    err = APIFunc(enddef)(ncid);
2128    IF (err != NC_NOERR)
2129        error("enddef: %s", APIFunc(strerror)(err));
2130
2131    for (i = -1; i < numVars; i++) {
2132        varid = VARID(i);
2133        numatts = NATTS(i);
2134        for (j = 0; j < numatts; j++) {
2135            name = ATT_NAME(i,j);
2136            err = APIFunc(del_att)(ncid, varid, name);
2137            IF (err != NC_ENOTINDEFINE)
2138                error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));
2139            ELSE_NOK
2140        }
2141    }
2142
2143    err = APIFunc(close)(ncid);
2144    IF (err != NC_NOERR)
2145        error("close: %s", APIFunc(strerror)(err));
2146    err = FileDelete(scratch, info);
2147    IF (err != NC_NOERR)
2148        error("remove of %s failed", scratch);
2149    return nok;
2150}
2151
2152
2153/*
2154 * Test APIFunc(set_fill)
2155 *    try with bad netCDF handle, check error
2156 *    try in read-only mode, check error
2157 *    try with bad new_fillmode, check error
2158 *    try in data mode, check error
2159 *    check that proper set to NC_FILL works for record & non-record variables
2160 *    (note that it is not possible to test NC_NOFILL mode!)
2161 *    close file & create again for test using attribute _FillValue
2162 */
2163int
2164TestFunc(set_fill)(VarArgs)
2165{
2166    int ncid;
2167    int varid;
2168    int err;
2169    int i;
2170    IntType j;
2171    int old_fillmode;
2172    int nok = 0;      /* count of valid comparisons */
2173    char text = 0;
2174    double value = 0;
2175    double fill;
2176    IntType index[MAX_RANK];
2177
2178    /* bad ncid */
2179    err = APIFunc(set_fill)(BAD_ID, NC_NOFILL, &old_fillmode);
2180    IF (err != NC_EBADID)
2181        error("expecting NC_EBADID but got %s", nc_err_code_name(err));
2182
2183    /* try in read-only mode */
2184    err = FileOpen(testfile, NC_NOWRITE, &ncid);
2185    IF (err != NC_NOERR)
2186        error("open: %s", APIFunc(strerror)(err));
2187    err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode);
2188    IF (err != NC_EPERM)
2189        error("expecting NC_EPERM but got %s", nc_err_code_name(err));
2190    err = APIFunc(close)(ncid);
2191    IF (err != NC_NOERR)
2192        error("close: %s", APIFunc(strerror)(err));
2193
2194    /* create scratch */
2195    err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
2196    IF (err != NC_NOERR) {
2197        error("create: %s", APIFunc(strerror)(err));
2198        return nok;
2199    }
2200
2201    /* BAD_FILLMODE */
2202    err = APIFunc(set_fill)(ncid, BAD_FILLMODE, &old_fillmode);
2203    IF (err != NC_EINVAL)
2204        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
2205
2206    /* proper calls */
2207    err = APIFunc(set_fill)(ncid, NC_NOFILL, &old_fillmode);
2208    IF (err != NC_NOERR)
2209        error("set_fill: %s", APIFunc(strerror)(err));
2210    IF (old_fillmode != NC_NOFILL)
2211        error("Unexpected old fill mode: %d", old_fillmode);
2212    err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode);
2213    IF (err != NC_NOERR)
2214        error("set_fill: %s", APIFunc(strerror)(err));
2215    IF (old_fillmode != NC_NOFILL)
2216        error("Unexpected old fill mode: %d", old_fillmode);
2217
2218    /* define dims & vars */
2219    def_dims(ncid);
2220    Def_Vars(ncid, numVars);
2221
2222    /* Change to data mode. Set fillmode again */
2223    err = APIFunc(enddef)(ncid);
2224    IF (err != NC_NOERR)
2225        error("enddef: %s", APIFunc(strerror)(err));
2226    err = APIFunc(set_fill)(ncid, NC_FILL, &old_fillmode);
2227ifdef(`PNETCDF',
2228    `IF (err != NC_ENOTINDEFINE)
2229        error("expecting NC_ENOTINDEFINE but got %s", nc_err_code_name(err));',
2230    `IF (err)
2231        error("nc_set_fill: %s", nc_strerror(err));
2232    IF (old_fillmode != NC_FILL)
2233        error("Unexpected old fill mode: %d", old_fillmode);')dnl
2234
2235    /* Write record number NRECS to force writing of preceding records */
2236    /* Assumes variable cr is char vector with UNLIMITED dimension */
2237    err = APIFunc(inq_varid)(ncid, "cr", &varid);
2238    IF (err != NC_NOERR)
2239        error("inq_varid: %s", APIFunc(strerror)(err));
2240    index[0] = NRECS;
2241
2242ifdef(`PNETCDF', `
2243    for (i=0; i<=index[0]; i++)
2244        err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl
2245
2246    err = PutVar1TYPE(text)(ncid, varid, index, &text);
2247    IF (err != NC_NOERR)
2248        error("put_var1_text_all: %s", APIFunc(strerror)(err));
2249
2250    /* get all variables & check all values equal default fill */
2251    for (i = 0; i < numVars; i++) {
2252        ifdef(`PNETCDF', `if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */')
2253        switch (var_type[i]) {
2254            case NC_CHAR:   fill = (double)NC_FILL_CHAR;   break;
2255            case NC_BYTE:   fill = (double)NC_FILL_BYTE;   break;
2256            case NC_SHORT:  fill = (double)NC_FILL_SHORT;  break;
2257            case NC_INT:    fill = (double)NC_FILL_INT;    break;
2258            case NC_FLOAT:  fill = (double)NC_FILL_FLOAT;  break;
2259            case NC_DOUBLE: fill = (double)NC_FILL_DOUBLE; break;
2260            case NC_UBYTE:  fill = (double)NC_FILL_UBYTE;  break;
2261            case NC_USHORT: fill = (double)NC_FILL_USHORT; break;
2262            case NC_UINT:   fill = (double)NC_FILL_UINT;   break;
2263            case NC_INT64:  fill = (double)NC_FILL_INT64;  break;
2264            case NC_UINT64: fill = (double)NC_FILL_UINT64; break;
2265            default: assert(0);
2266        }
2267        for (j = 0; j < var_nels[i]; j++) {
2268            err = toMixedBase(j, var_rank[i], var_shape[i], index);
2269            IF (err != 0) error("error in toMixedBase");
2270            if (var_type[i] == NC_CHAR) {
2271                err = GetVar1TYPE(text)(ncid, i, index, &text);
2272                IF (err != NC_NOERR)
2273                    error("get_var1_text_all failed: %s", APIFunc(strerror)(err));
2274                value = text;
2275            } else {
2276                err = GetVar1TYPE(double)(ncid, i, index, &value);
2277                IF (err != NC_NOERR)
2278                    error("get_var1_double_all failed: %s", APIFunc(strerror)(err));
2279            }
2280            IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
2281                error("\n\t\t%s Value expected: %-23.17e,\n\t\t          read: %-23.17e\n",
2282                        var_name[i],fill, value);
2283            ELSE_NOK
2284        }
2285    }
2286
2287    /* close scratch & create again for test using attribute _FillValue */
2288    err = APIFunc(close)(ncid);
2289    IF (err != NC_NOERR)
2290        error("close: %s", APIFunc(strerror)(err));
2291    err = FileCreate(scratch, NC_CLOBBER, &ncid);
2292    IF (err != NC_NOERR) {
2293        error("create: %s", APIFunc(strerror)(err));
2294        return nok;
2295    }
2296    def_dims(ncid);
2297    Def_Vars(ncid, numVars);
2298
2299    /* set _FillValue = 42 for all vars */
2300    fill = 42;
2301    text = 42;
2302    for (i = 0; i < numVars; i++) {
2303        if (var_type[i] == NC_CHAR) {
2304            err = APIFunc(put_att_text)(ncid, i, "_FillValue", 1, &text);
2305            IF (err != NC_NOERR)
2306                error("put_att_text: %s", APIFunc(strerror)(err));
2307        } else {
2308            err = APIFunc(put_att_double)(ncid, i, "_FillValue",var_type[i],1,&fill);
2309            IF (err != NC_NOERR)
2310                error("put_att_double: %s", APIFunc(strerror)(err));
2311        }
2312    }
2313
2314    /* data mode. write records */
2315    err = APIFunc(enddef)(ncid);
2316    IF (err != NC_NOERR)
2317        error("enddef: %s", APIFunc(strerror)(err));
2318    index[0] = NRECS;
2319
2320ifdef(`PNETCDF', `
2321    for (i=0; i<=index[0]; i++)
2322        err = APIFunc(fill_var_rec)(ncid, varid, i);')dnl
2323
2324    err = PutVar1TYPE(text)(ncid, varid, index, &text);
2325    IF (err != NC_NOERR)
2326        error("put_var1_text_all: %s", APIFunc(strerror)(err));
2327
2328    /* get all variables & check all values equal 42 */
2329    for (i = 0; i < numVars; i++) {
2330        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
2331        for (j = 0; j < var_nels[i]; j++) {
2332            err = toMixedBase(j, var_rank[i], var_shape[i], index);
2333            IF (err != 0) error("error in toMixedBase");
2334            if (var_type[i] == NC_CHAR) {
2335                err = GetVar1TYPE(text)(ncid, i, index, &text);
2336                IF (err != NC_NOERR)
2337                    error("get_var1_text_all failed: %s", APIFunc(strerror)(err));
2338                value = text;
2339            } else {
2340                err = GetVar1TYPE(double)(ncid, i, index, &value);
2341                IF (err != NC_NOERR)
2342                    error("get_var1_double_all failed: %s", APIFunc(strerror)(err));
2343            }
2344            IF (value != fill)
2345                error(" %s Value expected: %g, read: %g\n", var_name[i],fill, value);
2346            ELSE_NOK
2347        }
2348    }
2349
2350    /* enter redef mode and add a new variable, check NC_ELATEFILL */
2351    err = APIFunc(redef)(ncid);
2352    IF (err != NC_NOERR)
2353        error("redef: %s", APIFunc(strerror)(err));
2354
2355    /* it is not allowed to define fill value when variable already exists */
2356    err = APIFunc(def_var_fill)(ncid, 0, 0, &value);
2357    IF (err != NC_ELATEFILL)
2358        error("redef: expect NC_ELATEFILL but got %s", nc_err_code_name(err));
2359    err = APIFunc(def_var)(ncid, "new_var", NC_INT, 0, NULL, &varid);
2360    IF (err != NC_NOERR)
2361        error("redef: %s", APIFunc(strerror)(err));
2362    err = APIFunc(def_var_fill)(ncid, varid, 0, &value);
2363    IF (err != NC_NOERR)
2364        error("def_var_fill: %s", APIFunc(strerror)(err));
2365
2366    err = APIFunc(close)(ncid);
2367    IF (err != NC_NOERR)
2368        error("close: %s", APIFunc(strerror)(err));
2369    err = FileDelete(scratch, info);
2370    IF (err != NC_NOERR)
2371        error("remove of %s failed", scratch);
2372
2373    return nok;
2374}
2375
2376
2377/* This function gets the version of a netCDF file, 1 is for netCDF
2378   classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format,
2379   5 for 64-bit data format (CDF-5).
2380*/
2381#define MAGIC_NUM_LEN 4
2382static
2383int
2384APIFunc(get_file_version)(char *path, int *version)
2385{
2386   int fd;
2387   ssize_t read_len;
2388   char magic[MAGIC_NUM_LEN];
2389
2390   /* Need two valid pointers - check for NULL. */
2391   if (!version || !path)
2392      return NC_EINVAL;
2393
2394   /* Figure out if this is a netcdf or hdf5 file. */
2395   fd = open(path, O_RDONLY, 0600);
2396   if (fd == -1) return errno;
2397
2398   read_len = read(fd, magic, MAGIC_NUM_LEN);
2399   if (-1 == close(fd)) return errno;
2400
2401   if (read_len == -1)
2402       return errno;
2403
2404   if (read_len != MAGIC_NUM_LEN) {
2405       printf("Error: reading NC magic string unexpected short read\n");
2406       return 0;
2407   }
2408
2409   if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0) {
2410      if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC ||
2411          magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET
2412#ifdef ENABLE_CDF5
2413          || magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5
2414#endif
2415)
2416         *version = magic[MAGIC_NUM_LEN-1];
2417      else
2418        return NC_ENOTNC;
2419   }
2420   /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
2421       away! */
2422   /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
2423      *version = 3;*/
2424   return NC_NOERR;
2425}
2426
2427/*
2428 * Test APIFunc(set_default_format)
2429 *    try with bad default format
2430 *    try with NULL old_formatp
2431 *    try in data mode, check error
2432 *    check that proper set to NC_FILL works for record & non-record variables
2433 *    (note that it is not possible to test NC_NOFILL mode!)
2434 *    close file & create again for test using attribute _FillValue
2435 */
2436int
2437TestFunc(set_default_format)(void)
2438{
2439    int ncid, nok=0;
2440    int err;
2441    int i;
2442    int version=1;
2443    int old_format;
2444
2445    /* bad format */
2446    err = APIFunc(set_default_format)(BAD_DEFAULT_FORMAT, &old_format);
2447    IF (err != NC_EINVAL)
2448        error("expecting NC_EINVAL but got %s", nc_err_code_name(err));
2449    ELSE_NOK
2450
2451    /* NULL old_formatp */
2452    err = APIFunc(set_default_format)(NC_FORMAT_64BIT_OFFSET, NULL);
2453    IF (err != NC_NOERR)
2454       error("null old_fortmatp: status = %d", err);
2455    ELSE_NOK
2456
2457    /* Cycle through available formats. */
2458
2459    for(i=NC_FORMAT_CLASSIC; i<NC_FORMAT_64BIT_DATA; i++) {
2460       if (i == NC_FORMAT_NETCDF4 || i == NC_FORMAT_NETCDF4_CLASSIC)
2461           continue; /* test classic formats only */
2462       if ((err = APIFunc(set_default_format)(i, NULL)))
2463           error("setting classic format: status = %d", err);
2464       ELSE_NOK
2465       err = FileCreate(scratch, NC_CLOBBER, &ncid);
2466       if (err != NC_NOERR)
2467           error("bad nc_create: status = %d", err);
2468       err = APIFunc(put_att_text)(ncid, NC_GLOBAL, "testatt", sizeof("blah"), "blah");
2469       if (err != NC_NOERR)
2470           error("bad put_att: status = %d", err);
2471       err = APIFunc(close)(ncid);
2472       if (err != NC_NOERR)
2473           error("bad close: status = %d", err);
2474       err = APIFunc(get_file_version)(scratch, &version);
2475       if (err != NC_NOERR)
2476           error("bad file version = %d", err);
2477       if (version != i) {
2478#if 0
2479          if (i == 4) {
2480              if (version == 3) continue;
2481              printf("expect version 3 but got %d (file=%s)",version,scratch);
2482              continue;
2483          }
2484#endif
2485          printf("expect version %d but got %d (file=%s)",i,version,scratch);
2486          error("bad file version = %d", version);
2487        }
2488    }
2489
2490    /* Remove the left-over file. */
2491    err = FileDelete(scratch, info);
2492    IF (err != NC_NOERR)
2493        error("remove of %s failed", scratch);
2494
2495    return nok;
2496}
2497
2498
2499
2500
2501/*
2502 * Test FileDelete
2503 *         create netcdf file 'scratch.nc' with no data, close it
2504 *         delete the file
2505 */
2506int
2507TestFunc(delete)(void)
2508{
2509    int err, nok=0;
2510    int ncid;
2511
2512    err = FileCreate(scratch, NC_CLOBBER, &ncid);
2513    IF (err != NC_NOERR)
2514        error("error creating scratch file %s, status = %d\n", scratch,err);
2515    err = APIFunc(close)(ncid);
2516    IF (err != NC_NOERR)
2517        error("close: %s", APIFunc(strerror)(err));
2518    err = FileDelete(scratch, info);
2519    IF (err != NC_NOERR)
2520        error("remove of %s failed", scratch);
2521    ELSE_NOK
2522    return nok;
2523}
2524