1 /*********************************************************************
2 * Copyright 2018, UCAR/Unidata
3 * See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 * $Header: /upc/share/CVS/netcdf-3/nctest/cdftests.c,v 1.23 2009/02/14 14:11:28 ed Exp $
5 *********************************************************************/
6
7 #include <config.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h> /* for free() */
11 #include "netcdf.h"
12 #include "emalloc.h"
13 #include "testcdf.h" /* defines in-memory test netcdf structure */
14 #include "add.h" /* functions to update in-memory netcdf */
15 #include "error.h"
16 #include "tests.h"
17
18 #define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
19
20
21 /*
22 * Test nccreate
23 * create a netcdf with no data, close it, test that it can be opened
24 * try again with NC_CLOBBER mode, check that no errors occurred
25 * try again with NC_NOCLOBBER mode, check error return
26 * On exit, netcdf files are closed.
27 * Uses: nccreate, ncendef, ncclose, ncopen.
28 */
29 int
test_nccreate(path)30 test_nccreate(path)
31 const char *path; /* name of netCDF file to create */
32 {
33 int nerrs = 0;
34 static char pname[] = "test_nccreate";
35 int ncid;
36
37 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
38
39 if ((ncid = nccreate(path, NC_CLOBBER)) == -1) {
40 error("%s: nccreate failed to NC_CLOBBER", pname);
41 return 1;
42 }
43 /* in define mode already, so ncredef should fail */
44 if (ncredef(ncid) != -1) {
45 error("%s: ncredef should fail after nccreate", pname);
46 nerrs++;
47 }
48 /* created OK */
49 if (ncendef (ncid) == -1) {
50 error("%s: ncendef failed", pname);
51 nerrs++;
52 }
53 if (ncclose (ncid) == -1) {
54 error("%s: ncclose failed", pname);
55 nerrs++;
56 }
57 if ((ncid = ncopen(path, NC_NOWRITE)) == -1) {
58 error("%s: ncopen of newly created netcdf failed", pname);
59 return ++nerrs;
60 }
61 /* opened OK */
62 if (ncclose (ncid) == -1) {
63 error("%s: second ncclose failed", pname);
64 nerrs++;
65 }
66 /* this call should fail, since we're using NC_NOCLOBBER mode */
67 if (nccreate(path, NC_NOCLOBBER) != -1) {
68 error("%s: nccreate failed to honor NC_NOCLOBBER mode", pname);
69 nerrs++;
70 }
71
72 /* Initialize in-memory netcdf to empty */
73 add_reset(&test);
74 if (nerrs > 0)
75 (void) fprintf(stderr,"FAILED! ***\n");
76 else
77 (void) fprintf(stderr,"ok ***\n");
78
79 return nerrs;
80 }
81
82
83 /*
84 * Test ncopen
85 * try to open a non-existent netCDF, check error return
86 * open a file that is not a netCDF file, check error return
87 * open a netCDF with NC_WRITE mode, write something, close it
88 * open a netCDF with NC_NOWRITE mode, write something and check error
89 * try to open a netcdf twice, check whether returned netcdf ids different
90 * On exit, netcdf files are closed.
91 * Uses: ncopen, ncredef, ncattput, ncendef, ncclose.
92 */
93 #define DATA_LEN 32
94 #define TEMP_FILE_NAME "temp.tmp"
95 int
test_ncopen(path)96 test_ncopen(path)
97 const char *path; /* name of writable netcdf file to open */
98 {
99 int nerrs = 0;
100 static char pname[] = "test_ncopen";
101 int ncid0, ncid1;
102 static char title_val[] = "test netcdf";
103 static char xpath[] = "tooth-fairy.nc"; /* must not exist */
104 static struct cdfatt title = /* attribute */
105 {NC_GLOBAL, "title", NC_CHAR, LEN_OF (title_val), (void *) title_val};
106 FILE *temp;
107 char dummy_data[DATA_LEN];
108 int i;
109
110 /* Initialize to keep valgrind happy. */
111 for (i = 0; i < DATA_LEN; i++)
112 dummy_data[i] = 0;
113
114 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
115
116 /* Open a nonexistent file */
117 if(ncopen(xpath, NC_NOWRITE) != -1) {
118 error("%s: ncopen should fail opening nonexistent file",
119 pname);
120 return ++nerrs;
121 }
122 if (ncerr != NC_SYSERR) {
123 error("%s: ncopen of nonexistent file should set ncerr to %d",
124 pname, NC_SYSERR);
125 }
126 /*
127 * Open a non-netCDF file. Don't use "Makefile.in" because that
128 * name is munged to something else by PC/NFS and, consequently,
129 * won't exist in a cross-mounted directory. Also don't use a
130 * source file, because that will break building in another
131 * directory, and consequently, make dist. An object file is not
132 * safe, because sometimes it's a .o and sometimes a .obj. So just
133 * create a file!
134 */
135 if (!(temp = fopen(TEMP_FILE_NAME, "w+")))
136 {
137 error("could not create temp file");
138 return ++nerrs;
139 }
140 if (fwrite(dummy_data, 1, DATA_LEN, temp) != DATA_LEN)
141 {
142 error("could not write to temp file");
143 return ++nerrs;
144 }
145 if (fclose(temp))
146 {
147 error("could not close temp file");
148 return ++nerrs;
149 }
150
151 if(ncopen(TEMP_FILE_NAME, NC_NOWRITE) != -1) {
152 error("%s: ncopen should fail opening non-netCDF file",
153 pname);
154 return ++nerrs;
155 }
156 if(ncerr != NC_ENOTNC) {
157 error("%s: ncopen of non-netCDF file should set ncerr to %d",
158 pname, NC_ENOTNC);
159 return ++nerrs;
160 }
161
162
163 if ((ncid0 = ncopen(path, NC_WRITE)) == -1) {
164 error("%s: ncopen failed with NC_WRITE mode", pname);
165 return ++nerrs;
166 }
167
168 /* opened */
169 if (ncredef(ncid0) == -1) {
170 error("%s: cdredef failed", pname);
171 ncclose(ncid0); return ++nerrs;
172 }
173 /* in define mode */
174 if (ncattput(ncid0, NC_GLOBAL, "title", NC_CHAR, title.len, title.val)
175 == -1) {
176 error("%s: ncattput failed", pname);
177 ncclose(ncid0); return ++nerrs;
178 }
179 add_att(&test, NC_GLOBAL, &title); /* keep in-memory netcdf updated */
180 if (ncendef (ncid0) == -1) {
181 error("%s: ncendef failed after ncattput", pname);
182 ncclose(ncid0); return ++nerrs;
183 }
184 if (ncclose (ncid0) == -1) {
185 error("%s: ncclose failed in NC_WRITE mode", pname);
186 return ++nerrs;
187 }
188
189 if ((ncid0 = ncopen(path, NC_WRITE)) == -1) {
190 error("%s: ncopen failed with NC_NOWRITE mode", pname);
191 return ++nerrs;
192 }
193 if ((ncid1 = ncopen(path, NC_NOWRITE)) == -1) {
194 #ifndef vms
195 error("%s: second ncopen failed", pname);
196 nerrs++;
197 #else
198 fprintf(stderr,"Doesn't support shared access on vms\n") ;
199 #endif
200 }
201 else
202 {
203 /* this should fail, since in NC_NOWRITE mode */
204 if (ncredef(ncid1) != -1) {
205 error("%s: cdredef should fail after NC_NOWRITE open", pname);
206 ncclose(ncid1); return ++nerrs;
207 }
208 /* second open OK */
209 if (ncid0 == ncid1) {
210 error("%s: ncopen should return new ncid on second open",
211 pname);
212 nerrs++;
213 }
214 if (ncclose (ncid1) == -1) {
215 error("%s: ncclose failed to close after second open", pname);
216 nerrs++;
217 }
218 }
219 if (ncclose (ncid0) == -1) {
220 error("%s: ncclose failed in NC_NOWRITE mode", pname);
221 nerrs++;
222 }
223 if (nerrs > 0)
224 (void) fprintf(stderr,"FAILED! ***\n");
225 else
226 (void) fprintf(stderr,"ok ***\n");
227
228 return nerrs;
229 }
230
231
232 /*
233 * Test ncredef
234 * open a netCDF, enter define mode, add dimension, variable, attribute
235 * try ncredef from within define mode, check error
236 * leave define mode and close, releasing netcdf handle
237 * try ncredef with old handle, check error
238 * On exit netcdf files are closed.
239 * Uses: ncopen, ncredef, ncdimdef, ncvardef, ncattput, ncclose
240 */
241 int
test_ncredef(path)242 test_ncredef(path)
243 const char *path; /* name of writable netcdf file to open */
244 {
245 int nerrs = 0;
246 static char pname[] = "test_ncredef";
247 int ncid; /* netcdf id */
248 int ii_dim; /* dimension id */
249 static struct cdfdim ii = /* dimension */
250 {"ii", 4};
251 int aa_id; /* variable id */
252 static struct cdfvar aa = /* variable */
253 {"aa", NC_LONG, 1, ___, 0};
254 static char units_val[] = "furlongs";
255 static struct cdfatt aa_units = /* attribute */
256 {___, "units", NC_CHAR, LEN_OF(units_val), (void *)units_val};
257
258 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
259
260 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
261 error("%s: ncopen failed", pname);
262 return ++nerrs;
263 }
264 /* opened OK, enter define mode */
265 if (ncredef(ncid) == -1) {
266 error("%s: cdredef failed", pname);
267 ncclose(ncid); return ++nerrs;
268 }
269 /* in define mode OK, add a dimension */
270 if ((ii_dim = ncdimdef(ncid, ii.name, ii.size)) == -1) {
271 error("%s: ncdimdef failed", pname);
272 ncclose(ncid); return ++nerrs;
273 }
274 add_dim(&test, &ii); /* keep in-memory netcdf in sync */
275
276 /* dimension added OK, add a variable */
277 aa.dims = (int *)emalloc(sizeof(int) * aa.ndims);
278 aa.dims[0] = ii_dim;
279 if ((aa_id = ncvardef(ncid, aa.name, aa.type,
280 aa.ndims, aa.dims)) == -1) {
281 error("%s: ncvardef failed", pname);
282 ncclose(ncid); return ++nerrs;
283 }
284 add_var(&test, &aa); /* keep in-memory netcdf in sync */
285
286 /* variable added OK, add a variable attribute */
287 aa_units.var = aa_id;
288 if (ncattput(ncid, aa_units.var, aa_units.name,
289 aa_units.type, aa_units.len, (void *) aa_units.val) == -1) {
290 error("%s: ncattput failed", pname);
291 ncclose(ncid); return ++nerrs;
292 }
293 add_att(&test, aa_id, &aa_units); /* keep in-memory netcdf in sync */
294
295 if (ncredef(ncid) != -1) {
296 error("%s: cdredef in define mode should have failed", pname);
297 ncclose(ncid); return ++nerrs;
298 }
299 if (ncendef (ncid) == -1) {
300 error("%s: ncendef failed", pname);
301 ncclose(ncid); return ++nerrs;
302 }
303 if (ncclose (ncid) == -1) {
304 error("%s: ncclose failed", pname);
305 return ++nerrs;
306 }
307 if (ncredef(ncid) != -1) {
308 error("%s: ncredef failed to report bad netcdf handle", pname);
309 nerrs++;
310 }
311 free (aa.dims);
312 if (nerrs > 0)
313 (void) fprintf(stderr,"FAILED! ***\n");
314 else
315 (void) fprintf(stderr,"ok ***\n");
316
317 return nerrs;
318 }
319
320
321 /*
322 * Test ncendef
323 * check return from proper cdfendif after define mode
324 * try ncendef when in data mode, check error
325 * try ncendef with bad handle, check error
326 * On exit netcdf files are closed.
327 * Uses: ncopen, ncredef, ncdimdef, ncvardef, ncattput, ncendef, ncclose
328 */
329 int
test_ncendef(path)330 test_ncendef(path)
331 const char *path; /* name of writable netcdf file to open */
332 {
333 int nerrs = 0;
334 static char pname[] = "test_ncendef";
335 int ncid; /* netcdf id */
336 int jj_dim, kk_dim; /* dimension ids */
337 int bb_id; /* variable id */
338 static struct cdfdim kk = /* dimension */
339 {"kk", 3};
340 static struct cdfdim jj = /* dimension */
341 {"jj", 3};
342 static struct cdfvar bb = /* variable */
343 {"bb", NC_LONG, 2, ___, 0};
344 static float bb_rangev[2] = {0., 100.}; /* attribute vector */
345 static struct cdfatt bb_range = /* attribute */
346 {___, "valid_range", NC_FLOAT, LEN_OF(bb_rangev), (void *)bb_rangev};
347
348 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
349
350 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
351 error("%s: ncopen failed", pname);
352 return ++nerrs;
353 }
354 /* opened */
355 if (ncredef(ncid) == -1) {
356 error("%s: ncredef failed", pname);
357 ncclose(ncid); return ++nerrs;
358 }
359 /* in define mode, add dimensions */
360 if ((jj_dim = ncdimdef(ncid, jj.name, jj.size)) == -1 ||
361 (kk_dim = ncdimdef(ncid, kk.name, kk.size)) == -1) {
362 error("%s: ncdimdef failed", pname);
363 ncclose(ncid); return ++nerrs;
364 }
365 add_dim(&test, &jj); /* keep in-memory netcdf in sync */
366 add_dim(&test, &kk); /* keep in-memory netcdf in sync */
367
368 /* dimensions added OK, add a variable */
369 bb.dims = (int *) emalloc(sizeof(int) * bb.ndims);
370 bb.dims[0] = kk_dim;
371 bb.dims[1] = jj_dim;
372 if ((bb_id = ncvardef(ncid, bb.name, bb.type,
373 bb.ndims, bb.dims)) == -1) {
374 error("%s: ncvardef failed", pname);
375 ncclose(ncid); return ++nerrs;
376 }
377 add_var(&test, &bb); /* keep in-memory netcdf in sync */
378
379 /* variable added OK, add a variable attribute */
380 if (ncattput(ncid, bb_id, bb_range.name, bb_range.type, bb_range.len,
381 (void *) bb_range.val) == -1) {
382 error("%s: ncattput failed", pname);
383 ncclose(ncid); return ++nerrs;
384 }
385 add_att(&test, bb_id, &bb_range); /* keep in-memory netcdf in sync */
386
387 if (ncendef (ncid) == -1) {
388 error("%s: ncendef failed", pname);
389 ncclose(ncid); return ++nerrs;
390 }
391 /* in data mode */
392 if (ncendef (ncid) != -1) { /* should fail in data mode */
393 error("%s: ncendef in data mode should have failed", pname);
394 ncclose(ncid); return ++nerrs;
395 }
396 if (ncclose (ncid) == -1) {
397 error("%s: ncclose failed", pname);
398 return ++nerrs;
399 }
400 /* should fail on a bad handle */
401 if (ncendef (ncid) != -1) {
402 error("ncendef failed to report bad netcdf handle");
403 nerrs++;
404 }
405 if (nerrs > 0)
406 (void) fprintf(stderr,"FAILED! ***\n");
407 else
408 (void) fprintf(stderr,"ok ***\n");
409
410 free(bb.dims);
411
412 return nerrs;
413 }
414
415
416 /*
417 * Test ncclose
418 * try on open netCDF
419 * try in define mode and data mode
420 * try with bad handle, check error
421 * On exit netcdf files are closed.
422 */
423 int
test_ncclose(path)424 test_ncclose(path)
425 const char *path; /* name of writable netcdf file to open */
426 {
427 int nerrs = 0;
428 static char pname[] = "test_ncclose";
429 int ncid; /* netcdf id */
430
431 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
432
433 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
434 error("%s: ncopen failed", pname);
435 return ++nerrs;
436 }
437 /* opened */
438 if (ncredef(ncid) == -1) {
439 error("%s: ncredef failed", pname);
440 ncclose(ncid); return ++nerrs;
441 }
442 /* in define mode */
443 if (ncclose (ncid) == -1) {
444 error("%s: ncclose in define mode failed", pname);
445 nerrs++;
446 }
447
448 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
449 error("%s: ncopen failed", pname);
450 return ++nerrs;
451 }
452 /* in data mode */
453 if (ncclose (ncid) == -1) {
454 error("%s: ncclose failed", pname);
455 nerrs++;
456 }
457 if (ncclose (ncid) != -1) { /* should fail, since ncid is a bad handle */
458 error("%s: ncclose failed to report bad netcdf handle", pname);
459 nerrs++;
460 }
461 if (nerrs > 0)
462 (void) fprintf(stderr,"FAILED! ***\n");
463 else
464 (void) fprintf(stderr,"ok ***\n");
465
466 return nerrs;
467 }
468
469
470 /*
471 * Test ncinquire
472 * try in data mode, check returned values
473 * try in define mode, after adding an unlimited dimension, variable
474 * try with bad handle, check error
475 * On exit netcdf files are closed.
476 */
477 int
test_ncinquire(path)478 test_ncinquire(path)
479 const char *path; /* name of writable netcdf file to open */
480 {
481 int nerrs = 0;
482 static char pname[] = "test_ncinquire";
483 int ncid; /* netcdf id */
484 int ndims; /* number of dimensions */
485 int nvars; /* number of variables */
486 int ngatts; /* number of global attributes */
487 int xdimid; /* id of unlimited dimension */
488 int rec_dim; /* dimension id */
489 static struct cdfdim rec = /* dimension */
490 {"rec", NC_UNLIMITED};
491 static struct cdfdim dims[] = { /* dimensions */
492 {"i1", 5},{"i2", 3},{"i3", 7}
493 };
494 int id, nd = LEN_OF(dims); /* number of dimensions */
495 int dimids[LEN_OF(dims)];
496 int cc_id; /* variable id */
497 static struct cdfvar cc[] = { /* record variables of various sizes */
498 {"cc", NC_LONG, 1, ___, 0},
499 {"cd", NC_SHORT, 2, ___, 0},
500 {"ce", NC_FLOAT, 3, ___, 0}
501 };
502 int iv;
503 int nv = LEN_OF(cc); /* number of record variables */
504 static char units_val[] = "moles";
505 static struct cdfatt cc_units = /* attribute */
506 {___, "units", NC_CHAR, LEN_OF(units_val), (void *)units_val};
507
508 (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
509
510 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
511 error("%s: ncopen failed", pname);
512 return ++nerrs;
513 }
514 /* opened, in data mode */
515 if (ncinquire(ncid, &ndims, &nvars, &ngatts, &xdimid) == -1) {
516 error("%s: ncinquire in data mode failed", pname);
517 ncclose(ncid); return ++nerrs;
518 }
519 /* compare returned with expected values */
520 if (ndims != test.ndims) {
521 error("%s: ndims returned as %d, expected %d",
522 pname, ndims, test.ndims);
523 nerrs++;
524 }
525 if (nvars != test.nvars) {
526 error("%s: nvars returned as %d, expected %d",
527 pname, nvars, test.nvars);
528 nerrs++;
529 }
530 if (ngatts != test.ngatts) {
531 error("%s: ngatts returned as %d, expected %d",
532 pname, ngatts, test.ngatts);
533 nerrs++;
534 }
535 if (xdimid != test.xdimid) {
536 error("%s: xdimid returned as %d, expected %d",
537 pname, xdimid, test.xdimid);
538 nerrs++;
539 }
540
541 if (ncredef(ncid) == -1) {
542 error("%s: ncredef failed", pname);
543 ncclose(ncid); return ++nerrs;
544 }
545 /* add dimensions */
546 for (id = 0; id < nd; id++) {
547 if ((dimids[id] = ncdimdef(ncid, dims[id].name, dims[id].size))
548 == -1) {
549 error("%s: ncdimdef failed on normal dimension", pname);
550 ncclose(ncid); return ++nerrs;
551 }
552 add_dim(&test, &dims[id]);
553 }
554
555 /* add an unlimited dimension */
556 if ((rec_dim = ncdimdef(ncid, rec.name, rec.size)) == -1) {
557 error("%s: ncdimdef failed on NC_UNLIMITED dimension", pname);
558 ncclose(ncid); return ++nerrs;
559 }
560 add_dim(&test, &rec);
561
562 /* add some record variables */
563 for (iv = 0; iv < nv; iv++) {
564 cc[iv].dims = (int *) emalloc(sizeof(int) * cc[iv].ndims);
565 cc[iv].dims[0] = rec_dim; /* first dimension unlimited */
566 for (id = 1; id < cc[iv].ndims; id++)
567 cc[iv].dims[id] = dimids[id];
568 if ((cc_id = ncvardef(ncid, cc[iv].name, cc[iv].type,
569 cc[iv].ndims, cc[iv].dims)) == -1) {
570 error("%s: ncvardef failed", pname);
571 ncclose(ncid); return ++nerrs;
572 }
573 add_var(&test, &cc[iv]);
574
575 /* add a variable attribute */
576 if (ncattput(ncid, cc_id, cc_units.name, cc_units.type,
577 cc_units.len, (void *) cc_units.val) == -1) {
578 error("%s: ncattput failed", pname);
579 ncclose(ncid); return ++nerrs;
580 }
581 add_att(&test, cc_id, &cc_units);
582 free(cc[iv].dims);
583 }
584 /* try calling from define mode, compare returned values to expected */
585 if (ncinquire(ncid, &ndims, &nvars, &ngatts, &xdimid) == -1) {
586 error("%s: ncinquire in define mode failed", pname);
587 ncclose(ncid); return ++nerrs;
588 }
589 /* compare returned with expected values */
590 if (ndims != test.ndims) {
591 error("%s: ndims returned as %d, expected %d",
592 pname, ndims, test.ndims);
593 nerrs++;
594 }
595 if (nvars != test.nvars) {
596 error("%s: nvars returned as %d, expected %d",
597 pname, nvars, test.nvars);
598 nerrs++;
599 }
600 if (ngatts != test.ngatts) {
601 error("%s: ngatts returned as %d, expected %d",
602 pname, ngatts, test.ngatts);
603 nerrs++;
604 }
605 if (xdimid != test.xdimid) {
606 error("%s: xdimid returned as %d, expected %d",
607 pname, xdimid, test.xdimid);
608 nerrs++;
609 }
610
611 if (ncendef (ncid) == -1) {
612 error("%s: ncendef failed", pname);
613 ncclose(ncid); return ++nerrs;
614 }
615
616 if (ncclose (ncid) == -1) {
617 error("%s: ncclose failed", pname);
618 return ++nerrs;
619 }
620 /* should fail, since bad handle */
621 if (ncinquire (ncid, &ndims, &nvars, &ngatts, &xdimid) != -1) {
622 error("%s: ncinquire failed to report bad netcdf handle", pname);
623 nerrs++;
624 }
625 if (nerrs > 0)
626 (void) fprintf(stderr,"FAILED! ***\n");
627 else
628 (void) fprintf(stderr,"ok ***\n");
629
630 return nerrs;
631 }
632
633
634 /*
635 * Test ncsync
636 * try in define mode, check error
637 * try writing with one handle, reading with another on same netCDF
638 * try with bad handle, check error
639 * On exit netcdf files are closed.
640 */
641 int
test_ncsync(path)642 test_ncsync(path)
643 const char *path; /* name of writable netcdf file to open */
644 {
645 int nerrs = 0;
646 static char pname[] = "test_ncsync";
647 int ncid0, ncid1; /* netcdf ids */
648 int ll_dim; /* dimension id */
649 static struct cdfdim ll = /* dimension */
650 {"ll", 3};
651 int dd_id; /* variable id */
652 static struct cdfvar dd = /* variable */
653 {"dd", NC_SHORT, 1, ___, 0};
654 static short dd_fill_valv[] = {-999};
655 static struct cdfatt dd_fill_val = /* attribute */
656 {___, "fill_value", NC_SHORT, LEN_OF(dd_fill_valv), (void *) dd_fill_valv};
657
658 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
659
660 if ((ncid0 = ncopen(path, NC_WRITE)) == -1) {
661 error("%s: ncopen in NC_WRITE mode failed", pname);
662 return ++nerrs;
663 }
664
665 /* opened */
666 if (ncredef(ncid0) == -1) {
667 error("%s: ncredef failed", pname);
668 ncclose(ncid0); return ++nerrs;
669 }
670 /* in define mode, add a dimension, variable, and attribute */
671 if ((ll_dim = ncdimdef(ncid0, ll.name, ll.size)) == -1) {
672 error("%s: ncdimdef failed", pname);
673 ncclose(ncid0);
674 return ++nerrs;
675 }
676 add_dim(&test, &ll);
677
678 dd.dims = (int *) emalloc(sizeof(int) * dd.ndims);
679 dd.dims[0] = ll_dim;
680 if ((dd_id=ncvardef(ncid0, dd.name, dd.type, dd.ndims, dd.dims)) == -1) {
681 error("%s: ncvardef failed", pname);
682 ncclose(ncid0);
683 return ++nerrs;
684 }
685 add_var(&test, &dd);
686
687 if (ncattput(ncid0, dd_id, dd_fill_val.name, dd_fill_val.type,
688 dd_fill_val.len, (void *) dd_fill_val.val) == -1) {
689 error("%s: ncattput failed", pname);
690 ncclose(ncid0);
691 return ++nerrs;
692 }
693 add_att(&test, dd_id, &dd_fill_val);
694
695 if (ncsync (ncid0) != -1) {
696 error("%s: ncsync in define mode should fail", pname);
697 nerrs++;
698 }
699
700 if (ncendef (ncid0) == -1) {
701 error("%s: ncendef failed", pname);
702 ncclose(ncid0); return ++nerrs;
703 }
704 /* in data mode */
705 if (ncsync (ncid0) == -1) {
706 error("%s: ncsync in data mode failed", pname);
707 nerrs++;
708 }
709
710 /* put some data into a variable */
711 {
712 static long dd_start[] = {0};
713 static long dd_edges[] = {2};
714 static short dd_vals[] = {1, 2};
715 short got_vals[2];
716
717 if (ncvarput(ncid0,dd_id,dd_start,dd_edges,(void *)dd_vals) == -1) {
718 error("%s: ncvarput failed", pname);
719 ncclose(ncid0);
720 return ++nerrs;
721 }
722 add_data(&test,dd_id,dd_start,dd_edges); /* keep test in sync */
723 if (ncsync (ncid0) == -1) {
724 error("%s: ncsync after putting data failed", pname);
725 nerrs++;
726 }
727 if ((ncid1 = ncopen(path, NC_NOWRITE)) == -1) {
728 #ifndef vms
729 error("%s: second ncopen failed", pname);
730 nerrs++;
731 #else
732 fprintf(stderr,"Doesn't support shared access on vms\n") ;
733 #endif
734 } else {
735 if (ncid0 == ncid1) {
736 error("%s: second ncopen should return distinct handle",
737 pname);
738 nerrs++;
739 } /* read data just put after a sync, should succeed */
740 if (ncvarget(ncid1,dd_id,dd_start,dd_edges,(void *)got_vals)
741 == -1) {
742 error("%s: ncvarget failed", pname);
743 nerrs++;
744 }
745 if (dd_vals[0] != got_vals[0] || dd_vals[1] != got_vals[1]) {
746 error("%s: ncvarget succeeded but data values wrong",
747 pname);
748 }
749 if (ncclose (ncid1) == -1) {
750 error("%s: ncclose failed", pname);
751 nerrs++;
752 }
753 }
754 }
755 if (ncclose (ncid0) == -1) {
756 error("%s: ncclose failed", pname);
757 nerrs++;
758 }
759 if (ncsync (ncid0) != -1) { /* should fail, since ncid0 is bad handle */
760 error("%s: ncsync failed to report bad netcdf handle", pname);
761 nerrs++;
762 }
763 if (nerrs > 0)
764 (void) fprintf(stderr,"FAILED! ***\n");
765 else
766 (void) fprintf(stderr,"ok ***\n");
767
768 /* Free resources. */
769 free(dd.dims);
770
771 return nerrs;
772 }
773
774
775 /*
776 * Test ncabort
777 * try in define mode, check that file was deleted
778 * try after writing variable
779 * try with bad handle, check error
780 * On exit netcdf files are closed.
781 */
782 int
test_ncabort(path)783 test_ncabort(path)
784 const char *path; /* name of writable netcdf file to open */
785 {
786 int nerrs = 0;
787 static char pname[] = "test_ncabort";
788 static char fpath[] = "ufo.nc";
789 static short attv[] = {3};
790 static struct cdfatt att = /* attribute */
791 {___, "temp", NC_SHORT, LEN_OF(attv), (void *) attv};
792 int ncid; /* netcdf id */
793
794 (void) fprintf(stderr, "*** Testing %s ...\t\t", &pname[5]);
795
796 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
797 error("%s: ncopen failed", pname);
798 return ++nerrs;
799 }
800 /* opened */
801 if (ncredef(ncid) == -1) {
802 error("%s: ncredef failed", pname);
803 ncclose(ncid); return ++nerrs;
804 }
805 /* in define mode, add a new global attribute */
806 if (ncattput(ncid, NC_GLOBAL, att.name, att.type, att.len, att.val) == -1) {
807 error("%s: ncattput failed", pname);
808 ncclose(ncid); return ++nerrs;
809 }
810
811 /* abort in define mode, should restore to state before define mode */
812 if (ncabort(ncid) == -1) {
813 error("%s: ncabort in define mode failed", pname);
814 ncclose(ncid); return ++nerrs;
815 }
816 if ((ncid = ncopen(path, NC_WRITE)) == -1) {
817 error("%s: ncopen after ncabort failed", pname);
818 return ++nerrs;
819 }
820 /* check that new global attribute was not added */
821 if (ncattinq(ncid, NC_GLOBAL, att.name, &att.type, &att.len) != -1) {
822 error("%s: ncabort should have restored state before ncredef", pname);
823 ncclose(ncid); return ++nerrs;
824 }
825 /* in data mode not being created, should just close */
826 if (ncabort(ncid) == -1) {
827 error("%s: ncabort in define mode failed", pname);
828 return ++nerrs;
829 }
830 if ((ncid = nccreate(fpath, NC_CLOBBER)) == -1) {
831 error("%s: nccreate failed to NC_CLOBBER", pname);
832 return ++nerrs;
833 }
834 /* in define mode being created, should delete */
835 if (ncabort(ncid) == -1) {
836 error("%s: ncabort after nccreate failed", pname);
837 return ++nerrs;
838 }
839 /* check with ncopen that file doesn't exist */
840 if (ncopen(fpath, NC_NOWRITE) != -1) {
841 error("%s: ncabort deleted file, but ncopen found it", pname);
842 return ++nerrs;
843 }
844 if (ncabort(ncid) != -1) { /* should fail, ncid is bad handle */
845 error("%s: ncclose failed to report bad netcdf handle", pname);
846 nerrs++;
847 }
848 if (nerrs > 0)
849 (void) fprintf(stderr,"FAILED! ***\n");
850 else
851 (void) fprintf(stderr,"ok ***\n");
852
853 return nerrs;
854 }
855