Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

502 lines
15 KiB

  1. /*++
  2. Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. GB18030Regressions.c
  5. Abstract:
  6. GB18030 (codepage 54936) smoke test and bug regressions.
  7. NOTE: This code was simply hacked together quickly in order to
  8. test the different code modules of the NLS component.
  9. This is NOT meant to be a formal regression test.
  10. Revision History:
  11. 02-22-02 YSLin Created.
  12. --*/
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #define NLS_CP_CPINFO 0x10000000
  16. #define NLS_CP_CPINFOEX 0x20000000
  17. #define NLS_CP_MBTOWC 0x40000000
  18. #define NLS_CP_WCTOMB 0x80000000
  19. CHAR g_szBuffer[512];
  20. WCHAR g_wszBuffer[512];
  21. HMODULE g_hLangModule;
  22. WCHAR g_wszDllName[] = L".\\c_g18030.dll";
  23. typedef DWORD (__stdcall *NlsDllCodePageTranslation)(
  24. DWORD CodePage,
  25. DWORD dwFlags,
  26. LPSTR lpMultiByteStr,
  27. int cchMultiByte,
  28. LPWSTR lpWideCharStr,
  29. int cchWideChar,
  30. LPCPINFO lpCPInfo);
  31. NlsDllCodePageTranslation g_pGBFunc = NULL;
  32. void PrintBytes(BYTE* lpMultiByteStr, DWORD size)
  33. {
  34. for (DWORD i = 0; i < size; i++)
  35. {
  36. printf("\\x%02x", lpMultiByteStr[i]);
  37. }
  38. }
  39. void PrintWords(WORD* lpWideCharStr, int size)
  40. {
  41. if (size == -1)
  42. {
  43. size = wcslen(lpWideCharStr);
  44. }
  45. for (int i = 0; i < size; i++)
  46. {
  47. printf("\\x%04x", lpWideCharStr[i]);
  48. }
  49. }
  50. BOOL TestIsValidCodePage(int codepage)
  51. {
  52. BOOL bResult = IsValidCodePage(codepage);
  53. printf("IsValidCodePage(%d) = %d\n", codepage, bResult);
  54. return (bResult);
  55. }
  56. BOOL VerifyResult(int result, int expect)
  57. {
  58. printf(" Result: [%d]\n", result);
  59. if (result != expect)
  60. {
  61. printf(">> Expect: [%d]\n", expect);
  62. return (FALSE);
  63. }
  64. return (TRUE);
  65. }
  66. BOOL VerifyResult(BYTE* result, int nResultLen, BYTE* expect, int nExpectLen)
  67. {
  68. BOOL bEqual = (nResultLen == nExpectLen);
  69. if (bEqual)
  70. {
  71. for (int i = 0; i < nResultLen; i++)
  72. {
  73. if (result[i] != expect[i])
  74. {
  75. bEqual = FALSE;
  76. break;
  77. }
  78. }
  79. }
  80. printf(" Result: [");
  81. PrintBytes(result, nResultLen);
  82. printf("]\n");
  83. if (!bEqual)
  84. {
  85. printf(">> Expect: [");
  86. PrintBytes(expect, nExpectLen);
  87. printf("]\n");
  88. }
  89. return (bEqual);
  90. }
  91. BOOL VerifyResult(WORD* result, int nResultLen, WORD* expect, int nExpectLen)
  92. {
  93. BOOL bEqual = (nResultLen == nExpectLen);
  94. if (bEqual)
  95. {
  96. for (int i = 0; i < nResultLen; i++)
  97. {
  98. if (result[i] != expect[i])
  99. {
  100. bEqual = FALSE;
  101. break;
  102. }
  103. }
  104. }
  105. printf(" Result: [");
  106. PrintWords(result, nResultLen);
  107. printf("]\n");
  108. if (!bEqual)
  109. {
  110. printf(">> Expect: [");
  111. PrintWords(expect, nExpectLen);
  112. printf("]\n");
  113. }
  114. return (bEqual);
  115. }
  116. BOOL DoGetCPInfoExTest(int codepage)
  117. {
  118. CPINFOEX cpInfoEx;
  119. if (!GetCPInfoEx(codepage, 0, &cpInfoEx))
  120. {
  121. return (FALSE);
  122. }
  123. printf(" MaxCharSize = %d\n", cpInfoEx.MaxCharSize);
  124. printf(" DefaultChar = [%02x][%02x]\n", cpInfoEx.DefaultChar[0], cpInfoEx.DefaultChar[1]);
  125. printf(" LeadByte = [%s]\n", cpInfoEx.LeadByte);
  126. wprintf(L" UnicodeDefaultChar = %c\n", cpInfoEx.UnicodeDefaultChar);
  127. printf(" CodePage = %d\n", cpInfoEx.CodePage);
  128. wprintf(L" CodePageName = [%s]\n", cpInfoEx.CodePageName);
  129. return (TRUE);
  130. }
  131. BOOL DoWCToMBTest(
  132. int codepage,
  133. LPWSTR lpWideCharStr, int cchWideChar,
  134. LPSTR expect, int nExpectLen,
  135. BOOL bTestRoundtrip)
  136. {
  137. BOOL bPassed = TRUE;
  138. int nResult = 0;
  139. printf(" WideCharToMultiByte(%d, 0, \"", codepage);
  140. PrintWords(lpWideCharStr, cchWideChar);
  141. printf("\", %d)\n", cchWideChar);
  142. if (g_pGBFunc)
  143. {
  144. nExpectLen--;
  145. }
  146. //
  147. // First test if the byte count is correct.
  148. //
  149. printf(" --- Test byte count ---\n");
  150. if (g_pGBFunc)
  151. {
  152. nResult = g_pGBFunc(codepage, NLS_CP_WCTOMB,
  153. NULL, 0, lpWideCharStr, cchWideChar, NULL);
  154. } else {
  155. nResult = WideCharToMultiByte(codepage, 0,
  156. lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL);
  157. }
  158. bPassed &= VerifyResult(nResult, nExpectLen);
  159. printf(" --- Test conversion ---\n");
  160. //
  161. // Test the actual wide-char to multi-byte conversion is correct.
  162. //
  163. BOOL bUseDefault;
  164. if (g_pGBFunc)
  165. {
  166. nResult = g_pGBFunc(codepage, NLS_CP_WCTOMB,
  167. g_szBuffer, sizeof(g_szBuffer), lpWideCharStr, cchWideChar, NULL);
  168. } else {
  169. nResult = WideCharToMultiByte(codepage, 0,
  170. lpWideCharStr, cchWideChar, g_szBuffer, sizeof(g_szBuffer), NULL, NULL);
  171. }
  172. bPassed &= VerifyResult(nResult, nExpectLen);
  173. bPassed &= VerifyResult((BYTE*)g_szBuffer, nResult, (BYTE*)expect, nExpectLen);
  174. if (!g_pGBFunc)
  175. {
  176. nResult = WideCharToMultiByte(codepage, 0,
  177. lpWideCharStr, cchWideChar, g_szBuffer, nExpectLen, NULL, NULL);
  178. }
  179. bPassed &= VerifyResult(nResult, nExpectLen);
  180. bPassed &= VerifyResult((BYTE*)g_szBuffer, nResult, (BYTE*)expect, nExpectLen);
  181. if (bTestRoundtrip)
  182. {
  183. printf(" --- Test roundtrip ---\n");
  184. if (cchWideChar == -1)
  185. {
  186. cchWideChar = wcslen(lpWideCharStr) + 1;
  187. }
  188. if (g_pGBFunc)
  189. {
  190. nResult = g_pGBFunc(codepage, NLS_CP_MBTOWC, g_szBuffer, nResult, g_wszBuffer, sizeof(g_szBuffer), NULL);
  191. cchWideChar--;
  192. } else
  193. {
  194. nResult = MultiByteToWideChar(codepage, 0, g_szBuffer, nResult, g_wszBuffer, sizeof(g_szBuffer));
  195. }
  196. bPassed &= VerifyResult(nResult, cchWideChar);
  197. bPassed &= VerifyResult((WORD*)g_wszBuffer, nResult, (WORD*)lpWideCharStr, cchWideChar);
  198. }
  199. printf(" --- Test insuffient buffer ---\n");
  200. for (int i = nExpectLen - 1; i >= 1; i--)
  201. {
  202. if (g_pGBFunc)
  203. {
  204. nResult = g_pGBFunc(codepage, NLS_CP_WCTOMB,
  205. g_szBuffer, i, lpWideCharStr, cchWideChar, NULL);
  206. } else {
  207. nResult = WideCharToMultiByte(codepage, 0,
  208. lpWideCharStr, cchWideChar, g_szBuffer, i, NULL, NULL);
  209. }
  210. bPassed &= VerifyResult(nResult, 0);
  211. bPassed &= VerifyResult(GetLastError(), ERROR_INSUFFICIENT_BUFFER);
  212. }
  213. return (bPassed);
  214. }
  215. BOOL DoMBToWCTest(
  216. int codepage,
  217. LPSTR lpMultiByteStr, int cchMulitByteChar,
  218. LPWSTR expect, int nExpectLen)
  219. {
  220. BOOL bPassed = TRUE;
  221. int nResult = 0;
  222. printf(" MultiByteToWideChar(%d, 0, \"", codepage);
  223. PrintBytes((BYTE*)lpMultiByteStr, cchMulitByteChar);
  224. printf("\", %d)\n", cchMulitByteChar);
  225. /*
  226. if (g_pGBFunc)
  227. {
  228. nExpectLen--;
  229. }
  230. */
  231. //
  232. // First test if the byte count is correct.
  233. //
  234. printf(" --- Test byte count ---\n");
  235. //if (g_pGBFunc)
  236. //{
  237. // nResult = g_pGBFunc(codepage, NLS_CP_WCTOMB,
  238. // NULL, 0, lpWideCharStr, cchWideChar, NULL);
  239. //} else
  240. {
  241. nResult = MultiByteToWideChar(codepage, 0,
  242. lpMultiByteStr, cchMulitByteChar, NULL, 0);
  243. }
  244. bPassed &= VerifyResult(nResult, nExpectLen);
  245. printf(" --- Test conversion ---\n");
  246. //
  247. // Test the actual wide-char to multi-byte conversion is correct.
  248. //
  249. BOOL bUseDefault;
  250. //if (g_pGBFunc)
  251. //{
  252. // nResult = g_pGBFunc(codepage, NLS_CP_WCTOMB,
  253. // g_szBuffer, sizeof(g_szBuffer), lpWideCharStr, cchWideChar, NULL);
  254. //} else
  255. {
  256. nResult = MultiByteToWideChar(codepage, 0,
  257. lpMultiByteStr, cchMulitByteChar, g_wszBuffer, sizeof(g_wszBuffer));
  258. }
  259. bPassed &= VerifyResult(nResult, nExpectLen);
  260. bPassed &= VerifyResult((WORD*)g_wszBuffer, nResult, (WORD*)expect, nExpectLen);
  261. //if (!g_pGBFunc)
  262. {
  263. nResult = MultiByteToWideChar(codepage, 0,
  264. lpMultiByteStr, cchMulitByteChar, g_wszBuffer, nExpectLen);
  265. }
  266. bPassed &= VerifyResult(nResult, nExpectLen);
  267. bPassed &= VerifyResult((WORD*)g_wszBuffer, nResult, (WORD*)expect, nExpectLen);
  268. printf(" --- Test insuffient buffer ---\n");
  269. for (int i = nExpectLen - 1; i >= 1; i--)
  270. {
  271. //if (g_pGBFunc)
  272. //{
  273. // nResult = g_pGBFunc(codepage, NLS_CP_WCTOMB,
  274. //g_szBuffer, i, lpWideCharStr, cchWideChar, NULL);
  275. //} else
  276. {
  277. nResult = MultiByteToWideChar(codepage, 0,
  278. lpMultiByteStr, cchMulitByteChar, g_wszBuffer, i);
  279. }
  280. bPassed &= VerifyResult(nResult, 0);
  281. bPassed &= VerifyResult(GetLastError(), ERROR_INSUFFICIENT_BUFFER);
  282. }
  283. return (bPassed);
  284. }
  285. BOOL TryLoadGB18030DLL()
  286. {
  287. g_hLangModule = ::LoadLibrary(g_wszDllName);
  288. if (g_hLangModule == NULL)
  289. {
  290. wprintf(L"Error in loading %s DLL.", g_wszDllName);
  291. return (FALSE);
  292. }
  293. g_pGBFunc = (NlsDllCodePageTranslation)GetProcAddress(g_hLangModule, "NlsDllCodePageTranslation");
  294. if (g_pGBFunc == NULL)
  295. {
  296. wprintf(L"Error in loading function.\n");
  297. return (FALSE);
  298. }
  299. wprintf(L"%s is loaded.\n", g_wszDllName);
  300. return (TRUE);
  301. }
  302. BOOL DoSmokeTest()
  303. {
  304. BOOL bPassed = TRUE;
  305. printf("\n--- DoSmokeTest---\n");
  306. //
  307. // Some general tests.
  308. //
  309. // U+0000 ~ U+007F
  310. bPassed &= DoWCToMBTest(54936, L"ABC", -1, "ABC\x00", 4, TRUE);
  311. // Unicode to GB18030 two-bytes, compatible with GBK.
  312. bPassed &= DoWCToMBTest(54936, L"\x00a4", -1, "\xa1\xe8\x00", 3, TRUE);
  313. bPassed &= DoWCToMBTest(54936, L"\x3011", -1, "\xa1\xbf\x00", 3, TRUE);
  314. bPassed &= DoWCToMBTest(54936, L"\x3011", -1, "\xa1\xbf\x00", 3, TRUE);
  315. bPassed &= DoWCToMBTest(54936, L"\x00a4", 1, "\xa1\xe8", 2, TRUE);
  316. // Unicode to GB18030 two-bytes, NOT compatible with GBK.
  317. bPassed &= DoWCToMBTest(54936, L"\x01f9", -1, "\xa8\xbf\x00", 3, TRUE);
  318. bPassed &= DoWCToMBTest(54936, L"\x4dae", -1, "\xfe\x9f\x00", 3, TRUE);
  319. bPassed &= DoWCToMBTest(54936, L"\xffe5", -1, "\xA3\xA4\x00", 3, TRUE);
  320. // Unicode to GB18030 four-byte.
  321. bPassed &= DoWCToMBTest(54936, L"\x0081", -1, "\x81\x30\x81\x31\x00", 5, TRUE);
  322. bPassed &= DoWCToMBTest(54936, L"\xfeff", -1, "\x84\x31\x95\x33\x00", 5, TRUE);
  323. bPassed &= DoWCToMBTest(54936, L"\xffff", -1, "\x84\x31\xA4\x39\x00", 5, TRUE);
  324. // Surrogate to GB18030 four-byte
  325. bPassed &= DoWCToMBTest(54936, L"\xd800\xdc00", -1, "\x90\x30\x81\x30\x00", 5, TRUE);
  326. // The last surrogate pair to GB18030 four-byte
  327. bPassed &= DoWCToMBTest(54936, L"\xdbff\xdfff", -1, "\xe3\x32\x9a\x35\x00", 5, TRUE);
  328. // Mixed cases.
  329. bPassed &= DoWCToMBTest(54936, L"\x0081\x00a8", -1, "\x81\x30\x81\x31\xA1\xA7\x00", 7, TRUE);
  330. bPassed &= DoWCToMBTest(54936, L"A\x0081\x0042\x0043\x00a8", -1, "A\x81\x30\x81\x31\x42\x43\xA1\xA7\x00", 10, TRUE);
  331. //
  332. // Some exception cases.
  333. //
  334. // High surrogate without low surrogate
  335. bPassed &= DoWCToMBTest(54936, L"\xd800", -1, "?\x00", 2, FALSE);
  336. // High surrogate without low surrogate
  337. bPassed &= DoWCToMBTest(54936, L"\xd800\x0041", -1, "?\x41\x00", 3, FALSE);
  338. // High surrogate without low surrogate
  339. bPassed &= DoWCToMBTest(54936, L"\x0042\xd800\x0041", -1, "\x42?\x41\x00", 4, FALSE);
  340. // Low surrogate without high surrogate
  341. bPassed &= DoWCToMBTest(54936, L"\xdc00", -1, "?\x00", 2, FALSE);
  342. // Low surrogate without high surrogate
  343. bPassed &= DoWCToMBTest(54936, L"\xdc00\xd800", -1, "??\x00", 3, FALSE);
  344. // Low surrogate without high surrogate
  345. bPassed &= DoWCToMBTest(54936, L"A\xdc00", -1, "A?\x00", 3, FALSE);
  346. // Low surrogate without high surrogate
  347. bPassed &= DoWCToMBTest(54936, L"A\xdc00\x42", -1, "A?B\x00", 4, FALSE);
  348. // 1-byte GB18030
  349. bPassed &= DoMBToWCTest(54936, "ABC", 3, L"ABC", 3);
  350. bPassed &= DoMBToWCTest(54936, "\x7d\x7e\x7f", 3, L"\x007d\x007e\x007f", 3);
  351. // 2-byte GB18030
  352. bPassed &= DoMBToWCTest(54936, "\xa1\xe3", 2, L"\x00b0", 1);
  353. bPassed &= DoMBToWCTest(54936, "\xd2\xbb", 2, L"\x4e00", 1);
  354. // 4-byte GB18030
  355. bPassed &= DoMBToWCTest(54936, "\x81\x30\x86\x30", 4, L"\x00b8", 1);
  356. bPassed &= DoMBToWCTest(54936, "\x84\x31\xA4\x39", 4, L"\xffff", 1);
  357. return (bPassed);
  358. }
  359. BOOL Regress352949() {
  360. BOOL bPassed = true;
  361. printf("\n--- Bug 352949 ---\n");
  362. bPassed &= DoWCToMBTest(932, L"\x3000\x0045", -1, "\x81\x40\x45", 4, FALSE) ;
  363. bPassed &= DoWCToMBTest(54936, L"\x3094", -1, "\x81\x39\xA6\x36", 5, FALSE) ;
  364. printf("\n");
  365. return (bPassed);
  366. }
  367. BOOL Regress401919() {
  368. BOOL bPassed = true;
  369. printf("\n--- Bug 401919 ---\n");
  370. // Invalid 4-byte sequence.
  371. bPassed &= DoMBToWCTest(54936, "\x81\x30\x81\x20", 4, L"?\x30?\x20", 4);
  372. bPassed &= DoMBToWCTest(54936, "\x81\x20\x81\x30", 4, L"?\x20?\x30", 4);
  373. bPassed &= DoMBToWCTest(54936, "\x81\x30\x80\x30", 4, L"?\x30?\x30", 4);
  374. bPassed &= DoMBToWCTest(54936, "\x81\x30\xff\x30", 4, L"?\x30?\x30", 4);
  375. bPassed &= DoMBToWCTest(54936, "\xff\x30\x81\x30", 4, L"?\x30?\x30", 4);
  376. bPassed &= DoMBToWCTest(54936, "\x81\x20", 2, L"?\x20", 2);
  377. // Invalid 2-byte sequence
  378. bPassed &= DoMBToWCTest(54936, "\x81\x7f", 2, L"?\x7f", 2);
  379. bPassed &= DoMBToWCTest(54936, "\xff\x40", 2, L"?\x40", 2);
  380. // Invalid 1-byte sequence
  381. bPassed &= DoMBToWCTest(54936, "\x80", 1, L"?", 1);
  382. bPassed &= DoMBToWCTest(54936, "\xfe", 1, L"?", 1);
  383. bPassed &= DoMBToWCTest(54936, "\x81", 1, L"?", 1);
  384. bPassed &= DoMBToWCTest(54936, "\xff", 1, L"?", 1);
  385. return (bPassed);
  386. }
  387. int _cdecl main(int argc, char* argv[])
  388. {
  389. BOOL bPassed = TRUE;
  390. if (argc > 2)
  391. {
  392. if (!TryLoadGB18030DLL())
  393. {
  394. return(1);
  395. }
  396. } else
  397. {
  398. if (!TestIsValidCodePage(54936))
  399. {
  400. printf("54936 is not a installed codepage.\n");
  401. return (1);
  402. }
  403. }
  404. bPassed &= DoGetCPInfoExTest(54936);
  405. bPassed &= DoSmokeTest();
  406. bPassed &= Regress352949();
  407. bPassed &= Regress401919();
  408. if (!bPassed)
  409. {
  410. printf("FAIL");
  411. return(1);
  412. }
  413. if (g_hLangModule != NULL)
  414. {
  415. FreeLibrary(g_hLangModule);
  416. }
  417. printf("pass");
  418. return(0);
  419. }