1 /*
2 * Copyright (C) 2014, Northwestern University and Argonne National Laboratory
3 * See COPYRIGHT notice in top-level directory.
4 */
5 /* $Id: tst_small.c 2744 2016-12-28 16:25:22Z wkliao $ */
6
7 /* This program is based on the test program tst_small.c of the netCDF package */
8
9 /* This is part of the netCDF package. Copyright 2005 University
10 Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
11 conditions of use. See www.unidata.ucar.edu for more info.
12
13 Test small files.
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <libgen.h> /* basename() */
19 #include <mpi.h>
20 #include <pnetcdf.h>
21
22 #include <testutils.h>
23
24 /* Test everything for classic, 64-bit offseti, and 64-bit data files. */
25 #define NUM_FORMATS 3
26
27 #define ATT_NAME "Atom"
28 #define MAX_LEN 7
29
30 #define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); return 1;}}
31
32 static int
test_small_atts(const char * testfile,int cmode)33 test_small_atts(const char *testfile, int cmode)
34 {
35 int ncid, err;
36 char att[MAX_LEN + 1], att_in[MAX_LEN + 1], source[MAX_LEN + 1] = "0123456";
37 int ndims, nvars, natts, unlimdimid;
38 MPI_Offset len_in;
39 int t, f;
40
41 /* Run this with and without fill mode. */
42 for (f = 0; f < 2; f++)
43 {
44 /* Create small files with an attribute that grows by one each
45 * time. */
46 for (t = 1; t < MAX_LEN; t++)
47 {
48 /* Create null-terminated text string of correct length. */
49 strncpy(att, source, t);
50 att[t] = '\0';
51
52 /* Create a file with one attribute. */
53 err = ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
54 err = ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME, t + 1, att); ERR
55 if (f) { err=ncmpi_set_fill(ncid, NC_NOFILL, NULL); ERR}
56 err=ncmpi_close(ncid); ERR;
57
58 /* Reopen the file and check it. */
59 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
60 err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
61 if (ndims != 0 && nvars != 0 && natts != 1 && unlimdimid != -1) {printf("Error at line %d\n",__LINE__);return 1;}
62 err=ncmpi_inq_attlen(ncid, NC_GLOBAL, ATT_NAME, &len_in); ERR
63 if (len_in != t + 1) {printf("Error at line %d\n",__LINE__);return 1;}
64 err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_NAME, att_in); ERR
65 if (strncmp(att_in, att, t)) {printf("Error at line %d\n",__LINE__);return 1;}
66 err=ncmpi_close(ncid); ERR
67 }
68 }
69 return 0;
70 }
71
72 #define DIM1_NAME "Time"
73 #define DIM2_NAME "DataStrLen"
74 #define VAR_NAME "Times"
75 #define STR_LEN 19
76 #define NUM_VALS 2
77 #define NDIMS 2
78 #define TITLE " OUTPUT FROM WRF V2.0.3.1 MODEL"
79 #define ATT_NAME2 "TITLE"
80
81 /* Test a small file with an unlimited dimension. NOTE: Normally I
82 * write a NULL terminator for my attributes and text strings, but
83 * this reproduces a bug that a fortran user sent us. So string data
84 * are written to the file without null terminators. - Ed */
85 static int
test_small_unlim(const char * testfile,int cmode)86 test_small_unlim(const char *testfile, int cmode)
87 {
88 int i, err, ncid, dimids[NDIMS], varid;
89 char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
90 int ndims, nvars, natts, unlimdimid;
91 MPI_Offset start[NDIMS], count[NDIMS];
92
93 /* Create null-terminated text strings of correct length. */
94 /*for (i = 0; i < NUM_VALS; i++)
95 strcpy(data[i], source);*/
96 strcpy(data[0], "2005-04-11_12:00:00");
97 strcpy(data[1], "2005-04-11_13:00:00");
98
99 /* Create a file with two dimensions, one unlimited, and one
100 * var, and a global att. */
101 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
102 err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, dimids); ERR
103 err=ncmpi_def_dim(ncid, DIM2_NAME, STR_LEN, &dimids[1]); ERR
104 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 2, dimids, &varid); ERR
105 err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME2, strlen(TITLE), TITLE); ERR
106 err=ncmpi_enddef(ncid); ERR
107
108 /* Write some records of var data. */
109 count[0] = 1;
110 count[1] = STR_LEN;
111 start[1] = 0;
112 for (start[0] = 0; start[0] < NUM_VALS; start[0]++) {
113 err=ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]); ERR
114 }
115
116 /* We're done! */
117 err=ncmpi_close(ncid); ERR
118
119 /* Reopen the file and check it. */
120 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
121 err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
122 if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;}
123 err=ncmpi_get_var_text_all(ncid, varid, (char *)data_in); ERR
124 for (i = 0; i < NUM_VALS; i++)
125 /* if (strncmp(data[i], data_in[i], STR_LEN)) {printf("Error at line %d\n",__LINE__);return 1;} */
126 if (strncmp(data[i], data_in[i], STR_LEN)) {
127 printf("i=%d data=%s data_in=%s\n",i,data[i],data_in[i]);
128 }
129 err=ncmpi_close(ncid); ERR
130 return 0;
131 }
132
133 /* Test a small file with a fixed dimension. */
134 static int
test_small_fixed(const char * testfile,int cmode)135 test_small_fixed(const char *testfile, int cmode)
136 {
137 int i, err, ncid, dimids[NDIMS], varid;
138 char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
139 int ndims, nvars, natts, unlimdimid;
140 MPI_Offset start[NDIMS], count[NDIMS];
141
142 /* Create null-terminated text strings of correct length. */
143 /*for (i = 0; i < NUM_VALS; i++)
144 strcpy(data[i], source);*/
145 strcpy(data[0], "2005-04-11_12:00:00");
146 strcpy(data[1], "2005-04-11_13:00:00");
147
148 /* Create a file with two dimensions, one unlimited, and one
149 * var, and a global att. */
150 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
151 err=ncmpi_def_dim(ncid, DIM1_NAME, NUM_VALS, dimids); ERR
152 err=ncmpi_def_dim(ncid, DIM2_NAME, STR_LEN, &dimids[1]); ERR
153 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, NDIMS, dimids, &varid); ERR
154 err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME2, strlen(TITLE), TITLE); ERR
155 err=ncmpi_enddef(ncid); ERR
156
157 /* Write some records of var data. */
158 count[0] = 1;
159 count[1] = STR_LEN;
160 start[1] = 0;
161 for (start[0] = 0; start[0] < NUM_VALS; start[0]++) {
162 err=ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]); ERR
163 }
164
165 /* We're done! */
166 err=ncmpi_close(ncid); ERR
167
168 /* Reopen the file and check it. */
169 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
170 err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
171 if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != -1) {printf("Error at line %d\n",__LINE__);return 1;}
172 err=ncmpi_get_var_text_all(ncid, varid, (char *)data_in); ERR
173 for (i = 0; i < NUM_VALS; i++)
174 if (strncmp(data[i], data_in[i], STR_LEN)) {printf("Error at line %d\n",__LINE__);return 1;}
175 err=ncmpi_close(ncid); ERR
176 return 0;
177 }
178
179 /* Test a small file with one var. */
180 static int
test_small_one(const char * testfile,int cmode)181 test_small_one(const char *testfile, int cmode)
182 {
183 int err, ncid, dimid, varid;
184 char data = 'h', data_in;
185 int ndims, nvars, natts, unlimdimid;
186 MPI_Offset start[NDIMS], count[NDIMS];
187
188 /* Create a file with one ulimited dimensions, and one var. */
189 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
190 err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
191 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
192 err=ncmpi_enddef(ncid); ERR
193
194 /* Write one record of var data, a single character. */
195 count[0] = 1;
196 start[0] = 0;
197 err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data); ERR
198
199 /* We're done! */
200 err=ncmpi_close(ncid); ERR
201
202 /* Reopen the file and check it. */
203 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
204 err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
205 if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;}
206 err=ncmpi_get_var_text_all(ncid, varid, &data_in); ERR
207 if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;}
208 err=ncmpi_close(ncid); ERR
209 return 0;
210 }
211
212 #define ONE_DIM 1
213 #define MAX_RECS 10
214
215 /* Test a small file with one record var, which grows. */
216 static int
test_one_growing(const char * testfile,int cmode)217 test_one_growing(const char *testfile, int cmode)
218 {
219 int err, ncid, dimid, varid;
220 char data[MAX_RECS], data_in;
221 MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
222 int r, f;
223
224 /* Create some phoney data. */
225 for (data[0] = 'a', r = 1; r < MAX_RECS; r++)
226 data[r] = data[r - 1] + 1;
227
228 /* Run this with and without fill mode. */
229 for (f = 0; f < 2; f++)
230 {
231 /* Create a file with one ulimited dimensions, and one var. */
232 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
233 err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
234 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
235 err=ncmpi_close(ncid); ERR
236
237 /* Normally one would not close and reopen the file for each
238 * record, but I am giving the library a little work-out here... */
239 for (r = 0; r < MAX_RECS; r++)
240 {
241 /* Write one record of var data, a single character. */
242 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
243 /* if (f) { err=ncmpi_set_fill(ncid, NC_NOFILL, NULL); ERR} */
244 count[0] = 1;
245 start[0] = r;
246 err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data[r]); ERR
247 err=ncmpi_close(ncid); ERR
248
249 /* Reopen the file and check it. */
250 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
251 err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR
252 if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;}
253 index[0] = r;
254 err=ncmpi_begin_indep_data(ncid); ERR
255 err=ncmpi_get_var1_text(ncid, 0, index, &data_in); ERR
256 if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
257 err=ncmpi_close(ncid); ERR
258 } /* Next record. */
259 }
260 return 0;
261 }
262
263 #define ONE_DIM 1
264 #define MAX_RECS 10
265
266 /* Test a small file with one record var, which grows, and has
267 * attributes. */
268 static int
test_one_growing_with_att(const char * testfile,int cmode)269 test_one_growing_with_att(const char *testfile, int cmode)
270 {
271 int err, ncid, dimid, varid;
272 char data[MAX_RECS], data_in;
273 char att_name[NC_MAX_NAME + 1];
274 MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
275 int r;
276
277 /* Create a file with one ulimited dimensions, and one var. */
278 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
279 err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
280 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
281 err=ncmpi_close(ncid); ERR
282
283 /* Create some phoney data. */
284 for (data[0] = 'a', r = 1; r < MAX_RECS; r++)
285 data[r] = data[r - 1] + 1;
286
287 /* Normally one would not close and reopen the file for each
288 * record, nor add an attribute each time I add a record, but I am
289 * giving the library a little work-out here... */
290 for (r = 0; r < MAX_RECS; r++)
291 {
292 /* Write one record of var data, a single character. */
293 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
294 count[0] = 1;
295 start[0] = r;
296 err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data[r]); ERR
297 sprintf(att_name, "a_%d", data[r]);
298 err=ncmpi_redef(ncid); ERR
299 err=ncmpi_put_att_text(ncid, varid, att_name, 1, &data[r]); ERR
300 err=ncmpi_close(ncid); ERR
301
302 /* Reopen the file and check it. */
303 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
304 err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR
305 if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;}
306 index[0] = r;
307 err=ncmpi_begin_indep_data(ncid); ERR
308 err=ncmpi_get_var1_text(ncid, 0, index, &data_in); ERR
309 if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
310 err=ncmpi_get_att_text(ncid, varid, att_name, &data_in); ERR
311 if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
312 err=ncmpi_close(ncid); ERR
313 } /* Next record. */
314 return 0;
315 }
316
317 #define VAR_NAME2 "var2"
318 #define NUM_VARS 2
319
320 /* Test a small file with two record vars, which grow, and has
321 * attributes added. */
322 static int
test_two_growing_with_att(const char * testfile,int cmode)323 test_two_growing_with_att(const char *testfile, int cmode)
324 {
325 int err, ncid, dimid, varid[NUM_VARS];
326 char data[MAX_RECS], data_in;
327 char att_name[NC_MAX_NAME + 1];
328 MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
329 int v, r;
330
331 /* Create a file with one ulimited dimensions, and one var. */
332 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
333 err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
334 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid[0]); ERR
335 err=ncmpi_def_var(ncid, VAR_NAME2, NC_CHAR, 1, &dimid, &varid[1]); ERR
336 err=ncmpi_close(ncid); ERR
337
338 /* Create some phoney data. */
339 for (data[0] = 'a', r = 1; r < MAX_RECS; r++)
340 data[r] = data[r - 1] + 1;
341
342 /* Normally one would not close and reopen the file for each
343 * record, nor add an attribute each time I add a record, but I am
344 * giving the library a little work-out here... */
345 for (r = 0; r < MAX_RECS; r++)
346 {
347 /* Write one record of var data, a single character. */
348 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
349 count[0] = 1;
350 start[0] = r;
351 sprintf(att_name, "a_%d", data[r]);
352 for (v = 0; v < NUM_VARS; v++)
353 {
354 err=ncmpi_put_vara_text_all(ncid, varid[v], start, count, &data[r]); ERR
355 err=ncmpi_redef(ncid); ERR
356 err=ncmpi_put_att_text(ncid, varid[v], att_name, 1, &data[r]); ERR
357 err=ncmpi_enddef(ncid); ERR
358 }
359 err=ncmpi_close(ncid); ERR
360
361 /* Reopen the file and check it. */
362 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
363 err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR
364 if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;}
365 index[0] = r;
366 err=ncmpi_begin_indep_data(ncid); ERR
367 for (v = 0; v < NUM_VARS; v++)
368 {
369 err=ncmpi_get_var1_text(ncid, varid[v], index, &data_in); ERR
370 if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
371 }
372 err=ncmpi_close(ncid); ERR
373 } /* Next record. */
374 return 0;
375 }
376
377 /* Test a small file with one var and one att. */
378 static int
test_one_with_att(const char * testfile,int cmode)379 test_one_with_att(const char *testfile, int cmode)
380 {
381 int err, ncid, dimid, varid;
382 char data = 'h', data_in;
383 int ndims, nvars, natts, unlimdimid;
384 MPI_Offset start[NDIMS], count[NDIMS];
385
386 /* Create a file with one ulimited dimensions, and one var. */
387 err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
388 err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
389 err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
390 err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME, 1, &data); ERR
391 err=ncmpi_enddef(ncid); ERR
392
393 /* Write one record of var data, a single character. */
394 count[0] = 1;
395 start[0] = 0;
396 err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data); ERR
397
398 /* We're done! */
399 err=ncmpi_close(ncid); ERR
400
401 /* Reopen the file and check it. */
402 err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
403 err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
404 if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;}
405 err=ncmpi_get_var_text_all(ncid, varid, &data_in); ERR
406 if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;}
407 err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_NAME, &data_in); ERR
408 if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;}
409 err=ncmpi_close(ncid); ERR
410 return 0;
411 }
412
main(int argc,char * argv[])413 int main(int argc, char *argv[])
414 {
415 char filename[256];
416 int i, rank, nprocs, err, nerrs=0;
417 int cmode[NUM_FORMATS]={0, NC_64BIT_OFFSET, NC_64BIT_DATA};
418
419 MPI_Init(&argc, &argv);
420 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
421 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
422
423 if (argc > 2) {
424 if (!rank) printf("Usage: %s [filename]\n",argv[0]);
425 MPI_Finalize();
426 return 0;
427 }
428 if (argc == 2) snprintf(filename, 256, "%s", argv[1]);
429 else strcpy(filename, "testfile.nc");
430 MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
431
432 char *cmd_str = (char*)malloc(strlen(argv[0]) + 256);
433 sprintf(cmd_str, "*** TESTING C %s for emulating netCDF tst_small ", basename(argv[0]));
434 if (rank == 0) printf("%-66s ------ ", cmd_str);
435 free(cmd_str);
436
437 for (i=0; i<NUM_FORMATS; i++) {
438 #ifdef DEBUG
439 printf("*** testing simple small file with a global attribute...");
440 #endif
441 nerrs += test_small_atts(filename, cmode[i]|NC_CLOBBER);
442
443 #ifdef DEBUG
444 printf("*** testing simple small file with fixed dimensions...");
445 #endif
446 nerrs += test_small_fixed(filename, cmode[i]|NC_CLOBBER);
447
448 #ifdef DEBUG
449 printf("*** testing simple small file with an unlimited dimension...");
450 #endif
451 nerrs += test_small_unlim(filename, cmode[i]|NC_CLOBBER);
452
453 #ifdef DEBUG
454 printf("*** testing small file with one variable...");
455 #endif
456 nerrs += test_small_one(filename, cmode[i]|NC_CLOBBER);
457
458 #ifdef DEBUG
459 printf("*** testing small file with one variable and one att...");
460 #endif
461 nerrs += test_one_with_att(filename, cmode[i]|NC_CLOBBER);
462
463 #ifdef DEBUG
464 printf("*** testing small file with one record variable, which grows...");
465 #endif
466 nerrs += test_one_growing(filename, cmode[i]|NC_CLOBBER);
467
468 #ifdef DEBUG
469 printf("*** testing small file with one growing record "
470 "variable, with attributes added...");
471 #endif
472 nerrs += test_one_growing_with_att(filename, cmode[i]|NC_CLOBBER);
473
474 #ifdef DEBUG
475 if (verbose) printf("*** testing small file with two growing record "
476 "variables, with attributes added...");
477 #endif
478 nerrs += test_two_growing_with_att(filename, cmode[i]|NC_CLOBBER);
479 }
480
481 /* check if PnetCDF freed all internal malloc */
482 MPI_Offset malloc_size, sum_size;
483 err = ncmpi_inq_malloc_size(&malloc_size);
484 if (err == NC_NOERR) {
485 MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
486 if (rank == 0 && sum_size > 0)
487 printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
488 sum_size);
489 }
490
491 MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
492 if (rank == 0) {
493 if (nerrs) printf(FAIL_STR,nerrs);
494 else printf(PASS_STR);
495 }
496
497 MPI_Finalize();
498 return 0;
499 }
500
501