use super::*;
use crate::core::config::{Language, NewAlefConfig, ResolvedCrateConfig};
fn config_for(languages: &str) -> ResolvedCrateConfig {
let cfg: NewAlefConfig = toml::from_str(&format!(
r#"
[workspace]
languages = [{languages}]
[[crates]]
name = "sample-model"
sources = ["src/lib.rs"]
"#
))
.expect("valid config");
cfg.resolve().unwrap().remove(0)
}
#[test]
fn python_package_dir_and_output_dir_are_genuinely_different_trees() {
let config = config_for(r#""python""#);
assert_eq!(config.package_dir(Language::Python), "packages/python");
assert_eq!(
config.output_for("python"),
Some(Path::new("crates/sample-model-py/src")),
"the PyO3 glue crate is generated outside the wheel package directory"
);
}
#[test]
fn a_partial_python_regen_formats_the_generated_glue_crate_too() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let config = config_for(r#""python""#);
let wheel = base.join(config.package_dir(Language::Python));
let glue = base.join(config.output_for("python").expect("python output dir"));
let glue_root = glue.parent().expect("glue src dir has a parent").to_path_buf();
std::fs::create_dir_all(&wheel).expect("wheel dir");
std::fs::create_dir_all(&glue).expect("glue crate src dir");
let only: HashSet<Language> = [Language::Python].into_iter().collect();
let paths = poly_paths(&config, base, Some(&only), &[Language::Python]);
assert!(
paths.contains(&wheel),
"the wheel package directory must still be formatted: {paths:?}"
);
assert!(
paths.contains(&glue_root),
"the generated PyO3 glue crate is stamped by `finalize_hashes` and swept by \
`generate_sweep_roots`, so it must be formatted by the same run that writes it -- \
otherwise generate emits non-canonical Rust and stamps it, and the next whole-tree \
format pass makes the stamp stale: {paths:?}"
);
}
#[test]
fn a_nested_output_dir_does_not_add_a_redundant_poly_path() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let config = config_for(r#""node""#);
let crate_root = base.join(config.package_dir(Language::Node));
let sources = base.join(config.output_for("node").expect("node output dir"));
std::fs::create_dir_all(&sources).expect("node src dir");
let only: HashSet<Language> = [Language::Node].into_iter().collect();
let paths = poly_paths(&config, base, Some(&only), &[Language::Node]);
assert_eq!(
paths,
vec![crate_root],
"the crate root already contains its own src/, so only the enclosing path is handed to poly"
);
}
#[test]
fn a_partial_python_regen_formats_the_glue_crate_root_holding_cargo_toml() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let config = config_for(r#""python""#);
let glue_src = base.join(config.output_for("python").expect("python output dir"));
std::fs::create_dir_all(&glue_src).expect("glue crate src dir");
let crate_root = glue_src.parent().expect("glue src dir has a parent").to_path_buf();
std::fs::write(crate_root.join("Cargo.toml"), "[package]\n").expect("write Cargo.toml");
let only: HashSet<Language> = [Language::Python].into_iter().collect();
let paths = poly_paths(&config, base, Some(&only), &[Language::Python]);
assert!(
paths.contains(&crate_root),
"the glue crate root holding Cargo.toml must be formatted, not just its src/ subdirectory: {paths:?}"
);
}
#[test]
fn every_default_crate_root_language_formats_its_manifest_directory() {
for (languages, lang, lang_name) in [(r#""ffi""#, Language::Ffi, "ffi"), (r#""php""#, Language::Php, "php")] {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let config = config_for(languages);
let output_dir = base.join(config.output_for(lang_name).expect("output dir"));
std::fs::create_dir_all(&output_dir).expect("glue crate src dir");
let crate_root = output_dir.parent().expect("output dir has a parent").to_path_buf();
std::fs::write(crate_root.join("Cargo.toml"), "[package]\n").expect("write Cargo.toml");
let only: HashSet<Language> = [lang].into_iter().collect();
let paths = poly_paths(&config, base, Some(&only), &[lang]);
assert!(
paths.contains(&crate_root),
"[{lang_name}] the manifest directory {crate_root:?} must be formatted: {paths:?}"
);
}
}
#[test]
fn a_missing_output_dir_is_still_dropped() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let config = config_for(r#""python""#);
std::fs::create_dir_all(base.join(config.package_dir(Language::Python))).expect("wheel dir");
let only: HashSet<Language> = [Language::Python].into_iter().collect();
let paths = poly_paths(&config, base, Some(&only), &[Language::Python]);
assert_eq!(
paths,
vec![base.join("packages/python")],
"an output directory this run did not create must not be handed to poly"
);
}