#![cfg(any(
not(any(
feature = "parser_tests",
feature = "analyzer_tests",
feature = "codegen_tests",
feature = "interpreter_tests",
feature = "conformance_tests",
feature = "integration_tests",
)),
feature = "analyzer_tests",
))]
use std::fs;
use tempfile::TempDir;
use windjammer::ejector::{EjectConfig, Ejector};
use windjammer::CompilationTarget;
fn create_temp_wj_project(files: &[(&str, &str)]) -> TempDir {
let temp_dir = TempDir::new().unwrap();
for (name, content) in files {
let file_path = temp_dir.path().join(name);
fs::write(file_path, content).unwrap();
}
temp_dir
}
#[test]
fn test_eject_simple_program() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
let x = 42
println!("Hello, world!")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok(), "Ejection should succeed");
assert!(output.path().join("main.rs").exists());
assert!(output.path().join("Cargo.toml").exists());
assert!(output.path().join("README.md").exists());
assert!(output.path().join(".gitignore").exists());
}
#[test]
fn test_eject_with_functions() {
let input = create_temp_wj_project(&[(
"lib.wj",
r#"
fn add(a: int, b: int) -> int {
a + b
}
fn multiply(a: int, b: int) -> int {
a * b
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
let rust_code = fs::read_to_string(output.path().join("lib.rs")).unwrap();
assert!(rust_code.contains("fn add"));
assert!(rust_code.contains("fn multiply"));
}
#[test]
fn test_eject_with_structs() {
let input = create_temp_wj_project(&[(
"lib.wj",
r#"
struct Point {
x: int
y: int
}
fn origin() -> Point {
Point { x: 0, y: 0 }
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
let rust_code = fs::read_to_string(output.path().join("lib.rs")).unwrap();
assert!(rust_code.contains("struct Point"));
assert!(rust_code.contains("fn origin"));
}
#[test]
fn test_eject_with_comments_enabled() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("test")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig {
comments: true,
..Default::default()
};
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
let rust_code = fs::read_to_string(output.path().join("main.rs")).unwrap();
assert!(rust_code.contains("This file was automatically generated by Windjammer eject"));
assert!(rust_code.contains("Ownership inference"));
}
#[test]
fn test_eject_with_comments_disabled() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("test")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig {
comments: false,
..Default::default()
};
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
let rust_code = fs::read_to_string(output.path().join("main.rs")).unwrap();
assert!(!rust_code.contains("This file was automatically generated by Windjammer eject"));
}
#[test]
fn test_eject_cargo_toml_with_binary() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("app")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
let cargo_toml = fs::read_to_string(output.path().join("Cargo.toml")).unwrap();
assert!(cargo_toml.contains("[[bin]]"));
assert!(cargo_toml.contains("name = \"app\""));
assert!(cargo_toml.contains("path = \"main.rs\""));
}
#[test]
fn test_eject_cargo_toml_with_library() {
let input = create_temp_wj_project(&[(
"lib.wj",
r#"
fn helper() -> int {
42
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
let cargo_toml = fs::read_to_string(output.path().join("Cargo.toml")).unwrap();
assert!(cargo_toml.contains("[lib]"));
assert!(cargo_toml.contains("path = \"lib.rs\""));
}
#[test]
fn test_eject_skip_cargo_toml() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("test")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig {
generate_cargo_toml: false,
..Default::default()
};
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
assert!(!output.path().join("Cargo.toml").exists());
assert!(output.path().join("main.rs").exists());
assert!(output.path().join("README.md").exists());
}
#[test]
fn test_eject_multiple_files() {
let input = create_temp_wj_project(&[
(
"main.wj",
r#"
fn main() {
lib.helper()
}
"#,
),
(
"lib.wj",
r#"
fn helper() -> int {
42
}
"#,
),
]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
assert!(output.path().join("main.rs").exists());
assert!(output.path().join("lib.rs").exists());
}
#[test]
fn test_eject_with_generics() {
let input = create_temp_wj_project(&[(
"lib.wj",
r#"
fn identity<T>(x: T) -> T {
x
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
let rust_code = fs::read_to_string(output.path().join("lib.rs")).unwrap();
assert!(rust_code.contains("fn identity"));
}
#[test]
fn test_eject_with_pattern_matching() {
let input = create_temp_wj_project(&[(
"lib.wj",
r#"
fn is_zero(x: int) -> bool {
match x {
0 => true,
_ => false,
}
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
let rust_code = fs::read_to_string(output.path().join("lib.rs")).unwrap();
assert!(rust_code.contains("match"));
}
#[test]
fn test_eject_target_wasm() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("wasm")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig {
target: CompilationTarget::Wasm,
..Default::default()
};
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_ok());
}
#[test]
fn test_eject_readme_generation() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("test")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
let readme = fs::read_to_string(output.path().join("README.md")).unwrap();
assert!(readme.contains("Ejected Windjammer Project"));
assert!(readme.contains("cargo build"));
assert!(readme.contains("Windjammer"));
}
#[test]
fn test_eject_gitignore_generation() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main() {
println!("test")
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
let gitignore = fs::read_to_string(output.path().join(".gitignore")).unwrap();
assert!(gitignore.contains("/target/"));
assert!(gitignore.contains("Cargo.lock"));
}
#[test]
fn test_eject_invalid_syntax_fails() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
fn main(( {
this is not valid syntax!!!
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_err(), "Ejection should fail for invalid syntax");
}
#[test]
fn test_eject_empty_directory_fails() {
let input = TempDir::new().unwrap(); let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(input.path(), output.path());
assert!(result.is_err(), "Ejection should fail for empty directory");
}
#[test]
fn test_eject_single_file() {
let input = TempDir::new().unwrap();
let wj_file = input.path().join("test.wj");
fs::write(
&wj_file,
r#"
fn test() -> int {
42
}
"#,
)
.unwrap();
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
let result = ejector.eject_project(&wj_file, output.path());
assert!(result.is_ok());
assert!(output.path().join("test.rs").exists());
}
#[test]
fn test_cargo_dependencies_json() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
use std::json
fn main() {
// Use JSON functionality
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
let cargo_toml = fs::read_to_string(output.path().join("Cargo.toml")).unwrap();
assert!(cargo_toml.contains("serde"));
assert!(cargo_toml.contains("serde_json"));
}
#[test]
fn test_cargo_dependencies_multiple_modules() {
let input = create_temp_wj_project(&[(
"main.wj",
r#"
use std::json
use std::regex
use std::time
fn main() {
// Use multiple stdlib modules
}
"#,
)]);
let output = TempDir::new().unwrap();
let config = EjectConfig::default();
let mut ejector = Ejector::new(config);
ejector.eject_project(input.path(), output.path()).unwrap();
let cargo_toml = fs::read_to_string(output.path().join("Cargo.toml")).unwrap();
assert!(cargo_toml.contains("serde"));
assert!(cargo_toml.contains("regex"));
assert!(cargo_toml.contains("chrono"));
}