diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 4d166002510..7cc7f5d3768 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -4416,100 +4416,44 @@ static void test_GetStringTypeW(void) static void test_IdnToNameprepUnicode(void) { struct { - DWORD in_len; - const WCHAR in[64]; + int in_len; + const WCHAR in[80]; + DWORD flags; DWORD ret; DWORD broken_ret; - const WCHAR out[64]; - DWORD flags; - DWORD err; + const WCHAR out[80]; + NTSTATUS status; + NTSTATUS broken_status; } test_data[] = { - { - 5, {'t','e','s','t',0}, - 5, 5, {'t','e','s','t',0}, - 0, 0xdeadbeef - }, - { - 3, {'a',0xe111,'b'}, - 0, 0, {0}, - 0, ERROR_INVALID_NAME - }, - { - 4, {'t',0,'e',0}, - 0, 0, {0}, - 0, ERROR_INVALID_NAME - }, - { - 1, {'T',0}, - 1, 1, {'T',0}, - 0, 0xdeadbeef - }, - { - 1, {0}, - 0, 0, {0}, - 0, ERROR_INVALID_NAME - }, - { - 6, {' ','-','/','[',']',0}, - 6, 6, {' ','-','/','[',']',0}, - 0, 0xdeadbeef - }, - { - 3, {'a','-','a'}, - 3, 3, {'a','-','a'}, - IDN_USE_STD3_ASCII_RULES, 0xdeadbeef - }, - { - 3, {'a','a','-'}, - 0, 0, {0}, - IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME - }, - { - 10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0}, - 12, 12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0}, - 0, 0xdeadbeef - }, - { - 11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0}, - 2, 0, {'t',0}, - 0, 0xdeadbeef - }, - { - 2, {0x3b0, 0}, - 2, 2, {0x3b0, 0}, - 0, 0xdeadbeef, - }, - { - 2, {0x221, 0}, - 0, 2, {0}, - 0, ERROR_NO_UNICODE_TRANSLATION - }, - { - 2, {0x221, 0}, - 2, 2, {0x221, 0}, - IDN_ALLOW_UNASSIGNED, 0xdeadbeef - }, - { - 5, {'a','.','.','a',0}, - 0, 0, {0}, - 0, ERROR_INVALID_NAME - }, - { - 3, {'a','.',0}, - 3, 3, {'a','.',0}, - 0, 0xdeadbeef - }, + /* 0 */ + { 5, L"test", 0, 5, 5, L"test" }, + { 3, L"a\xe111z", 0, 0, 0, L"a\xe111z", 0, STATUS_NO_UNICODE_TRANSLATION }, + { 4, L"t\0e", 0, 0, 0, {0}, STATUS_NO_UNICODE_TRANSLATION, STATUS_NO_UNICODE_TRANSLATION }, + { 1, L"T", 0, 1, 1, L"t" }, + { 1, {0}, 0, 0 }, + /* 5 */ + { 6, L" -/[]", 0, 6, 6, L" -/[]" }, + { 3, L"a-a", IDN_USE_STD3_ASCII_RULES, 3, 3, L"a-a" }, + { 3, L"aa-", IDN_USE_STD3_ASCII_RULES, 0, 0, L"aa-" }, + { -1, L"T\xdf\x130\x143\x37a\x6a\x30c \xaa", 0, 12, 12, L"tssi\x307\x144 \x3b9\x1f0 a" }, + { 11, L"t\xad\x34f\x1806\x180b\x180c\x180d\x200b\x200c\x200d", 0, 2, 0, L"t", + STATUS_NO_UNICODE_TRANSLATION }, + /* 10 */ + { 2, {0x3b0}, 0, 2, 2, {0x3b0} }, + { 2, {0x380}, 0, 0, 2, {0x380} }, + { 2, {0x380}, IDN_ALLOW_UNASSIGNED, 2, 2, {0x380} }, + { 5, L"a..a", 0, 0, 0, L"a..a" }, + { 3, L"a.", 0, 3, 3, L"a." }, + /* 15 */ + { 63, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, + 63, 63, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, + { 64, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, + 0, 0, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, }; WCHAR buf[1024]; DWORD i, ret, err; - if (!pIdnToNameprepUnicode) - { - win_skip("IdnToNameprepUnicode is not available\n"); - return; - } - ret = pIdnToNameprepUnicode(0, test_data[0].in, test_data[0].in_len, NULL, 0); ok(ret == test_data[0].ret, "ret = %d\n", ret); @@ -4519,7 +4463,7 @@ static void test_IdnToNameprepUnicode(void) test_data[1].in_len, NULL, 0); err = GetLastError(); ok(ret == test_data[1].ret, "ret = %d\n", ret); - ok(err == test_data[1].err, "err = %d\n", err); + ok(err == ret ? 0xdeadbeef : ERROR_INVALID_NAME, "err = %d\n", err); SetLastError(0xdeadbeef); ret = pIdnToNameprepUnicode(0, test_data[0].in, -1, buf, ARRAY_SIZE(buf)); @@ -4559,167 +4503,217 @@ static void test_IdnToNameprepUnicode(void) for (i=0; i 9) + ok(ret == test_data[i].ret || broken(ret == test_data[i].broken_ret), "%d: ret = %d\n", i, ret); + ok(err == ret ? 0xdeadbeef : ERROR_INVALID_NAME, "%d: err = %d\n", i, err); + ok(!wcsncmp(test_data[i].out, buf, ret), "%d: buf = %s\n", i, wine_dbgstr_wn(buf, ret)); } } static void test_IdnToUnicode(void) { struct { - DWORD in_len; - const WCHAR in[64]; - DWORD ret; - const WCHAR out[64]; + int in_len; + const WCHAR in[80]; DWORD flags; - DWORD err; + DWORD ret; + DWORD broken_ret; + const WCHAR out[80]; } test_data[] = { - { - 5, {'T','e','s','.',0}, - 5, {'T','e','s','.',0}, - 0, 0xdeadbeef - }, - { - 2, {0x105,0}, - 0, {0}, - 0, ERROR_INVALID_NAME - }, - { - 33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b', - 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0}, - 23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8, - 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2, - 0x05d1,0x05e8,0x05d9,0x05ea,0}, - 0, 0xdeadbeef - }, - { - 34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e', - '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'}, - 16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107, - 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'}, - 0, 0xdeadbeef - }, - { - 64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', - 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', - 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a', - 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'}, - 0, {0}, - 0, ERROR_INVALID_NAME - }, - { - 8, {'x','n','-','-','6','l','a',0}, - 2, {0x221,0}, - IDN_ALLOW_UNASSIGNED, 0xdeadbeef - }, + /* 0 */ + { 5, L"Tes.", 0, 5, 5, L"Tes." }, + { 2, L"\x105", 0, 0 }, + { 33, L"xn--4dbcagdahymbxekheh6e0a7fei0b", 0, + 23, 23, L"\x05dc\x05de\x05d4\x05d4\x05dd\x05e4\x05e9\x05d5\x05d8\x05dc\x05d0\x05de\x05d3\x05d1\x05e8\x05d9\x05dd\x05e2\x05d1\x05e8\x05d9\x05ea" }, + { 34, L"test.xn--kda9ag5e9jnfsj.xn--pz-fna", 0, + 16, 16, L"test.\x0105\x0119\x015b\x0107\x0142\x00f3\x017c.p\x0119z" }, + { 63, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, + 63, 63, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, + /* 5 */ + { 64, L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 0 }, + { 8, L"xn--7va", IDN_ALLOW_UNASSIGNED, 2, 2, L"\x380" }, + { -1, L"xn----bm3an932a1l5d.xn--xvj", 0, 8, 0, L"\xd803\xde78\x46b5-\xa861.\x2e87" }, + { -1, L"xn--z123456789012345678901234567890123456789012345678901234-9te", 0, + 57, 57, L"\xe4z123456789012345678901234567890123456789012345678901234" }, + { -1, L"foo.bar", 0, 8, 8, L"foo.bar" }, }; WCHAR buf[1024]; DWORD i, ret, err; - if (!pIdnToUnicode) + for (i=0; i 6) + ok(ret == test_data[i].ret || broken(ret == test_data[i].broken_ret), "%d: ret = %d\n", i, ret); + + SetLastError(0xdeadbeef); + ret = pIdnToUnicode(test_data[i].flags, test_data[i].in, test_data[i].in_len, buf, ARRAY_SIZE(buf)); + err = GetLastError(); + todo_wine_if (i > 6) + ok(ret == test_data[i].ret || broken(ret == test_data[i].broken_ret), "%d: ret = %d\n", i, ret); + ok(err == ret ? 0xdeadbeef : ERROR_INVALID_NAME, "%d: err = %d\n", i, err); + ok(!wcsncmp(test_data[i].out, buf, ret), "%d: buf = %s\n", i, wine_dbgstr_wn(buf, ret)); + } +} + +static BOOL is_idn_error( const WCHAR *str ) +{ + WCHAR *p, err[256]; + lstrcpyW( err, str ); + for (p = wcstok( err, L" []" ); p; p = wcstok( NULL, L" []" ) ) + { + if (*p == 'B' || !wcscmp( p, L"V8" )) continue; /* BiDi */ + if (!wcscmp( p, L"V2" ) || !wcscmp( p, L"V3" )) continue; /* CheckHyphens */ + if (!wcscmp( p, L"V7" )) continue; /* CheckJoiners */ + return TRUE; + } + return FALSE; +} + +static void test_Idn(void) +{ + FILE *f; + + if (!pIdnToAscii || !pIdnToUnicode || !pIdnToNameprepUnicode) + { + win_skip("Idn support is not available\n"); return; } - for (i=0; i p; end--) if (end[-1] != ' ') break; + *end = 0; + MultiByteToWideChar( CP_UTF8, 0, p, -1, columns[i], 256 ); + p = strtok( NULL, ";" ); + } + if (i < 7) continue; + + expect = columns[5]; + if (!*expect) expect = columns[3]; + if (!*expect) expect = columns[1]; + if (!*expect) expect = columns[0]; + error = columns[6]; + if (!*error) error = columns[4]; + if (!*error) error = columns[2]; + SetLastError( 0xdeadbeef ); + memset( dst, 0xcc, sizeof(dst) ); + ret = pIdnToAscii( 0, columns[0], -1, dst, ARRAY_SIZE(dst) ); + if (!is_idn_error( error )) + { + ok( ret, "line %u: toAscii failed for %s\n", line, debugstr_w(columns[0]) ); + if (ret) ok( !wcscmp( dst, expect ), "line %u: got %s expected %s\n", + line, debugstr_w(dst), debugstr_w(expect) ); + } + + expect = columns[1]; + if (!*expect) expect = columns[0]; + error = columns[2]; + SetLastError( 0xdeadbeef ); + memset( dst, 0xcc, sizeof(dst) ); + ret = pIdnToUnicode( 0, columns[0], -1, dst, ARRAY_SIZE(dst) ); + for (i = 0; columns[0][i]; i++) if (columns[0][i] > 0x7f) break; + if (columns[0][i]) + { + ok( !ret, "line %u: didn't fail for unicode chars in %s\n", line, debugstr_w(columns[0]) ); + } + else if (!is_idn_error( error )) + { + ok( ret, "line %u: toUnicode failed for %s\n", line, debugstr_w(columns[0]) ); + if (ret) ok( !wcscmp( dst, expect ), "line %u: got %s expected %s\n", + line, debugstr_w(dst), debugstr_w(expect) ); + } + } + fclose( f ); } } + static void test_GetLocaleInfoEx(void) { static const WCHAR enW[] = {'e','n',0}; @@ -6618,9 +6612,7 @@ START_TEST(locale) test_EnumUILanguageA(); test_GetCPInfo(); test_GetStringTypeW(); - test_IdnToNameprepUnicode(); - test_IdnToAscii(); - test_IdnToUnicode(); + test_Idn(); test_IsValidLocaleName(); test_CompareStringOrdinal(); test_GetGeoInfo();