1/* Copyright 1988-2010 University Corporation for Atmospheric Research
2   See netcdf/COPYRIGHT file for copying and redistribution
3   conditions.
4
5   Program to create a cdf, exercise all cdf functions.  Creates cdf,
6   stuff it full of numbers, closes it. Then reopens it, and checks
7   for consistency.  Leaves the file around afterwards.
8
9   Based on a program to test the nasa look-alike program, so not the
10   most appropropriate test. See ../nctest for a complete spec test.
11*/
12
13#define REDEF
14/* #define SYNCDEBUG */
15
16#undef NDEBUG /* always active assert() in this file */
17
18#include <config.h>
19#include <stdio.h>
20#include <stddef.h>
21#include <stdlib.h>
22#include <string.h>
23#include <assert.h>
24#include <netcdf.h>
25#ifdef USE_PNETCDF
26#include <netcdf_par.h>
27#endif
28
29#define MAXSHORT 32767
30#define MAXINT 2147483647
31#define MAXBYTE 127
32
33
34#define FNAME "t_nc.nc"
35#define NUM_DIMS  3
36#define DONT_CARE -1
37/* make these numbers big when you want to give this a real workout */
38#define NUM_RECS 8
39#define SIZE_1 7
40#define SIZE_2 8
41
42static struct {
43 int num_dims;
44 int num_vars;
45 int num_attrs;
46 int xtendim;
47cdesc[1];
48
49static struct {
50 char mnem[NC_MAX_NAME];
51 nc_type type;
52 int ndims;
53 int dims[NC_MAX_VAR_DIMS];
54 int num_attrs;
55vdesc[1];
56
57static struct {
58 char mnem[NC_MAX_NAME];
59 nc_type type;
60 size_t len;
61adesc[1];
62
63union getret
64{
65    char            by[8];
66    short           sh[4];
67    int          in[2];
68    float           fl[2];
69    double          dbl;
70};
71
72
73static void
74chkgot(nc_type type, union getret got, double check)
75{
76 switch(type){
77 case NC_BYTE :
78 assert( (char)check == got.by[0] );
79 break;
80 case NC_CHAR : /* TODO */
81 assert( (char)check == got.by[0] );
82 break;
83 case NC_SHORT :
84 assert( (short)check == got.sh[0] );
85 break;
86 case NC_INT :
87 assert( (int)check == got.in[0] );
88 break;
89 case NC_FLOAT :
90 assert( (float)check == got.fl[0] );
91 break;
92 case NC_DOUBLE :
93 assert( check == got.dbl );
94 break;
95 default:
96 break;
97 }
98}
99
100static const char *fname = FNAME;
101
102
103static size_t num_dims = NUM_DIMS;
104static size_t sizes[] = { NC_UNLIMITEDSIZE_1 , SIZE_2 };
105static const char * const dim_names[] = { "record", "ixx", "iyy"};
106
107static void
108createtestdims(int cdfid, size_t num_dims, const size_t *sizes, const char * const dim_names[])
109{
110 int dimid;
111 while(num_dims-- != 0)
112 {
113 assert( nc_def_dim(cdfid, *dim_names++, *sizes, &dimid)
114  == NC_NOERR);
115 sizes++;
116 }
117
118}
119
120
121static void
122testdims(int cdfid, size_t num_dims, size_t *sizes, const char * const dim_names[])
123{
124 int ii;
125 size_t size;
126 char cp[NC_MAX_NAME];
127 for(ii=0; (size_t) ii < num_dimsii++, sizes++)
128 {
129 assert( nc_inq_dim(cdfidiicp, &size) == NC_NOERR);
130 if( size != *sizes)
131 (void) fprintf(stderr, "%d: %lu != %lu\n",
132 ii, (unsigned long)size, (unsigned long)*sizes);
133 assert( size == *sizes);
134 assert( strcmp(cp, *dim_names++) == 0);
135 }
136
137}
138
139
140
141static const char * const reqattr[] = {
142 "UNITS",
143 "VALIDMIN",
144 "VALIDMAX",
145 "SCALEMIN",
146 "SCALEMAX",
147 "FIELDNAM",
148 _FillValue
149};
150#define NUM_RATTRS 6
151
152static struct tcdfvar {
153 const char *mnem;
154 nc_type type;
155 const char *fieldnam;
156 double validmin;
157 double validmax;
158 double scalemin;
159 double scalemax;
160 const char *units;
161 int ndims;
162 int dims[NUM_DIMS];
163} const testvars[]  = {
164#define Byte_id 0
165 { "Byte", NC_BYTE, "Byte sized integer variable",
166 -MAXBYTEMAXBYTE, -MAXBYTEMAXBYTE , "ones",
167 2, {0,1,DONT_CARE} },
168#define Char_id 1
169 { "Char", NC_CHAR, "char (string) variable",
170 DONT_CAREDONT_CAREDONT_CAREDONT_CARE, "(unitless)",
171 2, {0,2,DONT_CARE} },
172#define Short_id 2
173 { "Short", NC_SHORT, "Short variable",
174 -MAXSHORTMAXSHORT, -MAXSHORTMAXSHORT , "ones",
175 2, {0, 2, DONT_CARE }},
176#define Long_id 3
177 { "Long", NC_INT, "Long Integer variable", /* 2.x backward strings */
178 -MAXINTMAXINT, -MAXINTMAXINT, "ones",
179 2, {1, 2, DONT_CARE}},
180#define Float_id 4
181 { "Float", NC_FLOAT, "Single Precision Floating Point variable",
182 -MAXINTMAXINT, -MAXINTMAXINT, "flots",
183 3, {0, 1, 2 }},
184#define Double_id 5
185 { "Double", NC_DOUBLE, "Double Precision Floating Point variable",
186 -MAXINTMAXINT, -MAXINTMAXINT, "dflots",
187 3, {0, 1, 2 }},
188};
189#define NUM_TESTVARS 6
190
191static void
192createtestvars(int id, const struct tcdfvar *testvars, size_t count)
193{
194 int ii;
195 int varid;
196 const struct tcdfvar *vp = testvars;
197
198 for(ii = 0; (size_t) ii < countii++, vp++ )
199 {
200 assert(nc_def_var(idvp->mnemvp->typevp->ndimsvp->dims,
201  &varid)
202  == NC_NOERR );
203
204   assert(
205 nc_put_att_text(id,ii,reqattr[0],strlen(vp->units),
206 vp->units)
207 == NC_NOERR);
208   assert(
209 nc_put_att_double(id,ii,reqattr[1],NC_DOUBLE,1,
210 &vp->validmin)
211 == NC_NOERR);
212   assert(
213 nc_put_att_double(id,ii,reqattr[2],NC_DOUBLE,1,
214 &vp->validmax)
215 == NC_NOERR);
216   assert(
217 nc_put_att_double(id,ii,reqattr[3],NC_DOUBLE,1,
218 &vp->scalemin)
219 == NC_NOERR);
220   assert(
221 nc_put_att_double(id,ii,reqattr[4],NC_DOUBLE,1,
222 &vp->scalemax)
223 == NC_NOERR);
224   assert(
225 nc_put_att_text(id,ii,reqattr[5],strlen(vp->fieldnam),
226 vp->fieldnam)
227 == NC_NOERR);
228 }
229}
230
231/* static void */
232/* parray(const char *label, size_t count, const size_t array[]) */
233/* { */
234/*  (void) fprintf(stdout, "%s", label); */
235/*  (void) fputc('\t',stdout);  */
236/*  for(; count != 0; count--, array++) */
237/*  (void) fprintf(stdout," %lu", (unsigned long) *array); */
238/* } */
239
240
241static void
242fill_seq(int id)
243{
244 float values[NUM_RECS * SIZE_1 * SIZE_2];
245 size_t vindices[NUM_DIMS];
246
247 {
248 size_t ii = 0;
249 for(; ii < sizeof(values)/sizeof(values[0]); ii++)
250 {
251 values[ii] = (float) ii;
252 }
253 }
254
255 /* zero the vindices */
256 {
257 size_t *cc = vindices;
258 while (cc < &vindices[num_dims])
259 *cc++ = 0;
260 }
261
262 sizes[0] = NUM_RECS;
263
264 assert( nc_put_vara_float(idFloat_idvindicessizesvalues)== NC_NOERR);
265
266}
267
268static void
269check_fill_seq(int id)
270{
271 size_t vindices[NUM_DIMS];
272 size_t *cc, *mm;
273 union getret got;
274 int ii = 0;
275 /*float val;*/
276
277 sizes[0] = NUM_RECS;
278 cc = vindices;
279 while (cc < &vindices[num_dims])
280 *cc++ = 0;
281
282 /* ripple counter */
283 cc = vindices;
284 mm = sizes;
285 while (*vindices < *sizes)
286 {
287     while (*cc < *mm)
288     {
289 if (mm == &sizes[num_dims - 1])
290 {
291 if(nc_get_var1_float(idFloat_idvindices, &got.fl[0]) == -1)
292 goto bad_ret;
293 /* val = (float) ii;  */
294 /* if(val != got.fl[0]) */
295 /* { */
296 /*  parray("indices", NUM_DIMS, vindices); */
297 /*  (void) printf("\t%f != %f\n", val, got.fl[0]); */
298 /* } */
299     (*cc)++; ii++;
300     continue;
301 }
302 cc++;
303 mm++;
304     }
305 if(cc == vindices)
306 break;
307     *cc = 0;
308     cc--;
309     mm--;
310     (*cc)++;
311 }
312 return;
313bad_ret :
314 (void) printf("couldn't get a var in check_fill_seq() %d\n",
315 ii);
316 return;
317}
318
319static size_t indices[][3] = {
320 {0, 1, 3},
321 {0, 3, 0},
322 {1, 2, 3},
323 {3, 2, 1},
324 {2, 1, 3},
325 {1, 0, 0},
326 {0, 0, 0},
327};
328
329static const char chs[] = {'A','B', ((char)0xff) };
330static const size_t s_start[] = {0,1};
331static const size_t s_edges[] = {NUM_RECSSIZE_1 - 1};
332static char sentence[NUM_RECSSIZE_1 -1] =
333 "The red death had long devastated the country.";
334static short shs[] = {97, 99};
335static int birthday = 82555;
336#define M_E 2.7182818284590452354
337static float e = (float) M_E;
338static double pinot = 3.25;
339static double zed = 0.0;
340
341
342/*ARGSUSED*/
343int
344main(int argc, char *argv[])
345{
346 int cmode=NC_CLOBBERomoderet;
347 int  id;
348 char buf[256];
349#ifdef SYNCDEBUG
350 char *str = "one";
351#endif
352 int ii;
353 size_t ui;
354 const struct tcdfvar *tvp = testvars;
355 union getret got;
356 const size_t initialsz = 8192;
357 size_t chunksz = 8192;
358 size_t align = 8192/32;
359
360#ifdef USE_PNETCDF
361 MPI_Init(&argc, &argv);
362
363        cmode |= (NC_PNETCDF);
364 cmode |= (NC_64BIT_DATA);
365 ret = nc_create_par(fname,cmodeMPI_COMM_WORLDMPI_INFO_NULL, &id);
366#else
367 ret = nc__create(fname,cmodeinitialsz, &chunksz, &id);
368 if(ret != NC_NOERR) {
369  /* (void) fprintf(stderr, "trying again\n"); */
370 ret = nc__create(fname,cmodeinitialsz, &chunksz, &id);
371 }
372#endif
373 if(ret != NC_NOERR)  {
374 fprintf(stderr,"Error %s in file %s at line %d\n",nc_strerror(ret),__FILE__,__LINE__);
375 exit(ret);
376        }
377
378 assert( nc_put_att_text(idNC_GLOBAL,
379 "TITLE", 12, "another name") == NC_NOERR);
380 assert( nc_get_att_text(idNC_GLOBAL,
381 "TITLE", buf) == NC_NOERR);
382/* (void) printf("title 1 \"%s\"\n", buf); */
383 assert( nc_put_att_text(idNC_GLOBAL,
384 "TITLE", strlen(fname), fname) == NC_NOERR);
385 assert( nc_get_att_text(idNC_GLOBAL,
386 "TITLE", buf) == NC_NOERR);
387 buf[strlen(fname)] = 0;
388/* (void) printf("title 2 \"%s\"\n", buf); */
389 assert( strcmp(fnamebuf) == 0);
390
391 createtestdims(idNUM_DIMSsizesdim_names);
392 testdims(idNUM_DIMSsizesdim_names);
393
394 createtestvars(idtestvarsNUM_TESTVARS);
395
396  {
397  int ifill = -1; double dfill = -9999;
398  assert( nc_put_att_int(idLong_id,
399  _FillValueNC_INT, 1, &ifill) == NC_NOERR);
400  assert( nc_put_att_double(idDouble_id,
401  _FillValueNC_DOUBLE, 1, &dfill) == NC_NOERR);
402  }
403
404#ifdef REDEF
405 assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR );
406 assert( nc_put_var1_int(idLong_idindices[3], &birthday)
407 == NC_NOERR );
408 fill_seq(id);
409 assert( nc_redef(id) == NC_NOERR );
410/* assert( nc_rename_dim(id,2, "a long dim name") == NC_NOERR); */
411#endif
412
413 assert( nc_rename_dim(id,1, "IXX") == NC_NOERR);
414 assert( nc_inq_dim(id, 1, buf, &ui) == NC_NOERR);
415 /* (void) printf("dimrename: %s\n", buf); */
416 assert( nc_rename_dim(id,1, dim_names[1]) == NC_NOERR);
417
418#ifdef ATTRX
419 assert( nc_rename_att(id, 1, "UNITS", "units") == NC_NOERR);
420 assert( nc_del_att(id, 4, "FIELDNAM")== NC_NOERR);
421 assert( nc_del_att(id, 2, "SCALEMIN")== NC_NOERR);
422 assert( nc_del_att(id, 2, "SCALEMAX")== NC_NOERR);
423#endif /* ATTRX */
424
425 assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR );
426
427#ifndef REDEF
428 fill_seq(id);
429 assert( nc_put_var1_int(idLong_idindices[3], &birthday)== NC_NOERR );
430#endif
431
432 assert( nc_put_vara_schar(idByte_ids_starts_edges,
433 (signed char *)sentence)
434 == NC_NOERR);
435 assert( nc_put_var1_schar(idByte_idindices[6], (signed char *)(chs+1))
436 == NC_NOERR);
437 assert( nc_put_var1_schar(idByte_idindices[5], (signed char *)chs)
438 == NC_NOERR);
439
440 assert( nc_put_vara_text(idChar_ids_starts_edgessentence)
441 == NC_NOERR);
442 assert( nc_put_var1_text(idChar_idindices[6], (chs+1))
443 == NC_NOERR) ;
444 assert( nc_put_var1_text(idChar_idindices[5], chs)
445 == NC_NOERR);
446
447 assert( nc_put_var1_short(idShort_idindices[4], shs)
448 == NC_NOERR);
449
450 assert( nc_put_var1_float(idFloat_idindices[2], &e)
451 == NC_NOERR);
452
453 assert( nc_put_var1_double(idDouble_idindices[1], &zed)
454 == NC_NOERR);
455 assert( nc_put_var1_double(idDouble_idindices[0], &pinot)
456 == NC_NOERR);
457
458
459#ifdef SYNCDEBUG
460 (void) printf("Hit Return to sync\n");
461 gets(str);
462 nc_sync(id,0);
463 (void) printf("Sync done. Hit Return to continue\n");
464 gets(str);
465#endif /* SYNCDEBUG */
466
467 ret = nc_close(id);
468 /* (void) printf("nc_close ret = %d\n\n", ret); */
469
470
471/*
472 * read it
473 */
474        omode = NC_NOWRITE;
475#ifdef USE_PNETCDF
476        omode |= NC_PNETCDF;
477 ret = nc_open_par(fname,omodeMPI_COMM_WORLDMPI_INFO_NULL, &id);
478#else
479 ret = nc__open(fname,omode, &chunksz, &id);
480#endif
481 if(ret != NC_NOERR)
482 {
483        (void) printf("Could not open %s: %s\n", fname,
484 nc_strerror(ret));
485        exit(1);
486 }
487 /* (void) printf("reopen id = %d for filename %s\n", */
488 /*  id, fname); */
489
490 /* NC */
491 /* (void) printf("NC "); */
492 assert( nc_inq(id, &(cdesc->num_dims), &(cdesc->num_vars),
493 &(cdesc->num_attrs), &(cdesc->xtendim) ) == NC_NOERR);
494 assert((size_t) cdesc->num_dims == num_dims);
495 assert(cdesc->num_attrs == 1);
496 assert(cdesc->num_vars == NUM_TESTVARS);
497 /* (void) printf("done\n"); */
498
499 /* GATTR */
500 /* (void) printf("GATTR "); */
501
502 assert( nc_inq_attname(idNC_GLOBAL, 0, adesc->mnem) == 0);
503 assert(strcmp("TITLE",adesc->mnem) == 0);
504 assert( nc_inq_att(idNC_GLOBALadesc->mnem, &(adesc->type), &(adesc->len))== NC_NOERR);
505 assert( adesc->type == NC_CHAR );
506 assert( adesc->len == strlen(fname) );
507 assert( nc_get_att_text(idNC_GLOBAL, "TITLE", buf)== NC_NOERR);
508 buf[adesc->len] = 0;
509 assert( strcmp(fnamebuf) == 0);
510
511 /* VAR */
512 /* (void) printf("VAR "); */
513 assert( cdesc->num_vars == NUM_TESTVARS );
514
515 for(ii = 0; ii < cdesc->num_varsii++, tvp++ )
516 {
517 int jj;
518 assert( nc_inq_var(idii,
519 vdesc->mnem,
520 &(vdesc->type),
521 &(vdesc->ndims),
522 vdesc->dims,
523 &(vdesc->num_attrs)) == NC_NOERR);
524 if(strcmp(tvp->mnem , vdesc->mnem) != 0)
525 {
526 (void) printf("attr %d mnem mismatch %s, %s\n",
527 iitvp->mnemvdesc->mnem);
528 continue;
529 }
530 if(tvp->type != vdesc->type)
531 {
532 (void) printf("attr %d type mismatch %d, %d\n",
533 ii, (int)tvp->type, (int)vdesc->type);
534 continue;
535 }
536 for(jj = 0; jj < vdesc->ndimsjj++ )
537 {
538 if(tvp->dims[jj] != vdesc->dims[jj] )
539 {
540 (void) printf(
541 "inconsistent dim[%d] for variable %d: %d != %d\n",
542 jjiitvp->dims[jj], vdesc->dims[jj] );
543 continue;
544 }
545 }
546
547 /* VATTR */
548 /* (void) printf("VATTR\n"); */
549 for(jj=0; jj<vdesc->num_attrsjj++ )
550 {
551 assert( nc_inq_attname(idiijjadesc->mnem) == NC_NOERR);
552 if( strcmp(adesc->mnemreqattr[jj]) != 0 )
553 {
554 (void) printf("var %d attr %d mismatch %s != %s\n",
555 iijjadesc->mnemreqattr[jj] );
556 break;
557 }
558 }
559
560 if( nc_inq_att(idiireqattr[0], &(adesc->type), &(adesc->len))
561 != -1) {
562 assert( adesc->type == NC_CHAR );
563 assert( adesc->len == strlen(tvp->units) );
564   assert( nc_get_att_text(id,ii,reqattr[0],buf)== NC_NOERR);
565 buf[adesc->len] = 0;
566 assert( strcmp(tvp->unitsbuf) == 0);
567 }
568
569 if(
570 nc_inq_att(idiireqattr[1], &(adesc->type), &(adesc->len))
571 != -1)
572 {
573 assert( adesc->type == NC_DOUBLE );
574 assert( adesc->len == 1 );
575   assert( nc_get_att_double(idiireqattr[1], &got.dbl)== NC_NOERR);
576 chkgot(adesc->typegottvp->validmin);
577 }
578
579 if(
580 nc_inq_att(idiireqattr[2], &(adesc->type), &(adesc->len))
581 != -1)
582 {
583 assert( adesc->type == NC_DOUBLE );
584 assert( adesc->len == 1 );
585   assert( nc_get_att_double(idiireqattr[2], &got.dbl)== NC_NOERR);
586 chkgot(adesc->typegottvp->validmax);
587 }
588
589 if(
590 nc_inq_att(idiireqattr[3], &(adesc->type), &(adesc->len))
591 != -1)
592 {
593 assert( adesc->type == NC_DOUBLE );
594 assert( adesc->len ==1 );
595   assert( nc_get_att_double(idiireqattr[3], &got.dbl)== NC_NOERR);
596 chkgot(adesc->typegottvp->scalemin);
597 }
598
599 if(
600 nc_inq_att(idiireqattr[4], &(adesc->type), &(adesc->len))
601 != -1)
602 {
603 assert( adesc->type == NC_DOUBLE );
604 assert( adesc->len == 1 );
605   assert( nc_get_att_double(idiireqattr[4], &got.dbl)== NC_NOERR);
606 chkgot(adesc->typegottvp->scalemax);
607 }
608
609 if( nc_inq_att(idiireqattr[5], &(adesc->type), &(adesc->len))== NC_NOERR)
610 {
611 assert( adesc->type == NC_CHAR );
612 assert( adesc->len == strlen(tvp->fieldnam) );
613   assert( nc_get_att_text(id,ii,reqattr[5],buf)== NC_NOERR);
614 buf[adesc->len] = 0;
615 assert( strcmp(tvp->fieldnambuf) == 0);
616 }
617 }
618
619 /* (void) printf("fill_seq "); */
620 check_fill_seq(id);
621 /* (void) printf("Done\n"); */
622
623 assert( nc_get_var1_double(idDouble_idindices[0], &got.dbl)== NC_NOERR);
624 /* (void) printf("got val = %f\n", got.dbl ); */
625
626 assert( nc_get_var1_double(idDouble_idindices[1], &got.dbl)== NC_NOERR);
627 /* (void) printf("got val = %f\n", got.dbl ); */
628
629 assert( nc_get_var1_float(idFloat_idindices[2], &got.fl[0])== NC_NOERR);
630 /* (void) printf("got val = %f\n", got.fl[0] ); */
631
632 assert( nc_get_var1_int(idLong_idindices[3], &got.in[0])== NC_NOERR);
633 /* (void) printf("got val = %d\n", got.in[0] ); */
634
635 assert( nc_get_var1_short(idShort_idindices[4], &got.sh[0])== NC_NOERR);
636 /* (void) printf("got val = %d\n", got.sh[0] ); */
637
638 assert( nc_get_var1_text(idChar_idindices[5], &got.by[0]) == NC_NOERR);
639 /* (void) printf("got NC_CHAR val = %c (0x%02x) \n", */
640  /* got.by[0] , got.by[0]); */
641
642 assert( nc_get_var1_text(idChar_idindices[6], &got.by[0]) == NC_NOERR);
643 /* (void) printf("got NC_CHAR val = %c (0x%02x) \n", */
644 /*   got.by[0], got.by[0] ); */
645
646 (void) memset(buf,0,sizeof(buf));
647 assert( nc_get_vara_text(idChar_ids_starts_edgesbuf) == NC_NOERR);
648 /* (void) printf("got NC_CHAR val = \"%s\"\n", buf); */
649
650 assert( nc_get_var1_schar(idByte_idindices[5],
651 (signed char *)&got.by[0])== NC_NOERR);
652 /* (void) printf("got val = %c (0x%02x) \n", got.by[0] , got.by[0]); */
653
654 assert( nc_get_var1_schar(idByte_idindices[6],
655 (signed char *)&got.by[0])== NC_NOERR);
656 /* (void) printf("got val = %c (0x%02x) \n", got.by[0], got.by[0] ); */
657
658 (void) memset(buf,0,sizeof(buf));
659 assert( nc_get_vara_schar(idByte_ids_starts_edges,
660 (signed char *)buf)== NC_NOERR );
661 /* (void) printf("got val = \"%s\"\n", buf); */
662
663 {
664 double dbuf[NUM_RECS * SIZE_1 * SIZE_2];
665 assert(nc_get_var_double(idFloat_iddbuf) == NC_NOERR);
666 /* (void) printf("got vals = %f ... %f\n", dbuf[0], */
667 /*   dbuf[NUM_RECS * SIZE_1 * SIZE_2 -1] ); */
668 }
669
670 ret = nc_close(id);
671 /* (void) printf("re nc_close ret = %d\n", ret); */
672
673#ifdef USE_PNETCDF
674 MPI_Finalize();
675#endif
676 return 0;
677}


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