74 lines
3.6 KiB
Rust
74 lines
3.6 KiB
Rust
//! Persistent test component shared by HTTP and socket acceptance tests.
|
|
use std::{
|
|
path::{Path, PathBuf},
|
|
sync::OnceLock,
|
|
};
|
|
fn write(path: PathBuf, text: &str) -> std::io::Result<()> {
|
|
if std::fs::read_to_string(&path).ok().as_deref() != Some(text) {
|
|
std::fs::write(path, text)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
pub fn component() -> &'static Path {
|
|
static PATH: OnceLock<PathBuf> = OnceLock::new();
|
|
PATH.get_or_init(|| {
|
|
let directory = Path::new(env!("CARGO_TARGET_TMPDIR")).join("hook-guest");
|
|
std::fs::create_dir_all(directory.join("src")).unwrap();
|
|
std::fs::create_dir_all(directory.join("wit/deps")).unwrap();
|
|
write(directory.join("wit/process.wit"), include_str!("../wit/process.wit")).unwrap();
|
|
write(directory.join("wit/deps/io.wit"), include_str!("../wit/deps/io.wit")).unwrap();
|
|
write(directory.join("Cargo.toml"), "[package]\nname='hook-guest'\nversion='0.1.0'\nedition='2024'\n[workspace]\n[dependencies]\nwstd='=0.6.8'\nanyhow='1'\nfutures-lite='2'\nwit-bindgen='0.46'\n").unwrap();
|
|
write(directory.join("src/main.rs"), r#"
|
|
use wstd::http::{Body, BodyExt, Client, Request};
|
|
mod bindings { wit_bindgen::generate!({path:"wit",world:"program",generate_all}); }
|
|
#[wstd::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
let args: Vec<_> = std::env::args().collect();
|
|
match args[1].as_str() {
|
|
"follow" => {
|
|
let response=Client::new().send(Request::get(&args[2]).body(Body::empty())?).await?;
|
|
println!("first-status={}",response.status().as_u16());
|
|
let location=response.headers()["location"].to_str()?.to_owned();
|
|
response.into_body().into_boxed_body().collect().await?;
|
|
let response=Client::new().send(Request::get(location).body(Body::empty())?).await?;
|
|
println!("status={}",response.status().as_u16());
|
|
response.into_body().into_boxed_body().collect().await?;
|
|
},
|
|
"spawn" => {
|
|
use bindings::sausage::process::host::{self, Request, Stdio};
|
|
let child=host::spawn(&Request {program:"/bin/guest.wasm".into(),argv:vec!["guest".into(),args[2].clone(),"GET".into()],cwd:"/".into(),env:vec![],group:None,stdin:Stdio::Null,stdout:Stdio::Inherit,stderr:Stdio::Inherit}).unwrap();
|
|
println!("child={}",child.pid());
|
|
assert_eq!(child.wait(),0);
|
|
},
|
|
"listen" => {
|
|
let listener = std::net::TcpListener::bind(&args[2])?;
|
|
println!("ready");
|
|
let (mut stream, _) = listener.accept()?;
|
|
use std::io::{Read, Write};
|
|
let mut bytes = [0;4]; stream.read_exact(&mut bytes)?;
|
|
stream.write_all(&bytes)?;
|
|
},
|
|
"connect" => {
|
|
use std::io::{Read, Write};
|
|
match std::net::TcpStream::connect(&args[2]) {
|
|
Ok(mut stream) => { stream.write_all(b"ping")?; let mut bytes=[0;4]; stream.read_exact(&mut bytes)?; println!("{}", std::str::from_utf8(&bytes)?); },
|
|
Err(_) => println!("denied"),
|
|
}
|
|
},
|
|
_ => {
|
|
let body = if args.len() > 3 { Body::from_stream(futures_lite::stream::iter((0..args[3].parse::<usize>()?/8192).map(|_| vec![b'x';8192]))) } else { Body::empty() };
|
|
let request = Request::builder().uri(&args[1]).method(args[2].as_str()).body(body)?;
|
|
match Client::new().send(request).await {
|
|
Ok(response) => { println!("status={}", response.status().as_u16()); let bytes=response.into_body().into_boxed_body().collect().await?.to_bytes(); println!("{}",String::from_utf8_lossy(&bytes)); },
|
|
Err(_) => println!("error"),
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
"#).unwrap();
|
|
assert!(std::process::Command::new("cargo").args(["build", "--manifest-path"]).arg(directory.join("Cargo.toml")).args(["--target", "wasm32-wasip2", "--release", "-j", "2"]).env("CARGO_TARGET_DIR", directory.join("target")).status().unwrap().success(), "test guest build failed");
|
|
directory.join("target/wasm32-wasip2/release/hook-guest.wasm")
|
|
})
|
|
}
|