summaryrefslogtreecommitdiffstats
path: root/vendor/curl/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/curl/tests
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/curl/tests')
-rw-r--r--vendor/curl/tests/atexit.rs17
-rw-r--r--vendor/curl/tests/easy.rs972
-rw-r--r--vendor/curl/tests/formdata1
-rw-r--r--vendor/curl/tests/multi.rs297
-rw-r--r--vendor/curl/tests/post.rs118
-rw-r--r--vendor/curl/tests/protocols.rs19
-rw-r--r--vendor/curl/tests/server/mod.rs223
7 files changed, 1647 insertions, 0 deletions
diff --git a/vendor/curl/tests/atexit.rs b/vendor/curl/tests/atexit.rs
new file mode 100644
index 000000000..0872a4e97
--- /dev/null
+++ b/vendor/curl/tests/atexit.rs
@@ -0,0 +1,17 @@
+use curl::easy::Easy;
+
+pub extern "C" fn hook() {
+ let mut easy = Easy::new();
+ easy.url("google.com").unwrap();
+ easy.write_function(|data| Ok(data.len())).unwrap();
+ easy.perform().unwrap();
+}
+
+fn main() {
+ curl::init();
+ hook();
+ unsafe {
+ libc::atexit(hook);
+ }
+ println!("Finishing...")
+}
diff --git a/vendor/curl/tests/easy.rs b/vendor/curl/tests/easy.rs
new file mode 100644
index 000000000..942922933
--- /dev/null
+++ b/vendor/curl/tests/easy.rs
@@ -0,0 +1,972 @@
+use std::cell::{Cell, RefCell};
+use std::io::Read;
+use std::rc::Rc;
+use std::str;
+use std::time::Duration;
+
+macro_rules! t {
+ ($e:expr) => {
+ match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
+ }
+ };
+}
+
+use curl::easy::{Easy, List, ReadError, Transfer, WriteError};
+use curl::Version;
+
+use crate::server::Server;
+mod server;
+
+fn handle() -> Easy {
+ let mut e = Easy::new();
+ t!(e.timeout(Duration::new(20, 0)));
+ e
+}
+
+fn sink(data: &[u8]) -> Result<usize, WriteError> {
+ Ok(data.len())
+}
+
+#[test]
+fn get_smoke() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+ t!(handle.perform());
+}
+
+#[test]
+fn download_zero_size() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+ t!(handle.perform());
+ assert_eq!(handle.download_size().unwrap(), 0_f64);
+}
+
+#[test]
+fn download_nonzero_size() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\nHello!");
+
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+ t!(handle.perform());
+ assert_eq!(handle.download_size().unwrap(), 6_f64);
+}
+
+#[test]
+fn upload_zero_size() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+ t!(handle.perform());
+ assert_eq!(handle.upload_size().unwrap(), 0_f64);
+}
+
+#[test]
+fn upload_nonzero_size() {
+ let s = Server::new();
+ s.receive(
+ "\
+ PUT / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 5\r\n\
+ \r\n\
+ data\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut data = "data\n".as_bytes();
+ let mut list = List::new();
+ t!(list.append("Expect:"));
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.put(true));
+ t!(h.in_filesize(5));
+ t!(h.upload(true));
+ t!(h.http_headers(list));
+ {
+ let mut h = h.transfer();
+ t!(h.read_function(|buf| Ok(data.read(buf).unwrap())));
+ t!(h.perform());
+ }
+
+ assert_eq!(h.upload_size().unwrap(), 5_f64);
+}
+
+#[test]
+fn get_path() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET /foo HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ t!(handle.url(&s.url("/foo")));
+ t!(handle.perform());
+}
+
+#[test]
+fn write_callback() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\nhello!");
+
+ let mut all = Vec::<u8>::new();
+ {
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+ let mut handle = handle.transfer();
+ t!(handle.write_function(|data| {
+ all.extend(data);
+ Ok(data.len())
+ }));
+ t!(handle.perform());
+ }
+ assert_eq!(all, b"hello!");
+}
+
+#[test]
+fn resolve() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: example.com:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut list = List::new();
+ t!(list.append(&format!("example.com:{}:127.0.0.1", s.addr().port())));
+ let mut handle = handle();
+ t!(handle.url(&format!("http://example.com:{}/", s.addr().port())));
+ t!(handle.resolve(list));
+ t!(handle.perform());
+}
+
+#[test]
+fn progress() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET /foo HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\nHello!");
+
+ let mut hits = 0;
+ let mut dl = 0.0;
+ {
+ let mut handle = handle();
+ t!(handle.url(&s.url("/foo")));
+ t!(handle.progress(true));
+ t!(handle.write_function(sink));
+
+ let mut handle = handle.transfer();
+ t!(handle.progress_function(|_, a, _, _| {
+ hits += 1;
+ dl = a;
+ true
+ }));
+ t!(handle.perform());
+ }
+ assert!(hits > 0);
+ assert_eq!(dl, 6.0);
+}
+
+#[test]
+fn headers() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+HTTP/1.1 200 OK\r\n\
+Foo: bar\r\n\
+Bar: baz\r\n\
+\r\n
+Hello!",
+ );
+
+ let mut headers = Vec::new();
+ {
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+
+ let mut handle = handle.transfer();
+ t!(handle.header_function(|h| {
+ headers.push(str::from_utf8(h).unwrap().to_string());
+ true
+ }));
+ t!(handle.write_function(sink));
+ t!(handle.perform());
+ }
+ assert_eq!(
+ headers,
+ vec![
+ "HTTP/1.1 200 OK\r\n".to_string(),
+ "Foo: bar\r\n".to_string(),
+ "Bar: baz\r\n".to_string(),
+ "\r\n".to_string(),
+ ]
+ );
+}
+
+#[test]
+fn fail_on_error() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 401 Not so good\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.fail_on_error(true));
+ assert!(h.perform().is_err());
+
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 401 Not so good\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.fail_on_error(false));
+ t!(h.perform());
+}
+
+#[test]
+fn port() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: localhost:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url("http://localhost/"));
+ t!(h.port(s.addr().port()));
+ t!(h.perform());
+}
+
+#[test]
+fn proxy() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET http://example.com/ HTTP/1.1\r\n\
+ Host: example.com\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url("http://example.com/"));
+ t!(h.proxy(&s.url("/")));
+ t!(h.perform());
+}
+
+#[test]
+#[ignore] // fails on newer curl versions? seems benign
+fn noproxy() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.proxy(&s.url("/")));
+ t!(h.noproxy("127.0.0.1"));
+ t!(h.perform());
+}
+
+#[test]
+fn misc() {
+ let mut h = handle();
+ t!(h.tcp_nodelay(true));
+ // t!(h.tcp_keepalive(true));
+ // t!(h.tcp_keepidle(Duration::new(3, 0)));
+ // t!(h.tcp_keepintvl(Duration::new(3, 0)));
+ t!(h.buffer_size(10));
+
+ if Version::get().version_num() >= 0x073e00 {
+ // only available on curl 7.62.0 or later:
+ t!(h.upload_buffer_size(10));
+ }
+
+ t!(h.dns_cache_timeout(Duration::new(1, 0)));
+}
+
+#[test]
+fn dns_servers() {
+ let mut h = handle();
+ // Tests are not using a libcurl with c-ares, so this
+ // always fails. Test anyway to make sure it returns
+ // an error instead of panicing.
+ assert!(h.dns_servers("").is_err());
+ assert!(h.dns_servers("nonsense").is_err());
+ assert!(h.dns_servers("8.8.8.8,8.8.4.4").is_err());
+}
+
+#[test]
+fn userpass() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Authorization: Basic YmFyOg==\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.username("foo"));
+ t!(h.username("bar"));
+ t!(h.perform());
+}
+
+#[test]
+fn accept_encoding() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Accept-Encoding: gzip\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.accept_encoding("gzip"));
+ t!(h.perform());
+}
+
+#[test]
+fn follow_location() {
+ let s1 = Server::new();
+ let s2 = Server::new();
+ s1.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s1.send(&format!(
+ "\
+ HTTP/1.1 301 Moved Permanently\r\n\
+ Location: http://{}/foo\r\n\
+ \r\n",
+ s2.addr()
+ ));
+
+ s2.receive(
+ "\
+ GET /foo HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s2.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s1.url("/")));
+ t!(h.follow_location(true));
+ t!(h.perform());
+}
+
+#[test]
+fn put() {
+ let s = Server::new();
+ s.receive(
+ "\
+ PUT / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 5\r\n\
+ \r\n\
+ data\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut data = "data\n".as_bytes();
+ let mut list = List::new();
+ t!(list.append("Expect:"));
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.put(true));
+ t!(h.in_filesize(5));
+ t!(h.upload(true));
+ t!(h.http_headers(list));
+ let mut h = h.transfer();
+ t!(h.read_function(|buf| Ok(data.read(buf).unwrap())));
+ t!(h.perform());
+}
+
+#[test]
+fn post1() {
+ let s = Server::new();
+ s.receive(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 5\r\n\
+ Content-Type: application/x-www-form-urlencoded\r\n\
+ \r\n\
+ data\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.post(true));
+ t!(h.post_fields_copy(b"data\n"));
+ t!(h.perform());
+}
+
+#[test]
+fn post2() {
+ let s = Server::new();
+ s.receive(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 5\r\n\
+ Content-Type: application/x-www-form-urlencoded\r\n\
+ \r\n\
+ data\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.post(true));
+ t!(h.post_fields_copy(b"data\n"));
+ t!(h.write_function(sink));
+ t!(h.perform());
+}
+
+#[test]
+fn post3() {
+ let s = Server::new();
+ s.receive(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 5\r\n\
+ Content-Type: application/x-www-form-urlencoded\r\n\
+ \r\n\
+ data\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut data = "data\n".as_bytes();
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.post(true));
+ t!(h.post_field_size(5));
+ let mut h = h.transfer();
+ t!(h.read_function(|buf| Ok(data.read(buf).unwrap())));
+ t!(h.perform());
+}
+
+#[test]
+fn referer() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Referer: foo\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.referer("foo"));
+ t!(h.perform());
+}
+
+#[test]
+fn useragent() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ User-Agent: foo\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.useragent("foo"));
+ t!(h.perform());
+}
+
+#[test]
+fn custom_headers() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Foo: bar\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut custom = List::new();
+ t!(custom.append("Foo: bar"));
+ t!(custom.append("Accept:"));
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.http_headers(custom));
+ t!(h.perform());
+}
+
+#[test]
+fn cookie() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Cookie: foo\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.cookie("foo"));
+ t!(h.perform());
+}
+
+#[test]
+fn url_encoding() {
+ let mut h = handle();
+ assert_eq!(h.url_encode(b"foo"), "foo");
+ assert_eq!(h.url_encode(b"foo bar"), "foo%20bar");
+ assert_eq!(h.url_encode(b"foo bar\xff"), "foo%20bar%FF");
+ assert_eq!(h.url_encode(b""), "");
+ assert_eq!(h.url_decode("foo"), b"foo");
+ assert_eq!(h.url_decode("foo%20bar"), b"foo bar");
+ assert_eq!(h.url_decode("foo%2"), b"foo%2");
+ assert_eq!(h.url_decode("foo%xx"), b"foo%xx");
+ assert_eq!(h.url_decode("foo%ff"), b"foo\xff");
+ assert_eq!(h.url_decode(""), b"");
+}
+
+#[test]
+fn getters() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.cookie_file("/dev/null"));
+ t!(h.perform());
+ assert_eq!(t!(h.response_code()), 200);
+ assert_eq!(t!(h.redirect_count()), 0);
+ assert_eq!(t!(h.redirect_url()), None);
+ assert_eq!(t!(h.content_type()), None);
+
+ let addr = format!("http://{}/", s.addr());
+ assert_eq!(t!(h.effective_url()), Some(&addr[..]));
+
+ // TODO: test this
+ // let cookies = t!(h.cookies()).iter()
+ // .map(|s| s.to_vec())
+ // .collect::<Vec<_>>();
+ // assert_eq!(cookies.len(), 1);
+}
+
+#[test]
+#[should_panic]
+fn panic_in_callback() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.header_function(|_| panic!()));
+ t!(h.perform());
+}
+
+#[test]
+fn abort_read() {
+ let s = Server::new();
+ s.receive(
+ "\
+ PUT / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 2\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.read_function(|_| Err(ReadError::Abort)));
+ t!(h.put(true));
+ t!(h.in_filesize(2));
+ let mut list = List::new();
+ t!(list.append("Expect:"));
+ t!(h.http_headers(list));
+ let err = h.perform().unwrap_err();
+ assert!(err.is_aborted_by_callback());
+}
+
+#[test]
+fn pause_write_then_resume() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+HTTP/1.1 200 OK\r\n\
+\r\n
+a\n
+b",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.progress(true));
+
+ struct State<'a, 'b> {
+ paused: Cell<bool>,
+ unpaused: Cell<bool>,
+ transfer: RefCell<Transfer<'a, 'b>>,
+ }
+
+ let h = Rc::new(State {
+ paused: Cell::new(false),
+ unpaused: Cell::new(false),
+ transfer: RefCell::new(h.transfer()),
+ });
+
+ let h2 = h.clone();
+ t!(h.transfer
+ .borrow_mut()
+ .write_function(move |data| if h2.unpaused.get() {
+ h2.unpaused.set(false);
+ Ok(data.len())
+ } else {
+ h2.paused.set(true);
+ Err(WriteError::Pause)
+ }));
+ let h2 = h.clone();
+ t!(h.transfer
+ .borrow_mut()
+ .progress_function(move |_, _, _, _| {
+ if h2.paused.get() {
+ h2.paused.set(false);
+ h2.unpaused.set(true);
+ t!(h2.transfer.borrow().unpause_write());
+ }
+ true
+ }));
+ t!(h.transfer.borrow().perform());
+}
+
+#[test]
+fn perform_in_perform_is_bad() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+HTTP/1.1 200 OK\r\n\
+\r\n
+a\n
+b",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/")));
+ t!(h.progress(true));
+
+ let h = Rc::new(RefCell::new(h.transfer()));
+
+ let h2 = h.clone();
+ t!(h.borrow_mut().write_function(move |data| {
+ assert!(h2.borrow().perform().is_err());
+ Ok(data.len())
+ }));
+ t!(h.borrow().perform());
+}
+
+#[cfg(not(windows))]
+#[test]
+fn check_unix_socket() {
+ let s = Server::new_unix();
+ s.receive(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: localhost\r\n\
+ Accept: */*\r\n\
+ Content-Length: 5\r\n\
+ Content-Type: application/x-www-form-urlencoded\r\n\
+ \r\n\
+ data\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.unix_socket(s.path()));
+ t!(h.url(&s.url("/")));
+ t!(h.post(true));
+ t!(h.post_fields_copy(b"data\n"));
+ t!(h.perform());
+}
+
+#[cfg(feature = "upkeep_7_62_0")]
+#[test]
+fn test_upkeep() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ t!(handle.url(&s.url("/")));
+ t!(handle.perform());
+
+ // Ensure that upkeep can be called on the handle without problem.
+ t!(handle.upkeep());
+}
+
+#[test]
+fn path_as_is() {
+ let s = Server::new();
+ s.receive(
+ "\
+ GET /test/../ HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut h = handle();
+ t!(h.url(&s.url("/test/../")));
+ t!(h.path_as_is(true));
+ t!(h.perform());
+
+ let addr = format!("http://{}/test/../", s.addr());
+ assert_eq!(t!(h.response_code()), 200);
+ assert_eq!(t!(h.effective_url()), Some(&addr[..]));
+}
diff --git a/vendor/curl/tests/formdata b/vendor/curl/tests/formdata
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/vendor/curl/tests/formdata
@@ -0,0 +1 @@
+hello
diff --git a/vendor/curl/tests/multi.rs b/vendor/curl/tests/multi.rs
new file mode 100644
index 000000000..0c5e70150
--- /dev/null
+++ b/vendor/curl/tests/multi.rs
@@ -0,0 +1,297 @@
+#![cfg(unix)]
+
+use std::collections::HashMap;
+use std::io::{Cursor, Read};
+use std::time::Duration;
+
+use curl::easy::{Easy, List};
+use curl::multi::Multi;
+
+macro_rules! t {
+ ($e:expr) => {
+ match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
+ }
+ };
+}
+
+use crate::server::Server;
+mod server;
+
+#[test]
+fn smoke() {
+ let m = Multi::new();
+ let mut e = Easy::new();
+
+ let s = Server::new();
+ s.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ t!(e.url(&s.url("/")));
+ let _e = t!(m.add(e));
+ while t!(m.perform()) > 0 {
+ t!(m.wait(&mut [], Duration::from_secs(1)));
+ }
+}
+
+#[test]
+fn smoke2() {
+ let m = Multi::new();
+
+ let s1 = Server::new();
+ s1.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s1.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let s2 = Server::new();
+ s2.receive(
+ "\
+ GET / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ \r\n",
+ );
+ s2.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut e1 = Easy::new();
+ t!(e1.url(&s1.url("/")));
+ let _e1 = t!(m.add(e1));
+ let mut e2 = Easy::new();
+ t!(e2.url(&s2.url("/")));
+ let _e2 = t!(m.add(e2));
+
+ while t!(m.perform()) > 0 {
+ t!(m.wait(&mut [], Duration::from_secs(1)));
+ }
+
+ let mut done = 0;
+ m.messages(|msg| {
+ msg.result().unwrap().unwrap();
+ done += 1;
+ });
+ assert_eq!(done, 2);
+}
+
+#[test]
+fn upload_lots() {
+ use curl::multi::{Events, Socket, SocketEvents};
+
+ #[derive(Debug)]
+ enum Message {
+ Timeout(Option<Duration>),
+ Wait(Socket, SocketEvents, usize),
+ }
+
+ let mut m = Multi::new();
+ let poll = t!(mio::Poll::new());
+ let (tx, rx) = mio_extras::channel::channel();
+ let tx2 = tx.clone();
+ t!(m.socket_function(move |socket, events, token| {
+ t!(tx2.send(Message::Wait(socket, events, token)));
+ }));
+ t!(m.timer_function(move |dur| {
+ t!(tx.send(Message::Timeout(dur)));
+ true
+ }));
+
+ let s = Server::new();
+ s.receive(&format!(
+ "\
+ PUT / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 131072\r\n\
+ \r\n\
+ {}\n",
+ vec!["a"; 128 * 1024 - 1].join("")
+ ));
+ s.send(
+ "\
+ HTTP/1.1 200 OK\r\n\
+ \r\n",
+ );
+
+ let mut data = vec![b'a'; 128 * 1024 - 1];
+ data.push(b'\n');
+ let mut data = Cursor::new(data);
+ let mut list = List::new();
+ t!(list.append("Expect:"));
+ let mut h = Easy::new();
+ t!(h.url(&s.url("/")));
+ t!(h.put(true));
+ t!(h.read_function(move |buf| Ok(data.read(buf).unwrap())));
+ t!(h.in_filesize(128 * 1024));
+ t!(h.upload(true));
+ t!(h.http_headers(list));
+
+ t!(poll.register(&rx, mio::Token(0), mio::Ready::all(), mio::PollOpt::level()));
+
+ let e = t!(m.add(h));
+
+ assert!(t!(m.perform()) > 0);
+ let mut next_token = 1;
+ let mut token_map = HashMap::new();
+ let mut cur_timeout = None;
+ let mut events = mio::Events::with_capacity(128);
+ let mut running = true;
+
+ while running {
+ let n = t!(poll.poll(&mut events, cur_timeout));
+
+ if n == 0 && t!(m.timeout()) == 0 {
+ running = false;
+ }
+
+ for event in events.iter() {
+ while event.token() == mio::Token(0) {
+ match rx.try_recv() {
+ Ok(Message::Timeout(dur)) => cur_timeout = dur,
+ Ok(Message::Wait(socket, events, token)) => {
+ let evented = mio::unix::EventedFd(&socket);
+ if events.remove() {
+ token_map.remove(&token).unwrap();
+ } else {
+ let mut e = mio::Ready::empty();
+ if events.input() {
+ e |= mio::Ready::readable();
+ }
+ if events.output() {
+ e |= mio::Ready::writable();
+ }
+ if token == 0 {
+ let token = next_token;
+ next_token += 1;
+ t!(m.assign(socket, token));
+ token_map.insert(token, socket);
+ t!(poll.register(
+ &evented,
+ mio::Token(token),
+ e,
+ mio::PollOpt::level()
+ ));
+ } else {
+ t!(poll.reregister(
+ &evented,
+ mio::Token(token),
+ e,
+ mio::PollOpt::level()
+ ));
+ }
+ }
+ }
+ Err(_) => break,
+ }
+ }
+
+ if event.token() == mio::Token(0) {
+ continue;
+ }
+
+ let token = event.token();
+ let socket = token_map[&token.into()];
+ let mut e = Events::new();
+ if event.readiness().is_readable() {
+ e.input(true);
+ }
+ if event.readiness().is_writable() {
+ e.output(true);
+ }
+ if mio::unix::UnixReady::from(event.readiness()).is_error() {
+ e.error(true);
+ }
+ let remaining = t!(m.action(socket, &e));
+ if remaining == 0 {
+ running = false;
+ }
+ }
+ }
+
+ let mut done = 0;
+ m.messages(|m| {
+ m.result().unwrap().unwrap();
+ done += 1;
+ });
+ assert_eq!(done, 1);
+
+ let mut e = t!(m.remove(e));
+ assert_eq!(t!(e.response_code()), 200);
+}
+
+// Tests passing raw file descriptors to Multi::wait. The test is limited to Linux only as the
+// semantics of the underlying poll(2) system call used by curl apparently differ on other
+// platforms, making the test fail.
+#[cfg(target_os = "linux")]
+#[test]
+fn waitfds() {
+ use curl::multi::WaitFd;
+ use std::fs::File;
+ use std::os::unix::io::AsRawFd;
+
+ let filenames = ["/dev/null", "/dev/zero", "/dev/urandom"];
+ let files: Vec<File> = filenames
+ .iter()
+ .map(|filename| File::open(filename).unwrap())
+ .collect();
+ let mut waitfds: Vec<WaitFd> = files
+ .iter()
+ .map(|f| {
+ let mut waitfd = WaitFd::new();
+ waitfd.set_fd(f.as_raw_fd());
+ waitfd.poll_on_read(true);
+ waitfd
+ })
+ .collect();
+
+ let m = Multi::new();
+ let events = t!(m.wait(&mut waitfds, Duration::from_secs(1)));
+ assert_eq!(events, 3);
+ for waitfd in waitfds {
+ assert!(waitfd.received_read());
+ }
+}
+
+// Tests passing raw file descriptors to Multi::wait. The test is limited to Linux only as the
+// semantics of the underlying poll(2) system call used by curl apparently differ on other
+// platforms, making the test fail.
+#[cfg(feature = "poll_7_68_0")]
+#[cfg(target_os = "linux")]
+#[test]
+fn pollfds() {
+ use curl::multi::WaitFd;
+ use std::fs::File;
+ use std::os::unix::io::AsRawFd;
+
+ let filenames = ["/dev/null", "/dev/zero", "/dev/urandom"];
+ let files: Vec<File> = filenames
+ .iter()
+ .map(|filename| File::open(filename).unwrap())
+ .collect();
+ let mut waitfds: Vec<WaitFd> = files
+ .iter()
+ .map(|f| {
+ let mut waitfd = WaitFd::new();
+ waitfd.set_fd(f.as_raw_fd());
+ waitfd.poll_on_read(true);
+ waitfd
+ })
+ .collect();
+
+ let m = Multi::new();
+ let events = t!(m.poll(&mut waitfds, Duration::from_secs(1)));
+ assert_eq!(events, 3);
+ for waitfd in waitfds {
+ assert!(waitfd.received_read());
+ }
+}
diff --git a/vendor/curl/tests/post.rs b/vendor/curl/tests/post.rs
new file mode 100644
index 000000000..15e2df7d3
--- /dev/null
+++ b/vendor/curl/tests/post.rs
@@ -0,0 +1,118 @@
+use std::time::Duration;
+
+macro_rules! t {
+ ($e:expr) => {
+ match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
+ }
+ };
+}
+
+use curl::easy::{Easy, Form, List};
+
+use crate::server::Server;
+mod server;
+
+fn handle() -> Easy {
+ let mut e = Easy::new();
+ t!(e.timeout(Duration::new(20, 0)));
+ let mut list = List::new();
+ t!(list.append("Expect:"));
+ t!(e.http_headers(list));
+ e
+}
+
+#[test]
+fn custom() {
+ let s = Server::new();
+ s.receive(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 142\r\n\
+ Content-Type: multipart/form-data; boundary=--[..]\r\n\
+ \r\n\
+ --[..]\r\n\
+ Content-Disposition: form-data; name=\"foo\"\r\n\
+ \r\n\
+ 1234\r\n\
+ --[..]\r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ let mut form = Form::new();
+ t!(form.part("foo").contents(b"1234").add());
+ t!(handle.url(&s.url("/")));
+ t!(handle.httppost(form));
+ t!(handle.perform());
+}
+
+#[test]
+fn buffer() {
+ let s = Server::new();
+ s.receive(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: 181\r\n\
+ Content-Type: multipart/form-data; boundary=--[..]\r\n\
+ \r\n\
+ --[..]\r\n\
+ Content-Disposition: form-data; name=\"foo\"; filename=\"bar\"\r\n\
+ Content-Type: foo/bar\r\n\
+ \r\n\
+ 1234\r\n\
+ --[..]\r\n",
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ let mut form = Form::new();
+ t!(form
+ .part("foo")
+ .buffer("bar", b"1234".to_vec())
+ .content_type("foo/bar")
+ .add());
+ t!(handle.url(&s.url("/")));
+ t!(handle.httppost(form));
+ t!(handle.perform());
+}
+
+#[test]
+fn file() {
+ let s = Server::new();
+ let formdata = include_str!("formdata");
+ s.receive(
+ format!(
+ "\
+ POST / HTTP/1.1\r\n\
+ Host: 127.0.0.1:$PORT\r\n\
+ Accept: */*\r\n\
+ Content-Length: {}\r\n\
+ Content-Type: multipart/form-data; boundary=--[..]\r\n\
+ \r\n\
+ --[..]\r\n\
+ Content-Disposition: form-data; name=\"foo\"; filename=\"formdata\"\r\n\
+ Content-Type: application/octet-stream\r\n\
+ \r\n\
+ {}\
+ \r\n\
+ --[..]\r\n",
+ 199 + formdata.len(),
+ formdata
+ )
+ .as_str(),
+ );
+ s.send("HTTP/1.1 200 OK\r\n\r\n");
+
+ let mut handle = handle();
+ let mut form = Form::new();
+ t!(form.part("foo").file("tests/formdata").add());
+ t!(handle.url(&s.url("/")));
+ t!(handle.httppost(form));
+ t!(handle.perform());
+}
diff --git a/vendor/curl/tests/protocols.rs b/vendor/curl/tests/protocols.rs
new file mode 100644
index 000000000..7215fe972
--- /dev/null
+++ b/vendor/curl/tests/protocols.rs
@@ -0,0 +1,19 @@
+#[cfg(all(feature = "static-curl", not(feature = "protocol-ftp")))]
+#[test]
+fn static_with_ftp_disabled() {
+ assert!(curl::Version::get()
+ .protocols()
+ .filter(|&p| p == "ftp")
+ .next()
+ .is_none());
+}
+
+#[cfg(all(feature = "static-curl", feature = "protocol-ftp"))]
+#[test]
+fn static_with_ftp_enabled() {
+ assert!(curl::Version::get()
+ .protocols()
+ .filter(|&p| p == "ftp")
+ .next()
+ .is_some());
+}
diff --git a/vendor/curl/tests/server/mod.rs b/vendor/curl/tests/server/mod.rs
new file mode 100644
index 000000000..a474a1aa8
--- /dev/null
+++ b/vendor/curl/tests/server/mod.rs
@@ -0,0 +1,223 @@
+#![allow(dead_code)]
+
+use std::collections::HashSet;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::net::{SocketAddr, TcpListener, TcpStream};
+use std::path::PathBuf;
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::thread;
+
+pub struct Server {
+ messages: Option<Sender<Message>>,
+ addr: Addr,
+ thread: Option<thread::JoinHandle<()>>,
+}
+
+enum Message {
+ Read(String),
+ Write(String),
+}
+
+enum Addr {
+ Tcp(SocketAddr),
+ Unix(PathBuf),
+}
+
+fn run(stream: impl Read + Write, rx: &Receiver<Message>) {
+ let mut socket = BufReader::new(stream);
+ for msg in rx.iter() {
+ match msg {
+ Message::Read(ref expected) => {
+ let mut expected = &expected[..];
+ let mut expected_headers = HashSet::new();
+ while let Some(i) = expected.find('\n') {
+ let line = &expected[..i + 1];
+ expected = &expected[i + 1..];
+ expected_headers.insert(line);
+ if line == "\r\n" {
+ break;
+ }
+ }
+
+ let mut expected_len = None;
+ while !expected_headers.is_empty() {
+ let mut actual = String::new();
+ t!(socket.read_line(&mut actual));
+ if actual.starts_with("Content-Length") {
+ let len = actual.split(": ").nth(1).unwrap();
+ expected_len = len.trim().parse().ok();
+ }
+ // various versions of libcurl do different things here
+ if actual == "Proxy-Connection: Keep-Alive\r\n" {
+ continue;
+ }
+ if expected_headers.remove(&actual[..]) {
+ continue;
+ }
+
+ let mut found = None;
+ for header in expected_headers.iter() {
+ if lines_match(header, &actual) {
+ found = Some(header.clone());
+ break;
+ }
+ }
+ if let Some(found) = found {
+ expected_headers.remove(&found);
+ continue;
+ }
+ panic!(
+ "unexpected header: {:?} (remaining headers {:?})",
+ actual, expected_headers
+ );
+ }
+ for header in expected_headers {
+ panic!("expected header but not found: {:?}", header);
+ }
+
+ let mut line = String::new();
+ let mut socket = match expected_len {
+ Some(amt) => socket.by_ref().take(amt),
+ None => socket.by_ref().take(expected.len() as u64),
+ };
+ while socket.limit() > 0 {
+ line.truncate(0);
+ t!(socket.read_line(&mut line));
+ if line.is_empty() {
+ break;
+ }
+ if expected.is_empty() {
+ panic!("unexpected line: {:?}", line);
+ }
+ let i = expected.find('\n').unwrap_or(expected.len() - 1);
+ let expected_line = &expected[..i + 1];
+ expected = &expected[i + 1..];
+ if lines_match(expected_line, &line) {
+ continue;
+ }
+ panic!(
+ "lines didn't match:\n\
+ expected: {:?}\n\
+ actual: {:?}\n",
+ expected_line, line
+ )
+ }
+ if !expected.is_empty() {
+ println!("didn't get expected data: {:?}", expected);
+ }
+ }
+ Message::Write(ref to_write) => {
+ t!(socket.get_mut().write_all(to_write.as_bytes()));
+ return;
+ }
+ }
+ }
+
+ let mut dst = Vec::new();
+ t!(socket.read_to_end(&mut dst));
+ assert_eq!(dst.len(), 0);
+}
+
+fn lines_match(expected: &str, mut actual: &str) -> bool {
+ for (i, part) in expected.split("[..]").enumerate() {
+ match actual.find(part) {
+ Some(j) => {
+ if i == 0 && j != 0 {
+ return false;
+ }
+ actual = &actual[j + part.len()..];
+ }
+ None => return false,
+ }
+ }
+ actual.is_empty() || expected.ends_with("[..]")
+}
+
+impl Server {
+ pub fn new() -> Server {
+ let listener = t!(TcpListener::bind("127.0.0.1:0"));
+ let addr = t!(listener.local_addr());
+ let (tx, rx) = channel();
+ let thread = thread::spawn(move || run(listener.accept().unwrap().0, &rx));
+ Server {
+ messages: Some(tx),
+ addr: Addr::Tcp(addr),
+ thread: Some(thread),
+ }
+ }
+
+ #[cfg(not(windows))]
+ pub fn new_unix() -> Server {
+ use std::os::unix::net::UnixListener;
+
+ let path = "/tmp/easy_server.sock";
+ std::fs::remove_file(path).ok();
+ let listener = t!(UnixListener::bind(path));
+ let (tx, rx) = channel();
+ let thread = thread::spawn(move || run(listener.incoming().next().unwrap().unwrap(), &rx));
+ Server {
+ messages: Some(tx),
+ addr: Addr::Unix(path.into()),
+ thread: Some(thread),
+ }
+ }
+
+ pub fn receive(&self, msg: &str) {
+ self.msg(Message::Read(self.replace_port(msg)));
+ }
+
+ fn replace_port(&self, msg: &str) -> String {
+ match &self.addr {
+ Addr::Tcp(addr) => msg.replace("$PORT", &addr.port().to_string()),
+ Addr::Unix(_) => msg.to_string(),
+ }
+ }
+
+ pub fn send(&self, msg: &str) {
+ self.msg(Message::Write(self.replace_port(msg)));
+ }
+
+ fn msg(&self, msg: Message) {
+ t!(self.messages.as_ref().unwrap().send(msg));
+ }
+
+ pub fn addr(&self) -> &SocketAddr {
+ match &self.addr {
+ Addr::Tcp(addr) => addr,
+ Addr::Unix(_) => panic!("server is a UnixListener"),
+ }
+ }
+
+ #[cfg(not(windows))]
+ pub fn path(&self) -> &str {
+ match &self.addr {
+ Addr::Tcp(_) => panic!("server is a TcpListener"),
+ Addr::Unix(p) => p.as_os_str().to_str().unwrap(),
+ }
+ }
+
+ pub fn url(&self, path: &str) -> String {
+ match &self.addr {
+ Addr::Tcp(addr) => format!("http://{}{}", addr, path),
+ Addr::Unix(_) => format!("http://localhost{}", path),
+ }
+ }
+}
+
+impl Drop for Server {
+ fn drop(&mut self) {
+ match &self.addr {
+ Addr::Tcp(addr) => drop(TcpStream::connect(addr)),
+ Addr::Unix(p) => t!(std::fs::remove_file(p)),
+ }
+
+ drop(self.messages.take());
+ let res = self.thread.take().unwrap().join();
+ if !thread::panicking() {
+ t!(res);
+ } else if let Err(e) = res {
+ println!("child server thread also failed: {:?}", e);
+ }
+ }
+}