1/*********************************************************************
2 *   Copyright 1993, University Corporation for Atmospheric Research
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/nctest/rec.c,v 1.11 2006/10/31 16:21:58 ed Exp $
5 *********************************************************************/
6
7#include <config.h>
8#include <stdio.h>
9#include <stdlib.h> /* for free() */
10#include "netcdf.h"
11#include "testcdf.h" /* defines in-memory test cdf structure */
12#include "emalloc.h"
13#include "val.h"
14#include "error.h"
15#include "tests.h"
16
17/*
18 * Returns number of record variables in an open netCDF file, and an array of
19 * the record variable ids, if the array parameter is non-null.  Returns -1 on
20 * error.
21 */
22static int
23numrecvars(ncidrecvarids)
24     int ncid;
25     int *recvarids;
26{
27    int ndimsivnvars;
28    int nrecvars;
29    int recdimid;
30    int dimids[MAX_NC_DIMS];
31
32    if (ncinquire(ncid, 0, &nvars, 0, &recdimid) == -1)
33      return -1;
34    if (recdimid == -1)
35      return 0;
36    nrecvars = 0;
37    for (iv = 0; iv < nvarsiv++) {
38 if (ncvarinq(ncidiv, 0, 0, &ndimsdimids, 0) == -1)
39   return -1;
40 if (ndims > 0 && dimids[0] == recdimid) {
41     if (recvarids)
42       recvarids[nrecvars] = iv;
43     nrecvars++;
44 }
45    }
46    return nrecvars;
47}
48
49
50/*
51 * Returns record size (in bytes) of the record variable with a specified
52 * variable id.  Returns 0 if not a record variable.  Returns -1 on error.
53 */
54static long
55ncrecsize(ncid,vid)
56     int ncid;
57     int vid;
58{
59    int recdimid;
60    nc_type type;
61    int ndims;
62    int dimids[MAX_NC_DIMS];
63    int id;
64    long size;
65
66    if (ncinquire(ncid, 0, 0, 0, &recdimid) == -1)
67      return -1;
68    if (ncvarinq(ncidvid, 0, &type, &ndimsdimids, 0) == -1)
69      return -1;
70    if (ndims == 0 || dimids[0] != recdimid)
71      return 0;
72    size = nctypelen(type);
73    for (id = 1; id < ndimsid++) {
74 long len;
75 (void) ncdiminq(nciddimids[id], 0, &len);
76 size *= len;
77    }
78    return size;
79}
80
81
82/*
83 * Retrieves the number of record variables, the record variable ids, and the
84 * record size of each record variable.  If any pointer to info to be returned
85 * is null, the associated information is not returned.  Returns -1 on error.
86 * This is the same as the ncrecinq() in the library, except that can handle
87 * errors better.
88 */
89static int
90recinq(ncidnrecvarsrecvaridsrecsizes)
91     int ncid;
92     int *nrecvars;
93     int *recvarids;
94     long *recsizes;
95{
96    int iv;
97    int rvarids[MAX_NC_VARS];
98    int nrvars = numrecvars(ncidrvarids);
99
100    if (nrvars == -1)
101      return -1;
102
103    if (nrecvars)
104      *nrecvars = nrvars;
105    if (recvarids)
106      for (iv = 0; iv < nrvarsiv++)
107 recvarids[iv] = rvarids[iv];
108    if (recsizes)
109      for (iv = 0; iv < nrvarsiv++)
110 recsizes[iv] = ncrecsize(ncidrvarids[iv]);
111    return 0;
112}
113
114
115/*
116 * Test ncrecinq
117 *    try in both data and define modes
118 *    check returned values against independently computed values
119 *    try with bad netCDF handle, check error
120 */
121int
122test_ncrecinq(path)
123     const char *path; /* name of netcdf file to open */
124{
125    int nerrs = 0;
126    static char pname[] = "test_ncrecinq";
127    int ncid;
128    int nrvars; /* number of record variables */
129    int rvarids[MAX_NC_VARS]; /* id of each record variable */
130    long rvarsizes[MAX_NC_VARS]; /* record size of each record variable */
131    int tnrvars; /* true number of record variables */
132    int trvarids[MAX_NC_VARS]; /* true id of each record variable */
133    long trvarsizes[MAX_NC_VARS]; /* true rec size of each record variable */
134    int iv;
135
136    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
137
138    if ((ncid = ncopen(pathNC_WRITE)) == -1) {
139 error("%s: ncopen failed", pname);
140 return ++nerrs;
141    }
142
143    /* First compute independently what ncrecinq should return */
144    if (recinq(ncid, &tnrvarstrvaridstrvarsizes) == -1) {
145 error("%s: recinq failed", pname);
146 ncclose(ncid);
147 return ++nerrs;
148    }
149
150    /* check that ncrecinq() returns correct information in data mode */
151    if (ncrecinq(ncid, &nrvarsrvaridsrvarsizes) == -1) {
152 error("%s: ncrecinq failed", pname);
153 ncclose(ncid);
154 return ++nerrs;
155    }
156
157    if (nrvars != tnrvars) {
158 error("ncrecinq returned wrong number of rec vars, %d != %d",
159       nrvarstnrvars);
160 nerrs++;
161    }
162
163    for (iv = 0; iv < nrvarsiv++) {
164 if (rvarids[iv] != trvarids[iv]) {
165     error("ncrecinq returned wrong record id for var %d",
166   trvarids[iv]);
167     nerrs++;
168 }
169 if (rvarsizes[iv] != trvarsizes[iv]) {
170     error("ncrecinq returned wrong record size for var %d",
171   trvarids[iv]);
172     nerrs++;
173 }
174    }
175
176    if (ncredef(ncid) == -1) {
177 error("%s: ncredef failed", pname);
178 ncclose(ncid);
179 return ++nerrs;
180    }
181    /* check that ncrecinq() returns correct information in define mode too */
182    if (ncrecinq(ncid, &nrvarsrvaridsrvarsizes) == -1) {
183 error("%s: ncrecinq failed in define mode", pname);
184 ncclose(ncid);
185 return ++nerrs;
186    }
187    if (nrvars != tnrvars) {
188 error("define mode, ncrecinq returned wrong num of rec vars, %d != %d",
189       nrvarstnrvars);
190 nerrs++;
191    }
192    for (iv = 0; iv < nrvarsiv++) {
193 if (rvarids[iv] != trvarids[iv]) {
194     error("define mode, ncrecinq returned wrong record id for var %d",
195   trvarids[iv]);
196     nerrs++;
197 }
198 if (rvarsizes[iv] != trvarsizes[iv]) {
199     error("define mode, ncrecinq returned wrong rec size for var %d",
200   trvarids[iv]);
201     nerrs++;
202 }
203    }
204
205    if (ncclose (ncid) == -1) {
206 error("%s: ncclose failed", pname);
207 return ++nerrs;
208    }
209
210    if (ncrecinq(ncid, &nrvarsrvaridsrvarsizes) != -1) {
211 error("%s: ncrecinq failed to report bad handle", pname);
212 nerrs++;
213    }
214
215    if (nerrs > 0)
216      (void) fprintf(stderr,"FAILED! ***\n");
217    else
218      (void) fprintf(stderr,"ok ***\n");
219    return nerrs;
220}
221
222
223/*
224 * Retrieves the dimension sizes of a variable with a specified variable id in
225 * an open netCDF file.  Returns -1 on error.
226 */
227static int
228dimsizes(ncidvaridsizes)
229     int ncid;
230     int varid;
231     long *sizes;
232{
233    int ndims;
234    int id;
235    int dimids[MAX_NC_DIMS];
236
237    if (ncvarinq(ncidvarid, 0, 0, &ndimsdimids, 0) == -1)
238      return -1;
239    if (ndims == 0 || sizes == 0)
240      return 0;
241    for (id = 0; id < ndimsid++)
242      (void) ncdiminq(nciddimids[id], 0, &sizes[id]);
243    return 0;
244}
245
246
247/*
248 * Write one record's worth of data, except don't write to variables for which
249 * the address of the data to be written is NULL.  Return -1 on error.  This is
250 * the same as the ncrecput() in the library, except that can handle errors
251 * better.
252 */
253static int
254recput(ncidrecnumdatap)
255     int ncid;
256     long recnum;
257     void **datap;
258{
259    int iv;
260    int rvids[MAX_NC_VARS];
261    int nrvars = numrecvars(ncidrvids);
262    long start[MAX_NC_DIMS];
263    long edges[MAX_NC_DIMS];
264
265    if (nrvars == -1)
266      return -1;
267
268    start[0] = recnum;
269    for (iv = 1; iv < nrvarsiv++)
270 start[iv] = 0;
271
272    for (iv = 0; iv < nrvarsiv++) {
273 if (datap[iv] != 0) {
274     (void) dimsizes(ncidrvids[iv], edges);
275     edges[0] = 1; /* only 1 record's worth */
276     if (ncvarput(ncidrvids[iv], startedgesdatap[iv]) == -1)
277       return -1;
278 }
279    }
280    return 0;
281}
282
283
284/*
285 * Read one record's worth of data, except don't read from variables for which
286 * the address of the data to be read is null.  Return -1 on error.  This is
287 * the same as the ncrecget() in the library, except that can handle errors
288 * better.
289 */
290static int
291recget(ncidrecnumdatap)
292     int ncid;
293     long recnum;
294     void **datap;
295{
296    int iv;
297    int rvids[MAX_NC_VARS];
298    int nrvars = numrecvars(ncidrvids);
299    long start[MAX_NC_DIMS];
300    long edges[MAX_NC_DIMS];
301
302    if (nrvars == -1)
303      return -1;
304
305    start[0] = recnum;
306    for (iv = 1; iv < nrvarsiv++)
307 start[iv] = 0;
308
309    for (iv = 0; iv < nrvarsiv++) {
310 if (datap[iv] != 0) {
311     (void) dimsizes(ncidrvids[iv], edges);
312     edges[0] = 1; /* only 1 record's worth */
313     if (ncvarget(ncidrvids[iv], startedgesdatap[iv]) == -1)
314       return -1;
315 }
316    }
317    return 0;
318}
319
320
321/*
322 * Test ncrecput
323 *    check that proper call works putting all recoerd variables
324 *    try putting only a proper subset of variables
325 *    try putting the empty subset of variables
326 *    try in define mode, check error
327 *    try with bad netCDF handle, check error
328 */
329int
330test_ncrecput(path)
331     const char *path; /* name of writable netcdf file to open */
332{
333    int nerrs = 0;
334    static char pname[] = "test_ncrecput";
335    int nrvars; /* number of record variables */
336    int rvarids[MAX_NC_VARS]; /* id of each record variable */
337    long rvarsizes[MAX_NC_VARS]; /* record size of each record variable */
338    int ncid; /* netcdf id */
339    void *datap[MAX_NC_VARS]; /* array of address pointers for rec vars */
340    void *datar[MAX_NC_VARS]; /* pointers for comparison data */
341    long recnum = 1; /* we'll write the second record */
342    int iv;
343    long recsize[MAX_NC_VARS]; /* record size in data elements */
344    nc_type vartype[MAX_NC_VARS];
345    void *zeros[MAX_NC_VARS];
346
347    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
348
349    if ((ncid = ncopen(pathNC_WRITE)) == -1) {
350 error("%s: ncopen failed", pname);
351 return ++nerrs;
352    }
353
354    if (ncrecinq(ncid, &nrvarsrvaridsrvarsizes) == -1) {
355 error("%s: ncrecinq failed", pname);
356 ncclose(ncid);
357 return ++nerrs;
358    }
359
360    /* get a block of data of the right type for each record variable */
361    for (iv = 0; iv < nrvarsiv++) {
362 datap[iv] = emalloc(rvarsizes[iv]);
363 datar[iv] = emalloc(rvarsizes[iv]); /* for comparison values */
364 if (ncvarinq(ncidrvarids[iv], 0, &vartype[iv], 0, 0, 0) == -1) {
365     error("%s: ncvarinq failed", pname);
366     ncclose(ncid);
367     return ++nerrs;
368 }
369 recsize[iv] = rvarsizes[iv]/nctypelen(vartype[iv]);
370 /* Fill data blocks with 0,1,2,3,... */
371 val_fill(vartype[iv], recsize[iv], datap[iv]);
372 /* Zero out comparison data */
373 val_fill_zero(vartype[iv], recsize[iv], datar[iv]);
374    }
375
376    /* Zero data in recnum record, before trying to put non-zero data */
377    if (recput(ncidrecnumdatar) == -1) {
378 error("%s: recput failed", pname);
379 ncclose(ncid);
380 return ++nerrs;
381    }
382
383    /* opened in data mode, try putting a complete record */
384    if (ncrecput(ncidrecnumdatap) == -1) {
385 error("%s: ncrecput failed on complete record", pname);
386 nerrs++;
387    }
388
389    /* Check that right values were put */
390    if (recget(ncidrecnumdatar) == -1) {
391 error("%s: recget failed", pname);
392 nerrs++;
393    }
394    for (iv = 0; iv < nrvarsiv++) {
395 if (val_cmp(vartype[iv], recsize[iv], datap[iv], datar[iv]) != 0) {
396     error("%s: bad values written by recput", pname);
397     nerrs++;
398 }
399 val_fill_zero(vartype[iv], recsize[iv], datap[iv]);
400 val_fill_zero(vartype[iv], recsize[iv], datar[iv]);
401 zeros[iv] = 0;
402    }
403
404    if (nrvars > 0) {
405 void *datap0 = datap[0];
406
407 /* put a partial record, everything but first record variable */
408 datap[0] = 0;
409 val_fill(vartype[0], recsize[0], datar[0]);
410 if (ncrecput(ncidrecnumdatap) == -1) {
411     error("%s: ncrecput failed on partial record", pname);
412     nerrs++;
413 }
414
415 /* Check right values were put, first record variable undisturbed */
416 datap[0] = datap0;
417 if (recget(ncidrecnumdatap) == -1) {
418     error("%s: recget failed after partial record put", pname);
419     nerrs++;
420 }
421 for (iv = 0; iv < nrvarsiv++) {
422     if (val_cmp(vartype[iv], recsize[iv], datap[iv], datar[iv]) != 0) {
423 error("%s: bad values written by partial recput", pname);
424 nerrs++;
425     }
426 }
427    }
428
429    /* Put an empty record, check that values remain undisturbed */
430    if (ncrecput(ncidrecnumzeros) == -1) {
431 error("%s: ncrecput failed on empty record", pname);
432 nerrs++;
433    }
434    if (recget(ncidrecnumdatap) == -1) {
435 error("%s: recget failed after empty record put", pname);
436 nerrs++;
437    }
438    for (iv = 0; iv < nrvarsiv++) {
439 if (val_cmp(vartype[iv], recsize[iv], datap[iv], datar[iv]) != 0) {
440     error("%s: bad values written by empty recput", pname);
441     nerrs++;
442 }
443    }
444
445    /* try in define mode, check error */
446    if (ncredef(ncid) == -1) {
447 error("%s: ncredef failed", pname);
448  ncclose(ncid);
449 return ++nerrs;
450    }
451
452    if (ncrecput(ncidrecnumdatap) != -1) {
453 error("%s: ncrecput should fail in define mode", pname);
454 nerrs++;
455    }
456
457    /* try with bad netCDF handle, check error */
458    if (ncclose (ncid) == -1) {
459 error("%s: ncclose failed", pname);
460 return ++nerrs;
461    }
462    if (ncrecput(ncidrecnumdatap) != -1) {
463 error("%s: ncrecput failed to report bad handle", pname);
464 nerrs++;
465    }
466    for (iv = 0; iv < nrvarsiv++) {
467 free(datap[iv]);
468 free(datar[iv]);
469    }
470
471    if (nerrs > 0)
472      (void) fprintf(stderr,"FAILED! ***\n");
473    else
474      (void) fprintf(stderr,"ok ***\n");
475
476    return nerrs;
477}
478
479
480/*
481 * Test ncrecget
482 *    check that proper call works getting all record variables
483 *    try getting only a proper subset of variables
484 *    try getting the empty subset of variables
485 *    try with bad netCDF handle, check error
486 */
487int
488test_ncrecget(path)
489     const char *path; /* name of netcdf file to open */
490{
491    int nerrs = 0;
492    static char pname[] = "test_ncrecget";
493    int nrvars; /* number of record variables */
494    int rvarids[MAX_NC_VARS]; /* id of each record variable */
495    long rvarsizes[MAX_NC_VARS]; /* record size of each record variable */
496    int ncid; /* netcdf id */
497    void *datap[MAX_NC_VARS]; /* array of address pointers for rec vars */
498    void *datar[MAX_NC_VARS]; /* pointers for comparison data */
499    long recnum = 1; /* we'll write the second record */
500    int iv;
501    long recsize[MAX_NC_VARS]; /* record size in data elements */
502    nc_type vartype[MAX_NC_VARS];
503    void *zeros[MAX_NC_VARS];
504
505    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
506
507    if ((ncid = ncopen(pathNC_WRITE)) == -1) {
508 error("%s: ncopen failed", pname);
509 return ++nerrs;
510    }
511
512    if (ncrecinq(ncid, &nrvarsrvaridsrvarsizes) == -1) {
513 error("%s: ncrecinq failed", pname);
514 ncclose(ncid);
515 return ++nerrs;
516    }
517
518    /* get a block of data of the right type for each record variable */
519    for (iv = 0; iv < nrvarsiv++) {
520 datap[iv] = emalloc(rvarsizes[iv]);
521 datar[iv] = emalloc(rvarsizes[iv]); /* for comparison values */
522 if (ncvarinq(ncidrvarids[iv], 0, &vartype[iv], 0, 0, 0) == -1) {
523     error("%s: ncvarinq failed", pname);
524     ncclose(ncid);
525     return ++nerrs;
526 }
527 recsize[iv] = rvarsizes[iv]/nctypelen(vartype[iv]);
528 /* Fill data blocks with 0,1,2,3,... */
529 val_fill(vartype[iv], recsize[iv], datap[iv]);
530 /* Zero out comparison data */
531 val_fill_zero(vartype[iv], recsize[iv], datar[iv]);
532    }
533
534    if (recput(ncidrecnumdatap) == -1) {
535 error("%s: recput failed", pname);
536 ncclose(ncid);
537 return ++nerrs;
538    }
539
540    /* opened in data mode, try getting a complete record */
541    if (recget(ncidrecnumdatap) == -1) {
542 error("%s: recget failed on complete record", pname);
543 nerrs++;
544    }
545    if (ncrecget(ncidrecnumdatar) == -1) {
546 error("%s: ncrecget failed on complete record", pname);
547 nerrs++;
548    }
549
550    for (iv = 0; iv < nrvarsiv++) {
551 if (val_cmp(vartype[iv], recsize[iv], datap[iv], datar[iv]) != 0) {
552     error("%s: bad values written by recget", pname);
553     nerrs++;
554 }
555 val_fill_zero(vartype[iv], recsize[iv], datap[iv]);
556 val_fill_zero(vartype[iv], recsize[iv], datar[iv]);
557 zeros[iv] = 0;
558    }
559
560    if (nrvars > 0) {
561 void *datap0 = datap[0];
562 void *datar0 = datar[0];
563
564 /* get a partial record, everything but first record variable */
565 datap[0] = 0;
566 if (ncrecget(ncidrecnumdatap) == -1) {
567     error("%s: ncrecget failed on partial record", pname);
568     nerrs++;
569 }
570 datar[0] = 0;
571 if (recget(ncidrecnumdatar) == -1) {
572     error("%s: recget failed on partial record", pname);
573     nerrs++;
574 }
575 /* Check right values were got, first record variable undisturbed */
576 datap[0] = datap0;
577 datar[0] = datar0;
578 for (iv = 0; iv < nrvarsiv++) {
579     if (val_cmp(vartype[iv], recsize[iv], datap[iv], datar[iv]) != 0) {
580 error("%s: bad values read by partial recget", pname);
581 nerrs++;
582     }
583 }
584    }
585
586    /* Get an empty record */
587    if (ncrecget(ncidrecnumzeros) == -1) {
588 error("%s: ncrecget failed on empty record", pname);
589 nerrs++;
590    }
591
592    /* try with bad netCDF handle, check error */
593    if (ncclose (ncid) == -1) {
594 error("%s: ncclose failed", pname);
595 return ++nerrs;
596    }
597    if (ncrecget(ncidrecnumdatap) != -1) {
598 error("%s: ncrecget failed to report bad handle", pname);
599 nerrs++;
600    }
601    for (iv = 0; iv < nrvarsiv++) {
602 free(datap[iv]);
603 free(datar[iv]);
604    }
605
606    if (nerrs > 0)
607      (void) fprintf(stderr,"FAILED! ***\n");
608    else
609      (void) fprintf(stderr,"ok ***\n");
610
611    return nerrs;
612}
613


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