use std::process::Command;
use wiremock::matchers::{body_string, header, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
#[tokio::test]
async fn get_ok_returns_body() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(ResponseTemplate::new(200).set_body_string("world"))
.mount(&server)
.await;
let url = format!("{}/hello", server.uri());
let out = ilo()
.args([r#"f url:t>R t t;get url"#, &url])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("world"),
"expected 'world' in output, got: {stdout}"
);
}
#[tokio::test]
async fn get_server_error_returns_err_value() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/fail"))
.respond_with(ResponseTemplate::new(500).set_body_string("oops"))
.mount(&server)
.await;
let url = format!("{}/fail", server.uri());
let out = ilo()
.args([r#"f url:t>R t t;get url"#, &url])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("oops"),
"expected 'oops' in output, got: {stdout}"
);
}
#[tokio::test]
async fn get_bad_host_returns_err() {
let out = ilo()
.args([r#"f url:t>R t t;get url"#, "http://127.0.0.1:1"])
.output()
.expect("failed to run ilo");
assert_eq!(
out.status.code(),
Some(1),
"expected exit 1 from Value::Err return, got {:?}",
out.status.code(),
);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("Err") || stderr.contains("err") || stderr.contains('^'),
"expected Err in stderr, got: {stderr}"
);
}
#[tokio::test]
async fn post_ok_returns_body() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/echo"))
.respond_with(ResponseTemplate::new(200).set_body_string("echoed"))
.mount(&server)
.await;
let url = format!("{}/echo", server.uri());
let out = ilo()
.args([r#"f url:t body:t>R t t;post url body"#, &url, "hello"])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("echoed"),
"expected 'echoed' in output, got: {stdout}"
);
}
#[tokio::test]
async fn post_sends_body() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/submit"))
.and(body_string("payload"))
.respond_with(ResponseTemplate::new(200).set_body_string("ok"))
.mount(&server)
.await;
let url = format!("{}/submit", server.uri());
let out = ilo()
.args([r#"f url:t body:t>R t t;post url body"#, &url, "payload"])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("ok"),
"expected 'ok' in output, got: {stdout}"
);
}
#[tokio::test]
async fn post_ok_and_match_result() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/data"))
.respond_with(ResponseTemplate::new(200).set_body_string("result"))
.mount(&server)
.await;
let url = format!("{}/data", server.uri());
let out = ilo()
.args([
r#"f url:t body:t>t;r=post url body;?r{~v:v;^_:"err"}"#,
&url,
"input",
])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert_eq!(stdout.trim(), "result");
}
#[tokio::test]
async fn post_bad_host_returns_err() {
let out = ilo()
.args([
r#"f url:t body:t>R t t;post url body"#,
"http://127.0.0.1:1",
"body",
])
.output()
.expect("failed to run ilo");
assert_eq!(
out.status.code(),
Some(1),
"expected exit 1 from Value::Err return, got {:?}",
out.status.code(),
);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("Err") || stderr.contains("err") || stderr.contains('^'),
"expected Err in stderr, got: {stderr}"
);
}
#[tokio::test]
async fn get_with_header_sent() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/auth"))
.and(header("x-api-key", "secret"))
.respond_with(ResponseTemplate::new(200).set_body_string("authorized"))
.mount(&server)
.await;
let url = format!("{}/auth", server.uri());
let code = r#"f url:t>R t t;h=mmap;h=mset h "x-api-key" "secret";get url h"#;
let out = ilo()
.args([code, &url])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("authorized"),
"expected 'authorized' in output, got: {stdout}"
);
}
#[tokio::test]
async fn post_with_header_sent() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/submit"))
.and(header("x-api-key", "tok"))
.and(body_string("payload"))
.respond_with(ResponseTemplate::new(200).set_body_string("accepted"))
.mount(&server)
.await;
let url = format!("{}/submit", server.uri());
let code = r#"f url:t>R t t;h=mmap;h=mset h "x-api-key" "tok";post url "payload" h"#;
let out = ilo()
.args([code, &url])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"stderr: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("accepted"),
"expected 'accepted' in output, got: {stdout}"
);
}