1 #include <config.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "netcdf.h"
6 #include "t_srcdir.h"
7 
8 
9 #undef GENERATE
10 
11 #undef DEBUG
12 
13 /* Test (some) internal/external type conversions
14    using following DAP dataset (test.02).
15 	Dataset {
16 	    Byte b[DIMSIZE];
17 	    Int32 i32[DIMSIZE];
18 	    UInt32 ui32[DIMSIZE];
19 	    Int16 i16[DIMSIZE];
20 	    UInt16 ui16[DIMSIZE];
21 	    Float32 f32[DIMSIZE];
22 	    Float64 f64[DIMSIZE];
23 	    String s[DIMSIZE];
24 	    Url u[DIMSIZE];
25 	} OneDimensionalSimpleArrays;
26 */
27 
28 #define NDIMS 1
29 #define DIMSIZE 25
30 #define STRLEN 64
31 
32 #ifndef USE_NETCDF4
33 #define	NC_UBYTE 	7	/* unsigned 1 byte int */
34 #define	NC_USHORT 	8	/* unsigned 2-byte int */
35 #define	NC_UINT 	9	/* unsigned 4-byte int */
36 #define	NC_INT64 	10	/* signed 8-byte int */
37 #define	NC_UINT64 	11	/* unsigned 8-byte int */
38 #define	NC_STRING 	12	/* string */
39 #endif
40 
41 
42 #define CHECK(expr) check(expr,__FILE__,__LINE__);
43 
44 #define COMMA (i==0?"":",")
45 
46 #define COMPARE(t1,t2,v1,v2) compare(t1,t2,(void*)v1,(void*)v2,#v2,__FILE__,__LINE__)
47 
48 static int failure = 0;
49 
50 static void compare(nc_type,nc_type,void*,void*,char*,char*,int);
51 
52 static void
report(const int i,const char * var,const int line)53 report(const int i, const char* var, const int line)
54 {
55     fprintf(stdout,"%s mismatch: [%d] file: %s line: %d\n",var,i,__FILE__,line);
56     failure = 1;
57 }
58 
59 static void
check(int ncstat,char * file,int line)60 check(int ncstat, char* file, int line)
61 {
62     if(ncstat == NC_NOERR) return;
63     fprintf(stderr,"*** FAIL: %d (%s) at %s:%d\n",
64 	    ncstat,nc_strerror(ncstat),file,line);
65     exit(1);
66 }
67 
68 /* return 1 if |f1-f2| > 0.05 */
69 static int
fdiff(double f1,double f2)70 fdiff(double f1, double f2)
71 {
72     double delta = (f1 - f2);
73     if(delta < 0) delta = - delta;
74     if(delta > 0.05) {
75 	fprintf(stdout,"fdiff: %1.3f %1.3f delta=%1.3f\n",f1,f2,delta);
76     }
77     return (delta > 0.05?1:0);
78 }
79 
80 static char ch_data[DIMSIZE];
81 static signed char int8_data[DIMSIZE];
82 static unsigned char uint8_data[DIMSIZE];
83 static int int8toint32_data[DIMSIZE];
84 static float int82float32_data[DIMSIZE];
85 static short int16_data[DIMSIZE];
86 static int int16toint32_data[DIMSIZE];
87 static float int162float32_data[DIMSIZE];
88 static int int32_data[DIMSIZE];
89 static float int32tofloat32_data[DIMSIZE];
90 static long int32toilong_data[DIMSIZE];
91 static float float32_data[DIMSIZE];
92 static double float64_data[DIMSIZE];
93 #ifndef USE_NETCDF4
94 static char string3_data[DIMSIZE][STRLEN];
95 #endif
96 
97 static char ch[DIMSIZE];
98 static signed char int8v[DIMSIZE];
99 static unsigned char uint8v[DIMSIZE];
100 static short int16v[DIMSIZE];
101 static int int32v[DIMSIZE];
102 static float float32v[DIMSIZE];
103 static double float64v[DIMSIZE];
104 static long  ilong[DIMSIZE];
105 #ifndef USE_NETCDF4
106 static char string3[DIMSIZE][STRLEN];
107 #endif
108 
main()109 int main()
110 {
111     int ncid, varid;
112     int ncstat = NC_NOERR;
113     char url[8192];
114     const char* topsrcdir;
115     size_t len;
116 #ifndef USE_NETCDF4
117     int i,j;
118 #endif
119 
120     /* location of our target url: use file:// to avoid remote
121 	server downtime issues
122      */
123 
124     topsrcdir = gettopsrcdir();
125 
126     url[0] = '\0';
127 
128 #ifdef DEBUG
129     strlcat(url,"[log][show=fetch]",sizeof(url));
130 #endif
131 
132     strlcat(url,"file://",sizeof(url));
133     strlcat(url,topsrcdir,sizeof(url));
134     strlcat(url,"/ncdap_test/testdata3/test.02",sizeof(url));
135 
136     printf("*** Test: var conversions on URL: %s\n",url);
137 
138     /* open file, get varid */
139     CHECK(nc_open(url, NC_NOWRITE, &ncid));
140 
141     /* extract the string case for netcdf-3*/
142 #ifndef USE_NETCDF4
143     CHECK(nc_inq_varid(ncid, "s", &varid));
144     CHECK(nc_get_var_text(ncid,varid,(char*)string3));
145 #ifdef GENERATE
146     printf("static %s string3_data[DIMSIZE][STRLEN]={","char");
147     for(i=0;i<DIMSIZE;i++) {
148 	int j;
149 	/* Do simple escape */
150 	for(j=0;j<STRLEN;j++) {
151 	    if(string3[i][j] > 0
152 	       && string3[i][j] != '\n'
153 	       && string3[i][j] != '\r'
154 	       && string3[i][j] != '\t'
155 	       &&(string3[i][j] < ' ' || string3[i][j] >= '\177'))
156 		string3[i][j] = '?';
157 	}
158 	printf("%s\"%s\"",COMMA,string3[i]);
159     }
160     printf("};\n");
161 #else
162  	fprintf(stdout,"*** testing: %s\n","string3");
163 	for(i=0;i<DIMSIZE;i++) {
164    	    for(j=0;j<STRLEN;j++) {
165 	        if(string3[i][j] != string3_data[i][j]) {report(i,"string3",__LINE__); break;}
166 	    }
167 	}
168 #endif
169 #endif
170 
171     CHECK(nc_inq_varid(ncid, "b", &varid));
172     CHECK(nc_get_var_text(ncid,varid,ch));
173 #ifdef GENERATE
174     printf("static %s ch_data[DIMSIZE]={","char");
175     for(i=0;i<DIMSIZE;i++) printf("%s'\\%03hho'",COMMA,ch[i]);
176     printf("};\n");
177 #else
178     COMPARE(NC_CHAR,NC_CHAR,ch,ch_data);
179 #endif
180 
181     CHECK(nc_inq_varid(ncid, "b", &varid));
182     CHECK(nc_get_var_schar(ncid,varid,int8v));
183 #ifdef GENERATE
184     printf("static %s int8_data[DIMSIZE]={","signed char");
185     for(i=0;i<DIMSIZE;i++) printf("%s%hhd",COMMA,int8v[i]);
186     printf("};\n");
187 #else
188     COMPARE(NC_BYTE,NC_BYTE,int8v,int8_data);
189 #endif
190 
191     CHECK(nc_inq_varid(ncid, "b", &varid));
192     CHECK(nc_get_var_uchar(ncid,varid,uint8v));
193 #ifdef GENERATE
194     printf("static %s uint8_data[DIMSIZE]={","unsigned char");
195     for(i=0;i<DIMSIZE;i++) printf("%s%hhu",COMMA,uint8v[i]);
196     printf("};\n");
197 #else
198     COMPARE(NC_UBYTE,NC_UBYTE,uint8v,uint8_data);
199 #endif
200 
201     CHECK(nc_inq_varid(ncid, "b", &varid));
202     CHECK(nc_get_var_int(ncid,varid,int32v));
203 #ifdef GENERATE
204     printf("static %s int8toint32_data[DIMSIZE]={","int");
205     for(i=0;i<DIMSIZE;i++) printf("%s%d",COMMA,int32v[i]);
206     printf("};\n");
207 #else
208     COMPARE(NC_BYTE,NC_INT,int32v,int8toint32_data);
209 #endif
210 
211     CHECK(nc_inq_varid(ncid, "b", &varid));
212     CHECK(nc_get_var_float(ncid,varid,float32v));
213 #ifdef GENERATE
214     printf("static %s int82float32_data[DIMSIZE]={","float");
215     for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
216     printf("};\n");
217 #else
218     COMPARE(NC_FLOAT,NC_FLOAT,float32v,int82float32_data);
219 #endif
220 
221     CHECK(nc_inq_varid(ncid, "i16", &varid));
222     CHECK(nc_get_var_short(ncid,varid,int16v));
223 #ifdef GENERATE
224     printf("static %s int16_data[DIMSIZE]={","short");
225     for(i=0;i<DIMSIZE;i++) printf("%s%hd",COMMA,int16v[i]);
226     printf("};\n");
227 #else
228     COMPARE(NC_SHORT,NC_SHORT,int16v,int16_data);
229 #endif
230 
231     CHECK(nc_inq_varid(ncid, "i16", &varid));
232     CHECK(nc_get_var_int(ncid,varid,int32v));
233 #ifdef GENERATE
234     printf("static %s int16toint32_data[DIMSIZE]={","int");
235     for(i=0;i<DIMSIZE;i++) printf("%s%d",COMMA,int32v[i]);
236     printf("};\n");
237 #else
238     COMPARE(NC_SHORT,NC_INT,int32v,int16toint32_data);
239 #endif
240 
241     CHECK(nc_inq_varid(ncid, "i16", &varid));
242     CHECK(nc_get_var_float(ncid,varid,float32v));
243 #ifdef GENERATE
244     printf("static %s int162float32_data[DIMSIZE]={","float");
245     for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
246     printf("};\n");
247 #else
248     COMPARE(NC_SHORT,NC_FLOAT,float32v,int162float32_data);
249 #endif
250 
251     CHECK(nc_inq_varid(ncid, "i32", &varid));
252     CHECK(nc_get_var_int(ncid,varid,int32v));
253 #ifdef GENERATE
254     printf("static %s int32_data[DIMSIZE]={","int");
255     for(i=0;i<DIMSIZE;i++) printf("%s%d",COMMA,int32v[i]);
256     printf("};\n");
257 #else
258     COMPARE(NC_INT,NC_INT,int32v,int32_data);
259 #endif
260 
261     CHECK(nc_inq_varid(ncid, "i32", &varid));
262     CHECK(nc_get_var_float(ncid,varid,float32v));
263 #ifdef GENERATE
264     printf("static %s int32tofloat32_data[DIMSIZE]={","float");
265     for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
266     printf("};\n");
267 #else
268     COMPARE(NC_INT,NC_FLOAT,float32v,int32tofloat32_data);
269 #endif
270 
271     CHECK(nc_inq_varid(ncid, "i32", &varid));
272     CHECK(nc_get_var_long(ncid,varid,ilong));
273 #ifdef GENERATE
274     printf("static %s int32toilong_data[DIMSIZE]={","long");
275     for(i=0;i<DIMSIZE;i++) printf("%s%ld",COMMA,ilong[i]);
276     printf("};\n");
277 #else
278     COMPARE(NC_INT,NC_NAT,ilong,int32toilong_data);
279 #endif
280 
281     CHECK(nc_inq_varid(ncid, "f32", &varid));
282     CHECK(nc_get_var_float(ncid,varid,float32v));
283 #ifdef GENERATE
284     printf("static %s float32_data[DIMSIZE]={","float");
285     for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
286     printf("};\n");
287 #else
288     COMPARE(NC_FLOAT,NC_FLOAT,float32v,float32_data);
289 #endif
290 
291     CHECK(nc_inq_varid(ncid, "f64", &varid));
292     CHECK(nc_get_var_double(ncid,varid,float64v));
293 #ifdef GENERATE
294     printf("static %s float64_data[DIMSIZE]={","double");
295     for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float64v[i]);
296     printf("};\n");
297 #else
298     COMPARE(NC_DOUBLE,NC_DOUBLE,float64v,float64_data);
299 #endif
300 
301     if(failure) {
302         printf("ncstat=%d %s",ncstat,nc_strerror(ncstat));
303         exit(1);
304     }
305     nc_close(ncid);
306     return 0;
307 }
308 
309 static char ch_data[DIMSIZE]={'\000','\001','\002','\003','\004','\005','\006','\007','\010','\011','\012','\013','\014','\015','\016','\017','\020','\021','\022','\023','\024','\025','\026','\027','\030'};
310 static signed char int8_data[DIMSIZE]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
311 static unsigned char uint8_data[DIMSIZE]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
312 static int int8toint32_data[DIMSIZE]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
313 static float int82float32_data[DIMSIZE]={0.000,1.000,2.000,3.000,4.000,5.000,6.000,7.000,8.000,9.000,10.000,11.000,12.000,13.000,14.000,15.000,16.000,17.000,18.000,19.000,20.000,21.000,22.000,23.000,24.000};
314 static short int16_data[DIMSIZE]={0,256,512,768,1024,1280,1536,1792,2048,2304,2560,2816,3072,3328,3584,3840,4096,4352,4608,4864,5120,5376,5632,5888,6144};
315 static int int16toint32_data[DIMSIZE]={0,256,512,768,1024,1280,1536,1792,2048,2304,2560,2816,3072,3328,3584,3840,4096,4352,4608,4864,5120,5376,5632,5888,6144};
316 static float int162float32_data[DIMSIZE]={0.000,256.000,512.000,768.000,1024.000,1280.000,1536.000,1792.000,2048.000,2304.000,2560.000,2816.000,3072.000,3328.000,3584.000,3840.000,4096.000,4352.000,4608.000,4864.000,5120.000,5376.000,5632.000,5888.000,6144.000};
317 static int int32_data[DIMSIZE]={0,2048,4096,6144,8192,10240,12288,14336,16384,18432,20480,22528,24576,26624,28672,30720,32768,34816,36864,38912,40960,43008,45056,47104,49152};
318 static float int32tofloat32_data[DIMSIZE]={0.000,2048.000,4096.000,6144.000,8192.000,10240.000,12288.000,14336.000,16384.000,18432.000,20480.000,22528.000,24576.000,26624.000,28672.000,30720.000,32768.000,34816.000,36864.000,38912.000,40960.000,43008.000,45056.000,47104.000,49152.000};
319 static long int32toilong_data[DIMSIZE]={0,2048,4096,6144,8192,10240,12288,14336,16384,18432,20480,22528,24576,26624,28672,30720,32768,34816,36864,38912,40960,43008,45056,47104,49152};
320 static float float32_data[DIMSIZE]={0.000,0.010,0.020,0.030,0.040,0.050,0.060,0.070,0.080,0.090,0.100,0.110,0.120,0.130,0.140,0.149,0.159,0.169,0.179,0.189,0.199,0.208,0.218,0.228,0.238};
321 static double float64_data[DIMSIZE]={1.000,1.000,1.000,1.000,0.999,0.999,0.998,0.998,0.997,0.996,0.995,0.994,0.993,0.992,0.990,0.989,0.987,0.986,0.984,0.982,0.980,0.978,0.976,0.974,0.971};
322 
323 #ifndef USE_NETCDF4
324 static char string3_data[DIMSIZE][STRLEN]={"This is a data test string (pass 0).","This is a data test string (pass 1).","This is a data test string (pass 2).","This is a data test string (pass 3).","This is a data test string (pass 4).","This is a data test string (pass 5).","This is a data test string (pass 6).","This is a data test string (pass 7).","This is a data test string (pass 8).","This is a data test string (pass 9).","This is a data test string (pass 10).","This is a data test string (pass 11).","This is a data test string (pass 12).","This is a data test string (pass 13).","This is a data test string (pass 14).","This is a data test string (pass 15).","This is a data test string (pass 16).","This is a data test string (pass 17).","This is a data test string (pass 18).","This is a data test string (pass 19).","This is a data test string (pass 20).","This is a data test string (pass 21).","This is a data test string (pass 22).","This is a data test string (pass 23).","This is a data test string (pass 24)."};
325 #endif
326 
327 static void
compare(nc_type t1,nc_type t2,void * v0,void * vdata0,char * tag,char * file,int line)328 compare(nc_type t1, nc_type t2, void* v0, void* vdata0, char* tag,
329 	char* file, int line)
330 {
331     int i;
332     fprintf(stdout,"*** testing: %s\n",tag); \
333 
334 #ifdef DEBUG
335 #define test \
336     printf("v ="); \
337     for(i=0;i<DIMSIZE;i++) {printf(" %llu",(unsigned long long)v[i]);} \
338     printf("\n"); \
339     printf("vdata ="); \
340     for(i=0;i<DIMSIZE;i++) {printf(" %llu",(unsigned long long)vdata[i]);} \
341     printf("\n"); \
342     for(i=0;i<DIMSIZE;i++) {\
343         if(v[i] != vdata[i]) {report(i,tag,line); break;}\
344     }
345 #define ftest \
346     printf("v ="); \
347     for(i=0;i<DIMSIZE;i++) {printf(" %g",v[i]);} \
348     printf("\n"); \
349     printf("vdata ="); \
350     for(i=0;i<DIMSIZE;i++) {printf(" %g",vdata[i]);} \
351     printf("\n"); \
352     for(i=0;i<DIMSIZE;i++) {\
353         if(fdiff((double)v[i],(double)vdata[i])) {report(i,tag,line); break;}\
354     }
355 #else
356 #define test for(i=0;i<DIMSIZE;i++) {\
357         if(v[i] != vdata[i]) {report(i,tag,line); break;}\
358     }
359 #define ftest for(i=0;i<DIMSIZE;i++) {\
360         if(fdiff((double)v[i],(double)vdata[i])) {report(i,tag,line); break;}\
361     }
362 #endif
363 
364 #define setup(T) T* v = (T*)v0; T* vdata = (T*)vdata0;
365 
366 #define CASE(nc1,nc2) (nc1*256+nc2)
367     switch(CASE(t1,t2)) {
368 
369     default: {
370 	printf("unexpected compare:  %d %d\n",(int)t1,(int)t2);
371 	abort();
372     }
373 
374 case CASE(NC_CHAR,NC_CHAR): {
375     setup(char);
376     test;
377 } break;
378 case CASE(NC_BYTE,NC_BYTE): {
379     setup(signed char);
380     test;
381 } break;
382 case CASE(NC_SHORT,NC_SHORT): {
383     setup(short);
384     test;
385 } break;
386 case CASE(NC_INT,NC_INT): {
387     setup(int);
388     test;
389 } break;
390 case CASE(NC_FLOAT,NC_FLOAT): {
391     setup(float);
392     ftest;
393 } break;
394 case CASE(NC_DOUBLE,NC_DOUBLE): {
395     setup(double);
396     ftest;
397 } break;
398 
399 
400 /* Mixed comparisons */
401 case CASE(NC_BYTE,NC_INT): {
402     setup(int);
403     test;
404 } break;
405 case CASE(NC_SHORT,NC_INT): {
406     setup(int);
407     test;
408 } break;
409 case CASE(NC_SHORT,NC_FLOAT): {
410     setup(float);
411     ftest;
412 } break;
413 case CASE(NC_INT,NC_FLOAT): {
414     setup(float);
415     ftest;
416 } break;
417 
418 /* This is an get_var_long case */
419 case CASE(NC_INT,NC_NAT): {
420     setup(long);
421     test;
422 } break;
423 
424 case CASE(NC_UBYTE,NC_UBYTE): {
425     setup(unsigned char);
426     test;
427 } break;
428 case CASE(NC_USHORT,NC_USHORT): {
429     setup(unsigned short);
430     test;
431 } break;
432 case CASE(NC_UINT,NC_UINT): {
433     setup(unsigned int);
434     test;
435 } break;
436 
437 /* Mixed cases */
438 case CASE(NC_INT,NC_INT64): {
439     setup(long long);
440     test;
441 } break;
442 
443 case CASE(NC_INT,NC_UINT64): {
444     setup(unsigned long long);
445     test;
446 } break;
447 
448 case CASE(NC_STRING,NC_STRING):{
449     setup(char*);
450     for(i=0;i<DIMSIZE;i++) {
451 	if(strcmp(v[i],vdata[i])!=0) {report(i,tag,line); break;}
452     }
453 } break;
454 
455 case CASE(NC_CHAR,NC_STRING):{
456     setup(char*);
457     if(memcmp((void*)v[0],(void*)vdata,DIMSIZE+1)!=0)
458         {report(0,tag,line);}
459 } break;
460 
461     } /*switch*/
462 }
463 
464