1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/nctest/vardef.c,v 1.18 2009/10/28 18:30:50 dmh Exp $
5 *********************************************************************/
6
7#include <config.h>
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h> /* for free() */
11#ifndef NO_FLOAT_H
12#include <float.h> /* for FLT_EPSILON, DBL_EPSILON */
13#endif /* NO_FLOAT_H */
14#include <netcdf.h>
15#include "testcdf.h" /* defines in-memory test cdf structure */
16#include "emalloc.h"
17#include "add.h" /* functions to update in-memory netcdf */
18#include "error.h"
19#include "tests.h"
20
21#define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
22
23static float float_eps;
24static double double_eps;
25
26static float
27float_epsilon()
28{
29    float float_eps;
30#ifndef NO_FLOAT_H
31    float_eps = FLT_EPSILON;
32#else /* NO_FLOAT_H */
33    {
34 float etopeboteps;
35 float one = 1.0;
36 float two = 2.0;
37 etop = 1.0;
38 ebot = 0.0;
39 eps = ebot + (etop - ebot)/two;
40 while (eps != ebot && eps != etop) {
41     float epsp1;
42
43     epsp1 = one + eps;
44     if (epsp1 > one)
45 etop = eps;
46     else
47 ebot = eps;
48     eps = ebot + (etop - ebot)/two;
49 }
50 float_eps = two * etop;
51    }
52#endif /* NO_FLOAT_H */
53    return float_eps;
54}
55
56
57static double
58double_epsilon()
59{
60    double double_eps;
61#ifndef NO_FLOAT_H
62    double_eps = DBL_EPSILON;
63#else /* NO_FLOAT_H */
64    {
65 double etopeboteps;
66 double one = 1.0;
67 double two = 2.0;
68 etop = 1.0;
69 ebot = 0.0;
70 eps = ebot + (etop - ebot)/two;
71 while (eps != ebot && eps != etop) {
72     double epsp1;
73
74     epsp1 = one + eps;
75     if (epsp1 > one)
76 etop = eps;
77     else
78 ebot = eps;
79     eps = ebot + (etop - ebot)/two;
80 }
81 double_eps = two * etop;
82    }
83#endif /* NO_FLOAT_H */
84    return double_eps;
85}
86
87
88static void
89init_epsilons()
90{
91    float_eps = float_epsilon();
92    double_eps = double_epsilon();
93}
94
95
96/*
97 * Test ncvardef
98 *    check that proper define worked with ncvarinq
99 *    check that returned id is one more than previous id
100 *    try redefining an existing variable, check error
101 *    try adding scalar variable (no dimensions)
102 *    try with bad datatype, check error
103 *    try with bad number of dimensions, check error
104 *    try with bad dimension ids, check error
105 *    try in data mode, check error
106 */
107int
108test_ncvardef(path)
109     const char *path; /* name of writable netcdf file to open */
110{
111    int nerrs = 0;
112    int cdfid; /* netcdf id */
113    static char pname[] = "test_ncvardef";
114    int idiv;
115    static struct cdfvar va[] = { /* variables of all shapes and sizes */
116 {"bytev", NC_BYTE, 6, ___, 0},
117 {"charv", NC_CHAR, 5, ___, 0},
118 {"shortv", NC_SHORT, 4, ___, 0},
119 {"longv", NC_LONG, 3, ___, 0},
120 {"floatv", NC_FLOAT, 2, ___, 0},
121 {"doublev", NC_DOUBLE, 1, ___, 0},
122 {"scalarv", NC_DOUBLE, 0, ___, 0}
123    };
124    int nv = LEN_OF(va); /* number of variables to define */
125    int va_id[LEN_OF(va)]; /* variable ids */
126    static struct cdfvar tmp = /* variable for testing bad types, etc. */
127 {"tmpv", NC_DOUBLE, 1, ___, 0};
128    /* if d5 >= 91 in following, problem on machines with 16-bit ints ??? */
129    static struct cdfdim di[] = { /* a bunch of dimensions */
130 {"d0", 2}, {"d1",3}, {"d2",5}, {"d3", 6}, {"d4", 4}, {"d5", 31}};
131    int nd = LEN_OF(di); /* number of dimensions */
132    int di_id[LEN_OF(di)]; /* dimension ids */
133
134    (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
135
136    init_epsilons();
137    if ((cdfid = ncopen(pathNC_WRITE)) == -1) {
138 error("%s: ncopen failed", pname);
139 return ++nerrs;
140    }
141    /* opened, defining a variable should fail in data mode */
142    if (ncvardef(cdfidva[0].nameva[0].typeva[0].ndimsva[0].dims)
143 != -1) {
144 error("%s: ncvardef should have failed in data mode", pname);
145 ncclose(cdfid); return ++nerrs;
146    }
147    /* enter define mode */
148    if (ncredef(cdfid) == -1) {
149 error("%s: cdredef failed", pname);
150 ncclose(cdfid); return ++nerrs;
151    }
152
153    /* Add nd more dimensions */
154    for (id = 0; id < ndid++) {
155 if ((di_id[id] = ncdimdef(cdfiddi[id].namedi[id].size)) == -1) {
156     error("%s: ncdimdef failed for %s, size %d",
157   pnamedi[id].namedi[id].size);
158     ncclose(cdfid); return ++nerrs;
159 }
160 add_dim(&test, &di[id]); /* keep in-memory netcdf in sync */
161    }
162
163    tmp.dims = (int *) emalloc(sizeof(int) * MAX_VAR_DIMS);
164    tmp.name = (char *) emalloc(MAX_NC_NAME);
165
166    /* in define mode, add variables of each type with various shapes */
167    for (iv = 0; iv < nviv++) {
168 /* set shape to use subset of dimensions previously defined */
169 va[iv].dims = (int *) emalloc(sizeof(int) * va[iv].ndims);
170 for (id = 0; id < va[iv].ndimsid++)
171   va[iv].dims[id] = di_id[id];
172 if ((va_id[iv] = ncvardef(cdfidva[iv].nameva[iv].type,
173   va[iv].ndimsva[iv].dims)) == -1) {
174     error("%s: ncvardef failed", pname);
175     errvar(&test,&va[iv]); /* prints details about variable */
176     ncclose(cdfid); return ++nerrs;
177 }
178 add_var(&test, &va[iv]); /* keep in-memory netcdf in sync */
179 /* check that var id returned is one more than previous var id */
180 if (va_id[iv] != test.nvars - 1) {
181     error("%s: ncvardef returned %d for var id, expected %d",
182   pnameva_id[iv], test.nvars-1);
183     ncclose(cdfid); return ++nerrs;
184 }
185 /* use ncvarinq to get values just set and compare values */
186 if (ncvarinq(cdfidva_id[iv], tmp.name, &tmp.type,
187       &tmp.ndimstmp.dims, &tmp.natts) == -1) {
188     error("%s: ncvarinq failed", pname);
189     errvar(&test,&va[iv]); /* prints details about variable */
190     ncclose(cdfid); return ++nerrs;
191 }
192 if (strcmp(tmp.nameva[iv].name) != 0 ||
193     tmp.type != va[iv].type ||
194     tmp.ndims != va[iv].ndims ||
195     tmp.natts != va[iv].natts) {
196     error("%s: ncvardef and ncvarinq don't agree for %s",
197   pnameva[iv].name);
198     nerrs++;
199     errvar(&test,&va[iv]);
200     errvar(&test,&tmp);
201 }
202 for (id = 0; id < va[iv].ndimsid++) {
203     if (tmp.dims[id] != va[iv].dims[id]) {
204     error("%s: ncvardef and ncvarinq don't agree on shape of %s",
205   pnameva[iv].name);
206     nerrs++;
207     errvar(&test,&va[iv]);
208     errvar(&test,&tmp);
209     }
210 }
211    }
212    /* try adding same variable again, this should fail */
213    if (ncvardef(cdfidva[0].nameva[0].type,
214   va[0].ndimsva[0].dims) != -1) {
215 error("%s: ncvardef should not allow redefinition", pname);
216 ncclose(cdfid); return ++nerrs;
217    }
218    /* try bad type, should fail */
219    if (ncvardef(cdfid, "badtype", BAD_TYPEva[0].ndimsva[0].dims) != -1) {
220 error("%s: ncvardef should have failed on bad type", pname);
221 ncclose(cdfid); return ++nerrs;
222    }
223    /* try bad ndims, should fail */
224    if (ncvardef(cdfid, "badndims", va[0].type, -1, va[0].dims) != -1) {
225 error("%s: ncvardef should have failed on bad ndims", pname);
226 ncclose(cdfid); return ++nerrs;
227    }
228    /* try bad ids in dims vector, should fail */
229    va[0].dims[va[0].ndims-1] = -1;
230    if (ncvardef(cdfid, "baddims", va[0].typeva[0].ndimsva[0].dims)
231 != -1) {
232 error("%s: ncvardef should have failed on negative dim id in dims",
233       pname);
234 ncclose(cdfid); return ++nerrs;
235    }
236    if (ncendef (cdfid) == -1) {
237 error("%s: ncendef failed", pname);
238 ncclose(cdfid); return ++nerrs;
239    }
240
241    /* try reading a value of each type, should get appropriate fill value */
242    for (iv = 0; iv < nviv++) {
243 static long where[] = {0,0,0,0,0,0};
244
245 switch(va[iv].type) {
246   case NC_BYTE:
247     {
248 char valfillval = FILL_BYTE;
249 if (ncvarget1(cdfidva_id[iv], where, (void *) &val) != -1) {
250     if (val != fillval) {
251 error("%s: unwritten byte not FILL_BYTE", pname);
252 nerrs++;
253     }
254 } else {
255     error("%s: ncvarget1 failure for byte", pname);
256     nerrs++;
257 }
258     }
259     break;
260   case NC_CHAR:
261     {
262 char valfillval = FILL_CHAR;
263 if (ncvarget1(cdfidva_id[iv], where, (void *) &val) != -1) {
264     if (val != fillval) {
265 error("%s: unwritten char not FILL_CHAR", pname);
266 nerrs++;
267     }
268 } else {
269     error("%s: ncvarget1 failure for char", pname);
270     nerrs++;
271 }
272     }
273     break;
274   case NC_SHORT:
275     {
276 short valfillval = FILL_SHORT;
277 if (ncvarget1(cdfidva_id[iv], where, (void *) &val) != -1) {
278     if (val != fillval) {
279 error("%s: unwritten short not FILL_SHORT", pname);
280 nerrs++;
281     }
282 } else {
283     error("%s: ncvarget1 failure for short", pname);
284     nerrs++;
285 }
286     }
287     break;
288   case NC_LONG:
289     {
290 nclong valfillval = FILL_LONG;
291 if (ncvarget1(cdfidva_id[iv], where, (void *) &val) != -1) {
292     if (val != fillval) {
293 error("%s: unwritten long not FILL_LONG", pname);
294 nerrs++;
295     }
296 } else {
297     error("%s: ncvarget1 failure for long", pname);
298     nerrs++;
299 }
300     }
301     break;
302#define absval(x)  ( (x) < 0 ? -(x) : (x) )
303   case NC_FLOAT:
304     {
305 float valfillval = FILL_FLOAT;
306 if (ncvarget1(cdfidva_id[iv], where, (void *) &val) != -1) {
307     if (absval(val-fillval) > absval(float_eps * fillval)) {
308 error("%s: unwritten float not FILL_FLOAT", pname);
309 nerrs++;
310     }
311 } else {
312     error("%s: ncvarget1 failure for float", pname);
313     nerrs++;
314 }
315     }
316     break;
317   case NC_DOUBLE:
318     {
319 double valfillval = FILL_DOUBLE;
320 if (ncvarget1(cdfidva_id[iv], where, (void *) &val) != -1) {
321#define DBL_FUDGE 8.0 /* can be 1.0 on every platform we've seen
322    except for VAX/Ultrix 4.3 with cc */
323     if (absval(val-fillval) > DBL_FUDGE * absval(double_eps * fillval)) {
324 error("%s: unwritten double not FILL_DOUBLE", pname);
325 nerrs++;
326     }
327 } else {
328     error("%s: ncvarget1 failure for double", pname);
329     nerrs++;
330 }
331     }
332     break;
333   default: break;
334 }
335    }
336
337    if (ncclose (cdfid) == -1) {
338 error("%s: ncclose failed", pname);
339 return ++nerrs;
340    }
341    free (tmp.dims);
342    free (tmp.name);
343    for (iv = 0; iv < nviv++)
344      if (va[iv].dims)
345 free(va[iv].dims);
346    if (nerrs > 0)
347      (void) fprintf(stderr,"FAILED! ***\n");
348    else
349      (void) fprintf(stderr,"ok ***\n");
350
351    return nerrs;
352}


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