#![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::process::Command;
use tempfile::TempDir;
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_cross_module_copy_type_arg() {
let temp_dir = TempDir::new().unwrap();
let item_source = r#"
pub struct Stack {
pub quantity: i32,
}
impl Stack {
pub fn remove(self, amount: i32) -> bool {
if self.quantity < amount {
return false
}
self.quantity = self.quantity - amount
true
}
}
"#;
let inventory_source = r#"
use crate::Stack
pub fn remove_from_stack(mut stack: Stack, quantity: i32) {
stack.remove(quantity);
}
"#;
fs::create_dir_all(temp_dir.path().join("src")).unwrap();
fs::write(temp_dir.path().join("src").join("item.wj"), item_source).unwrap();
fs::write(
temp_dir.path().join("src").join("inventory.wj"),
inventory_source,
)
.unwrap();
let toml_content = r#"
[package]
name = "test_cross_module"
version = "0.1.0"
[lib]
path = "src/item.wj"
[[bin]]
name = "inventory"
path = "src/inventory.wj"
"#;
fs::write(temp_dir.path().join("wj.toml"), toml_content).unwrap();
let wj_output = Command::new(env!("CARGO_BIN_EXE_wj"))
.arg("build")
.arg("--no-cargo")
.arg("src/") .current_dir(temp_dir.path())
.output()
.expect("Failed to execute wj compiler");
if !wj_output.status.success() {
panic!(
"Compilation failed:\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&wj_output.stdout),
String::from_utf8_lossy(&wj_output.stderr)
);
}
let inventory_rs = temp_dir.path().join("build").join("inventory.rs");
let generated = fs::read_to_string(&inventory_rs).unwrap_or_else(|_| {
panic!(
"Failed to read generated inventory.rs. Build output:\n{}",
String::from_utf8_lossy(&wj_output.stdout)
)
});
assert!(
generated.contains("stack.remove(quantity)"),
"Expected 'stack.remove(quantity)' but got:\n{}",
generated
);
assert!(
!generated.contains("stack.remove(&quantity)"),
"Should NOT generate 'stack.remove(&quantity)', found in:\n{}",
generated
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_cross_module_multiple_files() {
let temp_dir = TempDir::new().unwrap();
let stack_source = r#"
pub struct Stack {
pub quantity: i32,
}
impl Stack {
pub fn new(quantity: i32) -> Stack {
Stack { quantity: quantity }
}
pub fn remove(self, amount: i32) -> bool {
if self.quantity < amount {
return false
}
self.quantity = self.quantity - amount
true
}
pub fn add(self, amount: i32) {
self.quantity = self.quantity + amount
}
}
"#;
let inventory_source = r#"
use crate::Stack
pub struct Inventory {
pub items: Vec<Option<Stack>>,
}
impl Inventory {
pub fn new() -> Inventory {
Inventory { items: Vec::new() }
}
pub fn remove_at(self, index: i32, quantity: i32) {
if let Some(stack) = self.items[index as usize] {
stack.remove(quantity);
}
}
pub fn add_at(self, index: i32, quantity: i32) {
if let Some(stack) = self.items[index as usize] {
stack.add(quantity);
}
}
}
"#;
fs::create_dir_all(temp_dir.path().join("src")).unwrap();
fs::write(temp_dir.path().join("src").join("stack.wj"), stack_source).unwrap();
fs::write(
temp_dir.path().join("src").join("inventory.wj"),
inventory_source,
)
.unwrap();
let toml_content = r#"
[package]
name = "test_multi_file"
version = "0.1.0"
"#;
fs::write(temp_dir.path().join("wj.toml"), toml_content).unwrap();
let wj_output = Command::new(env!("CARGO_BIN_EXE_wj"))
.arg("build")
.arg("--no-cargo")
.arg("src/")
.current_dir(temp_dir.path())
.output()
.expect("Failed to execute wj compiler");
if !wj_output.status.success() {
panic!(
"Compilation failed:\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&wj_output.stdout),
String::from_utf8_lossy(&wj_output.stderr)
);
}
let inventory_rs = temp_dir.path().join("build").join("inventory.rs");
let generated = fs::read_to_string(&inventory_rs)
.unwrap_or_else(|_| panic!("Failed to read generated inventory.rs"));
assert!(
generated.contains("stack.remove(quantity)"),
"Expected 'stack.remove(quantity)' but got:\n{}",
generated
);
assert!(
generated.contains("stack.add(quantity)"),
"Expected 'stack.add(quantity)' but got:\n{}",
generated
);
assert!(
!generated.contains("stack.remove(&quantity)"),
"Should NOT generate 'stack.remove(&quantity)', found in:\n{}",
generated
);
assert!(
!generated.contains("stack.add(&quantity)"),
"Should NOT generate 'stack.add(&quantity)', found in:\n{}",
generated
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_cross_module_nested_if_let() {
let temp_dir = TempDir::new().unwrap();
let item_source = r#"
pub struct Item {
pub id: string,
}
pub struct ItemStack {
pub item: Item,
pub quantity: i32,
}
impl ItemStack {
pub fn remove(self, amount: i32) -> bool {
if self.quantity < amount {
return false
}
self.quantity = self.quantity - amount
true
}
}
"#;
let inventory_source = r#"
use crate::ItemStack
pub fn process(mut slots: Vec<Option<ItemStack>>, index: i32, quantity: i32) {
if let Some(stack) = &mut slots[index as usize] {
stack.remove(quantity);
}
}
"#;
fs::create_dir_all(temp_dir.path().join("src")).unwrap();
fs::write(temp_dir.path().join("src").join("item.wj"), item_source).unwrap();
fs::write(
temp_dir.path().join("src").join("inventory.wj"),
inventory_source,
)
.unwrap();
let toml_content = r#"
[package]
name = "test_nested"
version = "0.1.0"
"#;
fs::write(temp_dir.path().join("wj.toml"), toml_content).unwrap();
let wj_output = Command::new(env!("CARGO_BIN_EXE_wj"))
.arg("build")
.arg("--no-cargo")
.arg("src/")
.current_dir(temp_dir.path())
.output()
.expect("Failed to execute wj compiler");
if !wj_output.status.success() {
panic!(
"Compilation failed:\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&wj_output.stdout),
String::from_utf8_lossy(&wj_output.stderr)
);
}
let inventory_rs = temp_dir.path().join("build").join("inventory.rs");
let generated = fs::read_to_string(&inventory_rs)
.unwrap_or_else(|_| panic!("Failed to read generated inventory.rs"));
assert!(
generated.contains("stack.remove(quantity)"),
"Expected 'stack.remove(quantity)' but got:\n{}",
generated
);
assert!(
!generated.contains("stack.remove(&quantity)"),
"Should NOT generate 'stack.remove(&quantity)', found in:\n{}",
generated
);
}