[PATCH 1/6] ws2_32/tests: Add tests for setting and getting socket options with shorter length.

Paul Gofman pgofman at codeweavers.com
Thu Mar 3 11:05:36 CST 2022


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
     The aim of the patchset is to fix setting and getting 32bit sized socket options
     when the beaviour is different between Windows and Linux setsockopt() and
     getsockopt(). That behaviour partially regressed on the move from ws2_32 to ntdll:
     setsockopt() had the code which would adjust the size for option with the provided
     length less than 4 bytes (which helped, e. g., SO_REUSEADDR and SO_KEEPALIVE and
     Killing Floor 2 depended on that). ALthough, as my tests show, that was not universally
     correct across all the options and the details of getsockopt() were also different.
     I have another 16 patches on top of this series addressing the other options.

 dlls/ws2_32/tests/sock.c | 86 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 85 insertions(+), 1 deletion(-)

diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 6b6267dc153..0eece82bfb1 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1155,8 +1155,27 @@ static const LINGER linger_testvals[] = {
 
 static void test_set_getsockopt(void)
 {
+    static struct
+    {
+        int af;
+        int type;
+        int level;
+        int optname;
+        BOOL accepts_short_len;
+        unsigned int sizes[3];
+        DWORD values[3];
+    }
+    test_optsize[] =
+    {
+        {AF_INET, SOCK_STREAM, SOL_SOCKET, SO_RCVTIMEO, FALSE, {1, 2, 4}},
+        {AF_INET, SOCK_STREAM, SOL_SOCKET, SO_SNDTIMEO, FALSE, {1, 2, 4}},
+        {AF_INET, SOCK_DGRAM, IPPROTO_IP, IP_MULTICAST_LOOP, TRUE, {1, 1, 4}},
+        {AF_INET, SOCK_DGRAM, IPPROTO_IP, IP_MULTICAST_TTL, TRUE, {1, 1, 4}},
+        {AF_INET, SOCK_DGRAM, IPPROTO_IP, IP_TOS, TRUE, {1, 1, 4}},
+        {AF_INET, SOCK_DGRAM, IPPROTO_IP, IP_TTL, TRUE, {1, 1, 4}},
+    };
     SOCKET s, s2;
-    int i, err, lasterr;
+    int i, j, err, lasterr;
     int timeout;
     LINGER lingval;
     int size;
@@ -1375,6 +1394,71 @@ static void test_set_getsockopt(void)
         err, WSAGetLastError());
 
     closesocket(s);
+
+    /* Test option short length. */
+    for (i = 0; i < ARRAY_SIZE(test_optsize); ++i)
+    {
+        s2 = socket( test_optsize[i].af, test_optsize[i].type, 0 );
+        ok(s2 != INVALID_SOCKET, "socket() failed error %d\n", WSAGetLastError());
+        for (j = 0; j < 3; ++j)
+        {
+            DWORD expected_last_error, expected_value, expected_size, save_value;
+            int expected_err;
+
+            winetest_push_context("i %u, level %d, optname %d, len %u",
+                    i, test_optsize[i].level, test_optsize[i].optname, 1 << j);
+
+            size = sizeof(save_value);
+            err = getsockopt(s2, test_optsize[i].level, test_optsize[i].optname, (char*)&save_value, &size);
+            ok(!err, "Unexpected getsockopt result %d.\n", err);
+
+            if (test_optsize[i].accepts_short_len || j == 2)
+            {
+                expected_err = 0;
+                expected_last_error = ERROR_SUCCESS;
+                expected_size = test_optsize[i].sizes[j] ? test_optsize[i].sizes[j] : 4;
+                if (test_optsize[i].values[j])
+                    expected_value = test_optsize[i].values[j];
+                else if (expected_size == 4)
+                    expected_value = 1;
+                else
+                    expected_value = (0xdeadbeef & ~((1 << expected_size * 8) - 1)) | 1;
+            }
+            else
+            {
+                expected_err = -1;
+                expected_last_error = WSAEFAULT;
+                expected_size = test_optsize[i].sizes[j];
+                if (test_optsize[i].values[j])
+                    expected_value = test_optsize[i].values[j];
+                else
+                    expected_value = 0xdeadbeef;
+            }
+
+            value = 1;
+            SetLastError(0xdeadbeef);
+            err = setsockopt(s2, test_optsize[i].level, test_optsize[i].optname, (char*)&value, 1 << j);
+            ok(err == expected_err, "Unexpected setsockopt result %d.\n", err);
+            ok(WSAGetLastError() == expected_last_error, "Unexpected WSAGetLastError() %u.\n", WSAGetLastError());
+
+            value = 0xdeadbeef;
+            SetLastError(0xdeadbeef);
+            size = 1 << j;
+            err = getsockopt(s2, test_optsize[i].level, test_optsize[i].optname, (char*)&value, &size);
+            ok(err == expected_err, "Unexpected getsockopt result %d.\n", err);
+            ok(WSAGetLastError() == expected_last_error, "Unexpected WSAGetLastError() %u.\n", WSAGetLastError());
+            ok(value == expected_value, "Got unexpected value %#x, expected %#x.\n", value, expected_value);
+            ok(size == expected_size, "Got unexpected size %u, expected %u.\n", size, expected_size);
+
+            err = setsockopt(s2, test_optsize[i].level, test_optsize[i].optname,
+                    (char*)&save_value, sizeof(save_value));
+            ok(!err, "Unexpected getsockopt result %d.\n", err);
+
+            winetest_pop_context();
+        }
+        closesocket(s2);
+    }
+
     /* Test with the closed socket */
     SetLastError(0xdeadbeef);
     size = sizeof(i);
-- 
2.35.1




More information about the wine-devel mailing list