diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/neqo-http3/tests/webtransport.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/neqo-http3/tests/webtransport.rs')
-rw-r--r-- | third_party/rust/neqo-http3/tests/webtransport.rs | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/third_party/rust/neqo-http3/tests/webtransport.rs b/third_party/rust/neqo-http3/tests/webtransport.rs new file mode 100644 index 0000000000..e0556708f1 --- /dev/null +++ b/third_party/rust/neqo-http3/tests/webtransport.rs @@ -0,0 +1,320 @@ +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use neqo_common::{event::Provider, Header}; +use neqo_crypto::AuthenticationStatus; +use neqo_http3::{ + Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server, + Http3ServerEvent, Http3State, WebTransportEvent, WebTransportRequest, WebTransportServerEvent, + WebTransportSessionAcceptAction, +}; +use neqo_transport::{StreamId, StreamType}; +use std::cell::RefCell; +use std::rc::Rc; +use test_fixture::{ + addr, anti_replay, fixture_init, now, CountingConnectionIdGenerator, DEFAULT_ALPN_H3, + DEFAULT_KEYS, DEFAULT_SERVER_NAME, +}; + +fn connect() -> (Http3Client, Http3Server) { + fixture_init(); + let mut client = Http3Client::new( + DEFAULT_SERVER_NAME, + Rc::new(RefCell::new(CountingConnectionIdGenerator::default())), + addr(), + addr(), + Http3Parameters::default().webtransport(true), + now(), + ) + .expect("create a default client"); + let mut server = Http3Server::new( + now(), + DEFAULT_KEYS, + DEFAULT_ALPN_H3, + anti_replay(), + Rc::new(RefCell::new(CountingConnectionIdGenerator::default())), + Http3Parameters::default().webtransport(true), + None, + ) + .expect("create a server"); + assert_eq!(client.state(), Http3State::Initializing); + let out = client.process(None, now()); + assert_eq!(client.state(), Http3State::Initializing); + + let out = server.process(out.dgram(), now()); + let out = client.process(out.dgram(), now()); + let out = server.process(out.dgram(), now()); + assert!(out.as_dgram_ref().is_none()); + + let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded); + assert!(client.events().any(authentication_needed)); + client.authenticated(AuthenticationStatus::Ok, now()); + + let mut out = client.process(out.dgram(), now()).dgram(); + let connected = |e| matches!(e, Http3ClientEvent::StateChange(Http3State::Connected)); + assert!(client.events().any(connected)); + + assert_eq!(client.state(), Http3State::Connected); + + // Exchange H3 setttings + loop { + out = server.process(out, now()).dgram(); + let dgram_present = out.is_some(); + out = client.process(out, now()).dgram(); + if out.is_none() && !dgram_present { + break; + } + } + (client, server) +} + +fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server) { + let mut out = None; + loop { + out = client.process(out, now()).dgram(); + out = server.process(out, now()).dgram(); + if out.is_none() { + break; + } + } +} + +fn create_wt_session(client: &mut Http3Client, server: &mut Http3Server) -> WebTransportRequest { + let wt_session_id = client + .webtransport_create_session(now(), &("https", "something.com", "/"), &[]) + .unwrap(); + exchange_packets(client, server); + + let mut wt_server_session = None; + while let Some(event) = server.next_event() { + match event { + Http3ServerEvent::WebTransport(WebTransportServerEvent::NewSession { + mut session, + headers, + }) => { + assert!( + headers + .iter() + .any(|h| h.name() == ":method" && h.value() == "CONNECT") + && headers + .iter() + .any(|h| h.name() == ":protocol" && h.value() == "webtransport") + ); + session + .response(&WebTransportSessionAcceptAction::Accept) + .unwrap(); + wt_server_session = Some(session); + } + Http3ServerEvent::Data { .. } => { + panic!("There should not be any data events!"); + } + _ => {} + } + } + + exchange_packets(client, server); + + let wt_session_negotiated_event = |e| { + matches!( + e, + Http3ClientEvent::WebTransport(WebTransportEvent::Session{ + stream_id, + status, + headers, + }) if ( + stream_id == wt_session_id && + status == 200 && + headers.contains(&Header::new(":status", "200")) + ) + ) + }; + assert!(client.events().any(wt_session_negotiated_event)); + + let wt_server_session = wt_server_session.unwrap(); + assert_eq!(wt_session_id, wt_server_session.stream_id()); + wt_server_session +} + +fn send_data_client( + client: &mut Http3Client, + server: &mut Http3Server, + wt_stream_id: StreamId, + data: &[u8], +) { + assert_eq!(client.send_data(wt_stream_id, data).unwrap(), data.len()); + exchange_packets(client, server); +} + +fn send_data_server( + client: &mut Http3Client, + server: &mut Http3Server, + wt_stream: &mut Http3OrWebTransportStream, + data: &[u8], +) { + assert_eq!(wt_stream.send_data(data).unwrap(), data.len()); + exchange_packets(client, server); +} + +fn receive_data_client( + client: &mut Http3Client, + expected_stream_id: StreamId, + new_stream: bool, + expected_data: &[u8], + expected_fin: bool, +) { + let mut new_stream_received = false; + let mut data_received = false; + while let Some(event) = client.next_event() { + match event { + Http3ClientEvent::WebTransport(WebTransportEvent::NewStream { stream_id, .. }) => { + assert_eq!(stream_id, expected_stream_id); + new_stream_received = true; + } + Http3ClientEvent::DataReadable { stream_id } => { + assert_eq!(stream_id, expected_stream_id); + let mut buf = [0; 100]; + let (amount, fin) = client.read_data(now(), stream_id, &mut buf).unwrap(); + assert_eq!(fin, expected_fin); + assert_eq!(amount, expected_data.len()); + assert_eq!(&buf[..amount], expected_data); + data_received = true; + } + _ => {} + } + } + assert!(data_received); + assert_eq!(new_stream, new_stream_received); +} + +fn receive_data_server( + client: &mut Http3Client, + server: &mut Http3Server, + stream_id: StreamId, + new_stream: bool, + expected_data: &[u8], + expected_fin: bool, +) -> Http3OrWebTransportStream { + exchange_packets(client, server); + let mut new_stream_received = false; + let mut data_received = false; + let mut wt_stream = None; + let mut stream_closed = false; + let mut recv_data = Vec::new(); + while let Some(event) = server.next_event() { + match event { + Http3ServerEvent::WebTransport(WebTransportServerEvent::NewStream(request)) => { + assert_eq!(stream_id, request.stream_id()); + new_stream_received = true; + } + Http3ServerEvent::Data { + mut data, + fin, + stream, + } => { + recv_data.append(&mut data); + stream_closed = fin; + data_received = true; + wt_stream = Some(stream); + } + _ => {} + } + } + assert_eq!(&recv_data[..], expected_data); + assert!(data_received); + assert_eq!(new_stream, new_stream_received); + assert_eq!(stream_closed, expected_fin); + wt_stream.unwrap() +} + +#[test] +fn wt_client_stream_uni() { + const BUF_CLIENT: &[u8] = &[0; 10]; + + let (mut client, mut server) = connect(); + let wt_session = create_wt_session(&mut client, &mut server); + let wt_stream = client + .webtransport_create_stream(wt_session.stream_id(), StreamType::UniDi) + .unwrap(); + send_data_client(&mut client, &mut server, wt_stream, BUF_CLIENT); + exchange_packets(&mut client, &mut server); + receive_data_server(&mut client, &mut server, wt_stream, true, BUF_CLIENT, false); +} + +#[test] +fn wt_client_stream_bidi() { + const BUF_CLIENT: &[u8] = &[0; 10]; + const BUF_SERVER: &[u8] = &[1; 20]; + + let (mut client, mut server) = connect(); + let wt_session = create_wt_session(&mut client, &mut server); + let wt_client_stream = client + .webtransport_create_stream(wt_session.stream_id(), StreamType::BiDi) + .unwrap(); + send_data_client(&mut client, &mut server, wt_client_stream, BUF_CLIENT); + let mut wt_server_stream = receive_data_server( + &mut client, + &mut server, + wt_client_stream, + true, + BUF_CLIENT, + false, + ); + send_data_server(&mut client, &mut server, &mut wt_server_stream, BUF_SERVER); + receive_data_client(&mut client, wt_client_stream, false, BUF_SERVER, false); +} + +#[test] +fn wt_server_stream_uni() { + const BUF_SERVER: &[u8] = &[2; 30]; + + let (mut client, mut server) = connect(); + let mut wt_session = create_wt_session(&mut client, &mut server); + let mut wt_server_stream = wt_session.create_stream(StreamType::UniDi).unwrap(); + send_data_server(&mut client, &mut server, &mut wt_server_stream, BUF_SERVER); + receive_data_client( + &mut client, + wt_server_stream.stream_id(), + true, + BUF_SERVER, + false, + ); +} + +#[test] +fn wt_server_stream_bidi() { + const BUF_CLIENT: &[u8] = &[0; 10]; + const BUF_SERVER: &[u8] = &[1; 20]; + + let (mut client, mut server) = connect(); + let mut wt_session = create_wt_session(&mut client, &mut server); + let mut wt_server_stream = wt_session.create_stream(StreamType::BiDi).unwrap(); + send_data_server(&mut client, &mut server, &mut wt_server_stream, BUF_SERVER); + receive_data_client( + &mut client, + wt_server_stream.stream_id(), + true, + BUF_SERVER, + false, + ); + send_data_client( + &mut client, + &mut server, + wt_server_stream.stream_id(), + BUF_CLIENT, + ); + assert_eq!( + receive_data_server( + &mut client, + &mut server, + wt_server_stream.stream_id(), + false, + BUF_CLIENT, + false + ) + .stream_id(), + wt_server_stream.stream_id() + ); +} |