[PATCH 2/2] kernel32/tests: Test Get/SetUserGeoID, GetUserDefaultGeoName, SetUserGeoName.

João Diogo Ferreira devilj at outlook.pt
Wed Oct 2 23:40:20 CDT 2019


This adds unit tests for these four functions:
  GetUserGeoID();
  SetUserGeoID();
  GetUserDefaultGeoName();
  SetUserGeoName().

These are all functions I intend to improve and/or implement
in the short future.

Signed-off-by: João Diogo Craveiro Ferreira <devilj at outlook.pt>
---
 dlls/kernel32/tests/locale.c | 319 +++++++++++++++++++++++++++++++++++
 1 file changed, 319 insertions(+)

diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 81e74531ea..e3e46bfb53 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -108,6 +108,8 @@ static LANGID (WINAPI *pSetThreadUILanguage)(LANGID);
 static LANGID (WINAPI *pGetThreadUILanguage)(VOID);
 static INT (WINAPI *pNormalizeString)(NORM_FORM, LPCWSTR, INT, LPWSTR, INT);
 static INT (WINAPI *pFindStringOrdinal)(DWORD, LPCWSTR lpStringSource, INT, LPCWSTR, INT, BOOL);
+static int (WINAPI *pGetUserDefaultGeoName)(LPWSTR, int);
+static BOOL (WINAPI *pSetUserGeoName)(PWSTR);
 
 static void InitFunctionPointers(void)
 {
@@ -145,6 +147,8 @@ static void InitFunctionPointers(void)
   X(GetThreadUILanguage);
   X(NormalizeString);
   X(FindStringOrdinal);
+  X(GetUserDefaultGeoName);
+  X(SetUserGeoName);
 
   mod = GetModuleHandleA("ntdll");
   X(RtlUpcaseUnicodeChar);
@@ -4745,6 +4749,317 @@ static void test_CompareStringOrdinal(void)
     }
 }
 
+static void test_GetUserGeoID(void)
+{
+    GEOID id;
+    todo_wine {
+        if (pGetUserDefaultGeoName && pSetUserGeoName)
+        {
+            ok(GEOID_NOT_AVAILABLE != GetUserGeoID(GEOCLASS_NATION),
+                "GEOCLASS_NATION: should never return GEOID_NOT_AVAILABLE when GeoName API is available.\n");
+            ok(GEOID_NOT_AVAILABLE != GetUserGeoID(GEOCLASS_REGION),
+                "GEOCLASS_REGION: should never return GEOID_NOT_AVAILABLE when GeoName API is available.\n");
+        }
+        else
+            win_skip("This platform allows GEOID_NOT_AVAILABLE to be returned.\n");
+    }
+
+    id = GetUserGeoID(GEOCLASS_ALL);
+    ok(id == GEOID_NOT_AVAILABLE,
+        "GEOCLASS_ALL: Expected GEOID_NOT_AVAILABLE, got %d.\n", id);
+    id = GetUserGeoID(12345);
+    ok(id == GEOID_NOT_AVAILABLE,
+        "Gibberish argument: Expected GEOID_NOT_AVAILABLE, got %d.\n", id);
+}
+
+static void test_GetUserDefaultGeoName(void)
+{
+    todo_wine {
+        if (pGetUserDefaultGeoName && pSetUserGeoName)
+        {
+            WCHAR *name = malloc(sizeof(WCHAR) * 10);
+            int count = 0;
+
+            if (!name)
+            {
+                trace("Couldn't allocate 20 bytes to store geo name. Aborting test!\n");
+                return;
+            }
+
+            SetLastError(ERROR_SUCCESS);
+            count = pGetUserDefaultGeoName(NULL, 10);
+            ok(count == 0 && (GetLastError() == ERROR_INVALID_PARAMETER),
+                "Expected count == 0, got %d; and expected last error = ERROR_INVALID_PARAMETER (87), got %d\n",
+                count, GetLastError());
+
+            count = pGetUserDefaultGeoName(NULL, -1);
+            ok(count == 0 && (GetLastError() == ERROR_INVALID_PARAMETER),
+                "Expected count == 0, got %d; and expected last error = ERROR_INVALID_PARAMETER (87), got %d\n",
+                count, GetLastError());
+
+            SetLastError(ERROR_SUCCESS);
+            count = pGetUserDefaultGeoName(name, 0);
+            ok(count > 0, "Expected character count > 0, got %d; last error was %d.\n", count, GetLastError());
+
+            count = pGetUserDefaultGeoName(name, 1);
+            ok(count == 0 && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
+                "Expected count == 0, got %d; and expected last error = ERROR_INSUFFICIENT_BUFFER (122), got %d\n",
+                count, GetLastError());
+
+            count = pGetUserDefaultGeoName(name, -1);
+            ok(count == 0 && (GetLastError() == ERROR_INVALID_PARAMETER),
+                "Expected count == 0, got %d; and expected last error = ERROR_INVALID_PARAMETER (87), got %d\n",
+                count, GetLastError());
+
+            free(name);
+
+            SetLastError(ERROR_SUCCESS);
+            count = pGetUserDefaultGeoName(NULL, 0);
+            ok(count > 0, "Expected character count > 0, got %d; last error was %d.\n", count, GetLastError());
+            if (count)
+            {
+                name = malloc(count * sizeof(WCHAR));
+                if (name)
+                {
+                    int result = pGetUserDefaultGeoName(name, count);
+                    ok(result,
+                    "Expected character count == %d, got %d; last error was %d.\n",
+                    count, result, GetLastError());
+                    free(name);
+                }
+                else
+                    trace("Couldn't allocate %d bytes to store geo name.\n", count);
+            }
+        }
+        else win_skip("GetUserDefaultGeoName: procedure not implemented on this platform.\n");
+    }
+}
+
+static void test_SetUserGeoID(void)
+{
+    BOOL status;
+    const int geoname_supported = (pGetUserDefaultGeoName && pSetUserGeoName);
+
+    const GEOID original_nation = GetUserGeoID(GEOCLASS_NATION);
+    const GEOID original_region = GetUserGeoID(GEOCLASS_REGION);
+    int original_name_count = 0; /* We only need the char count. */
+
+    struct geopair {
+        GEOID id;
+        WCHAR name[4];
+    };
+
+    struct testsuit {
+        const char *const stage;
+        struct geopair geo, geo_backup;
+        GEOCLASS geoclass;
+    };
+
+    struct testsuit const tests[] = {
+        {"GEOCLASS_NATION", {193, {'P','T',0}}, {56, {'C','U',0}}, GEOCLASS_NATION},
+        {"GEOCLASS_REGION", {21206, {'0','5','7',0}}, {10039880, {'0','2','9',0}}, GEOCLASS_REGION}
+    };
+
+    struct testsuit const bad_args[] = {
+        {"invalid GEOID -1", {GEOID_NOT_AVAILABLE}},
+        {"invalid GEOID 1", {1}}
+    };
+
+    if (geoname_supported)
+        original_name_count = pGetUserDefaultGeoName(NULL, 0);
+
+    /* Invalid args */
+    for (int i = 0; i < ARRAY_SIZE(bad_args); i++)
+    {
+        BOOL status;
+
+        SetLastError(ERROR_SUCCESS);
+
+        status = SetUserGeoID(bad_args[i].geo.id);
+        ok(!status &&
+            (GetLastError() == ERROR_INVALID_PARAMETER || /* Vista+ */
+             broken(GetLastError() == ERROR_SUCCESS)), /* WinXP */
+        "Setting %s: got ret=%d (expected 0), error=%d (expected 87=ERROR_INVALID_PARAMETER)\n",
+        bad_args[i].stage, status, GetLastError());
+    }
+
+    for (int i = 0; i < ARRAY_SIZE(tests); i++)
+    {
+        const struct geopair *geo;
+
+        if (original_nation != tests[i].geo.id)
+            geo = &tests[i].geo;
+        else
+            geo = &tests[i].geo_backup;
+
+        SetLastError(ERROR_SUCCESS);
+        ok(status = SetUserGeoID(geo->id),
+            "%s: Setting to %d failed with last error: %d\n", tests[i].stage, geo->id, GetLastError());
+        if (status)
+        {
+            const GEOID id = GetUserGeoID(tests[i].geoclass);
+            const int status = (id == geo->id);
+            ok(status, "%s: we just set it to %d but retrieved %d instead \n", tests[i].stage, geo->id, id);
+
+            if (status)
+            {
+                todo_wine {
+                    if (geoname_supported)
+                    {
+                        const int count = pGetUserDefaultGeoName(NULL, 0);
+                        WCHAR *const name = malloc(count * sizeof(WCHAR));
+
+                        if (name)
+                        {
+                            const int written = pGetUserDefaultGeoName(name, count);
+                            const int status = (count == written);
+
+                            ok(status,
+                                "%s: Failed to get geoname after setting ID to %d: got %d characters, expected %d\n",
+                                tests[i].stage, id, written, count);
+                            ok(!winetest_strcmpW(name, geo->name),
+                                "%s: wrong geoname for ID %d: got %s, expected %s\n",
+                                tests[i].stage, geo->id, wine_dbgstr_w(name), wine_dbgstr_w(geo->name));
+                            free(name);
+                        }
+                        else if (count > 0)
+                            trace("Couldn't allocate memory to store geoname string! (Size = %lu bytes)\n",
+                                count * sizeof(WCHAR));
+                    }
+                    else
+                        win_skip("%s: Can't check geoname: unsupported platform.\n", tests[i].stage);
+                }
+            }
+        }
+    }
+
+    /* Best attempt at restoring original values */
+    if (geoname_supported)
+    {
+        if (original_name_count <= 3)
+        {
+            SetUserGeoID(original_region);
+            SetUserGeoID(original_nation);
+        }
+        else
+        {
+            SetUserGeoID(original_nation);
+            SetUserGeoID(original_region);
+        }
+    }
+    else
+    {
+        const GEOID neutral = 39070; /* World */
+        original_region != GEOID_NOT_AVAILABLE ? SetUserGeoID(original_region) : SetUserGeoID(neutral);
+        original_nation != GEOID_NOT_AVAILABLE ? SetUserGeoID(original_nation) : SetUserGeoID(neutral);
+    }
+}
+
+static void test_SetUserGeoName(void)
+{
+    todo_wine
+    {
+        if (pGetUserDefaultGeoName && pSetUserGeoName)
+        {
+            struct geopair {
+                    WCHAR *name;
+                    GEOID id;
+                };
+
+            struct testsuit {
+                const char *stage;
+                BOOL exp_return;
+                int exp_error;
+                struct geopair geo, geo_backup;
+                GEOCLASS geoclass;
+            };
+
+            /* Known valid test nations and regions */
+            struct geopair vietnam = {(WCHAR[]){'V','N',0}, 251};
+            struct geopair brasil = {(WCHAR[]){'B','R',0}, 32};
+            struct geopair west_europe = {(WCHAR[]){'1','5','5',0}, 10210824};
+            struct geopair east_asia = {(WCHAR[]){'0','3','0',0}, 47600};
+
+            /* Invalid arguments */
+            WCHAR too_long[] = {'w','e',' ','t','o','o',' ','l','o','n','g',0}; /* Names must have less than 3 chars */
+            WCHAR too_short[] = {'P',0}; /* Names must be at least two characters */
+            WCHAR wrong_un_m49[] = {'A','A','A',0}; /* UN M49 codes use numbers only */
+            WCHAR wrong_iso_3166a2[] = {'1','2',0}; /* ISO 3166-1 alpha-2 country codes use the latin alphabet only */
+
+            const struct testsuit good_args[] = {
+                {"nation geoname", TRUE, ERROR_SUCCESS, vietnam, brasil, GEOCLASS_NATION},
+                {"region geoname", TRUE, ERROR_SUCCESS, west_europe, east_asia, GEOCLASS_REGION}
+            };
+
+            const struct testsuit bad_args[] = {
+                {"too long geoname", FALSE, ERROR_INVALID_PARAMETER, {too_long}},
+                {"too short geoname", FALSE, ERROR_INVALID_PARAMETER, {too_short}},
+                {"invalid UN M49 code", FALSE, ERROR_INVALID_PARAMETER, {wrong_un_m49}},
+                {"invalid ISO 3166 code", FALSE, ERROR_INVALID_PARAMETER, {wrong_iso_3166a2}}
+            };
+
+            const int original_count = pGetUserDefaultGeoName(NULL, 0);
+            WCHAR *const original_name = malloc(original_count * sizeof(WCHAR));
+            const GEOID original_nation = GetUserGeoID(GEOCLASS_NATION);
+            const GEOID original_region = GetUserGeoID(GEOCLASS_REGION);
+
+            /* Get current values before testing */
+            if (original_name)
+            {
+                if (original_count != pGetUserDefaultGeoName(original_name, original_count))
+                    trace("Couldn't get original geo name; restoring is not possible.\n");
+            }
+            else if (original_count)
+                trace("Couldn't allocate %lu bytes to store original name.\n", sizeof(WCHAR) * original_count);
+
+
+            for (int i = 0; i < ARRAY_SIZE(bad_args); i++)
+            {
+                BOOL status;
+                SetLastError(ERROR_SUCCESS);
+
+                status = pSetUserGeoName(bad_args[i].geo.name);
+                ok((status == bad_args[i].exp_return) && (GetLastError() == bad_args[i].exp_error),
+                  "Setting %s: Got ret=%d (expected %d) and lasterror=%d (expected %d).\n",
+                  bad_args[i].stage, status, bad_args[i].exp_return, GetLastError(), bad_args[i].exp_error);
+            };
+
+
+            for (int i = 0; i < ARRAY_SIZE(good_args); i++)
+            {
+                BOOL status;
+                const struct geopair *geo;
+
+                if (winetest_strcmpW(original_name, good_args[i].geo.name))
+                    geo = &good_args[i].geo;
+                else
+                    geo = &good_args[i].geo_backup;
+
+                SetLastError(ERROR_SUCCESS);
+
+                status = pSetUserGeoName(geo->name);
+                ok((status == good_args[i].exp_return) && (GetLastError() == good_args[i].exp_error),
+                   "Setting geoname to %s: failed with ret=%d (expected %d) and lasterror=%d (expected %d).\n",
+                   wine_dbgstr_w(geo->name), status, good_args[i].exp_return, GetLastError(), good_args[i].exp_error);
+
+                if (status == good_args[i].exp_return)
+                {
+                    const GEOID geoid = GetUserGeoID(good_args[i].geoclass);
+
+                    ok(geoid == geo->id, "%s (geoclass %d): Wrong GeoID for geoname %s: got %d (expected %d).\n",
+                        good_args[i].stage, good_args[i].geoclass, wine_dbgstr_w(geo->name), geoid, geo->id);
+                }
+            }
+
+            /* Best attempt at restoring original values */
+            SetUserGeoID(original_region);
+            SetUserGeoID(original_nation);
+            pSetUserGeoName(original_name);
+        }
+        else win_skip("SetUserGeoName: procedure not implemented on this platform.\n");
+    }
+}
+
 static void test_GetGeoInfo(void)
 {
     char buffA[20];
@@ -6058,6 +6373,10 @@ START_TEST(locale)
   test_SetThreadUILanguage();
   test_NormalizeString();
   test_SpecialCasing();
+  test_GetUserGeoID();
+  test_GetUserDefaultGeoName();
+  test_SetUserGeoID();
+  test_SetUserGeoName();
   /* this requires collation table patch to make it MS compatible */
   if (0) test_sorting();
 }
-- 
2.23.0



More information about the wine-devel mailing list