From: Hugo Landau Date: Mon, 13 May 2024 19:20:23 +0000 (+0100) Subject: QUIC RADIX: Test new SSL_poll functionality X-Git-Tag: openssl-3.5.0-alpha1~343 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=381a2b5789460a08dd54c781e564a9e5ee6b3ca7;p=thirdparty%2Fopenssl.git QUIC RADIX: Test new SSL_poll functionality Reviewed-by: Matt Caswell Reviewed-by: Saša Nedvědický Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/25416) --- diff --git a/test/radix/quic_bindings.c b/test/radix/quic_bindings.c index ab501a21251..79fb85274e0 100644 --- a/test/radix/quic_bindings.c +++ b/test/radix/quic_bindings.c @@ -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) \ diff --git a/test/radix/quic_ops.c b/test/radix/quic_ops.c index 89b2a4e22c7..47949dececd 100644 --- a/test/radix/quic_ops.c +++ b/test/radix/quic_ops.c @@ -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)) diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c index e8dcef240ec..edead29fe3a 100644 --- a/test/radix/quic_tests.c +++ b/test/radix/quic_tests.c @@ -12,6 +12,10 @@ * ============================================================================ */ +/* + * 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) };