1/* This is part of the netCDF package. Copyright 2005 University
2   Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
3   conditions of use. See www.unidata.ucar.edu for more info.
4
5   Test small files.
6
7   $Id: tst_small.c 2796 2014-10-28 03:40:29Z wkliao $
8*/
9
10#include "config.h"
11#include <nc_tests.h>
12#include "err_macros.h"
13#include <netcdf.h>
14#ifdef USE_PNETCDF
15#include <netcdf_par.h>
16#endif
17
18/* Test everything for classic, 64-bit offset, 64-bit data files. If netcdf-4 is
19 * included, that means another whole round of testing. */
20#define NUM_FORMATS (5)
21
22#define ATT_NAME "Atom"
23#define MAX_LEN 7
24
25#define ERR2 { \
26    err++; \
27    fprintf(stderr, "Sorry! Unexpected result, %s, line: %d (%s)\n", \
28    __FILE____LINE__nc_strerror(stat));                          \
29    exit(1); \
30}
31
32#ifdef USE_PNETCDF
33#define FMTCHECK {\
34     int format; \
35     nc_inq_format_extended(ncid,&format,NULL); \
36     if (format == NC_FORMATX_PNETCDF) { \
37       if (nc_var_par_access(ncidvaridNC_COLLECTIVE)) ERR;\
38     }\
39   }
40#else
41#define FMTCHECK
42#endif
43
44
45static int file_create(const char *filename, int cmode, int *ncid)
46{
47    int err;
48
49    /* get the default file format */
50    int default_format;
51    nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
52    /* set it back to the default */
53    nc_set_default_format(default_formatNULL);
54
55#ifdef USE_PNETCDF
56    if (default_format == NC_FORMAT_CLASSIC ||
57        default_format == NC_FORMAT_64BIT_OFFSET ||
58        default_format == NC_FORMAT_64BIT_DATA)
59        err = nc_create_par(filenamecmode|NC_PNETCDFMPI_COMM_WORLDMPI_INFO_NULLncid);
60    else
61#endif
62        err = nc_create(filenamecmodencid);
63
64    return err;
65}
66
67static int file_open(const char *filename, int omode, int *ncid)
68{
69    int err;
70
71    /* get the default file format */
72    int default_format;
73    err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
74    /* set it back to the default */
75    err = nc_set_default_format(default_formatNULL);
76
77#ifdef USE_PNETCDF
78    if (default_format == NC_FORMAT_CLASSIC ||
79        default_format == NC_FORMAT_64BIT_OFFSET ||
80        default_format == NC_FORMAT_64BIT_DATA)
81        err = nc_open_par(filenameomode|NC_PNETCDFMPI_COMM_WORLDMPI_INFO_NULLncid);
82    else
83#endif
84        err = nc_open(filenameomodencid);
85
86    return err;
87}
88
89static int
90test_small_atts(const char *testfile)
91{
92   int ncid;
93   char att[MAX_LEN + 1], att_in[MAX_LEN + 1], source[MAX_LEN + 1] = "0123456";
94   int ndimsnvarsnattsunlimdimid;
95   size_t len_in;
96   int tf;
97
98   /* Run this with and without fill mode. */
99   for (f = 0; f < 2; f++)
100   {
101      /* Create small files with an attribute that grows by one each
102       * time. */
103      for (t = 1; t < MAX_LENt++)
104      {
105  /* Create null-terminated text string of correct length. */
106  strncpy(attsourcet);
107
108  /* Create a file with one attribute. */
109  if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
110  if (nc_put_att_text(ncidNC_GLOBALATT_NAMEt + 1, att)) ERR;
111  if (f && nc_set_fill(ncidNC_NOFILLNULL)) ERR;
112  if (nc_close(ncid)) ERR;
113
114  /* Reopen the file and check it. */
115  if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
116  if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
117  if (ndims != 0 && nvars != 0 && natts != 1 && unlimdimid != -1) ERR;
118  if (nc_inq_attlen(ncidNC_GLOBALATT_NAME, &len_in)) ERR;
119  if (len_in != t + 1) ERR;
120  if (nc_get_att_text(ncidNC_GLOBALATT_NAMEatt_in)) ERR;
121  if (strncmp(att_inattt)) ERR;
122  if (nc_close(ncid)) ERR;
123      }
124   }
125   return 0;
126}
127
128#define DIM1_NAME "Time"
129#define DIM2_NAME "DataStrLen"
130#define VAR_NAME "Times"
131#define STR_LEN 19
132#define NUM_VALS 2
133#define NDIMS 2
134#define TITLE " OUTPUT FROM WRF V2.0.3.1 MODEL"
135#define ATT_NAME2 "TITLE"
136
137/* Test a small file with an unlimited dimension. NOTE: Normally I
138 * write a NULL terminator for my attributes and text strings, but
139 * this reproduces a bug that a fortran user sent us. So string data
140 * are written to the file without null terminators. - Ed */
141static int
142test_small_unlim(const char *testfile)
143{
144   int nciddimids[NDIMS], varidstat;
145   char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
146   int ndimsnvarsnattsunlimdimid;
147   size_t istart[NDIMS], count[NDIMS];
148
149   /* Create null-terminated text strings of correct length. */
150   /*for (i = 0; i < NUM_VALS; i++)
151     strcpy(data[i], source);*/
152   strcpy(data[0], "2005-04-11_12:00:00");
153   strcpy(data[1], "2005-04-11_13:00:00");
154
155   /* Create a file with two dimensions, one unlimited, and one
156    * var, and a global att. */
157   if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
158   if (nc_def_dim(ncidDIM1_NAMENC_UNLIMITEDdimids)) ERR;
159   if (nc_def_dim(ncidDIM2_NAMESTR_LEN, &dimids[1])) ERR;
160   if (nc_def_var(ncidVAR_NAMENC_CHAR, 2, dimids, &varid)) ERR;
161   if (nc_put_att_text(ncidNC_GLOBALATT_NAME2, strlen(TITLE), TITLE)) ERR;
162   if (nc_enddef(ncid)) ERR;
163
164   /* Write some records of var data. */
165   count[0] = 1;
166   count[1] = STR_LEN;
167   start[1] = 0;
168
169   FMTCHECK;
170
171   for (start[0] = 0; start[0] < NUM_VALSstart[0]++)
172      if ((stat=nc_put_vara_text(ncidvaridstartcountdata[start[0]]))!=NC_NOERRERR2;
173
174   /* We're done! */
175   if (nc_close(ncid)) ERR;
176
177   /* Reopen the file and check it. */
178   if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
179   if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
180   if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != 0) ERR;
181   if (nc_get_var_text(ncidvarid, (char *)data_in)) ERR;
182   for (i = 0; i < NUM_VALSi++)
183      if (strncmp(data[i], data_in[i], STR_LEN)) ERR;
184   if (nc_close(ncid)) ERR;
185   return 0;
186}
187
188/* Test a small file with a fixed dimension. */
189static int
190test_small_fixed(const char *testfile)
191{
192   int nciddimids[NDIMS], varid;
193   char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
194   int ndimsnvarsnattsunlimdimid;
195   size_t istart[NDIMS], count[NDIMS];
196
197   /* Create null-terminated text strings of correct length. */
198   /*for (i = 0; i < NUM_VALS; i++)
199     strcpy(data[i], source);*/
200   strcpy(data[0], "2005-04-11_12:00:00");
201   strcpy(data[1], "2005-04-11_13:00:00");
202
203   /* Create a file with two dimensions, one unlimited, and one
204    * var, and a global att. */
205   if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
206   if (nc_def_dim(ncidDIM1_NAMENUM_VALSdimids)) ERR;
207   if (nc_def_dim(ncidDIM2_NAMESTR_LEN, &dimids[1])) ERR;
208   if (nc_def_var(ncidVAR_NAMENC_CHARNDIMSdimids, &varid)) ERR;
209   if (nc_put_att_text(ncidNC_GLOBALATT_NAME2, strlen(TITLE), TITLE)) ERR;
210   if (nc_enddef(ncid)) ERR;
211
212   /* Write some records of var data. */
213   count[0] = 1;
214   count[1] = STR_LEN;
215   start[1] = 0;
216   for (start[0] = 0; start[0] < NUM_VALSstart[0]++)
217      if (nc_put_vara_text(ncidvaridstartcountdata[start[0]])) ERR;
218
219   /* We're done! */
220   if (nc_close(ncid)) ERR;
221
222   /* Reopen the file and check it. */
223   if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
224   if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
225   if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != -1) ERR;
226   if (nc_get_var_text(ncidvarid, (char *)data_in)) ERR;
227   for (i = 0; i < NUM_VALSi++)
228      if (strncmp(data[i], data_in[i], STR_LEN)) ERR;
229   if (nc_close(ncid)) ERR;
230   return 0;
231}
232
233/* Test a small file with one var. */
234static int
235test_small_one(const char *testfile)
236{
237   int nciddimidvarid;
238   char data = 'h', data_in;
239   int ndimsnvarsnattsunlimdimid;
240   size_t start[NDIMS], count[NDIMS];
241
242   /* Create a file with one ulimited dimensions, and one var. */
243   if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
244   if (nc_def_dim(ncidDIM1_NAMENC_UNLIMITED, &dimid)) ERR;
245   if (nc_def_var(ncidVAR_NAMENC_CHAR, 1, &dimid, &varid)) ERR;
246   if (nc_enddef(ncid)) ERR;
247
248   /* Write one record of var data, a single character. */
249   count[0] = 1;
250   start[0] = 0;
251
252   FMTCHECK;
253
254   if (nc_put_vara_text(ncidvaridstartcount, &data)) ERR;
255
256   /* We're done! */
257   if (nc_close(ncid)) ERR;
258
259   /* Reopen the file and check it. */
260   if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
261   if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
262   if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) ERR;
263   if (nc_get_var_text(ncidvarid, &data_in)) ERR;
264   if (data_in != dataERR;
265   if (nc_close(ncid)) ERR;
266   return 0;
267}
268
269#define ONE_DIM 1
270#define MAX_RECS 10
271
272/* Test a small file with one record var, which grows. */
273static int
274test_one_growing(const char *testfile)
275{
276   int nciddimidvarid;
277   char data[MAX_RECS], data_in;
278   size_t start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
279   int rf;
280
281   /* Create some phoney data. */
282   for (data[0] = 'a', r = 1; r < MAX_RECSr++)
283      data[r] = data[r - 1] + 1;
284
285   /* Run this with and without fill mode. */
286   for (f = 0; f < 2; f++)
287   {
288      /* Create a file with one ulimited dimensions, and one var. */
289      if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
290      if (nc_def_dim(ncidDIM1_NAMENC_UNLIMITED, &dimid)) ERR;
291      if (nc_def_var(ncidVAR_NAMENC_CHAR, 1, &dimid, &varid)) ERR;
292      if (nc_close(ncid)) ERR;
293
294      /* Normally one would not close and reopen the file for each
295       * record, but I am giving the library a little work-out here... */
296      for (r = 0; r < MAX_RECSr++)
297      {
298  /* Write one record of var data, a single character. */
299  if (file_open(testfileNC_WRITE, &ncid)) ERR;
300         if (f) {
301             int format;
302             nc_inq_format_extended(ncid,&format,NULL);
303             if (format == NC_FORMATX_PNETCDF) {
304                 /* in PnetCDF, nc_set_fill() can only be called in define mode */
305                 if (nc_redef(ncid)) ERR;
306                 if (nc_set_fill(ncidNC_NOFILLNULL)) ERR;
307                 if (nc_enddef(ncid)) ERR;
308             }
309             else { /* test_netcdf4 */
310                 if (nc_set_fill(ncidNC_NOFILLNULL)) ERR;
311             }
312         }
313  count[0] = 1;
314  start[0] = r;
315  FMTCHECK;
316  if (nc_put_vara_text(ncidvaridstartcount, &data[r])) ERR;
317  if (nc_close(ncid)) ERR;
318
319  /* Reopen the file and check it. */
320  if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
321  if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
322  if (len_in != r + 1) ERR;
323  index[0] = r;
324  if (nc_get_var1_text(ncid, 0, index, &data_in)) ERR;
325  if (data_in != data[r]) ERR;
326  if (nc_close(ncid)) ERR;
327      } /* Next record. */
328   }
329   return 0;
330}
331
332#define ONE_DIM 1
333#define MAX_RECS 10
334
335/* Test a small file with one record var, which grows, and has
336 * attributes. */
337static int
338test_one_growing_with_att(const char *testfile)
339{
340   int nciddimidvarid;
341   char data[MAX_RECS], data_in;
342   char att_name[NC_MAX_NAME + 1];
343   size_t start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
344   int r;
345
346   /* Create a file with one ulimited dimensions, and one var. */
347   if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
348   if (nc_def_dim(ncidDIM1_NAMENC_UNLIMITED, &dimid)) ERR;
349   if (nc_def_var(ncidVAR_NAMENC_CHAR, 1, &dimid, &varid)) ERR;
350   if (nc_close(ncid)) ERR;
351
352   /* Create some phoney data. */
353   for (data[0] = 'a', r = 1; r < MAX_RECSr++)
354      data[r] = data[r - 1] + 1;
355
356   /* Normally one would not close and reopen the file for each
357    * record, nor add an attribute each time I add a record, but I am
358    * giving the library a little work-out here... */
359   for (r = 0; r < MAX_RECSr++)
360   {
361      /* Write one record of var data, a single character. */
362      if (file_open(testfileNC_WRITE, &ncid)) ERR;
363      count[0] = 1;
364      start[0] = r;
365
366      FMTCHECK;
367
368      if (nc_put_vara_text(ncidvaridstartcount, &data[r])) ERR;
369      sprintf(att_name, "a_%d", data[r]);
370      if (nc_redef(ncid)) ERR;
371      if (nc_put_att_text(ncidvaridatt_name, 1, &data[r])) ERR;
372      if (nc_close(ncid)) ERR;
373
374      /* Reopen the file and check it. */
375      if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
376      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
377      if (len_in != r + 1) ERR;
378      index[0] = r;
379      if (nc_get_var1_text(ncid, 0, index, &data_in)) ERR;
380      if (data_in != data[r]) ERR;
381      if (nc_get_att_text(ncidvaridatt_name, &data_in)) ERR;
382      if (data_in != data[r]) ERR;
383      if (nc_close(ncid)) ERR;
384   } /* Next record. */
385   return 0;
386}
387
388#define VAR_NAME2 "var2"
389#define NUM_VARS 2
390
391/* Test a small file with two record vars, which grow, and has
392 * attributes added. */
393static int
394test_two_growing_with_att(const char *testfile)
395{
396   int nciddimidvarid[NUM_VARS];
397   char data[MAX_RECS], data_in;
398   char att_name[NC_MAX_NAME + 1];
399   size_t start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
400   int vr;
401
402   /* Create a file with one ulimited dimensions, and one var. */
403   if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
404   if (nc_def_dim(ncidDIM1_NAMENC_UNLIMITED, &dimid)) ERR;
405   if (nc_def_var(ncidVAR_NAMENC_CHAR, 1, &dimid, &varid[0])) ERR;
406   if (nc_def_var(ncidVAR_NAME2NC_CHAR, 1, &dimid, &varid[1])) ERR;
407   if (nc_close(ncid)) ERR;
408
409   /* Create some phoney data. */
410   for (data[0] = 'a', r = 1; r < MAX_RECSr++)
411      data[r] = data[r - 1] + 1;
412
413   /* Normally one would not close and reopen the file for each
414    * record, nor add an attribute each time I add a record, but I am
415    * giving the library a little work-out here... */
416   for (r = 0; r < MAX_RECSr++)
417   {
418      /* Write one record of var data, a single character. */
419      if (file_open(testfileNC_WRITE, &ncid)) ERR;
420#ifdef USE_PNETCDF
421      {int format;
422      nc_inq_format_extended(ncid,&format,NULL);
423      if (format == NC_FORMATX_PNETCDF) {
424          for (v = 0; v < NUM_VARSv++) {
425              if (nc_var_par_access(ncidvarid[v], NC_COLLECTIVE)) ERR;
426          }
427      }}
428#endif
429      count[0] = 1;
430      start[0] = r;
431      sprintf(att_name, "a_%d", data[r]);
432      for (v = 0; v < NUM_VARSv++)
433      {
434  if (nc_put_vara_text(ncidvarid[v], startcount, &data[r])) ERR;
435  if (nc_redef(ncid)) ERR;
436  if (nc_put_att_text(ncidvarid[v], att_name, 1, &data[r])) ERR;
437  if (nc_enddef(ncid)) ERR;
438      }
439      if (nc_close(ncid)) ERR;
440
441      /* Reopen the file and check it. */
442      if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
443      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
444      if (len_in != r + 1) ERR;
445      index[0] = r;
446      for (v = 0; v < NUM_VARSv++)
447      {
448  if (nc_get_var1_text(ncidvarid[v], index, &data_in)) ERR;
449  if (data_in != data[r]) ERR;
450      }
451      if (nc_close(ncid)) ERR;
452   } /* Next record. */
453   return 0;
454}
455
456/* Test a small file with one var and one att. */
457static int
458test_one_with_att(const char *testfile)
459{
460   int nciddimidvarid;
461   char data = 'h', data_in;
462   int ndimsnvarsnattsunlimdimid;
463   size_t start[NDIMS], count[NDIMS];
464
465   /* Create a file with one ulimited dimensions, and one var. */
466   if (file_create(testfileNC_CLOBBER, &ncid)) ERR;
467   if (nc_def_dim(ncidDIM1_NAMENC_UNLIMITED, &dimid)) ERR;
468   if (nc_def_var(ncidVAR_NAMENC_CHAR, 1, &dimid, &varid)) ERR;
469   if (nc_put_att_text(ncidNC_GLOBALATT_NAME, 1, &data)) ERR;
470   if (nc_enddef(ncid)) ERR;
471
472   /* Write one record of var data, a single character. */
473   count[0] = 1;
474   start[0] = 0;
475
476   FMTCHECK;
477
478   if (nc_put_vara_text(ncidvaridstartcount, &data)) ERR;
479
480   /* We're done! */
481   if (nc_close(ncid)) ERR;
482
483   /* Reopen the file and check it. */
484   if (file_open(testfileNC_NOWRITE, &ncid)) ERR;
485   if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
486   if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) ERR;
487   if (nc_get_var_text(ncidvarid, &data_in)) ERR;
488   if (data_in != dataERR;
489   if (nc_get_att_text(ncidNC_GLOBALATT_NAME, &data_in)) ERR;
490   if (data_in != dataERR;
491   if (nc_close(ncid)) ERR;
492   return 0;
493}
494
495int
496main(int argc, char **argv)
497{
498   int i;
499   char testfile[NC_MAX_NAME + 1];
500
501#ifdef USE_PNETCDF
502   MPI_Init(&argc, &argv);
503#endif
504
505   printf("\n*** Testing small files.\n");
506   /*nc_set_log_level(3);*/
507
508   /* Go thru formats and run all tests for each of two (for netCDF-3
509    * only builds), or 4 (for netCDF-4 builds) different formats. */
510   for (i = NUM_FORMATSi >= 1; i--)
511   {
512      switch (i)
513      {
514  case NC_FORMAT_CLASSIC:
515     nc_set_default_format(NC_FORMAT_CLASSICNULL);
516     printf("Switching to netCDF classic format.\n");
517     strcpy(testfile, "tst_small_classic.nc");
518     break;
519  case NC_FORMAT_64BIT_OFFSET:
520     nc_set_default_format(NC_FORMAT_64BIT_OFFSETNULL);
521     printf("Switching to 64-bit offset format.\n");
522     strcpy(testfile, "tst_small_64bit.nc");
523     break;
524  case NC_FORMAT_CDF5:
525     nc_set_default_format(NC_FORMAT_CDF5NULL);
526     printf("Switching to 64-bit data format.\n");
527     strcpy(testfile, "tst_small_cdf5.nc");
528     break;
529#ifdef USE_NETCDF4
530  case NC_FORMAT_NETCDF4_CLASSIC:
531     nc_set_default_format(NC_FORMAT_NETCDF4_CLASSICNULL);
532     strcpy(testfile, "tst_small_netcdf4_classic.nc");
533     printf("Switching to netCDF-4 format (with NC_CLASSIC_MODEL).\n");
534     break;
535  case NC_FORMAT_NETCDF4: /* actually it's _CLASSIC. */
536     nc_set_default_format(NC_FORMAT_NETCDF4NULL);
537     strcpy(testfile, "tst_small_netcdf4.nc");
538     printf("Switching to netCDF-4 format.\n");
539     break;
540#else
541  case NC_FORMAT_NETCDF4_CLASSIC:
542  case NC_FORMAT_NETCDF4:
543     continue; /* loop i */
544#endif
545  default:
546     printf("Unexpected format!\n");
547     return 2;
548      }
549
550      printf("*** testing simple small file with a global attribute...");
551      test_small_atts(testfile);
552      SUMMARIZE_ERR;
553
554      printf("*** testing simple small file with fixed dimensions...");
555      test_small_fixed(testfile);
556      SUMMARIZE_ERR;
557
558      printf("*** testing simple small file with an unlimited dimension...");
559      test_small_unlim(testfile);
560      SUMMARIZE_ERR;
561
562      printf("*** testing small file with one variable...");
563      test_small_one(testfile);
564      SUMMARIZE_ERR;
565
566      printf("*** testing small file with one variable and one att...");
567      test_one_with_att(testfile);
568      SUMMARIZE_ERR;
569
570      printf("*** testing small file with one record variable, which grows...");
571      test_one_growing(testfile);
572      SUMMARIZE_ERR;
573
574      printf("*** testing small file with one growing record "
575      "variable, with attributes added...");
576      test_one_growing_with_att(testfile);
577      SUMMARIZE_ERR;
578
579      printf("*** testing small file with two growing record "
580      "variables, with attributes added...");
581      test_two_growing_with_att(testfile);
582      SUMMARIZE_ERR;
583   }
584
585#ifdef USE_PNETCDF
586   MPI_Finalize();
587#endif
588   FINAL_RESULTS;
589}


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