diff options
Diffstat (limited to 'third_party/rust/neqo-http3/tests/send_message.rs')
-rw-r--r-- | third_party/rust/neqo-http3/tests/send_message.rs | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/third_party/rust/neqo-http3/tests/send_message.rs b/third_party/rust/neqo-http3/tests/send_message.rs new file mode 100644 index 0000000000..ef4a571dff --- /dev/null +++ b/third_party/rust/neqo-http3/tests/send_message.rs @@ -0,0 +1,329 @@ +// 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 lazy_static::lazy_static; +use neqo_common::event::Provider; +use neqo_crypto::AuthenticationStatus; +use neqo_http3::{ + Error, Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Server, + Http3ServerEvent, Priority, +}; +use test_fixture::*; + +const RESPONSE_DATA: &[u8] = &[0x61, 0x62, 0x63]; + +lazy_static! { + static ref RESPONSE_HEADER_NO_DATA: Vec<Header> = + vec![Header::new(":status", "200"), Header::new("something", "3")]; +} + +lazy_static! { + static ref RESPONSE_HEADER_103: Vec<Header> = + vec![Header::new(":status", "103"), Header::new("link", "...")]; +} + +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 receive_request(server: &mut Http3Server) -> Option<Http3OrWebTransportStream> { + while let Some(event) = server.next_event() { + if let Http3ServerEvent::Headers { + stream, + headers, + fin, + } = event + { + assert_eq!( + &headers, + &[ + Header::new(":method", "GET"), + Header::new(":scheme", "https"), + Header::new(":authority", "something.com"), + Header::new(":path", "/") + ] + ); + assert!(fin); + return Some(stream); + } + } + None +} + +fn send_trailers(request: &mut Http3OrWebTransportStream) -> Result<(), Error> { + request.send_headers(&[ + Header::new("something1", "something"), + Header::new("something2", "3"), + ]) +} + +fn send_informational_headers(request: &mut Http3OrWebTransportStream) -> Result<(), Error> { + request.send_headers(&RESPONSE_HEADER_103) +} + +fn send_headers(request: &mut Http3OrWebTransportStream) -> Result<(), Error> { + request.send_headers(&[ + Header::new(":status", "200"), + Header::new("content-length", "3"), + ]) +} + +fn process_client_events(conn: &mut Http3Client) { + let mut response_header_found = false; + let mut response_data_found = false; + while let Some(event) = conn.next_event() { + match event { + Http3ClientEvent::HeaderReady { headers, fin, .. } => { + assert!( + (headers.as_ref() + == [ + Header::new(":status", "200"), + Header::new("content-length", "3"), + ]) + || (headers.as_ref() == *RESPONSE_HEADER_103) + ); + assert!(!fin); + response_header_found = true; + } + Http3ClientEvent::DataReadable { stream_id } => { + let mut buf = [0u8; 100]; + let (amount, fin) = conn.read_data(now(), stream_id, &mut buf).unwrap(); + assert!(fin); + assert_eq!(amount, RESPONSE_DATA.len()); + assert_eq!(&buf[..RESPONSE_DATA.len()], RESPONSE_DATA); + response_data_found = true; + } + _ => {} + } + } + assert!(response_header_found); + assert!(response_data_found); +} + +fn process_client_events_no_data(conn: &mut Http3Client) { + let mut response_header_found = false; + let mut fin_received = false; + while let Some(event) = conn.next_event() { + match event { + Http3ClientEvent::HeaderReady { headers, fin, .. } => { + assert_eq!(headers.as_ref(), *RESPONSE_HEADER_NO_DATA); + fin_received = fin; + response_header_found = true; + } + Http3ClientEvent::DataReadable { stream_id } => { + let mut buf = [0u8; 100]; + let (amount, fin) = conn.read_data(now(), stream_id, &mut buf).unwrap(); + assert!(fin); + fin_received = true; + assert_eq!(amount, 0); + } + _ => {} + } + } + assert!(response_header_found); + assert!(fin_received); +} + +fn connect_send_and_receive_request() -> (Http3Client, Http3Server, Http3OrWebTransportStream) { + let mut hconn_c = default_http3_client(); + let mut hconn_s = default_http3_server(); + + exchange_packets(&mut hconn_c, &mut hconn_s); + let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded); + assert!(hconn_c.events().any(authentication_needed)); + hconn_c.authenticated(AuthenticationStatus::Ok, now()); + exchange_packets(&mut hconn_c, &mut hconn_s); + + let req = hconn_c + .fetch( + now(), + "GET", + &("https", "something.com", "/"), + &[], + Priority::default(), + ) + .unwrap(); + assert_eq!(req, 0); + hconn_c.stream_close_send(req).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + + let request = receive_request(&mut hconn_s).unwrap(); + + (hconn_c, hconn_s, request) +} + +#[test] +fn response_trailers1() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + send_trailers(&mut request).unwrap(); + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn response_trailers2() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + send_trailers(&mut request).unwrap(); + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn response_trailers3() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + send_trailers(&mut request).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn response_trailers_no_data() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + request.send_headers(&RESPONSE_HEADER_NO_DATA).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + send_trailers(&mut request).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events_no_data(&mut hconn_c); +} + +#[test] +fn multiple_response_trailers() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + send_trailers(&mut request).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + + assert_eq!(send_trailers(&mut request), Err(Error::InvalidInput)); + + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn data_after_trailer() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + send_trailers(&mut request).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + + assert_eq!(request.send_data(RESPONSE_DATA), Err(Error::InvalidInput)); + + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn trailers_after_close() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + request.stream_close_send().unwrap(); + + assert_eq!(send_trailers(&mut request), Err(Error::InvalidStreamId)); + + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn multiple_response_headers() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + request.send_headers(&RESPONSE_HEADER_NO_DATA).unwrap(); + + assert_eq!( + request.send_headers(&RESPONSE_HEADER_NO_DATA), + Err(Error::InvalidHeader) + ); + + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events_no_data(&mut hconn_c); +} + +#[test] +fn informational_after_response_headers() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + request.send_headers(&RESPONSE_HEADER_NO_DATA).unwrap(); + + assert_eq!( + send_informational_headers(&mut request), + Err(Error::InvalidHeader) + ); + + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events_no_data(&mut hconn_c); +} + +#[test] +fn data_after_informational() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_informational_headers(&mut request).unwrap(); + + assert_eq!(request.send_data(RESPONSE_DATA), Err(Error::InvalidInput)); + + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn non_trailers_headers_after_data() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + + assert_eq!( + request.send_headers(&RESPONSE_HEADER_NO_DATA), + Err(Error::InvalidHeader) + ); + + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} + +#[test] +fn data_before_headers() { + let (mut hconn_c, mut hconn_s, mut request) = connect_send_and_receive_request(); + assert_eq!(request.send_data(RESPONSE_DATA), Err(Error::InvalidInput)); + + send_headers(&mut request).unwrap(); + request.send_data(RESPONSE_DATA).unwrap(); + request.stream_close_send().unwrap(); + exchange_packets(&mut hconn_c, &mut hconn_s); + process_client_events(&mut hconn_c); +} |