1 /* This is part of the netCDF package. Copyright 2005-2018 University
2    Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
3    for conditions of use.
4 
5    Test attributes.
6 
7    $Id: tst_atts3.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 <signal.h>
14 #include "netcdf.h"
15 #ifdef USE_PARALLEL
16 #include "netcdf_par.h"
17 #endif
18 
19 #define FILE_NAME "tst_atts_3.nc"
20 #define FILE_NAME2 "tst_atts_2.nc"
21 #define VAR1_NAME "Horace_Rumpole"
22 #define VAR2_NAME "Claude_Erskine-Brown"
23 #define VAR3_NAME "Phillida_Erskine-Brown_Q.C."
24 #define DIM1_NAME "Old_Bailey_case_number"
25 #define DIM1_LEN 10
26 #define DIM2_NAME "occupancy_in_chambers"
27 #define DIM2_LEN 15
28 #define ATT_INT_NAME "Old_Bailey_Room_Numbers"
29 #define ATT_DOUBLE_NAME "Equity_Court_Canteen_Charges"
30 #define ATT_SHORT_NAME "Ecclesiastical_Court_Appearences"
31 #define ATT_TEXT_NAME "Speech_to_Jury"
32 #define ATT_TEXT_NAME2 "Speech_to_She_Who_Must_be_Obeyed"
33 #define ATT_UCHAR_NAME "Number_of_current_briefs"
34 #define ATT_SCHAR_NAME "Slate_totals_at_Pomeroys_Wine_Bar"
35 #define ATT_USHORT_NAME "brief_no"
36 #define ATT_UINT_NAME "Orders_from_SWMBO"
37 #define ATT_INT64_NAME "judges_golf_score"
38 #define ATT_UINT64_NAME "Number_of_drinks_in_career_to_date"
39 
40 /*
41 #define ATT_USHORT_NAME "Chamber_Gas_Electric_and_Telephone_Bill_Share"
42 */
43 #define ATT_FLOAT_NAME "Average_Nanoseconds_for_Lose_Win_or_Appeal"
44 #define ATT_LEN 3
45 
46 char speech[] = "Once more unto the breach, dear friends, once more;\n\
47 Or close the wall up with our English dead.\n\
48 In peace there's nothing so becomes a man\n\
49 As modest stillness and humility:\n\
50 But when the blast of war blows in our ears,\n\
51 Then imitate the action of the tiger;\n\
52 Stiffen the sinews, summon up the blood,\n\
53 Disguise fair nature with hard-favour'd rage;\n\
54 Then lend the eye a terrible aspect;\n\
55 Let pry through the portage of the head\n\
56 Like the brass cannon; let the brow o'erwhelm it\n\
57 As fearfully as doth a galled rock\n\
58 O'erhang and jutty his confounded base,\n\
59 Swill'd with the wild and wasteful ocean.\n\
60 Now set the teeth and stretch the nostril wide,\n\
61 Hold hard the breath and bend up every spirit\n\
62 To his full height. On, on, you noblest English.\n\
63 Whose blood is fet from fathers of war-proof!\n\
64 Fathers that, like so many Alexanders,\n\
65 Have in these parts from morn till even fought\n\
66 And sheathed their swords for lack of argument:\n\
67 Dishonour not your mothers; now attest\n\
68 That those whom you call'd fathers did beget you.\n\
69 Be copy now to men of grosser blood,\n\
70 And teach them how to war. And you, good yeoman,\n\
71 Whose limbs were made in England, show us here\n\
72 The mettle of your pasture; let us swear\n\
73 That you are worth your breeding; which I doubt not;\n\
74 For there is none of you so mean and base,\n\
75 That hath not noble lustre in your eyes.\n\
76 I see you stand like greyhounds in the slips,\n\
77 Straining upon the start. The game's afoot:\n\
78 Follow your spirit, and upon this charge\n\
79 Cry 'God for Harry, England, and Saint George!'";
80 
81 /* Test the ordering of atts for a cmode. */
82 #define NUM_ATTS 8
83 #define ATT_MAX_NAME 25
84 int
tst_att_ordering(int cmode)85 tst_att_ordering(int cmode)
86 {
87    int ncid;
88    char name[NUM_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf",
89 					    "Gd", "Gatt-name-dashes", "Gatt.name.dots"};
90    int len[NUM_ATTS] = {0, 2, 3, 3, 3, 3, 1, 1};
91    signed char b[2] = {-128, 127};
92    short s[3] = {-32768, 0, 32767};
93    int i[3] = {42, 0, -42};
94    float f[3] = {42.0, -42.0, 42.0};
95    double d[3] = {420.0, -420.0, 420.0};
96    int att_name_dashes = -1, att_name_dots = -2;
97    char name_in[NC_MAX_NAME];
98    int j;
99 
100    /* Create a file with some global atts. */
101 #ifdef TEST_PNETCDF
102    if (nc_create_par(FILE_NAME, cmode, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
103 #else
104    if (nc_create(FILE_NAME, cmode, &ncid)) ERR;
105 #endif
106    if (nc_put_att_text(ncid, NC_GLOBAL, name[0], len[0], NULL)) ERR;
107    if (nc_put_att_schar(ncid, NC_GLOBAL, name[1], NC_BYTE, len[1], b)) ERR;
108    if (nc_put_att_short(ncid, NC_GLOBAL, name[2], NC_SHORT, len[2], s)) ERR;
109    if (nc_put_att_int(ncid, NC_GLOBAL, name[3], NC_INT, len[3], i)) ERR;
110    if (nc_put_att_float(ncid, NC_GLOBAL, name[4], NC_FLOAT, len[4], f)) ERR;
111    if (nc_put_att_double(ncid, NC_GLOBAL, name[5], NC_DOUBLE, len[5], d)) ERR;
112    if (nc_put_att_int(ncid, NC_GLOBAL, name[6], NC_INT, len[6], &att_name_dashes)) ERR;
113    if (nc_put_att_int(ncid, NC_GLOBAL, name[7], NC_INT, len[7], &att_name_dots)) ERR;
114    if (nc_close(ncid)) ERR;
115 
116    /* Reopen the file and check the order. */
117 #ifdef TEST_PNETCDF
118    if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
119 #else
120    if (nc_open(FILE_NAME, 0, &ncid)) ERR;
121 #endif
122    for (j = 0; j < NUM_ATTS; j++)
123    {
124       if (nc_inq_attname(ncid, NC_GLOBAL, j, name_in)) ERR;
125       if (strcmp(name_in, name[j])) ERR;
126    }
127 
128    /* Close up shop. */
129    if (nc_close(ncid)) ERR;
130    return err;
131 }
132 
133 int
main(int argc,char ** argv)134 main(int argc, char **argv)
135 {
136     signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
137     unsigned char uchar_in[ATT_LEN];
138     short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
139     int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 127, 100000};
140     float float_in[ATT_LEN], float_out[ATT_LEN] = {-0.5, 0.25, 0.125};
141     double double_in[ATT_LEN], double_out[ATT_LEN] = {-0.25, .5, 0.125};
142     long long longlong_in[ATT_LEN] = {-1LL, -1LL, -1LL};
143 
144 #ifdef TEST_PNETCDF
145    MPI_Init(&argc, &argv);
146 #endif
147     (void) signal(SIGFPE, SIG_IGN);
148 
149    printf("\n*** Testing netcdf-3 attribute functions.\n");
150    printf("*** testing really simple global atts...");
151 #define NUM_SIMPLE_ATTS 9
152    {
153       int ncid;
154       char name[NUM_SIMPLE_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf",
155 						      "Gd", "G7", "G8", "G9"};
156       char name_in[NC_MAX_NAME];
157       int j;
158 
159       /* Create a file with some global atts. */
160 #ifdef TEST_PNETCDF
161       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
162 #else
163       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
164 #endif
165       for (j = 0; j < NUM_SIMPLE_ATTS; j++)
166 	 if (nc_put_att_int(ncid, NC_GLOBAL, name[j], NC_INT, 0, NULL)) ERR;
167       if (nc_close(ncid)) ERR;
168 
169       /* Reopen the file and check the order. */
170 #ifdef TEST_PNETCDF
171       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
172 #else
173       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
174 #endif
175       for (j = 0; j < NUM_SIMPLE_ATTS; j++)
176       {
177 	 if (nc_inq_attname(ncid, NC_GLOBAL, j, name_in)) ERR;
178 	 if (strcmp(name_in, name[j])) ERR;
179       }
180 
181       /* Close up shop. */
182       if (nc_close(ncid)) ERR;
183    }
184    SUMMARIZE_ERR;
185    printf("*** testing simple global atts...");
186    {
187       int ncid;
188       nc_type att_type;
189       size_t att_len;
190       int i;
191 
192       char *speech_in;
193 
194       /* This won't work, because classic files can't create these types. */
195 #ifdef TEST_PNETCDF
196       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
197 #else
198       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
199 #endif
200       if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN,
201 			    int_out)) ERR;
202       /* It is also OK to read classic types converted into
203        * supported C types. though the conversion may encounter
204        * out-of-range values */
205       if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_INT_NAME, uchar_in) != NC_ERANGE) ERR;
206       for (i = 0; i < ATT_LEN; i++) {
207         if (i == 0 || i == 2) continue;
208 	if (uchar_in[i] != (unsigned char) int_out[i]) ERR;
209       }
210 
211       /* This was bug NCF-171: on 32-bit platforms, bad values returned */
212       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in)) ERR;
213       for (i = 0; i < ATT_LEN; i++)
214       	if (longlong_in[i] != (long long) int_out[i]) ERR;
215       if (nc_close(ncid)) ERR;
216 
217       /* Create a file with a global attribute of each type. */
218 #ifdef TEST_PNETCDF
219       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
220 #else
221       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
222 #endif
223       if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;
224       if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;
225       if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out)) ERR;
226       if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out)) ERR;
227       if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out)) ERR;
228       if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out)) ERR;
229       if (nc_close(ncid)) ERR;
230 
231       /* Open the file and check attributes. */
232 #ifdef TEST_PNETCDF
233       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
234 #else
235       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
236 #endif
237       /* Check text. */
238       if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len))
239 	 ERR;
240       if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
241       if (!(speech_in = malloc(att_len + 1))) ERR;
242       if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) ERR;
243       if (strcmp(speech, speech_in)) ERR;
244       free(speech_in);
245       /* Check numeric values. */
246       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
247       for (i = 0; i < ATT_LEN; i++)
248 	 if (schar_in[i] != schar_out[i]) ERR;
249       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
250       for (i = 0; i < ATT_LEN; i++)
251 	 if (short_in[i] != short_out[i]) ERR;
252       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
253       for (i = 0; i < ATT_LEN; i++)
254 	 if (int_in[i] != int_out[i]) ERR;
255       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
256       for (i = 0; i < ATT_LEN; i++)
257 	 if (float_in[i] != float_out[i]) ERR;
258       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
259       for (i = 0; i < ATT_LEN; i++)
260 	 if (double_in[i] != double_out[i]) ERR;
261       if (nc_close(ncid)) ERR;
262    }
263    SUMMARIZE_ERR;
264    printf("*** testing attribute data type conversions...");
265 
266    {
267       int ncid;
268       int i;
269 
270       /* Reopen the file and try different type conversions. */
271 #ifdef TEST_PNETCDF
272       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
273 #else
274       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
275 #endif
276 
277       /* No text conversions are allowed, and people who try them should
278        * be locked up, away from decent folk! */
279       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_TEXT_NAME, short_in) != NC_ECHAR) ERR;
280       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_TEXT_NAME, int_in) != NC_ECHAR) ERR;
281       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_TEXT_NAME, float_in) != NC_ECHAR) ERR;
282       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_TEXT_NAME, double_in) != NC_ECHAR) ERR;
283 
284       /* Read all atts (except text) as double. */
285       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_SCHAR_NAME, double_in)) ERR;
286       for (i = 0; i < ATT_LEN; i++)
287 	 if (double_in[i] != schar_out[i]) ERR;
288       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_SHORT_NAME, double_in)) ERR;
289       for (i = 0; i < ATT_LEN; i++)
290 	 if (double_in[i] != short_out[i]) ERR;
291       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_INT_NAME, double_in)) ERR;
292       for (i = 0; i < ATT_LEN; i++)
293 	 if (double_in[i] != int_out[i]) ERR;
294       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_FLOAT_NAME, double_in)) ERR;
295       for (i = 0; i < ATT_LEN; i++)
296 	 if (double_in[i] != float_out[i]) ERR;
297       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
298       for (i = 0; i < ATT_LEN; i++)
299 	 if (double_in[i] != double_out[i]) ERR;
300 
301       /* Read all atts (except text) as float. */
302       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_SCHAR_NAME, float_in)) ERR;
303       for (i = 0; i < ATT_LEN; i++)
304 	 if (float_in[i] != schar_out[i]) ERR;
305       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_SHORT_NAME, float_in)) ERR;
306       for (i = 0; i < ATT_LEN; i++)
307 	 if (float_in[i] != short_out[i]) ERR;
308       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_INT_NAME, float_in)) ERR;
309       for (i = 0; i < ATT_LEN; i++)
310 	 if (float_in[i] != int_out[i]) ERR;
311       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
312       for (i = 0; i < ATT_LEN; i++)
313 	 if (float_in[i] != float_out[i]) ERR;
314       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, float_in)) ERR;
315       for (i = 0; i < ATT_LEN; i++)
316 	  if (float_in[i] != (float) double_out[i]) ERR;
317 
318       /* Read all atts (except text) as int. */
319       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_SCHAR_NAME, int_in)) ERR;
320       for (i = 0; i < ATT_LEN; i++)
321 	 if (int_in[i] != schar_out[i]) ERR;
322       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_SHORT_NAME, int_in)) ERR;
323       for (i = 0; i < ATT_LEN; i++)
324 	 if (int_in[i] != short_out[i]) ERR;
325       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
326       for (i = 0; i < ATT_LEN; i++)
327 	 if (int_in[i] != int_out[i]) ERR;
328       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_FLOAT_NAME, int_in)) ERR;
329       for (i = 0; i < ATT_LEN; i++)
330 	  if (int_in[i] != (int) float_out[i]) ERR;
331       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, int_in)) ERR;
332       for (i = 0; i < ATT_LEN; i++)
333 	  if (int_in[i] != (int) double_out[i]) ERR;
334 
335       /* Read all atts (except text) as short. */
336       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SCHAR_NAME, short_in)) ERR;
337       for (i = 0; i < ATT_LEN; i++)
338 	 if (short_in[i] != schar_out[i]) ERR;
339       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
340       for (i = 0; i < ATT_LEN; i++)
341 	 if (short_in[i] != short_out[i]) ERR;
342       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_INT_NAME, short_in) != NC_ERANGE) ERR;
343       for (i = 0; i < ATT_LEN; i++) {
344           if (i == 0 || i == 2) continue;
345 	  if (short_in[i] != (short) int_out[i]) ERR;
346       }
347       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_FLOAT_NAME, short_in)) ERR;
348       for (i = 0; i < ATT_LEN; i++)
349 	  if (short_in[i] != (short) float_out[i]) ERR;
350       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, short_in)) ERR;
351       for (i = 0; i < ATT_LEN; i++)
352 	  if (short_in[i] != (short) double_out[i]) ERR;
353 
354       /* Read all atts (except text) as schar. */
355       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
356       for (i = 0; i < ATT_LEN; i++)
357 	 if (schar_in[i] != schar_out[i]) ERR;
358       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in) != NC_ERANGE) ERR;
359       for (i = 0; i < ATT_LEN; i++) {
360          if (i == 0 || i == 2) continue;
361 	 if (schar_in[i] != (signed char) short_out[i]) ERR;
362       }
363       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in) != NC_ERANGE) ERR;
364       for (i = 0; i < ATT_LEN; i++) {
365          if (i == 0 || i == 2) continue;
366 	 if (schar_in[i] != (signed char) int_out[i]) ERR;
367       }
368       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
369       for (i = 0; i < ATT_LEN; i++)
370 	 if (schar_in[i] != (signed char) float_out[i]) ERR;
371       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
372       for (i = 0; i < ATT_LEN; i++)
373 	 if (schar_in[i] != (signed char) double_out[i]) ERR;
374 
375       /* Read all atts (except text) as uchar. */
376       if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, uchar_in)) ERR;
377       for (i = 0; i < ATT_LEN; i++)
378 	 if (uchar_in[i] != (unsigned char) schar_out[i]) ERR;
379       if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_SHORT_NAME, uchar_in) != NC_ERANGE) ERR;
380       if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_INT_NAME, uchar_in) != NC_ERANGE) ERR;
381       for (i = 0; i < ATT_LEN; i++) {
382          if (i == 0 || i == 2) continue;
383 	 if (uchar_in[i] != (unsigned char) int_out[i]) ERR;
384       }
385       if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, uchar_in) != NC_ERANGE) ERR;
386       for (i = 0; i < ATT_LEN; i++) {
387          if (i == 0) continue;
388 	 if (uchar_in[i] != (unsigned char) float_out[i]) ERR;
389       }
390       if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, uchar_in) != NC_ERANGE) ERR;
391       for (i = 0; i < ATT_LEN; i++) {
392          if (i == 0) continue;
393 	 if (uchar_in[i] != (unsigned char) double_out[i]) ERR;
394       }
395 
396       /* Read all atts (except text) into long long variable. */
397       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_SCHAR_NAME, longlong_in)) ERR;
398       for (i = 0; i < ATT_LEN; i++)
399 	 if (longlong_in[i] != schar_out[i]) ERR;
400       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_SHORT_NAME, longlong_in)) ERR;
401       for (i = 0; i < ATT_LEN; i++)
402 	 if (longlong_in[i] != short_out[i]) ERR;
403       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in)) ERR;
404       /* This was bug NCF-171: on 32-bit platforms, bad values returned */
405       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in)) ERR;
406       for (i = 0; i < ATT_LEN; i++)
407       	if (longlong_in[i] != (long long) int_out[i]) ERR;
408       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_FLOAT_NAME, longlong_in)) ERR;
409       for (i = 0; i < ATT_LEN; i++)
410 	 if (longlong_in[i] != (long long)float_out[i]) ERR;
411       if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, longlong_in)) ERR;
412       for (i = 0; i < ATT_LEN; i++)
413 	 if (longlong_in[i] != (long long)double_out[i]) ERR;
414 
415       if (nc_close(ncid)) ERR;
416    }
417    SUMMARIZE_ERR;
418    printf("*** testing zero-length attributes...");
419    {
420       int ncid;
421 
422       /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
423 
424       /* Create a file with a global attribute of each type of zero length. */
425 #ifdef TEST_PNETCDF
426       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
427 #else
428       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
429 #endif
430       if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR;
431       if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR;
432       if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR;
433       if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR;
434       if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR;
435       if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL)) ERR;
436       if (nc_close(ncid)) ERR;
437    }
438 
439    /* Make sure we can read all these zero-length atts. */
440    {
441       int ncid;
442       signed char schar_in[ATT_LEN];
443       short short_in[ATT_LEN];
444       /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
445       int int_in[ATT_LEN];
446       float float_in[ATT_LEN];
447       double double_in[ATT_LEN];
448       size_t len;
449       nc_type xtype;
450 
451 #ifdef TEST_PNETCDF
452       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
453 #else
454       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
455 #endif
456       if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR;
457       if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &xtype, &len)) ERR;
458       if (len || xtype != NC_CHAR) ERR;
459       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
460       if (nc_inq_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, &xtype, &len)) ERR;
461       if (len || xtype != NC_BYTE) ERR;
462       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
463       if (nc_inq_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, &xtype, &len)) ERR;
464       if (len || xtype != NC_SHORT) ERR;
465       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
466       if (nc_inq_att(ncid, NC_GLOBAL, ATT_INT_NAME, &xtype, &len)) ERR;
467       if (len || xtype != NC_INT) ERR;
468       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
469       if (nc_inq_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, &xtype, &len)) ERR;
470       if (len || xtype != NC_FLOAT) ERR;
471       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
472       if (nc_inq_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, &xtype, &len)) ERR;
473       if (len || xtype != NC_DOUBLE) ERR;
474       /* Conversions no longer result in range errors, since there's no data. */
475       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
476       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
477       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) ERR;
478       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) ERR;
479       if (nc_close(ncid)) ERR;
480    }
481 
482    SUMMARIZE_ERR;
483    printf("*** testing zero-length attributes and redef...(this test skipped for HDF5-1.8.0 beta1");
484    {
485       int ncid;
486       signed char schar_in[ATT_LEN];
487       short short_in[ATT_LEN];
488       int int_in[ATT_LEN];
489       float float_in[ATT_LEN];
490       double double_in[ATT_LEN];
491 
492 
493       /* Create a file with a global attribute of each type of zero length. */
494 #ifdef TEST_PNETCDF
495       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
496 #else
497       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
498 #endif
499       if (nc_enddef(ncid)) ERR;
500       if (nc_redef(ncid)) ERR;
501       if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR;
502       if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR;
503       if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR;
504       if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR;
505       if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR;
506       if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL)) ERR;
507       if (nc_close(ncid)) ERR;
508 
509       /* Make sure we can read all these zero-length atts added during a
510        * redef. */
511 #ifdef TEST_PNETCDF
512       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
513 #else
514       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
515 #endif
516       if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR;
517       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
518       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
519       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
520       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
521       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
522       /* Conversions no longer result in range errors, since there's no data. */
523       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
524       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
525       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) ERR;
526       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) ERR;
527       if (nc_close(ncid)) ERR;
528    }
529    SUMMARIZE_ERR;
530 
531    printf("*** testing attribute deletes and renames...");
532    {
533       int ncid, varid, dimids[2];
534       nc_type att_type;
535       size_t att_len;
536       char *speech_in;
537       char name_in[NC_MAX_NAME + 1];
538       int attid_in, natts_in;
539       int int_out[ATT_LEN] = {-100000, 128, 100000};
540 
541       /* Create a file with a global attribute. */
542 #ifdef TEST_PNETCDF
543       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
544 #else
545       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
546 #endif
547       if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1,
548 			  speech)) ERR;
549       if (nc_close(ncid)) ERR;
550 
551       /* Rename it. */
552 #ifdef TEST_PNETCDF
553       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
554 #else
555       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
556 #endif
557       if (nc_inq_attid(ncid, NC_GLOBAL, ATT_TEXT_NAME, &attid_in)) ERR;
558       if (attid_in != 0) ERR;
559       if (nc_inq_attname(ncid, NC_GLOBAL, attid_in, name_in)) ERR;
560       if (strcmp(name_in, ATT_TEXT_NAME)) ERR;
561       if (nc_redef(ncid)) ERR;
562       if (nc_rename_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ATT_TEXT_NAME2)) ERR;
563       if (nc_inq_attname(ncid, NC_GLOBAL, attid_in, name_in)) ERR;
564       if (strcmp(name_in, ATT_TEXT_NAME2)) ERR;
565       if (nc_close(ncid)) ERR;
566 
567 #ifdef TEST_PNETCDF
568       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
569 #else
570       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
571 #endif
572       if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2, &att_type, &att_len)) ERR;
573       if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
574       if (!(speech_in = malloc(att_len + 1))) ERR;
575       if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME2, speech_in)) ERR;
576       if (strcmp(speech, speech_in)) ERR;
577       free(speech_in);
578       if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in) != NC_ENOTATT) ERR;
579       if (nc_close(ncid)) ERR;
580 
581       /* Now delete the att. */
582 #ifdef TEST_PNETCDF
583       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
584 #else
585       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
586 #endif
587       if (nc_redef(ncid)) ERR;
588       if (nc_del_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2)) ERR;
589       if (nc_close(ncid)) ERR;
590 
591       /* Now create a file with a variable, which has an att. */
592 #ifdef TEST_PNETCDF
593       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
594 #else
595       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
596 #endif
597       if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;
598       if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
599       if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
600       if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
601       if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;
602       if (nc_close(ncid)) ERR;
603 
604       /* Reopen the file and delete it. Make sure it's gone. */
605 #ifdef TEST_PNETCDF
606       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
607 #else
608       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
609 #endif
610       if (nc_redef(ncid)) ERR;
611       if (nc_del_att(ncid, 0, ATT_INT_NAME)) ERR;
612       if (nc_close(ncid)) ERR;
613 
614       /* Reopen the file and readd the attribute. Enddef and redef,
615        * and delete it, then check to make sure it's gone. */
616 #ifdef TEST_PNETCDF
617       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
618 #else
619       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
620 #endif
621       if (nc_redef(ncid)) ERR;
622       if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;
623       if (nc_enddef(ncid)) ERR;
624       if (nc_redef(ncid)) ERR;
625       if (nc_del_att(ncid, 0, ATT_INT_NAME)) ERR;
626       if (nc_inq_varnatts(ncid, 0, &natts_in)) ERR;
627       if (natts_in != 0) ERR;
628       if (nc_close(ncid)) ERR;
629    }
630 
631    SUMMARIZE_ERR;
632    printf("*** testing attribute create order...");
633 
634 #define ATT0 "Maturin"
635 #define ATT1 "Aubery"
636    {
637       int ncid, varid, dimids[2];
638       int attid_in;
639       const int number = 42;
640 
641       /* Create a file with several global attributes. */
642 #ifdef TEST_PNETCDF
643       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
644 #else
645       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
646 #endif
647       if (nc_put_att_int(ncid, NC_GLOBAL, ATT0, NC_INT, 1, &number)) ERR;
648       if (nc_put_att_int(ncid, NC_GLOBAL, ATT1, NC_INT, 1, &number)) ERR;
649       if (nc_close(ncid)) ERR;
650 
651       /* Open it and check the order. */
652 #ifdef TEST_PNETCDF
653       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
654 #else
655       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
656 #endif
657       if (nc_inq_attid(ncid, NC_GLOBAL, ATT0, &attid_in)) ERR;
658       if (attid_in != 0) ERR;
659       if (nc_inq_attid(ncid, NC_GLOBAL, ATT1, &attid_in)) ERR;
660       if (attid_in != 1) ERR;
661       if (nc_close(ncid)) ERR;
662 
663       /* Now create a file with a variable, which has two atts. */
664 #ifdef TEST_PNETCDF
665       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
666 #else
667       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
668 #endif
669       if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
670       if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
671       if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
672       if (nc_put_att_int(ncid, varid, ATT0, NC_INT, 1, &number)) ERR;
673       if (nc_put_att_int(ncid, varid, ATT1, NC_INT, 1, &number)) ERR;
674       if (nc_close(ncid)) ERR;
675 
676       /* Reopen the file and check the order of the attributes on the var. */
677 #ifdef TEST_PNETCDF
678       if (nc_open_par(FILE_NAME, NC_WRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
679 #else
680       if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
681 #endif
682       if (nc_inq_attid(ncid, 0, ATT0, &attid_in)) ERR;
683       if (attid_in != 0) ERR;
684       if (nc_inq_attid(ncid, 0, ATT1, &attid_in)) ERR;
685       if (attid_in != 1) ERR;
686       if (nc_close(ncid)) ERR;
687    }
688 
689    SUMMARIZE_ERR;
690    printf("*** testing attribute ordering some more...");
691 
692 #define VAR_NAME "i"
693 #define A1_NAME "i"
694 #define A2_NAME "f"
695 #define A3_NAME "d"
696 #define A1_LEN 3
697 #define A2_LEN 4
698 #define A3_LEN 5
699    {
700       int ncid;
701       int varid, natts, nvars;
702       double dvalue[] = {999.99, 999.99, 999.99, 999.99, 999.99};
703       char name_in[NC_MAX_NAME + 1];
704 
705       /* Create a file with one var, and attach three atts to it. */
706 #ifdef TEST_PNETCDF
707       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
708 #else
709       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
710 #endif
711       if (nc_def_var(ncid, VAR_NAME, NC_INT, 0, NULL, &varid)) ERR;
712       if (nc_put_att_double(ncid, varid, A1_NAME, NC_INT, A1_LEN, dvalue)) ERR;
713       if (nc_put_att_double(ncid, varid, A2_NAME, NC_INT, A2_LEN, dvalue)) ERR;
714       if (nc_put_att_double(ncid, varid, A3_NAME, NC_INT, A3_LEN, dvalue)) ERR;
715       if (nc_close(ncid)) ERR;
716 
717       /* Reopen the file and check. */
718 #ifdef TEST_PNETCDF
719       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
720 #else
721       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
722 #endif
723       if (nc_inq_nvars(ncid, &nvars)) ERR;
724       if (nvars != 1) ERR;
725       if (nc_inq_varnatts(ncid, 0, &natts)) ERR;
726       if (natts != 3) ERR;
727       if (nc_inq_attname(ncid, 0, 0, name_in)) ERR;
728       if (strcmp(name_in, A1_NAME)) ERR;
729       if (nc_inq_attname(ncid, 0, 1, name_in)) ERR;
730       if (strcmp(name_in, A2_NAME)) ERR;
731       if (nc_inq_attname(ncid, 0, 2, name_in)) ERR;
732       if (strcmp(name_in, A3_NAME)) ERR;
733 
734       /* Close up shop. */
735       if (nc_close(ncid)) ERR;
736    }
737 
738    SUMMARIZE_ERR;
739    printf("*** testing attribute ordering even more...");
740 
741    /* Test the ordering of atts for each cmode. */
742    if (tst_att_ordering(NC_CLOBBER)) ERR;
743    if (tst_att_ordering(NC_CLOBBER|NC_64BIT_OFFSET)) ERR;
744 
745    SUMMARIZE_ERR;
746    printf("*** testing attributes and enddef/redef...");
747 
748 #define ATT_1 "a"
749 #define ATT_2 "b"
750 #define ATT_3 "c"
751    {
752       int ncid, att = 1;
753 
754 #ifdef TEST_PNETCDF
755       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
756 #else
757       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
758 #endif
759       if (nc_enddef(ncid)) ERR;
760       if (nc_redef(ncid)) ERR;
761       if (nc_put_att(ncid, NC_GLOBAL, ATT_1, NC_INT, 1, &att)) ERR;
762       if (nc_put_att(ncid, NC_GLOBAL, ATT_2, NC_INT, 1, &att)) ERR;
763       if (nc_put_att(ncid, NC_GLOBAL, ATT_3, NC_INT, 1, &att)) ERR;
764 
765       if (nc_close(ncid)) ERR;
766 
767 #ifdef TEST_PNETCDF
768       if (nc_open_par(FILE_NAME, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
769 #else
770       if (nc_open(FILE_NAME, 0, &ncid)) ERR;
771 #endif
772       if (nc_close(ncid)) ERR;
773    }
774 
775    SUMMARIZE_ERR;
776    printf("*** testing copy of simple global atts...");
777    {
778       int ncid, ncid2;
779       nc_type att_type;
780       size_t att_len;
781       int i;
782 
783       char *speech_in;
784       signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
785       short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
786       int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
787       float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
788       double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
789 
790       /* Create a file with a global attribute of each type. */
791 #ifdef TEST_PNETCDF
792       if (nc_create_par(FILE_NAME, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid)) ERR;
793 #else
794       if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
795 #endif
796       if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;
797       if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;
798       if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out)) ERR;
799       if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out)) ERR;
800       if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out)) ERR;
801       if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out)) ERR;
802 
803       /* Create another file and copy all the attributes. */
804 #ifdef TEST_PNETCDF
805       if (nc_create_par(FILE_NAME2, NC_CLOBBER, MPI_COMM_WORLD, MPI_INFO_NULL,&ncid2)) ERR;
806 #else
807       if (nc_create(FILE_NAME2, NC_CLOBBER, &ncid2)) ERR;
808 #endif
809       if (nc_copy_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ncid2, NC_GLOBAL)) ERR;
810       if (nc_copy_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, ncid2, NC_GLOBAL)) ERR;
811       if (nc_copy_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, ncid2, NC_GLOBAL)) ERR;
812       if (nc_copy_att(ncid, NC_GLOBAL, ATT_INT_NAME, ncid2, NC_GLOBAL)) ERR;
813       if (nc_copy_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, ncid2, NC_GLOBAL)) ERR;
814       if (nc_copy_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, ncid2, NC_GLOBAL)) ERR;
815 
816       /* Close both files. */
817       if (nc_close(ncid)) ERR;
818       if (nc_close(ncid2)) ERR;
819 
820       /* Open the file and check attributes. */
821 #ifdef TEST_PNETCDF
822       if (nc_open_par(FILE_NAME2, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid)) ERR;
823 #else
824       if (nc_open(FILE_NAME2, 0, &ncid)) ERR;
825 #endif
826       /* Check text. */
827       if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len)) ERR;
828       if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
829       if (!(speech_in = malloc(att_len + 1))) ERR;
830       if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) ERR;
831       if (strcmp(speech, speech_in)) ERR;
832       free(speech_in);
833       /* Check numeric values. */
834       if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
835       for (i = 0; i < ATT_LEN; i++)
836 	 if (schar_in[i] != schar_out[i]) ERR;
837       if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
838       for (i = 0; i < ATT_LEN; i++)
839 	 if (short_in[i] != short_out[i]) ERR;
840       if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
841       for (i = 0; i < ATT_LEN; i++)
842 	 if (int_in[i] != int_out[i]) ERR;
843       if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
844       for (i = 0; i < ATT_LEN; i++)
845 	 if (float_in[i] != float_out[i]) ERR;
846       if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
847       for (i = 0; i < ATT_LEN; i++)
848 	 if (double_in[i] != double_out[i]) ERR;
849       if (nc_close(ncid)) ERR;
850    }
851    SUMMARIZE_ERR;
852 #ifdef TEST_PNETCDF
853    MPI_Finalize();
854 #endif
855    FINAL_RESULTS;
856 }
857