]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
QUIC RADIX: Test new SSL_poll functionality
authorHugo Landau <hlandau@openssl.org>
Mon, 13 May 2024 19:20:23 +0000 (20:20 +0100)
committerNeil Horman <nhorman@openssl.org>
Mon, 17 Feb 2025 16:27:33 +0000 (11:27 -0500)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25416)

test/radix/quic_bindings.c
test/radix/quic_ops.c
test/radix/quic_tests.c

index ab501a21251b4a9a137dc42da37e93f9796522c8..79fb85274e06420ed96e78e02085cd94805add85 100644 (file)
@@ -77,7 +77,7 @@ typedef struct radix_process_st {
     int                     thread_composite_testresult;
 } RADIX_PROCESS;
 
-#define NUM_SLOTS       4
+#define NUM_SLOTS       8
 
 /* Thread-level state within a process */
 typedef struct radix_thread_st {
@@ -682,6 +682,36 @@ static int expect_slot_ssl(FUNC_CTX *fctx, size_t idx, SSL **p_ssl)
     } while (0)
 #define REQUIRE_SSL(ssl)    REQUIRE_SSL_N(0, (ssl))
 
+#define REQUIRE_SSL_2(a, b)                                     \
+    do {                                                        \
+        REQUIRE_SSL_N(0, (a));                                  \
+        REQUIRE_SSL_N(1, (b));                                  \
+    } while (0)
+
+#define REQUIRE_SSL_3(a, b, c)                                  \
+    do {                                                        \
+        REQUIRE_SSL_N(0, (a));                                  \
+        REQUIRE_SSL_N(1, (b));                                  \
+        REQUIRE_SSL_N(2, (c));                                  \
+    } while (0)
+
+#define REQUIRE_SSL_4(a, b, c, d)                               \
+    do {                                                        \
+        REQUIRE_SSL_N(0, (a));                                  \
+        REQUIRE_SSL_N(1, (b));                                  \
+        REQUIRE_SSL_N(2, (c));                                  \
+        REQUIRE_SSL_N(3, (d));                                  \
+    } while (0)
+
+#define REQUIRE_SSL_5(a, b, c, d, e)                            \
+    do {                                                        \
+        REQUIRE_SSL_N(0, (a));                                  \
+        REQUIRE_SSL_N(1, (b));                                  \
+        REQUIRE_SSL_N(2, (c));                                  \
+        REQUIRE_SSL_N(3, (d));                                  \
+        REQUIRE_SSL_N(4, (e));                                  \
+    } while (0)
+
 #define C_BIDI_ID(ordinal) \
     (((ordinal) << 2) | QUIC_STREAM_INITIATOR_CLIENT | QUIC_STREAM_DIR_BIDI)
 #define S_BIDI_ID(ordinal) \
index 89b2a4e22c7466bdecafd75ef6ee7b05ec30d23e..47949dececd74a7c9ad5c94aa737c9a0ee50735a 100644 (file)
@@ -233,19 +233,17 @@ err:
 DEF_FUNC(hf_new_stream)
 {
     int ok = 0;
-    const char *conn_name, *stream_name;
+    const char *stream_name;
     SSL *conn, *stream;
     uint64_t flags, do_accept;
 
     F_POP2(flags, do_accept);
-    F_POP2(conn_name, stream_name);
+    F_POP(stream_name);
+    REQUIRE_SSL(conn);
 
     if (!TEST_ptr_null(RADIX_PROCESS_get_obj(RP(), stream_name)))
         goto err;
 
-    if (!TEST_ptr(conn = RADIX_PROCESS_get_ssl(RP(), conn_name)))
-        goto err;
-
     if (do_accept) {
         stream = SSL_accept_stream(conn, flags);
 
@@ -909,6 +907,20 @@ err:
     return ok;
 }
 
+DEF_FUNC(hf_sleep)
+{
+    int ok = 0;
+    uint64_t ms;
+
+    F_POP(ms);
+
+    OSSL_sleep(ms);
+
+    ok = 1;
+err:
+    return ok;
+}
+
 #define OP_UNBIND(name)                                         \
     (OP_PUSH_PZ(#name),                                         \
      OP_FUNC(hf_unbind))
@@ -977,6 +989,10 @@ err:
      OP_SET_PEER_ADDR_FROM(C, L),                               \
      OP_CONNECT_WAIT(C))
 
+#define OP_SIMPLE_PAIR_CONN_ND()                                \
+    (OP_SIMPLE_PAIR_CONN(),                                     \
+     OP_SET_DEFAULT_STREAM_MODE(C, SSL_DEFAULT_STREAM_MODE_NONE))
+
 #define OP_NEW_STREAM(conn_name, stream_name, flags)            \
     (OP_SELECT_SSL(0, conn_name),                               \
      OP_PUSH_PZ(#stream_name),                                  \
@@ -1001,10 +1017,22 @@ err:
      OP_PUSH_U64(flags),                                        \
      OP_FUNC(hf_accept_conn))
 
+#define OP_ACCEPT_CONN_WAIT_ND(listener_name, conn_name, flags) \
+    (OP_ACCEPT_CONN_WAIT(listener_name, conn_name, flags),      \
+     OP_SET_DEFAULT_STREAM_MODE(conn_name, SSL_DEFAULT_STREAM_MODE_NONE))
+
 #define OP_ACCEPT_CONN_NONE(listener_name)                      \
     (OP_SELECT_SSL(0, listener_name),                           \
      OP_FUNC(hf_accept_conn_none))
 
+#define OP_ACCEPT_CONN_WAIT1(listener_name, conn_name, flags)   \
+    (OP_ACCEPT_CONN_WAIT(listener_name, conn_name, flags),      \
+     OP_ACCEPT_CONN_NONE(listener_name))
+
+#define OP_ACCEPT_CONN_WAIT1_ND(listener_name, conn_name, flags) \
+    (OP_ACCEPT_CONN_WAIT_ND(listener_name, conn_name, flags),    \
+     OP_ACCEPT_CONN_NONE(listener_name))
+
 #define OP_WRITE(name, buf, buf_len)                            \
     (OP_SELECT_SSL(0, name),                                    \
      OP_PUSH_BUFP(buf, buf_len),                                \
@@ -1114,3 +1142,7 @@ err:
 #define OP_SKIP_TIME(ms)                                        \
     (OP_PUSH_U64(ms),                                           \
      OP_FUNC(hf_skip_time))
+
+#define OP_SLEEP(ms)                                            \
+    (OP_PUSH_U64(ms),                                           \
+     OP_FUNC(hf_sleep))
index e8dcef240ec62683e7c093e2babe02890fecfd2e..edead29fe3ae007e69b7ca433199ac97fe184b79 100644 (file)
  * ============================================================================
  */
 
+/*
+ * Test: simple_conn
+ * -----------------
+ */
 DEF_SCRIPT(simple_conn, "simple connection to server")
 {
     size_t i;
@@ -40,6 +44,10 @@ DEF_SCRIPT(simple_thread_child,
 {
 }
 
+/*
+ * Test: simple_thread
+ * -------------------
+ */
 DEF_SCRIPT(simple_thread,
            "test that RADIX multithreading is working")
 {
@@ -49,6 +57,162 @@ DEF_SCRIPT(simple_thread,
         OP_SPAWN_THREAD(simple_thread_child);
 }
 
+/*
+ * Test: ssl_poll
+ * --------------
+ */
+DEF_SCRIPT(ssl_poll_child,
+           "test that SSL_poll is working (child)")
+{
+    OP_SLEEP(100);
+    OP_WRITE_B(C0, "extra");
+}
+
+DEF_FUNC(ssl_poll_check)
+{
+    int ok = 0;
+    SSL *La, *Lax[4];
+    SSL_POLL_ITEM items[5] = {0}, expected_items[5] = {0};
+    size_t result_count = 0, i;
+    const struct timeval z_timeout = {0}, *p_timeout = &z_timeout;
+    struct timeval timeout = {0};
+    uint64_t mode;
+    size_t expected_result_count;
+    OSSL_TIME time_before, time_after;
+
+    F_POP(mode);
+    REQUIRE_SSL_5(La, Lax[0], Lax[1], Lax[2], Lax[3]);
+
+    items[0].desc      = SSL_as_poll_descriptor(La);
+    items[0].events    = 0;
+    items[0].revents   = 0;
+
+    for (i = 0; i < 4; ++i) {
+        items[i + 1].desc        = SSL_as_poll_descriptor(Lax[i]);
+        items[i + 1].events      = SSL_POLL_EVENT_R | SSL_POLL_EVENT_I;
+        items[i + 1].revents     = 0;
+    }
+
+    switch (mode) {
+    case 0: /* Nothing ready */
+    case 2:
+        expected_result_count = 0;
+        break;
+    case 1: /* Various events reported correctly */
+        expected_result_count       = 5;
+        items[0].events             = SSL_POLL_EVENT_OS;
+        expected_items[0].revents   = SSL_POLL_EVENT_OS;
+
+        expected_items[1].revents   = SSL_POLL_EVENT_R;
+
+        for (i = 0; i < 4; ++i) {
+            items[i + 1].events             |= SSL_POLL_EVENT_W;
+            expected_items[i + 1].revents   |= SSL_POLL_EVENT_W;
+        }
+
+        break;
+    case 3: /* Blocking test */
+        expected_result_count       = 1;
+        expected_items[1].revents   = SSL_POLL_EVENT_R;
+
+        p_timeout = &timeout;
+        timeout.tv_sec  = 10;
+        timeout.tv_usec = 0;
+        break;
+    default:
+        goto err;
+    }
+
+    /* Zero-timeout call. */
+    result_count = SIZE_MAX;
+    time_before = ossl_time_now();
+    if (!TEST_true(SSL_poll(items, OSSL_NELEM(items), sizeof(SSL_POLL_ITEM),
+                            p_timeout, 0, &result_count)))
+        goto err;
+
+    time_after = ossl_time_now();
+    if (!TEST_size_t_eq(result_count, expected_result_count))
+        goto err;
+
+    for (i = 0; i < OSSL_NELEM(items); ++i)
+        if (!TEST_uint64_t_eq(items[i].revents, expected_items[i].revents))
+            goto err;
+
+    /*
+     * The SSL_poll call for the blocking test definitely shouldn't have
+     * returned sooner than in 100ms.
+     */
+    if (i == 3 && !TEST_uint64_t_ge(ossl_time2ms(ossl_time_subtract(time_after, time_before)), 100))
+        goto err;
+
+    ok = 1;
+err:
+    return ok;
+}
+
+DEF_SCRIPT(ssl_poll,
+           "test that SSL_poll is working")
+{
+    size_t i;
+
+    OP_SIMPLE_PAIR_CONN_ND();
+
+    /* Setup streams */
+    OP_NEW_STREAM(C, C0, 0);
+    OP_WRITE_B(C0, "apple");
+
+    OP_NEW_STREAM(C, C1, 0);
+    OP_WRITE_B(C1, "orange");
+
+    OP_NEW_STREAM(C, C2, 0);
+    OP_WRITE_B(C2, "Strawberry");
+
+    OP_NEW_STREAM(C, C3, 0);
+    OP_WRITE_B(C3, "sync");
+
+    OP_ACCEPT_CONN_WAIT1_ND(L, La, 0);
+
+    OP_ACCEPT_STREAM_WAIT(La, La0, 0);
+    OP_READ_EXPECT_B(La0, "apple");
+
+    OP_ACCEPT_STREAM_WAIT(La, La1, 0);
+    OP_READ_EXPECT_B(La1, "orange");
+
+    OP_ACCEPT_STREAM_WAIT(La, La2, 0);
+    OP_READ_EXPECT_B(La2, "Strawberry");
+
+    OP_ACCEPT_STREAM_WAIT(La, La3, 0);
+    OP_READ_EXPECT_B(La3, "sync");
+
+    for (i = 0; i <= 3; ++i) {
+        /* 0: Check nothing ready */
+        /* 1: Check that various events are reported correctly */
+        /* 2: Check nothing ready */
+        /* 3: Blocking call unblocked from child thread */
+
+        if (i == 1) {
+            OP_WRITE_B(C0, "orange");
+            OP_WRITE_B(C3, "sync");
+            OP_READ_EXPECT_B(La3, "sync");
+        } else if (i == 2) {
+            OP_READ_EXPECT_B(La0, "orange");
+        } else if (i == 3) {
+            OP_SPAWN_THREAD(ssl_poll_child);
+        }
+
+        OP_SELECT_SSL(0, La);
+        OP_SELECT_SSL(1, La0);
+        OP_SELECT_SSL(2, La1);
+        OP_SELECT_SSL(3, La2);
+        OP_SELECT_SSL(4, La3);
+        OP_PUSH_U64(i);
+        OP_FUNC(ssl_poll_check);
+
+        if (i == 3)
+            OP_READ_EXPECT_B(La0, "extra");
+    }
+}
+
 /*
  * List of Test Scripts
  * ============================================================================
@@ -56,4 +220,5 @@ DEF_SCRIPT(simple_thread,
 static SCRIPT_INFO *const scripts[] = {
     USE(simple_conn)
     USE(simple_thread)
+    USE(ssl_poll)
 };