kernel32: FindExSearchLimitToDirectories has no effect on FindFirstFileEx.
[wine] / dlls / msvcrt / tests / string.c
1 /*
2  * Unit test suite for string functions.
3  *
4  * Copyright 2004 Uwe Bonnes
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "wine/test.h"
22 #include "winbase.h"
23 #include <string.h>
24 #include <mbstring.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <mbctype.h>
28 #include <locale.h>
29
30 static char *buf_to_string(const unsigned char *bin, int len, int nr)
31 {
32     static char buf[2][1024];
33     char *w = buf[nr];
34     int i;
35
36     for (i = 0; i < len; i++)
37     {
38         sprintf(w, "%02x ", (unsigned char)bin[i]);
39         w += strlen(w);
40     }
41     return buf[nr];
42 }
43
44 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
45 #define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, "Binary buffer mismatch - expected %s, got %s\n", buf_to_string((unsigned char *)value, len, 1), buf_to_string((buf), len, 0)); }
46
47 static void* (*pmemcpy)(void *, const void *, size_t n);
48 static int* (*pmemcmp)(void *, const void *, size_t n);
49
50 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
51 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
52
53 HMODULE hMsvcrt;
54
55 static void test_swab( void ) {
56     char original[]  = "BADCFEHGJILKNMPORQTSVUXWZY@#";
57     char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#";
58     char expected2[] = "ABCDEFGHIJKLMNOPQRSTUVWX$";
59     char expected3[] = "$";
60     
61     char from[30];
62     char to[30];
63     
64     int testsize;
65     
66     /* Test 1 - normal even case */                               
67     memset(to,'$', sizeof(to));
68     memset(from,'@', sizeof(from));
69     testsize = 26;
70     memcpy(from, original, testsize);
71     _swab( from, to, testsize );
72     ok(memcmp(to,expected1,testsize) == 0, "Testing even size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
73
74     /* Test 2 - uneven case  */                               
75     memset(to,'$', sizeof(to));
76     memset(from,'@', sizeof(from));
77     testsize = 25;
78     memcpy(from, original, testsize);
79     _swab( from, to, testsize );
80     ok(memcmp(to,expected2,testsize) == 0, "Testing odd size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
81
82     /* Test 3 - from = to */                               
83     memset(to,'$', sizeof(to));
84     memset(from,'@', sizeof(from));
85     testsize = 26;
86     memcpy(to, original, testsize);
87     _swab( to, to, testsize );
88     ok(memcmp(to,expected1,testsize) == 0, "Testing overlapped size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
89
90     /* Test 4 - 1 bytes */                               
91     memset(to,'$', sizeof(to));
92     memset(from,'@', sizeof(from));
93     testsize = 1;
94     memcpy(from, original, testsize);
95     _swab( from, to, testsize );
96     ok(memcmp(to,expected3,testsize) == 0, "Testing small size %d returned '%*.*s'\n", testsize, testsize, testsize, to);
97 }
98
99 #if 0      /* use this to generate more tests */
100
101 static void test_codepage(int cp)
102 {
103     int i;
104     int prev;
105     int count = 1;
106
107     ok(_setmbcp(cp) == 0, "Couldn't set mbcp\n");
108
109     prev = _mbctype[0];
110     printf("static int result_cp_%d_mbctype[] = { ", cp);
111     for (i = 1; i < 257; i++)
112     {
113         if (_mbctype[i] != prev)
114         {
115             printf("0x%x,%d, ", prev, count);
116             prev = _mbctype[i];
117             count = 1;
118         }
119         else
120             count++;
121     }
122     printf("0x%x,%d };\n", prev, count);
123 }
124
125 #define test_codepage_todo(cp, todo) test_codepage(cp)
126
127 #else
128
129 /* RLE-encoded mbctype tables for given codepages */
130 static int result_cp_1252_mbctype[] = { 0x0,66, 0x10,26, 0x0,6, 0x20,26, 0x0,8, 0x20,1,
131   0x0,6, 0x10,1, 0x0,1, 0x10,1, 0x0,1, 0x10,1, 0x0,11, 0x20,1, 0x0,1, 0x20,1, 0x0,1,
132   0x20,1, 0x10,1, 0x0,10, 0x20,1, 0x0,10, 0x20,1, 0x0,4, 0x20,1, 0x0,5, 0x10,23, 0x0,1,
133   0x10,7, 0x20,24, 0x0,1, 32,8 };
134 static int result_cp_1250_mbctype[] = { 0x0,66, 0x10,26, 0x0,6, 0x20,26, 0x0,15, 0x10,1,
135   0x0,1, 0x10,4, 0x0,10, 0x20,1, 0x0,1, 0x20,4, 0x0,3, 0x10,1, 0x0,1, 0x10,1, 0x0,4,
136   0x10,1, 0x0,4, 0x10,1, 0x0,3, 0x20,1, 0x0,1, 0x20,1, 0x0,3, 0x20,2, 0x0,1, 0x10,1,
137   0x0,1, 0x20,2, 0x10,23, 0x0,1, 0x10,7, 0x20,24, 0x0,1, 0x20,7, 0,1 };
138 static int result_cp_932_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
139   0x0,1, 0x8,1, 0xc,31, 0x8,1, 0xa,5, 0x9,58, 0xc,29, 0,3 };
140 static int result_cp_936_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,6,
141   0xc,126, 0,1 };
142 static int result_cp_949_mbctype[] = { 0x0,66, 0x18,26, 0x8,6, 0x28,26, 0x8,6, 0xc,126,
143   0,1 };
144 static int result_cp_950_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4,
145   0x0,2, 0x4,32, 0xc,94, 0,1 };
146
147 static int todo_none[] = { -2 };
148 static int todo_cp_932[] = { 254, -2 };
149
150 void test_cp_table(int cp, int *result, int *todo)
151 {
152     int i;
153     int count = 0;
154     int curr = 0;
155     _setmbcp(cp);
156     for (i = 0; i < 256; i++)
157     {
158         if (count == 0)
159         {
160             curr = result[0];
161             count = result[1];
162             result += 2;
163         }
164         if (i == *todo + 1)
165         {
166             todo_wine ok(_mbctype[i] == curr, "CP%d: Mismatch in ctype for character %d - %d instead of %d\n", cp, i-1, _mbctype[i], curr);
167             todo++;
168         }
169         else
170             ok(_mbctype[i] == curr, "CP%d: Mismatch in ctype for character %d - %d instead of %d\n", cp, i-1, _mbctype[i], curr);
171         count--;
172     }
173 }
174
175 #define test_codepage(num) test_cp_table(num, result_cp_##num##_mbctype, todo_none);
176 #define test_codepage_todo(num, todo) test_cp_table(num, result_cp_##num##_mbctype, todo);
177
178 #endif
179
180 static void test_mbcp(void)
181 {
182     int mb_orig_max = __mb_cur_max;
183     int curr_mbcp = _getmbcp();
184     unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */
185     unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */
186     unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3";
187     unsigned char buf[16];
188     int step;
189
190     /* some two single-byte code pages*/
191     test_codepage(1252);
192     test_codepage(1250);
193     /* double byte code pages */
194     test_codepage_todo(932, todo_cp_932);
195     test_codepage(936);
196     test_codepage(949);
197     test_codepage(950);
198
199     _setmbcp(936);
200     ok(__mb_cur_max == mb_orig_max, "__mb_cur_max shouldn't be updated (is %d != %d)\n", __mb_cur_max, mb_orig_max);
201     ok(_ismbblead('\354'), "\354 should be a lead byte\n");
202     ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n");
203     ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n");
204     ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n");
205     ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n");
206     ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n");
207
208     /* _ismbslead */
209     expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d");
210     expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d");
211     expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d");
212     expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d");
213     expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d");
214     expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d");
215     expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d");
216     expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d");
217     expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d");
218
219     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d");
220     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d");
221     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
222     expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
223
224     /* _ismbstrail */
225     expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d");
226     expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d");
227     expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d");
228     expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d");
229     expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d");
230     expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d");
231     expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d");
232     expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d");
233     expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d");
234
235     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d");
236     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d");
237     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d");
238     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d");
239     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d");
240     expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d");
241
242     /* _mbsbtype */
243     expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d");
244     expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d");
245     expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d");
246     expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d");
247     expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d");
248     expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d");
249     expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d");
250     expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d");
251     expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d");
252
253     expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d");
254     expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d");
255     expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d");
256     expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d");
257     expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d");
258     expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d");
259
260     /* _mbsnextc */
261     expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x");
262     expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x");  /* lead + invalid tail */
263     expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x");    /* single char */
264
265     /* _mbclen/_mbslen */
266     expect_eq(_mbclen(mbstring), 2, int, "%d");
267     expect_eq(_mbclen(&mbstring[2]), 2, int, "%d");
268     expect_eq(_mbclen(&mbstring[3]), 1, int, "%d");
269     expect_eq(_mbslen(mbstring2), 4, int, "%d");
270     expect_eq(_mbslen(mbsonlylead), 0, int, "%d");          /* lead + NUL not counted as character */
271     expect_eq(_mbslen(mbstring), 4, int, "%d");             /* lead + invalid trail counted */
272
273     /* _mbccpy/_mbsncpy */
274     memset(buf, 0xff, sizeof(buf));
275     _mbccpy(buf, mbstring);
276     expect_bin(buf, "\xb0\xb1\xff", 3);
277
278     memset(buf, 0xff, sizeof(buf));
279     _mbsncpy(buf, mbstring, 1);
280     expect_bin(buf, "\xb0\xb1\xff", 3);
281     memset(buf, 0xff, sizeof(buf));
282     _mbsncpy(buf, mbstring, 2);
283     expect_bin(buf, "\xb0\xb1\xb2 \xff", 5);
284     memset(buf, 0xff, sizeof(buf));
285     _mbsncpy(buf, mbstring, 3);
286     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7);
287     memset(buf, 0xff, sizeof(buf));
288     _mbsncpy(buf, mbstring, 4);
289     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8);
290     memset(buf, 0xff, sizeof(buf));
291     _mbsncpy(buf, mbstring, 5);
292     expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10);
293     memset(buf, 0xff, sizeof(buf));
294     _mbsncpy(buf, mbsonlylead, 6);
295     expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8);
296
297     memset(buf, 0xff, sizeof(buf));
298     _mbsnbcpy(buf, mbstring2, 2);
299     expect_bin(buf, "\xb0\xb1\xff", 3);
300     _mbsnbcpy(buf, mbstring2, 3);
301     expect_bin(buf, "\xb0\xb1\0\xff", 4);
302     _mbsnbcpy(buf, mbstring2, 4);
303     expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5);
304     memset(buf, 0xff, sizeof(buf));
305     _mbsnbcpy(buf, mbsonlylead, 5);
306     expect_bin(buf, "\0\0\0\0\0\xff", 6);
307
308     /* _mbsinc/mbsdec */
309     step = _mbsinc(mbstring) - mbstring;
310     ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
311     step = _mbsinc(&mbstring[2]) - &mbstring[2];  /* lead + invalid tail */
312     ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step);
313
314     step = _mbsninc(mbsonlylead, 1) - mbsonlylead;
315     ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
316     step = _mbsninc(mbsonlylead, 2) - mbsonlylead;  /* lead + NUL byte + lead + char */
317     ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step);
318     step = _mbsninc(mbstring2, 0) - mbstring2;
319     ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step);
320     step = _mbsninc(mbstring2, 1) - mbstring2;
321     ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step);
322     step = _mbsninc(mbstring2, 2) - mbstring2;
323     ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step);
324     step = _mbsninc(mbstring2, 3) - mbstring2;
325     ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step);
326     step = _mbsninc(mbstring2, 4) - mbstring2;
327     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
328     step = _mbsninc(mbstring2, 5) - mbstring2;
329     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
330     step = _mbsninc(mbstring2, 17) - mbstring2;
331     ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step);
332
333     /* functions that depend on locale codepage, not mbcp.
334      * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet
335      * (as of Wine 0.9.43)
336      */
337     if (__mb_cur_max == 1)
338     {
339         expect_eq(mblen((char *)mbstring, 3), 1, int, "%x");
340         expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d");
341     }
342     else
343         skip("Current locale has double-byte charset - could leave to false positives\n");
344
345     _setmbcp(curr_mbcp);
346 }
347
348 static void test_mbsspn( void)
349 {
350     unsigned char str1[]="cabernet";
351     unsigned char str2[]="shiraz";
352     unsigned char set[]="abc";
353     unsigned char empty[]="";
354     int ret;
355     ret=_mbsspn( str1, set);
356     ok( ret==3, "_mbsspn returns %d should be 3\n", ret);
357     ret=_mbsspn( str2, set);
358     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
359     ret=_mbsspn( str1, empty);
360     ok( ret==0, "_mbsspn returns %d should be 0\n", ret);
361 }
362
363 static void test_mbsspnp( void)
364 {
365     unsigned char str1[]="cabernet";
366     unsigned char str2[]="shiraz";
367     unsigned char set[]="abc";
368     unsigned char empty[]="";
369     unsigned char full[]="abcenrt";
370     unsigned char* ret;
371     ret=_mbsspnp( str1, set);
372     ok( ret[0]=='e', "_mbsspnp returns %c should be e\n", ret[0]);
373     ret=_mbsspnp( str2, set);
374     ok( ret[0]=='s', "_mbsspnp returns %c should be s\n", ret[0]);
375     ret=_mbsspnp( str1, empty);
376     ok( ret[0]=='c', "_mbsspnp returns %c should be c\n", ret[0]);
377     ret=_mbsspnp( str1, full);
378     ok( ret==NULL, "_mbsspnp returns %p should be NULL\n", ret);
379 }
380
381 static void test_strdup(void)
382 {
383    char *str;
384    str = _strdup( 0 );
385    ok( str == 0, "strdup returns %s should be 0\n", str);
386    free( str );
387 }
388
389 START_TEST(string)
390 {
391     void *mem;
392     static const char xilstring[]="c:/xilinx";
393     int nLen;
394
395     hMsvcrt = GetModuleHandleA("msvcrt.dll");
396     if (!hMsvcrt)
397         hMsvcrt = GetModuleHandleA("msvcrtd.dll");
398     ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
399     SET(pmemcpy,"memcpy");
400     SET(pmemcmp,"memcmp");
401
402     /* MSVCRT memcpy behaves like memmove for overlapping moves,
403        MFC42 CString::Insert seems to rely on that behaviour */
404     mem = malloc(100);
405     ok(mem != NULL, "memory not allocated for size 0\n");
406     strcpy((char*)mem,xilstring);
407     nLen=strlen(xilstring);
408     pmemcpy((char*)mem+5, mem,nLen+1);
409     ok(pmemcmp((char*)mem+5,xilstring, nLen) == 0, 
410        "Got result %s\n",(char*)mem+5);
411
412     /* Test _swab function */
413     test_swab();
414
415     /* Test ismbblead*/
416     test_mbcp();
417    /* test _mbsspn */
418     test_mbsspn();
419     test_mbsspnp();
420    /* test _strdup */
421     test_strdup();
422 }