use super::*;
#[test]
fn splits_a_flat_bin_root_into_cohesive_under_budget_modules() {
let mut src = String::from("use std::fmt;\n\n");
for k in 0..4 {
for n in 0..4 {
let call = if n < 3 {
format!(" g{k}_{}();\n", n + 1)
} else {
String::new()
};
src.push_str(&format!("fn g{k}_{n}() {{\n{call}}}\n\n"));
}
}
src.push_str("fn main() {\n g0_0();\n}\n");
let exploded = explode(&src).unwrap();
let max_loc = 60;
let out = split_bin(&exploded, max_loc, "main");
assert!(out.still_oversized.is_empty());
for f in &out.files {
assert!(f.loc < max_loc, "{} over budget: {}", f.path, f.loc);
}
let root = out.files.iter().find(|f| f.path == "main.rs").unwrap();
assert!(root.contents.contains("fn main"), "main stays at root");
assert!(root.contents.contains("pub(crate) use "));
let part = out.files.iter().find(|f| f.path != "main.rs").unwrap();
assert!(part.contents.contains("use crate::*;"));
assert!(part.contents.contains("pub(crate) fn "));
let g0 = out
.files
.iter()
.find(|f| f.contents.contains("fn g0_1"))
.unwrap();
for n in 0..4 {
assert!(
g0.contents.contains(&format!("fn g0_{n}")),
"g0 group together"
);
}
}
#[test]
fn file_module_places_submodules_in_a_subdir() {
let mut src = String::new();
for k in 0..3 {
src.push_str(&format!("pub fn item{k}() -> i32 {{\n {k}\n}}\n\n"));
}
let exploded = explode(&src).unwrap();
let out = split_mod(&exploded, 10_000, "wstest");
let root = out.files.iter().find(|f| f.path == "wstest.rs").unwrap();
assert!(
root.contents.contains("mod item0;"),
"root file-module declares the sub-modules"
);
let subs: Vec<&str> = out
.files
.iter()
.map(|f| f.path.as_str())
.filter(|p| *p != "wstest.rs")
.collect();
assert!(!subs.is_empty(), "produced sub-module files");
for path in &subs {
assert!(
path.starts_with("wstest/"),
"sub-module {path} must live under wstest/ (file-module subdir)"
);
}
}
#[test]
fn mod_rs_keeps_submodules_as_siblings() {
let mut src = String::new();
for k in 0..3 {
src.push_str(&format!("pub fn item{k}() -> i32 {{\n {k}\n}}\n\n"));
}
let exploded = explode(&src).unwrap();
let out = split_mod(&exploded, 10_000, "mod");
for f in &out.files {
assert!(
!f.path.contains('/'),
"mod.rs sub-modules are siblings, not in a subdir: {}",
f.path
);
}
}
#[test]
fn crate_preamble_stays_at_root_not_copied_into_parts() {
let src = "//! crate docs\n#![allow(dead_code)]\n\npub fn alpha() -> i32 {\n beta()\n}\n\nfn beta() -> i32 {\n 1\n}\n";
let exploded = explode(src).unwrap();
let out = split_bin(&exploded, 10_000, "lib");
let root = out.files.iter().find(|f| f.path == "lib.rs").unwrap();
assert!(
root.contents.contains("#![allow(dead_code)]"),
"preamble stays at the root"
);
for f in &out.files {
if f.path != "lib.rs" {
assert!(
!f.contents.contains("#!["),
"part {} must not carry crate-level inner attrs",
f.path
);
assert!(
!f.contents.contains("//! crate docs"),
"part {} must not duplicate the crate docs",
f.path
);
}
}
}
#[test]
fn source_pub_use_reexports_stay_pub_use_at_the_root() {
let src = "mod helpers;\n\npub use helpers::Helper;\n\nuse std::fmt::Display;\n\n\
pub fn api(d: &dyn Display) {\n let _ = d;\n}\n";
let exploded = explode(src).unwrap();
let out = split_bin(&exploded, 10_000, "lib");
let root = out.files.iter().find(|f| f.path == "lib.rs").unwrap();
assert!(
root.contents.contains("mod helpers;"),
"content-less mod decl stays at the root (it binds helpers.rs):\n{}",
root.contents
);
assert!(
root.contents.contains("pub use helpers::Helper;"),
"source re-export stays verbatim at the root:\n{}",
root.contents
);
assert!(
!root.contents.contains("pub(crate) use helpers"),
"a source re-export must never be demoted"
);
for f in &out.files {
if f.path != "lib.rs" {
assert!(
!f.contents.contains("pub use helpers::Helper;"),
"{} must not carry the root's re-export",
f.path
);
assert!(
!f.contents.contains("mod helpers;"),
"{} must not carry the root's mod decl (would look for a \
sibling subdir file)",
f.path
);
}
}
}
#[test]
fn part_colliding_with_an_extracted_mod_name_is_renamed() {
let src = "fn tests() -> i32 {\n 1\n}\n\n\
mod tests {\n fn smoke() {}\n}\n";
let exploded = explode(src).unwrap();
let out = split_bin(&exploded, 10_000, "lib");
let paths: Vec<&str> = out.files.iter().map(|f| f.path.as_str()).collect();
assert!(paths.contains(&"tests.rs"), "extracted mod file: {paths:?}");
assert!(paths.contains(&"tests_.rs"), "renamed part file: {paths:?}");
let root = out.files.iter().find(|f| f.path == "lib.rs").unwrap();
assert!(root.contents.contains("mod tests_;"));
assert!(root.contents.contains("mod tests;"));
}