1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 1998-1999  Brian Bruns
3  * Copyright (C) 2015  Frediano Ziglio
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 /**
22  * This test exercise manually conversions from types.
23  * Does not require any connection.
24  */
25 
26 #include "common.h"
27 #include <freetds/convert.h>
28 
29 static TDSCONTEXT ctx;
30 
31 static void
test0(const char * src,int len,int midtype,int dsttype,const char * result,int line)32 test0(const char *src, int len, int midtype, int dsttype, const char *result, int line)
33 {
34 	int i, res;
35 	char buf[256];
36 	CONV_RESULT cr, cr_mid, cr_out;
37 	int srctype = SYBVARCHAR;
38 	char *copy;
39 
40 	copy = tds_new(char, len);
41 	memcpy(copy, src, len);
42 	src = copy;
43 
44 	if (midtype) {
45 		if (midtype == SYBNUMERIC || midtype == SYBDECIMAL) {
46 			cr_mid.n.precision = 20;
47 			cr_mid.n.scale = 8;
48 		}
49 		res = tds_convert(&ctx, SYBVARCHAR, src, len, midtype, &cr_mid);
50 		if (res < 0) {
51 			fprintf(stderr, "Unexpected failure converting %*.*s\n", len, len, src);
52 			exit(1);
53 		}
54 		src = (const char *) &cr_mid;
55 		len = res;
56 		srctype = midtype;
57 	}
58 	if (dsttype == SYBNUMERIC || dsttype == SYBDECIMAL) {
59 		cr.n.precision = 20;
60 		cr.n.scale = 8;
61 	}
62 	res = tds_convert(&ctx, srctype, src, len, dsttype, &cr);
63 	if (res < 0)
64 		strcpy(buf, "error");
65 	else {
66 		buf[0] = 0;
67 		switch (dsttype) {
68 		case SYBINT1:
69 		case SYBUINT1:
70 			sprintf(buf, "%d", cr.ti);
71 			break;
72 		case SYBINT2:
73 			sprintf(buf, "%d", cr.si);
74 			break;
75 		case SYBUINT2:
76 			sprintf(buf, "%u", cr.usi);
77 			break;
78 		case SYBINT4:
79 			sprintf(buf, "%d", cr.i);
80 			break;
81 		case SYBUINT4:
82 			sprintf(buf, "%u", cr.ui);
83 			break;
84 		case SYBINT8:
85 			sprintf(buf, "0x%08x%08x", (unsigned int) ((cr.bi >> 32) & 0xfffffffflu), (unsigned int) (cr.bi & 0xfffffffflu));
86 			break;
87 		case SYB5BIGTIME:
88 		case SYB5BIGDATETIME:
89 		case SYBUINT8:
90 			sprintf(buf, "0x%08x%08x", (unsigned int) ((cr.ubi >> 32) & 0xfffffffflu), (unsigned int) (cr.ubi & 0xfffffffflu));
91 			break;
92 		case SYBUNIQUE:
93 			sprintf(buf, "%08X-%04X-%04X-%02X%02X%02X%02X"
94 				"%02X%02X%02X%02X",
95 				cr.u.Data1,
96 				cr.u.Data2, cr.u.Data3,
97 				cr.u.Data4[0], cr.u.Data4[1],
98 				cr.u.Data4[2], cr.u.Data4[3], cr.u.Data4[4], cr.u.Data4[5], cr.u.Data4[6], cr.u.Data4[7]);
99 			break;
100 		case SYBBINARY:
101 			sprintf(buf, "len=%d", res);
102 			for (i = 0; i < res; ++i)
103 				sprintf(strchr(buf, 0), " %02X", (TDS_UCHAR) cr.ib[i]);
104 			free(cr.ib);
105 			break;
106 		case SYBCHAR:
107 			sprintf(buf, "len=%d %s", res, cr.c);
108 			free(cr.c);
109 			break;
110 		case SYBDATETIME:
111 			sprintf(buf, "%ld %ld", (long int) cr.dt.dtdays, (long int) cr.dt.dttime);
112 			break;
113 		case SYBDATE:
114 			sprintf(buf, "%ld", (long int) cr.date);
115 			break;
116 		case SYBTIME:
117 			sprintf(buf, "%ld", (long int) cr.time);
118 			break;
119 		case SYBNUMERIC:
120 		case SYBDECIMAL:
121 			cr_out.cc.c = buf;
122 			cr_out.cc.len = sizeof(buf) - 1;
123 			res = tds_convert(&ctx, dsttype, &cr.n, sizeof(cr.n), TDS_CONVERT_CHAR, &cr_out);
124 			if (res < 0) {
125 				fprintf(stderr, "Unexpected failure converting %*.*s\n", len, len, src);
126 				exit(1);
127 			}
128 			buf[res] = 0;
129 		}
130 	}
131 	printf("%s\n", buf);
132 	if (strcmp(buf, result) != 0) {
133 		fprintf(stderr, "Expected '%s' got '%s' at line %d\n", result, buf, line);
134 		exit(1);
135 	}
136 	free(copy);
137 }
138 
139 #define test(s,d,r)    test0(s,strlen(s),0,d,r,__LINE__)
140 #define test2(s,m,d,r) test0(s,strlen(s),m,d,r,__LINE__)
141 
142 static int
143 int_types[] = {
144 	SYBINT1, SYBUINT1, SYBINT2, SYBUINT2,
145 	SYBINT4, SYBUINT4, SYBINT8, SYBUINT8,
146 	SYBMONEY4, SYBMONEY,
147 	SYBNUMERIC,
148 	-1
149 };
150 
151 static const char *
152 int_values[] = {
153 	"0",
154 	"127", "255",
155 	"128", "256",
156 	"32767", "65535",
157 	"32768", "65536",
158 	"214748",
159 	"214749",
160 	"2147483647", "4294967295",
161 	"2147483648", "4294967296",
162 	"922337203685477",
163 	"922337203685478",
164 	"9223372036854775807", "18446744073709551615",
165 	"9223372036854775808", "18446744073709551616",
166 	"-128",
167 	"-129",
168 	"-32768",
169 	"-32769",
170 	"-214748",
171 	"-214749",
172 	"-2147483648",
173 	"-2147483649",
174 	"-922337203685477",
175 	"-922337203685478",
176 	"-9223372036854775808",
177 	"-9223372036854775809",
178 	NULL
179 };
180 
181 int
main(int argc,char ** argv)182 main(int argc, char **argv)
183 {
184 	int *type1, *type2;
185 	const char **value;
186 	int big_endian = 1;
187 	if (((char *) &big_endian)[0] == 1)
188 		big_endian = 0;
189 
190 	memset(&ctx, 0, sizeof(ctx));
191 
192 	if ((ctx.locale = tds_get_locale()) == NULL)
193 		return 1;
194 
195 	/* date */
196 	free(ctx.locale->date_fmt);
197 	ctx.locale->date_fmt = strdup("%Y-%m-%d %H:%M:%S.%z");
198 
199 	/* test some conversion */
200 	printf("some checks...\n");
201 	test("1234", SYBINT4, "1234");
202 	test("1234", SYBUINT4, "1234");
203 	test("123", SYBINT1, "123");
204 	test("123", SYBUINT1, "123");
205 	test("  -    1234   ", SYBINT2, "-1234");
206 	test("  -    1234   a", SYBINT2, "error");
207 	test("", SYBINT4, "0");
208 	test("    ", SYBINT4, "0");
209 	test("    123", SYBINT4, "123");
210 	test("    123    ", SYBINT4, "123");
211 	test("  +  123  ", SYBINT4, "123");
212 	test("  +  123  ", SYBUINT4, "123");
213 	test("  - 0  ", SYBINT4, "0");
214 	test("  -  0  ", SYBUINT4, "0");
215 	test("+", SYBINT4, "error");
216 	test("   +", SYBINT4, "error");
217 	test("+   ", SYBINT4, "error");
218 	test("   +   ", SYBINT4, "error");
219 	test("-", SYBINT4, "error");
220 	test("   -", SYBINT4, "error");
221 	test("-   ", SYBINT4, "error");
222 	test("   -   ", SYBINT4, "error");
223 
224 	test("  -    1234   ", SYBINT8, "0xfffffffffffffb2e");
225 	test("1234x", SYBINT8, "error");
226 	test("  -    1234   a", SYBINT8, "error");
227 	test("", SYBINT8, "0x0000000000000000");
228 	test("    ", SYBINT8, "0x0000000000000000");
229 	test("    123", SYBINT8, "0x000000000000007b");
230 	test("    123    ", SYBINT8, "0x000000000000007b");
231 	test("  +  123  ", SYBINT8, "0x000000000000007b");
232 	test("    123", SYBUINT8, "0x000000000000007b");
233 	test("    123    ", SYBUINT8, "0x000000000000007b");
234 	test("  +  123  ", SYBUINT8, "0x000000000000007b");
235 	test("+", SYBINT8, "error");
236 	test("   +", SYBINT8, "error");
237 	test("+   ", SYBINT8, "error");
238 	test("   +   ", SYBINT8, "error");
239 	test("-", SYBINT8, "error");
240 	test("   -", SYBINT8, "error");
241 	test("-   ", SYBINT8, "error");
242 	test("   -   ", SYBINT8, "error");
243 
244 	/* test for overflow */
245 	/* for SYBUINT8 a test with all different digit near limit is required */
246 	printf("overflow checks...\n");
247 	test("9223372036854775807", SYBINT8, "0x7fffffffffffffff");
248 	test("9223372036854775807", SYBUINT8, "0x7fffffffffffffff");
249 	test("9223372036854775808", SYBINT8, "error");
250 	test("-9223372036854775808", SYBINT8, "0x8000000000000000");
251 	test("9223372036854775808", SYBUINT8, "0x8000000000000000");
252 	test("18446744073709551610", SYBUINT8, "0xfffffffffffffffa");
253 	test("18446744073709551611", SYBUINT8, "0xfffffffffffffffb");
254 	test("18446744073709551612", SYBUINT8, "0xfffffffffffffffc");
255 	test("18446744073709551613", SYBUINT8, "0xfffffffffffffffd");
256 	test("18446744073709551614", SYBUINT8, "0xfffffffffffffffe");
257 	test("18446744073709551615", SYBUINT8, "0xffffffffffffffff");
258 	test("18446744073709551616", SYBUINT8, "error");
259 	test("18446744073709551617", SYBUINT8, "error");
260 	test("18446744073709551618", SYBUINT8, "error");
261 	test("18446744073709551619", SYBUINT8, "error");
262 	test("18446744073709551620", SYBUINT8, "error");
263 	test("20496382304121724025", SYBUINT8, "error");
264 	test("20496382308118429681", SYBUINT8, "error");
265 	test("-1", SYBUINT8, "error");
266 	test("-9223372036854775809", SYBINT8, "error");
267 	test("2147483647", SYBINT4, "2147483647");
268 	test("2147483648", SYBINT4, "error");
269 	test("2147483647", SYBUINT4, "2147483647");
270 	test("4294967295", SYBUINT4, "4294967295");
271 	test("4294967296", SYBUINT4, "error");
272 	test("-2147483648", SYBINT4, "-2147483648");
273 	test("-2147483648", SYBUINT4, "error");
274 	test("-2147483649", SYBINT4, "error");
275 	test("32767", SYBINT2, "32767");
276 	test("32767", SYBUINT2, "32767");
277 	test("65535", SYBUINT2, "65535");
278 	test("65536", SYBUINT2, "error");
279 	test("32768", SYBINT2, "error");
280 	test("-32768", SYBINT2, "-32768");
281 	test("-32769", SYBINT2, "error");
282 	test("255", SYBINT1, "255");
283 	test("256", SYBINT1, "error");
284 	test("255", SYBUINT1, "255");
285 	test("256", SYBUINT1, "error");
286 	test("0", SYBINT1, "0");
287 	test("-1", SYBINT1, "error");
288 	test("0", SYBUINT1, "0");
289 	test("-1", SYBUINT1, "error");
290 
291 	/*
292 	 * test overflow on very big numbers
293 	 * I use increment of 10^9 to be sure lower 32bit be correct
294 	 * in a case
295 	 */
296 	printf("overflow on big number checks...\n");
297 	test("62147483647", SYBINT4, "error");
298 	test("63147483647", SYBINT4, "error");
299 	test("64147483647", SYBINT4, "error");
300 	test("65147483647", SYBINT4, "error");
301 	test("53248632876323876761", SYBINT8, "error");
302 	test("56248632876323876761", SYBINT8, "error");
303 	test("59248632876323876761", SYBINT8, "error");
304 	test("12248632876323876761", SYBINT8, "error");
305 
306 	/* money */
307 	test2("1234.11111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
308 		SYBMONEY, SYBCHAR, "len=9 1234.1111");
309 
310 	/* some test for unique */
311 	printf("unique type...\n");
312 	test("12345678-1234-1234-9876543298765432", SYBUNIQUE, "12345678-1234-1234-9876543298765432");
313 	test("{12345678-1234-1E34-9876ab3298765432}", SYBUNIQUE, "12345678-1234-1E34-9876AB3298765432");
314 	test(" 12345678-1234-1234-9876543298765432", SYBUNIQUE, "error");
315 	test(" {12345678-1234-1234-9876543298765432}", SYBUNIQUE, "error");
316 	test("12345678-1234-G234-9876543298765432", SYBUNIQUE, "error");
317 	test("12345678-1234-a234-9876543298765432", SYBUNIQUE, "12345678-1234-A234-9876543298765432");
318 	test("123a5678-1234-a234-98765-43298765432", SYBUNIQUE, "error");
319 	test("123-5678-1234-a234-9876543298765432", SYBUNIQUE, "error");
320 
321 	printf("binary test...\n");
322 	test("0x1234", SYBBINARY, "len=2 12 34");
323 	test("0xaBFd  ", SYBBINARY, "len=2 AB FD");
324 	test("AbfD  ", SYBBINARY, "len=2 AB FD");
325 	test("0x000", SYBBINARY, "len=2 00 00");
326 	test("0x0", SYBBINARY, "len=1 00");
327 	test("0x100", SYBBINARY, "len=2 01 00");
328 	test("0x1", SYBBINARY, "len=1 01");
329 
330 	test("Jan 01 2006", SYBDATETIME, "38716 0");
331 	test("January 01 2006", SYBDATETIME, "38716 0");
332 	test("March 05 2005", SYBDATETIME, "38414 0");
333 	test("may 13 2001", SYBDATETIME, "37022 0");
334 
335 	test("02 Jan 2006", SYBDATETIME, "38717 0");
336 	test("2 Jan 2006", SYBDATETIME, "38717 0");
337 	test("02Jan2006", SYBDATETIME, "38717 0");
338 	test("20060102", SYBDATETIME, "38717 0");
339 	test("060102", SYBDATETIME, "38717 0");
340 
341 	test("2006-01-02", SYBDATE, "38717");
342 	test("12:34:56.337", SYBTIME, "13588901");
343 
344 	test2("2006-01-02", SYBDATE, SYBDATE, "38717");
345 	test2("12:34:56.337", SYBTIME, SYBTIME, "13588901");
346 
347 	test2("2006-01-02 12:34:56.337", SYBDATETIME, SYBDATE, "38717");
348 	test2("2006-01-02 12:34:56.337", SYBDATETIME, SYBTIME, "13588901");
349 
350 	test("2006-01-02 12:34:56.337321", SYB5BIGTIME, "0x0000000a8bdf41a9");
351 	test("2006-01-23 12:34:56.337321", SYB5BIGDATETIME, "0x00e0e7c784d661a9");
352 	test("2006-01-02 12:34:56.337321", SYB5BIGDATETIME, "0x00e0e621122b81a9");
353 
354 	test2("2006-01-02 12:34:56.337765", SYB5BIGDATETIME, SYBCHAR, "len=26 2006-01-02 12:34:56.337765");
355 	test("2006-01-02 12:34:56.337765", SYB5BIGDATETIME, "0x00e0e621122b8365");
356 
357 	test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBDATE, "38717");
358 	test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBTIME, "13588901");
359 
360 	test2("2006-01-02 12:34:56.337", SYBMSDATETIME2, SYBCHAR, "len=27 2006-01-02 12:34:56.3370000");
361 #if 0
362 	/* FIXME should fail conversion ?? */
363 	test2("2006-01-02", SYBDATE, SYBTIME, "0");
364 	test2("12:34:56.337", SYBTIME, SYBDATE, "0");
365 #endif
366 
367 	test2("2006-01-02", SYBDATE, SYBCHAR, "len=23 2006-01-02 00:00:00.000");
368 	test2("12:34:56.337", SYBTIME, SYBCHAR, "len=23 1900-01-01 12:34:56.337");
369 
370 	test2("123", SYBINT1, SYBBINARY, "len=1 7B");
371 	test2("0.000001", SYBFLT8, SYBNUMERIC, "0.00000100");
372 	if (big_endian) {
373 		test2("12345", SYBINT2, SYBBINARY, "len=2 30 39");
374 		test2("123456789", SYBINT4, SYBBINARY, "len=4 07 5B CD 15");
375 		test2("123456789", SYBUINT8, SYBBINARY, "len=8 00 00 00 00 07 5B CD 15");
376 		test2("123456789", SYBINT8, SYBBINARY, "len=8 00 00 00 00 07 5B CD 15");
377 		test2("-123456789", SYBINT8, SYBBINARY, "len=8 FF FF FF FF F8 A4 32 EB");
378 	} else {
379 		test2("12345", SYBINT2, SYBBINARY, "len=2 39 30");
380 		test2("123456789", SYBINT4, SYBBINARY, "len=4 15 CD 5B 07");
381 		test2("123456789", SYBUINT8, SYBBINARY, "len=8 15 CD 5B 07 00 00 00 00");
382 		test2("123456789", SYBINT8, SYBBINARY, "len=8 15 CD 5B 07 00 00 00 00");
383 		test2("-123456789", SYBINT8, SYBBINARY, "len=8 EB 32 A4 F8 FF FF FF FF");
384 	}
385 
386 	/* now try many int conversion operations */
387 	for (value = int_values; *value; ++value)
388 	for (type1 = int_types; *type1 >= 0; ++type1)
389 	for (type2 = int_types; *type2 >= 0; ++type2) {
390 		char buf[64], expected[64];
391 		CONV_RESULT cr_src, cr_dst;
392 		TDS_INT len_src, len_dst;
393 
394 		/* try conversion from char (already tested above) */
395 		cr_src.n.precision = 20; cr_src.n.scale = 0;
396 		len_src = tds_convert(&ctx, SYBVARCHAR, *value, strlen(*value), *type1, &cr_src);
397 		cr_dst.n.precision = 20; cr_dst.n.scale = 0;
398 		len_dst = tds_convert(&ctx, SYBVARCHAR, *value, strlen(*value), *type2, &cr_dst);
399 		if (len_src <= 0 || len_dst <= 0)
400 			continue;
401 		cr_dst.n.precision = 20; cr_dst.n.scale = 0;
402 		if (tds_convert(&ctx, *type1, &cr_src.i, len_src, *type2, &cr_dst) <= 0) {
403 			fprintf(stderr, "conversion from %s to %s of %s should succeed\n",
404 				tds_prtype(*type1), tds_prtype(*type2), *value);
405 			return 1;
406 		}
407 		memcpy(&cr_src, &cr_dst, sizeof(cr_dst));
408 		cr_dst.cc.c = buf;
409 		cr_dst.cc.len = sizeof(buf)-4;
410 		len_dst = tds_convert(&ctx, *type2, &cr_src.i, len_dst, TDS_CONVERT_CHAR, &cr_dst);
411 		if (len_dst <= 0) {
412 			fprintf(stderr, "conversion from %s to string should succeed\n",
413 				tds_prtype(*type1));
414 			return 1;
415 		}
416 		buf[len_dst] = 0;
417 		if (*type2 == SYBMONEY4 || *type2 == SYBMONEY)
418 			sprintf(expected, "%s.0000", *value);
419 		else
420 			strcpy(expected, *value);
421 		if (strcmp(buf, expected) != 0) {
422 			fprintf(stderr, "conversion from %s to %s of %s got wrong value '%s'\n",
423 				tds_prtype(*type1), tds_prtype(*type2), *value, buf);
424 			return 1;
425 		}
426 	}
427 
428 	tds_free_locale(ctx.locale);
429 
430 	return 0;
431 }
432