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