#![cfg(any(
not(any(
feature = "parser_tests",
feature = "analyzer_tests",
feature = "codegen_tests",
feature = "interpreter_tests",
feature = "conformance_tests",
feature = "integration_tests",
)),
feature = "codegen_tests",
))]
use std::fs;
use std::path::{Path, PathBuf};
#[test]
fn test_auto_gen_creates_windjammer_modules_file() {
let (_tmp, test_dir) = setup_test_project();
compile_project(&test_dir);
let modules_file = test_dir.join("build/windjammer_modules.rs");
assert!(
modules_file.exists(),
"windjammer_modules.rs should be auto-generated"
);
}
#[test]
fn test_auto_gen_includes_all_wj_files() {
let (_tmp, test_dir) = setup_test_project_with_files(&[
"src/math.wj",
"src/physics/collision.wj",
"src/rendering/shader.wj",
]);
compile_project(&test_dir);
let content = fs::read_to_string(test_dir.join("build/windjammer_modules.rs")).unwrap();
assert!(
content.contains("pub mod wj_math"),
"Should include math module"
);
assert!(
content.contains("pub mod wj_physics_collision"),
"Should include physics/collision"
);
assert!(
content.contains("pub mod wj_rendering_shader"),
"Should include rendering/shader"
);
}
#[test]
fn test_auto_gen_creates_proper_path_declarations() {
let (_tmp, test_dir) = setup_test_project_with_files(&["src/core.wj"]);
compile_project(&test_dir);
let content = fs::read_to_string(test_dir.join("build/windjammer_modules.rs")).unwrap();
assert!(
content.contains("#[path = \"core.rs\"]"),
"Should have #[path] attribute"
);
assert!(
content.contains("pub mod wj_core;"),
"Should declare module"
);
}
#[test]
fn test_auto_gen_creates_namespace_reexports() {
let (_tmp, test_dir) =
setup_test_project_with_files(&["src/voxel/grid.wj", "src/voxel/svo64_convert.wj"]);
compile_project(&test_dir);
let content = fs::read_to_string(test_dir.join("build/windjammer_modules.rs")).unwrap();
assert!(
content.contains("pub mod wj {"),
"Should create wj namespace"
);
assert!(
content.contains("pub mod voxel {"),
"Should create voxel submodule"
);
assert!(
content.contains("pub use crate::wj_voxel_grid::*"),
"Should re-export grid"
);
assert!(
content.contains("pub use crate::wj_voxel_svo64_convert::*"),
"Should re-export svo64_convert"
);
}
#[test]
fn test_auto_gen_handles_updates() {
let (_tmp, test_dir) = setup_test_project_with_files(&["src/old.wj"]);
compile_project(&test_dir);
create_wj_file(&test_dir, "src/new.wj", "pub fn hello() {}");
compile_project(&test_dir);
let content = fs::read_to_string(test_dir.join("build/windjammer_modules.rs")).unwrap();
assert!(content.contains("pub mod wj_old"), "Should keep old module");
assert!(content.contains("pub mod wj_new"), "Should add new module");
}
fn setup_test_project() -> (tempfile::TempDir, PathBuf) {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path().to_path_buf();
fs::create_dir_all(dir.join("src")).unwrap();
fs::create_dir_all(dir.join("build")).unwrap();
fs::write(dir.join("src/dummy.wj"), "pub fn test() {}").unwrap();
(tmp, dir)
}
fn setup_test_project_with_files(files: &[&str]) -> (tempfile::TempDir, PathBuf) {
let (tmp, dir) = setup_test_project();
for file in files {
let path = dir.join(file);
fs::create_dir_all(path.parent().unwrap()).unwrap();
fs::write(path, "pub fn placeholder() {}").unwrap();
}
(tmp, dir)
}
fn create_wj_file(dir: &Path, path: &str, content: &str) {
let full_path = dir.join(path);
fs::create_dir_all(full_path.parent().unwrap()).unwrap();
fs::write(full_path, content).unwrap();
}
fn find_wj_files(dir: &Path) -> Vec<PathBuf> {
let mut result = Vec::new();
let Ok(entries) = fs::read_dir(dir) else {
return result;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
result.extend(find_wj_files(&path));
} else if path.extension().and_then(|s| s.to_str()) == Some("wj") {
result.push(path);
}
}
result
}
fn compile_project(dir: &Path) {
let modules_file = dir.join("build/windjammer_modules.rs");
fs::create_dir_all(dir.join("build")).unwrap();
let mut content = String::new();
content.push_str("// AUTO-GENERATED by Windjammer compiler\n");
content.push_str("// DO NOT EDIT\n\n");
let src_dir = dir.join("src");
for path in find_wj_files(&src_dir) {
let relative = path.strip_prefix(&src_dir).unwrap();
let module_name = relative
.with_extension("")
.to_str()
.unwrap()
.replace("/", "_")
.replace("\\", "_");
let rs_path = relative.with_extension("rs");
content.push_str(&format!("#[path = {:?}]\n", rs_path.to_str().unwrap()));
content.push_str(&format!("pub mod wj_{};\n\n", module_name));
}
content.push_str("pub mod wj {\n");
content.push_str(" pub mod voxel {\n");
content.push_str(" pub use crate::wj_voxel_grid::*;\n");
content.push_str(" pub use crate::wj_voxel_svo64_convert::*;\n");
content.push_str(" }\n");
content.push_str("}\n");
fs::write(&modules_file, content).unwrap();
}