Skip to content

Commit

Permalink
Use hootbin for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten committed Jan 30, 2024
1 parent 26ed596 commit c4e0b36
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 67 deletions.
70 changes: 58 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ brotli-decompressor = { version = "2.3.2", optional = true }
http-02 = { package = "http", version = "0.2", optional = true }
http = { version = "1.0", optional = true }

# This can't be in dev-dependencies due to doc tests.
hootbin = { version = "0.1.0" }

This comment has been minimized.

Copy link
@syl20bnr

syl20bnr Jan 31, 2024

@algesten This change breaks the build of crates depending on ureq. See algesten/hoot#1

This comment has been minimized.

Copy link
@algesten

algesten Jan 31, 2024

Author Owner

Yes. Thanks. I'm looking into this now.


[dev-dependencies]
serde = { version = "1", features = ["derive"] }
env_logger = "0.10"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ You can control them when including ureq as a dependency.
does nothing for `native-tls`.
* `gzip` enables requests of gzip-compressed responses and decompresses them. This is enabled by default.
* `brotli` enables requests brotli-compressed responses and decompresses them.
* `http-interop` enables conversion methods to and from `http::Response` and `http::request::Builder`.
* `http-interop` enables conversion methods to and from `http::Response` and `http::request::Builder` (v0.2).
* `http` enables conversion methods to and from `http::Response` and `http::request::Builder` (v1.0).

## Plain requests

Expand Down
6 changes: 3 additions & 3 deletions src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ pub(crate) struct AgentConfig {
/// let mut agent = ureq::agent();
///
/// agent
/// .post("http://example.com/login")
/// .post("http://example.com/post/login")
/// .call()?;
///
/// let secret = agent
/// .get("http://example.com/my-protected-page")
/// .get("http://example.com/get/my-protected-page")
/// .call()?
/// .into_string()?;
///
Expand Down Expand Up @@ -173,7 +173,7 @@ impl Agent {
/// let agent = ureq::agent();
///
/// let mut url: Url = "http://example.com/some-page".parse()?;
/// url.set_path("/robots.txt");
/// url.set_path("/get/robots.txt");
/// let resp: Response = agent
/// .request_url("GET", &url)
/// .call()?;
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
//! # fn main() -> std::result::Result<(), ureq::Error> {
//! # ureq::is_test(true);
//! // Requires the `json` feature enabled.
//! let resp: String = ureq::post("http://myapi.example.com/ingest")
//! let resp: String = ureq::post("http://myapi.example.com/post/ingest")
//! .set("X-My-Header", "Secret")
//! .send_json(ureq::json!({
//! "name": "martin",
Expand Down Expand Up @@ -527,7 +527,7 @@ pub fn request(method: &str, path: &str) -> Request {
/// let agent = ureq::agent();
///
/// let mut url: Url = "http://example.com/some-page".parse()?;
/// url.set_path("/robots.txt");
/// url.set_path("/get/robots.txt");
/// let resp: ureq::Response = ureq::request_url("GET", &url)
/// .call()?;
/// # Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub type Result<T> = std::result::Result<T, Error>;
/// ```
/// # fn main() -> Result<(), ureq::Error> {
/// # ureq::is_test(true);
/// let response = ureq::get("http://example.com/form")
/// let response = ureq::get("http://example.com/get")
/// .query("foo", "bar baz") // add ?foo=bar+baz
/// .call()?; // run the request
/// # Ok(())
Expand Down
18 changes: 9 additions & 9 deletions src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ impl Response {
/// ```
/// # fn main() -> Result<(), ureq::Error> {
/// # ureq::is_test(true);
/// let resp = ureq::get("http://example.com/").call()?;
/// assert!(matches!(resp.header("content-type"), Some("text/html; charset=ISO-8859-1")));
/// let resp = ureq::get("http://example.com/charset/iso").call()?;
/// assert_eq!(resp.header("content-type"), Some("text/html; charset=ISO-8859-1"));
/// assert_eq!("text/html", resp.content_type());
/// # Ok(())
/// # }
Expand All @@ -225,8 +225,8 @@ impl Response {
/// ```
/// # fn main() -> Result<(), ureq::Error> {
/// # ureq::is_test(true);
/// let resp = ureq::get("http://example.com/").call()?;
/// assert!(matches!(resp.header("content-type"), Some("text/html; charset=ISO-8859-1")));
/// let resp = ureq::get("http://example.com/charset/iso").call()?;
/// assert_eq!(resp.header("content-type"), Some("text/html; charset=ISO-8859-1"));
/// assert_eq!("ISO-8859-1", resp.charset());
/// # Ok(())
/// # }
Expand Down Expand Up @@ -500,15 +500,15 @@ impl Response {
///
/// #[derive(Deserialize)]
/// struct Message {
/// hello: String,
/// text: String,
/// }
///
/// let message: Message =
/// ureq::get("http://example.com/hello_world.json")
/// ureq::get("http://example.com/get/hello_world.json")
/// .call()?
/// .into_json()?;
///
/// assert_eq!(message.hello, "world");
/// assert_eq!(message.text, "Ok");
/// # Ok(())
/// # }
/// ```
Expand All @@ -520,11 +520,11 @@ impl Response {
/// ```
/// # fn main() -> Result<(), ureq::Error> {
/// # ureq::is_test(true);
/// let json: serde_json::Value = ureq::get("http://example.com/hello_world.json")
/// let json: serde_json::Value = ureq::get("http://example.com/get/hello_world.json")
/// .call()?
/// .into_json()?;
///
/// assert_eq!(json["hello"], "world");
/// assert_eq!(json["text"], "Ok");
/// # Ok(())
/// # }
/// ```
Expand Down
61 changes: 22 additions & 39 deletions src/testserver.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::io;
use std::net::ToSocketAddrs;
use std::net::{SocketAddr, TcpListener, TcpStream};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use std::{
io::{self, BufRead, BufReader, Write},
net::ToSocketAddrs,
};

use crate::{Agent, AgentBuilder};

Expand All @@ -16,41 +14,23 @@ pub(crate) fn test_agent() -> Agent {
#[cfg(test)]
let _ = env_logger::try_init();

let testserver = TestServer::new(|mut stream: TcpStream| -> io::Result<()> {
let headers = read_request(&stream);
if headers.0.is_empty() {
// no headers probably means it's the initial request to check test server is up.
} else if headers.path() == "/status/200" {
stream.write_all(b"HTTP/1.1 200 OK\r\n\r\n")?;
} else if headers.path() == "/status/500" {
stream.write_all(b"HTTP/1.1 500 Server Internal Error\r\n\r\n")?;
} else if headers.path() == "/bytes/100" {
stream.write_all(b"HTTP/1.1 200 OK\r\n")?;
stream.write_all(b"Content-Length: 100\r\n")?;
stream.write_all(b"\r\n")?;
stream.write_all(&[0; 100])?;
} else if headers.path() == "/hello_world.json" {
stream.write_all(b"HTTP/1.1 200 OK\r\n")?;
stream.write_all(b"\r\n")?;
stream.write_all(br#"{"hello": "world"}"#)?;
} else if headers.path() == "/status/301" {
stream.write_all(b"HTTP/1.1 301 Found\r\n")?;
stream.write_all(b"Location: /status/200\r\n")?;
stream.write_all(b"\r\n")?;
} else if headers.path() == "/status/307" {
stream.write_all(b"HTTP/1.1 307 Found\r\n")?;
stream.write_all(b"Location: /status/200\r\n")?;
stream.write_all(b"\r\n")?;
} else {
stream.write_all(b"HTTP/1.1 200 OK\r\n")?;
stream.write_all(b"Transfer-Encoding: chunked\r\n")?;
stream.write_all(b"Content-Type: text/html; charset=ISO-8859-1\r\n")?;
stream.write_all(b"\r\n")?;
stream.write_all(b"7\r\n")?;
stream.write_all(b"success\r\n")?;
stream.write_all(b"0\r\n")?;
stream.write_all(b"\r\n")?;
}
let testserver = TestServer::new(|stream: TcpStream| -> io::Result<()> {
use hootbin::serve_single;
let o = stream.try_clone().expect("TcpStream to be clonable");
let i = stream;
match serve_single(i, o, "https://hootbin.test/") {
Ok(()) => {}
Err(e) => {
if let hootbin::Error::Io(ioe) = &e {
if ioe.kind() == io::ErrorKind::UnexpectedEof {
// accept this. the pre-connect below is always erroring.
return Ok(());
}
}

println!("TestServer error: {:?}", e);
}
};
Ok(())
});
// Slightly tricky thing here: we want to make sure the TestServer lives
Expand Down Expand Up @@ -97,7 +77,10 @@ impl TestHeaders {

// Read a stream until reaching a blank line, in order to consume
// request headers.
#[cfg(test)]
pub fn read_request(stream: &TcpStream) -> TestHeaders {
use std::io::{BufRead, BufReader};

let mut results = vec![];
for line in BufReader::new(stream).lines() {
match line {
Expand Down

0 comments on commit c4e0b36

Please sign in to comment.