#[macro_export]
macro_rules! create_plugin {
($sandbox:ident, $id:literal, $schema:expr, $factory:expr) => {
if let Some(schema) = $schema {
$sandbox
.create_schema_plugin_with_config($id, schema, $factory)
.await
} else {
$sandbox.create_plugin_with_config($id, $factory).await
}
};
}
#[macro_export]
macro_rules! check_install_success {
($plugin:ident, $spec:ident) => {
let mut locator = flow::locate::Locator::new(&$plugin.tool, &$spec);
locator.locate_exe_file().await.unwrap();
assert!(locator.product_dir.exists());
for bin in locator.locate_bins(None).await.unwrap() {
assert!(bin.path.exists());
}
for shim in locator.locate_shims().await.unwrap() {
assert!(shim.path.exists());
}
};
}
#[macro_export]
macro_rules! do_build_from_source {
($sandbox:ident, $plugin:ident, $spec:literal) => {
let mut spec = ToolSpec::parse($spec).unwrap();
let result = flow::manage::Manager::new(&mut $plugin.tool)
.install(
&mut spec,
flow::install::InstallOptions {
console: Some(ProtoConsole::new_testing()),
log_writer: Some(Default::default()),
strategy: InstallStrategy::BuildFromSource,
skip_prompts: true,
skip_ui: true,
..Default::default()
},
)
.await;
if result.is_err() {
println!(
"{}",
std::fs::read_to_string(
$sandbox
.path()
.join(format!("proto-{}-build.log", $plugin.tool.get_id()))
)
.unwrap()
);
}
result.unwrap();
check_install_success!($plugin, spec);
};
}
#[macro_export]
macro_rules! generate_build_install_tests {
($id:literal, $spec:literal) => {
generate_build_install_tests!($id, $spec, None);
};
($id:literal, $spec:literal, $schema:expr) => {
generate_build_install_tests!($id, $spec, $schema, |_| {});
};
($id:literal, $spec:literal, $schema:expr, $factory:expr) => {
#[tokio::test(flavor = "multi_thread")]
async fn builds_tool_from_source() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
do_build_from_source!(sandbox, plugin, $spec);
}
};
}
#[macro_export]
macro_rules! do_install_prebuilt {
($sandbox:ident, $plugin:ident, $spec:literal) => {
let mut spec = ToolSpec::parse($spec).unwrap();
let result = flow::manage::Manager::new(&mut $plugin.tool)
.install(&mut spec, flow::install::InstallOptions::default())
.await;
check_install_success!($plugin, spec);
};
}
#[macro_export]
macro_rules! generate_download_install_tests {
($id:literal, $spec:literal) => {
generate_download_install_tests!($id, $spec, None);
};
($id:literal, $spec:literal, $schema:expr) => {
generate_download_install_tests!($id, $spec, $schema, |_| {});
};
($id:literal, $spec:literal, $schema:expr, $factory:expr) => {
generate_native_install_tests!($id, $spec, $schema);
#[tokio::test(flavor = "multi_thread")]
async fn downloads_prebuilt_and_checksum_to_temp() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
let mut tool = plugin.tool;
let mut spec = ToolSpec::parse($spec).unwrap();
flow::resolve::Resolver::new(&tool)
.resolve_version(&mut spec, false)
.await
.unwrap();
flow::install::Installer::new(&tool, &mut spec)
.install(flow::install::InstallOptions::default())
.await
.unwrap();
assert!(tool.get_temp_dir().exists());
}
#[tokio::test(flavor = "multi_thread")]
async fn doesnt_install_if_already_installed() {
if $spec == "canary" {
return;
}
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
let mut tool = plugin.tool;
let mut spec = ToolSpec::new_resolved(VersionSpec::parse($spec).unwrap());
tool.inventory
.manifest
.installed_versions
.insert(spec.get_resolved_version());
std::fs::create_dir_all(tool.get_product_dir(&spec)).unwrap();
assert!(
flow::install::Installer::new(&tool, &mut spec)
.install(flow::install::InstallOptions::default())
.await
.unwrap()
.is_none()
);
}
};
}
#[macro_export]
macro_rules! generate_native_install_tests {
($id:literal, $spec:literal) => {
generate_native_install_tests!($id, $spec, None);
};
($id:literal, $spec:literal, $schema:expr) => {
generate_native_install_tests!($id, $spec, $schema, |_| {});
};
($id:literal, $spec:literal, $schema:expr, $factory:expr) => {
#[tokio::test(flavor = "multi_thread")]
async fn installs_tool() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
do_install_prebuilt!(sandbox, plugin, $spec);
}
};
}
#[macro_export]
macro_rules! generate_resolve_versions_tests {
($id:literal, { $( $k:literal => $v:literal, )* }) => {
generate_resolve_versions_tests!($id, { $( $k => $v, )* }, None);
};
($id:literal, { $( $k:literal => $v:literal, )* }, $schema:expr) => {
generate_resolve_versions_tests!($id, { $( $k => $v, )* }, $schema, |_| {});
};
($id:literal, { $( $k:literal => $v:literal, )* }, $schema:expr, $factory:expr) => {
#[tokio::test(flavor = "multi_thread")]
async fn resolves_latest_alias() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
let mut spec = ToolSpec::parse("latest").unwrap();
flow::resolve::Resolver::new(&plugin.tool)
.resolve_version(
&mut spec,
false,
)
.await
.unwrap();
assert_ne!(spec.get_resolved_version(), "latest");
}
#[tokio::test(flavor = "multi_thread")]
async fn resolve_version_or_alias() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
$(
let mut spec = ToolSpec::parse($k).unwrap();
flow::resolve::Resolver::new(&plugin.tool)
.resolve_version(
&mut spec,
false,
)
.await
.unwrap();
assert_eq!(
spec.get_resolved_version(),
$v
);
)*
}
#[tokio::test(flavor = "multi_thread")]
#[should_panic(expected = "FailedVersionResolve")]
async fn errors_invalid_alias() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
flow::resolve::Resolver::new(&plugin.tool)
.resolve_version(
&mut ToolSpec::parse("unknown").unwrap(),
false,
)
.await
.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
#[should_panic(expected = "FailedVersionResolve")]
async fn errors_invalid_version() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
flow::resolve::Resolver::new(&plugin.tool)
.resolve_version(
&mut ToolSpec::parse("99.99.99").unwrap(),
false,
)
.await
.unwrap();
}
};
}
#[macro_export]
macro_rules! generate_shims_test {
($id:literal) => {
generate_shims_test!($id, [$id]);
};
($id:literal, [ $($bin:literal),* ]) => {
generate_shims_test!($id, [ $($bin),* ], None);
};
($id:literal, [ $($bin:literal),* ], $schema:expr) => {
generate_shims_test!($id, [ $($bin),* ], $schema, |_| {});
};
($id:literal, [ $($bin:literal),* ], $schema:expr, $factory:expr) => {
#[tokio::test(flavor = "multi_thread")]
async fn creates_shims() {
let sandbox = create_empty_proto_sandbox();
let mut plugin = create_plugin!(sandbox, $id, $schema, $factory);
flow::link::Linker::new(&mut plugin.tool, &ToolSpec::default())
.link_shims(false)
.await
.unwrap();
$(
assert!(
sandbox.proto_dir.join("shims").join(if cfg!(windows) {
format!("{}.exe", $bin)
} else {
$bin.to_string()
}).exists()
);
)*
starbase_sandbox::assert_snapshot!(std::fs::read_to_string(
sandbox.path().join(".proto/shims/registry.json")
).unwrap());
}
};
}