Commit 8776ba0fb3 for openssl.org
commit 8776ba0fb36a164302a31e374742183e2242639a
Author: Alexandr Nedvedicky <sashan@openssl.org>
Date: Wed Apr 22 14:17:39 2026 +0200
Port script_2 from test/quic_multistream.c to test/radix/quic_tests.c
The multistream tests use so-called t-server to test QUIC connection
and stream functionality. With introduction of QUIC SSL listener
object and QUIC TLS server method, using t-server is no longer
necessary (and welcomed). All multisttream tests should be
ported to QUIC radix test infratructure.
Co-authored-by: Matt Caswell <matt@openssl.foundation>
Reviewed-by: Norbert Pocs <norbertp@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.foundation>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
MergeDate: Mon Jun 15 14:38:19 2026
(Merged from https://github.com/openssl/openssl/pull/30935)
diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c
index a45a9407a3..de7ea27a49 100644
--- a/test/quic_multistream_test.c
+++ b/test/quic_multistream_test.c
@@ -373,19 +373,6 @@ static void s_unlock(struct helper *h, struct helper_local *hl);
#define ACQUIRE_S() s_lock(h, hl)
#define ACQUIRE_S_NOHL() s_lock(h, NULL)
-static int check_rejected(struct helper *h, struct helper_local *hl)
-{
- uint64_t stream_id = hl->check_op->arg2;
-
- if (!ossl_quic_tserver_stream_has_peer_stop_sending(ACQUIRE_S(), stream_id, NULL)
- || !ossl_quic_tserver_stream_has_peer_reset_stream(ACQUIRE_S(), stream_id, NULL)) {
- h->check_spin_again = 1;
- return 0;
- }
-
- return 1;
-}
-
static int check_stream_reset(struct helper *h, struct helper_local *hl)
{
uint64_t stream_id = hl->check_op->arg2, aec = 0;
@@ -2048,88 +2035,7 @@ static const struct script_op script_1[] = {
/* 2. Multi-stream test */
static const struct script_op script_2[] = {
- OP_C_SET_ALPN("ossltest"),
- OP_C_CONNECT_WAIT(),
- OP_C_SET_INCOMING_STREAM_POLICY(SSL_INCOMING_STREAM_POLICY_ACCEPT),
- OP_C_WRITE(DEFAULT, "apple", 5),
- OP_S_BIND_STREAM_ID(a, C_BIDI_ID(0)),
- OP_S_READ_EXPECT(a, "apple", 5),
- OP_S_WRITE(a, "orange", 6),
- OP_C_READ_EXPECT(DEFAULT, "orange", 6),
-
- OP_C_NEW_STREAM_BIDI(b, C_BIDI_ID(1)),
- OP_C_WRITE(b, "flamingo", 8),
- OP_C_CONCLUDE(b),
- OP_S_BIND_STREAM_ID(b, C_BIDI_ID(1)),
- OP_S_READ_EXPECT(b, "flamingo", 8),
- OP_S_EXPECT_FIN(b),
- OP_S_WRITE(b, "gargoyle", 8),
- OP_S_CONCLUDE(b),
- OP_C_READ_EXPECT(b, "gargoyle", 8),
- OP_C_EXPECT_FIN(b),
-
- OP_C_NEW_STREAM_UNI(c, C_UNI_ID(0)),
- OP_C_WRITE(c, "elephant", 8),
- OP_C_CONCLUDE(c),
- OP_S_BIND_STREAM_ID(c, C_UNI_ID(0)),
- OP_S_READ_EXPECT(c, "elephant", 8),
- OP_S_EXPECT_FIN(c),
- OP_S_WRITE_FAIL(c),
-
- OP_C_ACCEPT_STREAM_NONE(),
-
- OP_S_NEW_STREAM_BIDI(d, S_BIDI_ID(0)),
- OP_S_WRITE(d, "frog", 4),
- OP_S_CONCLUDE(d),
-
- OP_C_ACCEPT_STREAM_WAIT(d),
- OP_C_ACCEPT_STREAM_NONE(),
- OP_C_READ_EXPECT(d, "frog", 4),
- OP_C_EXPECT_FIN(d),
-
- OP_S_NEW_STREAM_BIDI(e, S_BIDI_ID(1)),
- OP_S_WRITE(e, "mixture", 7),
- OP_S_CONCLUDE(e),
-
- OP_C_ACCEPT_STREAM_WAIT(e),
- OP_C_READ_EXPECT(e, "mixture", 7),
- OP_C_EXPECT_FIN(e),
- OP_C_WRITE(e, "ramble", 6),
- OP_S_READ_EXPECT(e, "ramble", 6),
- OP_C_CONCLUDE(e),
- OP_S_EXPECT_FIN(e),
-
- OP_S_NEW_STREAM_UNI(f, S_UNI_ID(0)),
- OP_S_WRITE(f, "yonder", 6),
- OP_S_CONCLUDE(f),
-
- OP_C_ACCEPT_STREAM_WAIT(f),
- OP_C_ACCEPT_STREAM_NONE(),
- OP_C_READ_EXPECT(f, "yonder", 6),
- OP_C_EXPECT_FIN(f),
- OP_C_WRITE_FAIL(f),
-
- OP_C_SET_INCOMING_STREAM_POLICY(SSL_INCOMING_STREAM_POLICY_REJECT),
- OP_S_NEW_STREAM_BIDI(g, S_BIDI_ID(2)),
- OP_S_WRITE(g, "unseen", 6),
- OP_S_CONCLUDE(g),
-
- OP_C_ACCEPT_STREAM_NONE(),
-
- OP_C_SET_INCOMING_STREAM_POLICY(SSL_INCOMING_STREAM_POLICY_AUTO),
- OP_S_NEW_STREAM_BIDI(h, S_BIDI_ID(3)),
- OP_S_WRITE(h, "UNSEEN", 6),
- OP_S_CONCLUDE(h),
-
- OP_C_ACCEPT_STREAM_NONE(),
-
- /*
- * Streams g, h should have been rejected, so server should have got
- * STOP_SENDING/RESET_STREAM.
- */
- OP_CHECK(check_rejected, S_BIDI_ID(2)),
- OP_CHECK(check_rejected, S_BIDI_ID(3)),
-
+ /* test moved to test/radix/quic_tests.c */
OP_END
};
diff --git a/test/radix/quic_ops.c b/test/radix/quic_ops.c
index 87c3f77084..11cf93be30 100644
--- a/test/radix/quic_ops.c
+++ b/test/radix/quic_ops.c
@@ -1010,8 +1010,10 @@ err:
OP_PUSH_U64(1), \
OP_FUNC(hf_new_stream))
-#define OP_ACCEPT_STREAM_NONE(conn_name) \
- (OP_SELECT_SSL(0, conn_name), \
+#define OP_ACCEPT_STREAM_NONE(conn_name, flags) \
+ (OP_SELECT_SSL(0, conn_name), \
+ OP_PUSH_PZ(#conn_name), \
+ OP_PUSH_U64(flags), \
OP_FUNC(hf_accept_stream_none))
#define OP_ACCEPT_CONN_WAIT(listener_name, conn_name, flags) \
@@ -1071,7 +1073,7 @@ err:
#define OP_READ_EXPECT_B(name, buf) \
OP_READ_EXPECT(name, (buf), sizeof(buf))
-#define OP_READ_FAIL() \
+#define OP_READ_FAIL(name) \
(OP_SELECT_SSL(0, name), \
OP_PUSH_U64(0), \
OP_FUNC(hf_read_fail))
diff --git a/test/radix/quic_tests.c b/test/radix/quic_tests.c
index 90b8727bdf..a840c02ee8 100644
--- a/test/radix/quic_tests.c
+++ b/test/radix/quic_tests.c
@@ -7,6 +7,8 @@
* https://www.openssl.org/source/license.html
*/
+#include "internal/quic_stream_map.h"
+
#if defined(_AIX)
/*
* Some versions of AIX define macros for events and revents for use when
@@ -22,6 +24,128 @@
* ============================================================================
*/
+DEF_FUNC(check_rejected)
+{
+ QUIC_CHANNEL *ch;
+ SSL *ssl, *stream;
+ QUIC_STREAM *qs;
+ uint64_t stream_id;
+ int ok = 0;
+
+ REQUIRE_SSL_2(ssl, stream);
+ ch = ossl_quic_conn_get_channel(ssl);
+ if (!TEST_ptr(ch))
+ goto err;
+
+ stream_id = SSL_get_stream_id(stream);
+ qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(ch), stream_id);
+ if (!TEST_ptr(qs))
+ goto err;
+
+ if (qs->peer_stop_sending)
+ ok = 1;
+ else
+ F_SPIN_AGAIN();
+
+err:
+
+ return ok;
+}
+
+/*
+ * Multi-stream test
+ */
+DEF_SCRIPT(multi_stream, "multi stream test")
+{
+ OP_SIMPLE_PAIR_CONN();
+ OP_WRITE_B(C, "apple");
+ OP_ACCEPT_CONN_WAIT(L, S, 0);
+ OP_SET_INCOMING_STREAM_POLICY(C, SSL_INCOMING_STREAM_POLICY_ACCEPT, 42 /* error code */);
+ OP_SET_INCOMING_STREAM_POLICY(S, SSL_INCOMING_STREAM_POLICY_ACCEPT, 42 /* error code */);
+ OP_READ_EXPECT_B(S, "apple");
+ OP_WRITE_B(S, "orange");
+ OP_READ_EXPECT_B(C, "orange");
+
+ OP_NEW_STREAM(C, C0, 0 /* bidirectional stream */);
+ OP_WRITE_B(C0, "flamingo");
+ OP_ACCEPT_STREAM_WAIT(S, S0, 0 /* bidirectional stream */);
+ OP_READ_EXPECT_B(S0, "flamingo");
+ OP_CONCLUDE(C0);
+ OP_EXPECT_FIN(S0);
+ OP_WRITE_B(S0, "gargoyle");
+ OP_READ_EXPECT_B(C0, "gargoyle");
+ OP_CONCLUDE(S0);
+ OP_EXPECT_FIN(C0);
+
+ OP_NEW_STREAM(C, C1, SSL_STREAM_FLAG_UNI);
+ OP_WRITE_B(C1, "elephant");
+ OP_ACCEPT_STREAM_WAIT(S, S1, SSL_STREAM_FLAG_UNI);
+ OP_READ_EXPECT_B(S1, "elephant");
+ OP_CONCLUDE(C1);
+ OP_EXPECT_FIN(S1);
+ OP_READ_FAIL(S1);
+ OP_WRITE_FAIL(S1);
+
+ OP_ACCEPT_STREAM_NONE(C, SSL_STREAM_FLAG_UNI);
+
+ OP_NEW_STREAM(S, S2, 0 /* bidirectional stream */);
+ OP_WRITE_B(S2, "frog");
+ OP_ACCEPT_STREAM_WAIT(C, C2, 0 /* bidirectional stream */);
+ OP_READ_EXPECT_B(C2, "frog");
+ OP_CONCLUDE(S2);
+ OP_EXPECT_FIN(C2);
+
+ OP_ACCEPT_STREAM_NONE(C, 0);
+
+ OP_NEW_STREAM(S, S3, 0 /* bidirectional stream */);
+ OP_WRITE_B(S3, "mixture");
+ OP_CONCLUDE(S3);
+
+ OP_ACCEPT_STREAM_WAIT(C, C3, 0 /* bidirectional stream */);
+ OP_READ_EXPECT_B(C3, "mixture");
+ OP_EXPECT_FIN(C3);
+ OP_WRITE_B(C3, "ramble");
+ OP_READ_EXPECT_B(S3, "ramble");
+ OP_CONCLUDE(C3);
+ OP_EXPECT_FIN(S3);
+
+ OP_NEW_STREAM(S, S4, SSL_STREAM_FLAG_UNI);
+ OP_WRITE_B(S4, "yonder");
+ OP_CONCLUDE(S4);
+ OP_ACCEPT_STREAM_WAIT(C, C4, SSL_STREAM_FLAG_UNI);
+ OP_ACCEPT_STREAM_NONE(C, SSL_STREAM_FLAG_UNI);
+ OP_READ_EXPECT_B(C4, "yonder");
+ OP_EXPECT_FIN(C4);
+ OP_WRITE_FAIL(C4);
+
+ OP_SET_INCOMING_STREAM_POLICY(C, SSL_INCOMING_STREAM_POLICY_REJECT, 42 /* application error code */);
+ OP_NEW_STREAM(S, S5, 0 /* bidirectional stream */);
+ OP_WRITE_B(S5, "unseen");
+ OP_ACCEPT_STREAM_NONE(C, 0);
+ OP_SELECT_SSL(0, S);
+ OP_SELECT_SSL(1, S5);
+ /*
+ * Stream S5 is rejected because of reject policy on client side.
+ */
+ OP_FUNC(check_rejected);
+
+ OP_SET_INCOMING_STREAM_POLICY(C, SSL_INCOMING_STREAM_POLICY_AUTO, 0 /* app. error code */);
+ OP_NEW_STREAM(S, S6, 0 /* bidirectional stream */);
+ OP_WRITE_B(S6, "UNSEEN");
+ OP_ACCEPT_STREAM_NONE(C, 0);
+ OP_SELECT_SSL(0, S);
+ OP_SELECT_SSL(1, S6);
+ /*
+ * Remember the client `C` and server `S` got created by
+ * OP_SIMPLE_PAIR_CON() which creates QUIC connection objects switched to
+ * default (implicit) stream mode (see SSL_set_default_stream_mode(3ossl)).
+ * The stream policy on client `C` is AUTO now which in combination with
+ * default stream mode makes `C` to reject incoming stream `S6`
+ * (see SSL_set_incoming_stream_policy(3ossl) for details).
+ */
+ OP_FUNC(check_rejected);
+}
+
/*
* Simple single-stream test
*/
@@ -639,6 +763,7 @@ DEF_SCRIPT(check_ctx_cbks, "Check new_pending and client_hello callbacks")
*/
static SCRIPT_INFO *const scripts[] = {
USE(simple_stream),
+ USE(multi_stream),
USE(simple_conn),
USE(simple_thread),
USE(ssl_poll),