mod client;
mod config;
mod file;
pub use client::S3Client;
pub use config::S3Config;
pub use file::S3File;
use rong::*;
pub fn init(ctx: &JSContext) -> JSResult<()> {
ctx.register_hidden_class::<S3File>()?;
ctx.register_hidden_class::<S3Client>()?;
let ctor = Class::lookup::<S3Client>(ctx)?.clone();
ctx.host_namespace().set("S3Client", ctor)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use rong_test::*;
async fn spawn_s3_server() -> String {
let tmp = tempfile::tempdir().expect("tempdir");
let fs = s3s_fs::FileSystem::new(tmp.path()).expect("s3s-fs");
std::fs::create_dir_all(tmp.path().join("test-bucket")).expect("create bucket dir");
let mut auth = s3s::auth::SimpleAuth::new();
auth.register("minioadmin".to_string(), "minioadmin".into());
let mut builder = s3s::service::S3ServiceBuilder::new(fs);
builder.set_auth(auth);
let service = builder.build();
let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
.await
.expect("bind");
let addr = listener.local_addr().expect("local_addr");
let _tmp = Box::leak(Box::new(tmp));
tokio::spawn(async move {
let http_server =
hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());
loop {
let Ok((stream, _)) = listener.accept().await else {
continue;
};
let service = service.clone();
let builder = http_server.clone();
tokio::spawn(async move {
let _ = builder
.serve_connection(hyper_util::rt::TokioIo::new(stream), service)
.await;
});
}
});
format!("http://127.0.0.1:{}", addr.port())
}
fn setup_s3_env(ctx: &JSContext, endpoint: &str) -> JSResult<()> {
ctx.global().set("TEST_S3_ENDPOINT", endpoint)?;
ctx.global().set("TEST_S3_ACCESS_KEY", "minioadmin")?;
ctx.global().set("TEST_S3_SECRET_KEY", "minioadmin")?;
ctx.global().set("TEST_S3_BUCKET", "test-bucket")?;
rong_console::init(ctx)?;
rong_assert::init(ctx)?;
init(ctx)?;
Ok(())
}
fn test_s3_config(endpoint: &str) -> S3Config {
S3Config {
access_key_id: "minioadmin".to_string(),
secret_access_key: "minioadmin".to_string(),
bucket: "test-bucket".to_string(),
endpoint: Some(endpoint.to_string()),
..Default::default()
}
}
#[test]
fn test_s3() {
let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.canonicalize()
.expect("workspace root");
std::env::set_current_dir(&workspace_root).expect("set cwd");
async_run!(|ctx: JSContext| async move {
unsafe {
std::env::set_var("NO_PROXY", "127.0.0.1,localhost");
}
let endpoint = spawn_s3_server().await;
setup_s3_env(&ctx, &endpoint)?;
let passed = UnitJSRunner::load_script(&ctx, "s3.js")
.await?
.run()
.await?;
assert!(passed);
Ok(())
});
}
#[test]
fn test_s3_namespace() {
let workspace_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../..")
.canonicalize()
.expect("workspace root");
std::env::set_current_dir(&workspace_root).expect("set cwd");
async_run!(|ctx: JSContext| async move {
unsafe {
std::env::set_var("NO_PROXY", "127.0.0.1,localhost");
}
let endpoint = spawn_s3_server().await;
setup_s3_env(&ctx, &endpoint)?;
let client = S3Client::new(test_s3_config(&endpoint), Some("app1/".to_string()));
let js_client = Class::lookup::<S3Client>(&ctx)?.instance(client);
ctx.global().set("s3", js_client)?;
let passed = UnitJSRunner::load_script(&ctx, "s3_namespace.js")
.await?
.run()
.await?;
assert!(passed);
Ok(())
});
}
}