[PATCH 2/3] iphlpapi/tests: Add tests for GetBestRoute2.

Jinoh Kang wine at gitlab.winehq.org
Fri Jun 17 09:00:14 CDT 2022


From: Jinoh Kang <jinoh.kang.kr at gmail.com>

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
 dlls/iphlpapi/tests/iphlpapi.c | 224 +++++++++++++++++++++++++++++++++
 1 file changed, 224 insertions(+)

diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index 29256eb2774..f2148d29b52 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -2391,6 +2391,229 @@ static void test_GetUnicastIpAddressTable(void)
     FreeMibTable( table );
 }
 
+static void test_GetBestRoute2(void)
+{
+    DWORD apiReturn;
+    SOCKADDR_INET source, destination, bestaddress, bestaddress_memory;
+    MIB_IPFORWARD_ROW2 bestroute, bestroute_memory;
+    int validmemflags = 0;
+    static const MIB_IPFORWARD_ROW2 route_zero;
+    static const NET_LUID zero_luid, ones_luid = { -1 };
+    static const SOCKADDR_INET unspecaddr;
+    static const SOCKADDR invalidaddr = { -1 };
+    static const SOCKADDR_IN in4any = { AF_INET };
+    static const SOCKADDR_IN in4loopback = { AF_INET, 0, {{{ 127, 0, 0, 1 }}} };
+    static const SOCKADDR_IN in4broadcast = { AF_INET, 0, {{{ 255, 255, 255, 255 }}} };
+    static const SOCKADDR_IN6 in6any = { AF_INET6 };
+    static const SOCKADDR_IN6 in6loopback = { AF_INET6, 0, 0, {{{
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    }}} };
+    static const SOCKADDR_IN6 in6broadcast = { AF_INET6, 0, 0, {{{
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    }}} };
+    struct sockaddr_ptrlen
+    {
+        const struct sockaddr *ptr;
+        size_t len;
+    };
+    static const struct getbestroute_test
+    {
+        int line;
+        const NET_LUID *luid;
+        NET_IFINDEX ifindex;
+        struct sockaddr_ptrlen source;
+        struct sockaddr_ptrlen destination;
+        ULONG options;
+        DWORD result;
+        BOOL todo;
+        int memload;
+        int memstore;
+    } getbestroute_tests[] = {
+#define SA_PL(x) { ((struct sockaddr *)&(x)), sizeof(x) }
+        { __LINE__, &zero_luid, 0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, &zero_luid, -1, { NULL },            SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, &ones_luid, 0,  { NULL },            SA_PL(in4loopback), 0, ERROR_NOT_FOUND },
+        { __LINE__, NULL,       -1, { NULL },            SA_PL(in4loopback), 0, ERROR_FILE_NOT_FOUND },
+        { __LINE__, &zero_luid, 0,  SA_PL(unspecaddr),   SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, &ones_luid, 0,  SA_PL(unspecaddr),   SA_PL(in4loopback), 0, ERROR_NOT_FOUND },
+        { __LINE__, NULL,       0,  SA_PL(unspecaddr),   SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, NULL,       0,  SA_PL(in4any),       SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, NULL,       0,  SA_PL(in4loopback),  SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, NULL,       0,  SA_PL(in4broadcast), SA_PL(in4loopback), 0, ERROR_INVALID_PARAMETER, TRUE },
+        { __LINE__, NULL,       0,  SA_PL(in6any),       SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, NULL,       0,  SA_PL(in6loopback),  SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, NULL,       0,  SA_PL(in6broadcast), SA_PL(in4loopback), 0, NO_ERROR },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0, 0xc7 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc0 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc2 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc4 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc6 },
+#if 0 /* not reliable (fails spuriously) on Wine */
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc1 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc3 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc5 },
+        { __LINE__, NULL,       0,  { NULL },            SA_PL(in4loopback), 0, NO_ERROR, FALSE, 0xc7 },
+#endif
+#undef SA_PL
+    };
+    UINT i;
+
+    memset( &destination, 0, sizeof(destination) );
+    destination.Ipv4.sin_family = AF_INET;
+    destination.Ipv4.sin_addr.S_un.S_addr = htonl( INADDR_ANY );
+    apiReturn = GetBestRoute2( NULL, 0, NULL, &destination, 0, &bestroute, &bestaddress );
+    trace( "GetBestRoute2(NULL, 0, NULL, [...], 0, [...], [...]) = %lu\n", apiReturn );
+    if (apiReturn == ERROR_NOT_SUPPORTED)
+    {
+        skip("GetBestRoute2 not supported\n");
+        return;
+    }
+
+    apiReturn = GetBestRoute2( NULL, 0, NULL, NULL, 0, NULL, NULL );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, NULL, 0, NULL, NULL) returned %lu, expected %d\n",
+        apiReturn, ERROR_INVALID_PARAMETER );
+
+    apiReturn = GetBestRoute2( NULL, 0, NULL, NULL, 0, &bestroute, NULL );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, NULL, 0, %p, NULL) returned %lu, expected %d\n",
+        &bestroute, apiReturn, ERROR_INVALID_PARAMETER );
+
+    apiReturn = GetBestRoute2( NULL, 0, NULL, NULL, 0, NULL, &bestaddress );
+    memcpy( &bestaddress, &invalidaddr, sizeof(invalidaddr) );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, NULL, 0, NULL, %p) returned %lu, expected %d\n",
+        &bestaddress, apiReturn, ERROR_INVALID_PARAMETER );
+    ok( memcmp(&bestaddress, &invalidaddr, sizeof(invalidaddr)) == 0, "bestaddress(.si_family = %u) has changed\n", bestaddress.si_family );
+
+    apiReturn = GetBestRoute2( NULL, 0, NULL, NULL, 0, &bestroute, &bestaddress );
+    memcpy( &bestaddress, &invalidaddr, sizeof(invalidaddr) );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, NULL, 0, %p, %p) returned %lu, expected %d\n",
+        &bestroute, &bestaddress, apiReturn, ERROR_INVALID_PARAMETER );
+    ok( memcmp(&bestaddress, &invalidaddr, sizeof(invalidaddr)) == 0, "bestaddress(.si_family = %u) has changed\n", bestaddress.si_family );
+
+    memset( &destination, 0, sizeof(destination) );
+    destination.Ipv4.sin_family = AF_INET;
+    destination.Ipv4.sin_addr.S_un.S_addr = htonl( INADDR_LOOPBACK );
+    memcpy( &bestaddress, &invalidaddr, sizeof(invalidaddr) );
+    apiReturn = GetBestRoute2( NULL, 0, NULL, &destination, 0, &bestroute, NULL );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, [127.0.0.1], 0, %p, NULL) returned %lu, expected %d\n",
+        &bestroute, apiReturn, ERROR_INVALID_PARAMETER );
+    ok( memcmp(&bestaddress, &invalidaddr, sizeof(invalidaddr)) == 0, "bestaddress(.si_family = %u) has changed\n", bestaddress.si_family );
+
+    memset( &destination, 0, sizeof(destination) );
+    destination.Ipv4.sin_family = AF_INET;
+    destination.Ipv4.sin_addr.S_un.S_addr = htonl( INADDR_LOOPBACK );
+    memcpy( &bestaddress, &invalidaddr, sizeof(invalidaddr) );
+    apiReturn = GetBestRoute2( NULL, 0, NULL, &destination, 0, NULL, &bestaddress );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, [127.0.0.1], 0, NULL, %p) returned %lu, expected %d\n",
+        &bestaddress, apiReturn, ERROR_INVALID_PARAMETER );
+    ok( memcmp(&bestaddress, &invalidaddr, sizeof(invalidaddr)) == 0, "bestaddress(.si_family = %u) has changed\n", bestaddress.si_family );
+
+    memset( &destination, 0, sizeof(destination) );
+    memcpy( &bestaddress, &invalidaddr, sizeof(invalidaddr) );
+    apiReturn = GetBestRoute2( NULL, 0, NULL, &destination, 0, NULL, &bestaddress );
+    ok( apiReturn == ERROR_INVALID_PARAMETER,
+        "GetBestRoute2(NULL, 0, NULL, <AF_UNSPEC>, 0, NULL, %p) returned %lu, expected %d\n",
+        &bestaddress, apiReturn, ERROR_INVALID_PARAMETER );
+    ok( memcmp(&bestaddress, &invalidaddr, sizeof(invalidaddr)) == 0, "bestaddress(.si_family = %u) has changed\n", bestaddress.si_family );
+
+    for (i = 0; i < ARRAY_SIZE(getbestroute_tests); i++)
+    {
+        const struct getbestroute_test *item = &getbestroute_tests[i];
+        int validflags = item->memload & validmemflags;
+        NET_LUID luid;
+        NET_IFINDEX ifindex = 0;
+
+        winetest_push_context("Subtest #%u (decl at line %d)", i, item->line);
+
+        ok( (item->memload & ~validmemflags) == 0,
+            "current subtest may be incomplete due to previous test failure (memload = %d, validmemflags = %d)\n",
+            item->memload, validmemflags );
+
+        if (item->luid)
+        {
+            memcpy(&luid, item->luid, sizeof(luid));
+            validflags |= 1;
+        }
+        else if (validflags & 1)
+        {
+            memcpy(&luid, &bestroute_memory.InterfaceLuid, sizeof(luid));
+        }
+
+        if (item->ifindex)
+        {
+            ifindex = item->ifindex;
+            validflags |= 2;
+        }
+        else if (validflags & 2)
+        {
+            ifindex = bestroute_memory.InterfaceIndex;
+        }
+
+        if (item->source.len > sizeof(source)) abort();  /* prevent memory corruption */
+        if (item->source.ptr)
+        {
+            memset( &source, 0, sizeof(source) );
+            memcpy( &source, item->source.ptr, item->source.len );
+            validflags |= 4;
+        }
+        else if (validflags & 4)
+        {
+            memcpy( &source, &bestaddress_memory, sizeof(source) );
+        }
+
+        if (item->destination.len > sizeof(destination)) abort();  /* prevent memory corruption */
+        memset( &destination, 0, sizeof(destination) );
+        memcpy( &destination, item->destination.ptr, item->destination.len );
+
+        apiReturn = GetBestRoute2( (validflags & 1) ? &luid : NULL,
+                                   (validflags & 2) ? ifindex : 0,
+                                   (validflags & 4) ? &source : NULL,
+                                   &destination,
+                                   item->options,
+                                   &bestroute, &bestaddress );
+        todo_wine_if( item->todo )
+        ok( apiReturn == item->result,
+            "GetBestRoute2 returned %lu, expected %lu\n", apiReturn, item->result );
+        if (apiReturn == NO_ERROR)
+        {
+            ok( bestaddress.si_family == destination.si_family,
+                "bestaddress.si_family (%u) shall equal destination.si_family (%u)\n",
+                bestaddress.si_family, destination.si_family );
+
+            if (validflags & 0x40)
+            {
+                ok( memcmp( &bestroute_memory, &bestroute, sizeof(bestroute) ) == 0,
+                    "returned bestroute does not match last cached value\n" );
+            }
+
+            if (validflags & 0x80)
+            {
+                ok( memcmp( &bestaddress_memory, &bestaddress, sizeof(bestaddress) ) == 0,
+                    "returned bestaddress does not match last cached value\n" );
+            }
+
+            if (item->memstore)
+            {
+                memcpy( &bestroute_memory, &bestroute, sizeof(bestroute_memory) );
+                memcpy( &bestaddress_memory, &bestaddress, sizeof(bestaddress_memory) );
+                validmemflags = item->memstore;
+            }
+        }
+        else
+        {
+            ok( memcmp( &bestaddress, &unspecaddr, sizeof(bestaddress) ) == 0, "bestaddress shall be zeroed by GetBestRoute2\n" );
+            ok( memcmp( &bestroute, &route_zero, sizeof(bestroute) ) == 0, "bestroute shall be zeroed by GetBestRoute2\n" );
+        }
+
+        winetest_pop_context();
+    }
+}
+
 static void test_ConvertLengthToIpv4Mask(void)
 {
     DWORD ret;
@@ -2703,6 +2926,7 @@ START_TEST(iphlpapi)
     test_GetIfTable2Ex();
     test_GetUnicastIpAddressEntry();
     test_GetUnicastIpAddressTable();
+    test_GetBestRoute2();
     test_ConvertLengthToIpv4Mask();
     test_GetTcp6Table();
     test_GetUdp6Table();
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/263



More information about the wine-devel mailing list