2 * Unit test suite for string functions.
4 * Copyright 2004 Uwe Bonnes
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.
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.
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
21 #include "wine/test.h"
30 static char *buf_to_string(const unsigned char *bin, int len, int nr)
32 static char buf[2][1024];
36 for (i = 0; i < len; i++)
38 sprintf(w, "%02x ", (unsigned char)bin[i]);
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)); }
47 static void* (*pmemcpy)(void *, const void *, size_t n);
48 static int* (*pmemcmp)(void *, const void *, size_t n);
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)
55 static void test_swab( void ) {
56 char original[] = "BADCFEHGJILKNMPORQTSVUXWZY@#";
57 char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#";
58 char expected2[] = "ABCDEFGHIJKLMNOPQRSTUVWX$";
59 char expected3[] = "$";
66 /* Test 1 - normal even case */
67 memset(to,'$', sizeof(to));
68 memset(from,'@', sizeof(from));
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);
74 /* Test 2 - uneven case */
75 memset(to,'$', sizeof(to));
76 memset(from,'@', sizeof(from));
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);
82 /* Test 3 - from = to */
83 memset(to,'$', sizeof(to));
84 memset(from,'@', sizeof(from));
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);
90 /* Test 4 - 1 bytes */
91 memset(to,'$', sizeof(to));
92 memset(from,'@', sizeof(from));
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);
99 #if 0 /* use this to generate more tests */
101 static void test_codepage(int cp)
107 ok(_setmbcp(cp) == 0, "Couldn't set mbcp\n");
110 printf("static int result_cp_%d_mbctype[] = { ", cp);
111 for (i = 1; i < 257; i++)
113 if (_mbctype[i] != prev)
115 printf("0x%x,%d, ", prev, count);
122 printf("0x%x,%d };\n", prev, count);
125 #define test_codepage_todo(cp, todo) test_codepage(cp)
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,
142 static int result_cp_949_mbctype[] = { 0x0,66, 0x18,26, 0x8,6, 0x28,26, 0x8,6, 0xc,126,
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 };
147 static int todo_none[] = { -2 };
148 static int todo_cp_932[] = { 254, -2 };
150 void test_cp_table(int cp, int *result, int *todo)
156 for (i = 0; i < 256; i++)
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);
170 ok(_mbctype[i] == curr, "CP%d: Mismatch in ctype for character %d - %d instead of %d\n", cp, i-1, _mbctype[i], curr);
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);
180 static void test_mbcp(void)
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];
190 /* some two single-byte code pages*/
193 /* double byte code pages */
194 test_codepage_todo(932, todo_cp_932);
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");
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");
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");
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");
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");
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");
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");
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 */
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 */
273 /* _mbccpy/_mbsncpy */
274 memset(buf, 0xff, sizeof(buf));
275 _mbccpy(buf, mbstring);
276 expect_bin(buf, "\xb0\xb1\xff", 3);
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);
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);
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);
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);
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)
337 if (__mb_cur_max == 1)
339 expect_eq(mblen((char *)mbstring, 3), 1, int, "%x");
340 expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d");
343 skip("Current locale has double-byte charset - could leave to false positives\n");
348 static void test_mbsspn( void)
350 unsigned char str1[]="cabernet";
351 unsigned char str2[]="shiraz";
352 unsigned char set[]="abc";
353 unsigned char empty[]="";
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);
363 static void test_mbsspnp( void)
365 unsigned char str1[]="cabernet";
366 unsigned char str2[]="shiraz";
367 unsigned char set[]="abc";
368 unsigned char empty[]="";
369 unsigned char full[]="abcenrt";
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);
381 static void test_strdup(void)
385 ok( str == 0, "strdup returns %s should be 0\n", str);
392 static const char xilstring[]="c:/xilinx";
395 hMsvcrt = GetModuleHandleA("msvcrt.dll");
397 hMsvcrt = GetModuleHandleA("msvcrtd.dll");
398 ok(hMsvcrt != 0, "GetModuleHandleA failed\n");
399 SET(pmemcpy,"memcpy");
400 SET(pmemcmp,"memcmp");
402 /* MSVCRT memcpy behaves like memmove for overlapping moves,
403 MFC42 CString::Insert seems to rely on that behaviour */
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);
412 /* Test _swab function */