This patch does a bunch of refactoring, mostly around error types, but it also
paves the way to allow `Codec` to be used standalone.
* `Codec` (and `FramedRead` / `FramedWrite`) is broken out into a codec module.
* An h2-codec crate is created that re-exports the frame and codec modules.
* New error types are introduced in the internals:
* `RecvError` represents errors caused by trying to receive a frame.
* `SendError` represents errors caused by trying to send a frame.
* `UserError` is an enum of potential errors caused by invalid usage
by the user of the lib.
* `ProtoError` is either a `Reason` or an `io::Error`. However it doesn't
specify connection or stream level.
* `h2::Error` is an opaque error type and is the only error type exposed
by the public API (used to be `ConnectionError`).
There are misc code changes to enable this as well. The biggest is a new "sink"
API for `Codec`. It provides buffer which queues up a frame followed by flush
which writes everything that is queued. This departs from the `Sink` trait in
order to provide more accurate error values. For example, buffer can never fail
(but it will panic if `poll_ready` is not called first).
92 lines
1.9 KiB
Rust
92 lines
1.9 KiB
Rust
//! Utilities to support tests.
|
|
|
|
#![allow(unused_extern_crates)]
|
|
|
|
pub extern crate bytes;
|
|
pub extern crate h2;
|
|
pub extern crate http;
|
|
pub extern crate tokio_io;
|
|
pub extern crate futures;
|
|
pub extern crate mock_io;
|
|
pub extern crate env_logger;
|
|
|
|
pub use self::futures::{
|
|
Future,
|
|
Sink,
|
|
Stream,
|
|
};
|
|
pub use self::futures::future::poll_fn;
|
|
|
|
pub use self::http::{
|
|
request,
|
|
response,
|
|
method,
|
|
status,
|
|
Request,
|
|
Response,
|
|
HeaderMap,
|
|
};
|
|
|
|
pub use self::h2::client::{self, Client};
|
|
// pub use self::h2::server;
|
|
|
|
pub use self::bytes::{
|
|
Buf,
|
|
BufMut,
|
|
Bytes,
|
|
BytesMut,
|
|
IntoBuf,
|
|
};
|
|
|
|
pub use std::time::Duration;
|
|
|
|
use tokio_io::{AsyncRead, AsyncWrite};
|
|
|
|
pub trait MockH2 {
|
|
fn handshake(&mut self) -> &mut Self;
|
|
}
|
|
|
|
impl MockH2 for mock_io::Builder {
|
|
fn handshake(&mut self) -> &mut Self {
|
|
self.write(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
|
|
// Settings frame
|
|
.write(frames::SETTINGS)
|
|
.read(frames::SETTINGS)
|
|
.read(frames::SETTINGS_ACK)
|
|
}
|
|
}
|
|
|
|
pub trait ClientExt {
|
|
fn run<F: Future>(&mut self, f: F) -> Result<F::Item, F::Error>;
|
|
}
|
|
|
|
impl<T, B> ClientExt for Client<T, B>
|
|
where T: AsyncRead + AsyncWrite + 'static,
|
|
B: IntoBuf + 'static,
|
|
{
|
|
fn run<F: Future>(&mut self, f: F) -> Result<F::Item, F::Error> {
|
|
use futures::future::{self, Future};
|
|
use futures::future::Either::*;
|
|
|
|
let res = future::poll_fn(|| self.poll())
|
|
.select2(f).wait();
|
|
|
|
match res {
|
|
Ok(A((_, b))) => {
|
|
// Connection is done...
|
|
b.wait()
|
|
}
|
|
Ok(B((v, _))) => return Ok(v),
|
|
Err(A((e, _))) => panic!("err: {:?}", e),
|
|
Err(B((e, _))) => return Err(e),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub mod frames {
|
|
//! Some useful frames
|
|
|
|
pub const SETTINGS: &'static [u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0];
|
|
pub const SETTINGS_ACK: &'static [u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0];
|
|
}
|