add test for client sending over max concurrent limit (#105)
This commit is contained in:
		| @@ -74,6 +74,10 @@ impl Settings { | |||||||
|         self.max_concurrent_streams |         self.max_concurrent_streams | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn set_max_concurrent_streams(&mut self, max: Option<u32>) { | ||||||
|  |         self.max_concurrent_streams = max; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn max_frame_size(&self) -> Option<u32> { |     pub fn max_frame_size(&self) -> Option<u32> { | ||||||
|         self.max_frame_size |         self.max_frame_size | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -111,6 +111,64 @@ fn request_stream_id_overflows() { | |||||||
|     h2.join(srv).wait().expect("wait"); |     h2.join(srv).wait().expect("wait"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn request_over_max_concurrent_streams_errors() { | ||||||
|  |     let _ = ::env_logger::init(); | ||||||
|  |     let (io, srv) = mock::new(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     let srv = srv.assert_client_handshake_with_settings( | ||||||
|  |             frames::settings() | ||||||
|  |                 // super tiny server | ||||||
|  |                 .max_concurrent_streams(1) | ||||||
|  |         ) | ||||||
|  |         .unwrap() | ||||||
|  |         .recv_settings() | ||||||
|  |         .recv_frame( | ||||||
|  |             frames::headers(1) | ||||||
|  |                 .request("POST", "https://example.com/") | ||||||
|  |         ) | ||||||
|  |         .send_frame(frames::headers(1).response(200)) | ||||||
|  |         .close(); | ||||||
|  |  | ||||||
|  |     let h2 = Client::handshake(io) | ||||||
|  |         .expect("handshake") | ||||||
|  |         .and_then(|mut h2| { | ||||||
|  |             let request = Request::builder() | ||||||
|  |                 .method(Method::POST) | ||||||
|  |                 .uri("https://example.com/") | ||||||
|  |                 .body(()) | ||||||
|  |                 .unwrap(); | ||||||
|  |  | ||||||
|  |             // first request is allowed | ||||||
|  |             let req = h2.send_request(request, false) | ||||||
|  |                 .unwrap() | ||||||
|  |                 .unwrap(); | ||||||
|  |  | ||||||
|  |             // drive the connection some so we can receive the server settings | ||||||
|  |             h2.drive(req) | ||||||
|  |         }) | ||||||
|  |         .and_then(|(mut h2, _)| { | ||||||
|  |  | ||||||
|  |             let request = Request::builder() | ||||||
|  |                 .method(Method::GET) | ||||||
|  |                 .uri("https://example.com/") | ||||||
|  |                 .body(()) | ||||||
|  |                 .unwrap(); | ||||||
|  |  | ||||||
|  |             // second stream is over max concurrent | ||||||
|  |             assert!(h2.poll_ready().expect("poll_ready").is_not_ready()); | ||||||
|  |  | ||||||
|  |             let err = h2.send_request(request, true).unwrap_err(); | ||||||
|  |             assert_eq!(err.to_string(), "user error: rejected"); | ||||||
|  |  | ||||||
|  |             h2.expect("h2") | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     h2.join(srv).wait().expect("wait"); | ||||||
|  | } | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| #[ignore] | #[ignore] | ||||||
| fn request_without_scheme() {} | fn request_without_scheme() {} | ||||||
|   | |||||||
| @@ -58,6 +58,10 @@ pub fn reset<T>(id: T) -> Mock<frame::Reset> | |||||||
|     Mock(frame::Reset::new(id.into(), frame::Reason::NoError)) |     Mock(frame::Reset::new(id.into(), frame::Reason::NoError)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | pub fn settings() -> Mock<frame::Settings> { | ||||||
|  |     Mock(frame::Settings::default()) | ||||||
|  | } | ||||||
|  |  | ||||||
| // === Generic helpers of all frame types | // === Generic helpers of all frame types | ||||||
|  |  | ||||||
| pub struct Mock<T>(T); | pub struct Mock<T>(T); | ||||||
| @@ -230,6 +234,27 @@ impl From<Mock<frame::Reset>> for SendFrame { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ==== Settings helpers | ||||||
|  |  | ||||||
|  | impl Mock<frame::Settings> { | ||||||
|  |     pub fn max_concurrent_streams(mut self, max: u32) -> Self { | ||||||
|  |         self.0.set_max_concurrent_streams(Some(max)); | ||||||
|  |         self | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl From<Mock<frame::Settings>> for frame::Settings { | ||||||
|  |     fn from(src: Mock<frame::Settings>) -> Self { | ||||||
|  |         src.0 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl From<Mock<frame::Settings>> for SendFrame { | ||||||
|  |     fn from(src: Mock<frame::Settings>) -> Self { | ||||||
|  |         Frame::Settings(src.0) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| // ==== "trait alias" for types that are HttpTryFrom and have Debug Errors ==== | // ==== "trait alias" for types that are HttpTryFrom and have Debug Errors ==== | ||||||
|  |  | ||||||
| pub trait HttpTryInto<T> { | pub trait HttpTryInto<T> { | ||||||
|   | |||||||
| @@ -113,9 +113,11 @@ impl Handle { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Perform the H2 handshake |     /// Perform the H2 handshake | ||||||
|     pub fn assert_client_handshake_with_settings(mut self, settings: frame::Settings) |     pub fn assert_client_handshake_with_settings<T>(mut self, settings: T) | ||||||
|         -> Box<Future<Item = (frame::Settings, Self), Error = h2::Error>> |         -> Box<Future<Item = (frame::Settings, Self), Error = h2::Error>> | ||||||
|  |     where T: Into<frame::Settings>, | ||||||
|     { |     { | ||||||
|  |         let settings = settings.into(); | ||||||
|         // Send a settings frame |         // Send a settings frame | ||||||
|         self.send(settings.into()).unwrap(); |         self.send(settings.into()).unwrap(); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user