0.3.5-alpha.8.fix.1

This commit is contained in:
2026-09-22 07:37:57 +02:00
parent 7f139f631e
commit 17d9e18dcd
6 changed files with 189 additions and 41 deletions

View File

@@ -7,7 +7,6 @@
//! Executable localhost smoke for WebTransport-first realtime composition with classified WebSocket fallback.
use game_realtime_transport_lib::RealtimeConnection; // rust-rules: trait-import
use game_realtime_transport_lib::RealtimeReceiver; // rust-rules: trait-import
use game_realtime_transport_lib::RealtimeSender; // rust-rules: trait-import
@@ -107,15 +106,19 @@ async fn run_webtransport_preferred_branch() -> std::result::Result<(), String>
return session.accept_primary_connection().await;
};
let client = select_preferred_transport(
|| async {
let session = match game_realtime_webtransport_lib::connect(&client_config).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
|| {
return async {
let session = match game_realtime_webtransport_lib::connect(&client_config).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return session.open_primary_connection().await;
};
return session.open_primary_connection().await;
},
|| async {
return game_realtime_websocket_lib::connect(UNUSED_WEBSOCKET_ENDPOINT).await;
|| {
return async {
return game_realtime_websocket_lib::connect(UNUSED_WEBSOCKET_ENDPOINT).await;
};
},
);
let (server_result, client_result) = tokio::join!(server, client);
@@ -146,13 +149,17 @@ async fn run_websocket_fallback_branch() -> std::result::Result<(), String> {
let endpoint = format!("ws://{}/fallback", listener.local_addr());
let server = listener.accept();
let client = select_preferred_transport(
|| async {
return std::result::Result::<game_realtime_webtransport_lib::WebTransportConnection, game_realtime_transport_lib::TransportError>::Err(
game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::Timeout, FORCED_FALLBACK_DETAIL),
);
|| {
return async {
return std::result::Result::<game_realtime_webtransport_lib::WebTransportConnection, game_realtime_transport_lib::TransportError>::Err(
game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::Timeout, FORCED_FALLBACK_DETAIL),
);
};
},
|| async {
return game_realtime_websocket_lib::connect(endpoint.as_str()).await;
|| {
return async {
return game_realtime_websocket_lib::connect(endpoint.as_str()).await;
};
},
);
let (server_result, client_result) = tokio::join!(server, client);
@@ -184,15 +191,19 @@ async fn run_non_fallback_error_branch() -> std::result::Result<(), String> {
},
};
let result = select_preferred_transport(
|| async {
let session = match game_realtime_webtransport_lib::connect(&client_config).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
|| {
return async {
let session = match game_realtime_webtransport_lib::connect(&client_config).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return session.open_primary_connection().await;
};
return session.open_primary_connection().await;
},
|| async {
return game_realtime_websocket_lib::connect("ws://127.0.0.1:1/non-fallback-must-not-run").await;
|| {
return async {
return game_realtime_websocket_lib::connect("ws://127.0.0.1:1/non-fallback-must-not-run").await;
};
},
)
.await;

View File

@@ -19,34 +19,46 @@ fn fallback_policy_is_narrow_and_excludes_ambiguous_connect_failures() {
#[tokio::test(flavor = "current_thread")]
async fn selector_prefers_webtransport_and_falls_back_only_for_classified_errors() {
let preferred = super::select_preferred_transport(
|| async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Ok(7);
|| {
return async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Ok(7);
};
},
|| async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Err(test_error("fallback must not run"));
|| {
return async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Err(test_error("fallback must not run"));
};
},
)
.await;
assert!(matches!(preferred, std::result::Result::Ok(super::SelectedConnection::WebTransport(7))), "WebTransport success must remain preferred");
let fallback = super::select_preferred_transport(
|| async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Err(game_realtime_transport_lib::TransportError::new(
game_realtime_transport_lib::TransportErrorKind::Timeout,
"forced timeout",
));
|| {
return async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Err(game_realtime_transport_lib::TransportError::new(
game_realtime_transport_lib::TransportErrorKind::Timeout,
"forced timeout",
));
};
},
|| async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Ok(9);
|| {
return async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Ok(9);
};
},
)
.await;
assert!(matches!(fallback, std::result::Result::Ok(super::SelectedConnection::WebSocket(9))), "classified timeout must select WebSocket fallback");
let non_fallback = super::select_preferred_transport(
|| async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Err(test_error("visible primary error"));
|| {
return async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Err(test_error("visible primary error"));
};
},
|| async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Ok(11);
|| {
return async {
return std::result::Result::<u8, game_realtime_transport_lib::TransportError>::Ok(11);
};
},
)
.await;