1 /* This is part of the netCDF package.
2 Copyright 2005 University Corporation for Atmospheric Research/Unidata
3 See COPYRIGHT file for conditions of use.
4
5 Test data conversions and fill value handling.
6
7 $Id: tst_converts.c,v 1.16 2008/10/20 01:48:09 ed Exp $
8 */
9
10 #include <nc_tests.h>
11 #include "err_macros.h"
12 #include "netcdf.h"
13
14 #define FILE_NAME "tst_converts.nc"
15 #define ATT1_NAME "att1"
16 #define ATT2_NAME "att2"
17 #define DIM1_NAME "dim1"
18 #define DIM1_LEN 3
19 #define DIM2_NAME "dim2"
20 #define DIM2_LEN 15
21 #define VAR1_NAME "var1"
22 #define VAR2_NAME "var2"
23
24 /* This is handy for print statements. */
25 static char *format_name[MAX_NUM_FORMATS] = {"classic", "64-bit offset", "netCDF-4",
26 "netCDF-4 classic model", "CDF5"};
27
28 int check_file(int format, unsigned char *uchar_out);
29 int create_file(int format, unsigned char *uchar_out);
30
31 /* Determine how many formats are available, and what they are. */
32 void
determine_test_formats(int * num_formats,int * format)33 determine_test_formats(int *num_formats, int *format)
34 {
35 int ind = 0;
36 int num;
37
38 /* Check inputs. */
39 assert(num_formats && format);
40
41 /* We always have classic and 64-bit offset */
42 num = 2;
43 format[ind++] = NC_FORMAT_CLASSIC;
44 format[ind++] = NC_FORMAT_64BIT_OFFSET;
45
46 /* Do we have netCDF-4 and netCDF-4 classic? */
47 #ifdef USE_NETCDF4
48 num += 2;
49 format[ind++] = NC_FORMAT_NETCDF4_CLASSIC;
50 format[ind++] = NC_FORMAT_NETCDF4;
51 #endif /* USE_NETCDF4 */
52
53 /* Do we have CDF5? */
54 #ifdef ENABLE_CDF5
55 num++;
56 format[ind++] = NC_FORMAT_CDF5;
57 #endif /* ENABLE_CDF5 */
58
59 *num_formats = num;
60 }
61
62 int
main(int argc,char ** argv)63 main(int argc, char **argv)
64 {
65 unsigned char uchar_out[DIM1_LEN] = {0, 128, 255};
66 int format[MAX_NUM_FORMATS];
67 int num_formats;
68 int f = 0;
69
70 printf("\n*** Testing netcdf data conversion.\n");
71 determine_test_formats(&num_formats, format);
72
73 for (f = 0; f < num_formats; f++)
74 {
75 printf("*** Testing conversion in netCDF %s files... ", format_name[f]);
76 create_file(format[f], uchar_out);
77 check_file(format[f], uchar_out);
78 SUMMARIZE_ERR;
79 }
80
81 FINAL_RESULTS;
82 }
83
84 /* Create a test file with one var of type NC_BYTE. */
85 int
create_file(int format,unsigned char * uchar_out)86 create_file(int format, unsigned char *uchar_out)
87 {
88 int ncid, varid, cflags=0, dimids[1];
89 int retval;
90
91 if (format == NC_FORMAT_64BIT_OFFSET)
92 cflags |= NC_64BIT_OFFSET;
93 else if (format == NC_FORMAT_CDF5)
94 cflags |= NC_CDF5;
95 else if (format == NC_FORMAT_NETCDF4_CLASSIC)
96 {
97 cflags |= (NC_NETCDF4|NC_CLASSIC_MODEL);
98 }
99 else if (format == NC_FORMAT_NETCDF4)
100 cflags |= NC_NETCDF4;
101
102 if (nc_create(FILE_NAME, cflags, &ncid)) ERR;
103 if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
104 if (nc_def_var(ncid, VAR1_NAME, NC_BYTE, 1, dimids, &varid)) ERR;
105 if (nc_enddef(ncid)) ERR;
106 retval = nc_put_var_uchar(ncid, varid, uchar_out);
107 if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_64BIT_DATA)
108 {
109 if (retval != NC_ERANGE) ERR;
110 }
111 else if (retval != NC_NOERR) ERR;
112
113 if (nc_close(ncid)) ERR;
114 return NC_NOERR;
115 }
116
117 int
check_file(int format,unsigned char * uchar_out)118 check_file(int format, unsigned char *uchar_out)
119 {
120 int ncid;
121 int ndims, natts;
122 int dimids_var[1], var_type;
123 char var_name[NC_MAX_NAME+1];
124 unsigned char uchar_in[DIM1_LEN];
125 signed char char_in[DIM1_LEN];
126 unsigned short ushort_in[DIM1_LEN];
127 short short_in[DIM1_LEN];
128 unsigned int uint_in[DIM1_LEN];
129 int int_in[DIM1_LEN];
130 long long int64_in[DIM1_LEN];
131 unsigned long long uint64_in[DIM1_LEN];
132 int i, res;
133
134 /* Read it back in, and check conversions. */
135 if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
136 if (nc_inq_var(ncid, 0, var_name, &var_type, &ndims, dimids_var, &natts)) ERR;
137 if (strcmp(var_name, VAR1_NAME) || natts !=0 || ndims != 1 ||
138 dimids_var[0] != 0 || var_type != NC_BYTE) ERR;
139
140 /* This is actually an NC_BYTE, with some negatives, so this should
141 * generate a range error for netcdf-4, but not for netcdf-3,
142 * because range errors are not generated for byte type
143 * conversions. */
144 res = nc_get_var_uchar(ncid, 0, uchar_in);
145 if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_64BIT_DATA)
146 {
147 if (res != NC_ERANGE) ERR;
148 }
149 else if (res) ERR;
150
151 for (i=0; i<DIM1_LEN; i++)
152 #ifdef ERANGE_FILL
153 if (uchar_in[i] != uchar_out[i] && uchar_in[i] != NC_FILL_UBYTE) ERR;
154 #else
155 if (uchar_in[i] != uchar_out[i]) ERR;
156 #endif
157
158 if (nc_get_var_schar(ncid, 0, char_in)) ERR;
159 for (i=0; i<DIM1_LEN; i++)
160 #ifdef ERANGE_FILL
161 if (char_in[i] != (signed char)uchar_out[i] && char_in[i] != NC_FILL_BYTE) ERR;
162 #else
163 if (char_in[i] != (signed char)uchar_out[i]) ERR;
164 #endif
165
166 if (nc_get_var_short(ncid, 0, short_in)) ERR;
167 for (i=0; i<DIM1_LEN; i++)
168 #ifdef ERANGE_FILL
169 if (short_in[i] != (signed char)uchar_out[i] && short_in[i] != NC_FILL_BYTE) ERR;
170 #else
171 if (short_in[i] != (signed char)uchar_out[i]) ERR;
172 #endif
173
174 if (nc_get_var_int(ncid, 0, int_in)) ERR;
175 for (i=0; i<DIM1_LEN; i++)
176 #ifdef ERANGE_FILL
177 if (int_in[i] != (signed char)uchar_out[i] && int_in[i] != NC_FILL_BYTE) ERR;
178 #else
179 if (int_in[i] != (signed char)uchar_out[i]) ERR;
180 #endif
181
182 if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_NETCDF4_CLASSIC)
183 {
184 /* Since we wrote them as NC_BYTE, some of these are negative
185 * values, and will return a range error when reading into
186 * unsigned type. To compare values, first cast uchar_out to
187 * signed int, then cast again to the type we are reading it
188 * as. */
189 if (nc_get_var_ushort(ncid, 0, ushort_in) != NC_ERANGE) ERR;
190 for (i=0; i<DIM1_LEN; i++)
191 if (ushort_in[i] != (unsigned short)(signed char)uchar_out[i]) ERR;
192
193 if (nc_get_var_uint(ncid, 0, uint_in) != NC_ERANGE) ERR;
194 for (i=0; i<DIM1_LEN; i++)
195 if (uint_in[i] != (unsigned int)(signed char)uchar_out[i]) ERR;
196
197 if (nc_get_var_ulonglong(ncid, 0, uint64_in) != NC_ERANGE) ERR;
198 for (i=0; i<DIM1_LEN; i++)
199 if (uint64_in[i] != (unsigned long long)(signed char)uchar_out[i]) ERR;
200
201 if (nc_get_var_longlong(ncid, 0, int64_in)) ERR;
202 for (i=0; i<DIM1_LEN; i++)
203 if (int64_in[i] != (signed char)uchar_out[i]) ERR;
204
205 }
206
207 if (nc_close(ncid)) ERR;
208 return 0;
209 }
210