use serde_json::Value;
use std::fs;
use std::process::Command;
use tempfile::TempDir;
fn tldr_cmd() -> Command {
Command::new(assert_cmd::cargo::cargo_bin!("tldr"))
}
fn create_test_file(dir: &TempDir, name: &str, content: &str) -> std::path::PathBuf {
let path = dir.path().join(name);
fs::write(&path, content).unwrap();
path
}
mod resources_multilang {
use super::*;
#[test]
fn test_resources_kotlin() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.kt",
r#"
fun leakyFunction(path: String): String {
val reader = java.io.BufferedReader(java.io.FileReader(path))
val content = reader.readLine()
// reader is never closed - resource leak
return content
}
"#,
);
let output = tldr_cmd()
.args([
"resources",
file.to_str().unwrap(),
"leakyFunction",
"-f",
"json",
])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("leak") || json.to_string().contains("resource"),
"Kotlin resources should detect unclosed BufferedReader leak"
);
}
#[test]
fn test_resources_swift() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.swift",
r#"
func leakyFunction(path: String) -> String {
let handle = FileHandle(forReadingAtPath: path)!
let data = handle.readDataToEndOfFile()
// handle is never closed - resource leak
return String(data: data, encoding: .utf8)!
}
"#,
);
let output = tldr_cmd()
.args([
"resources",
file.to_str().unwrap(),
"leakyFunction",
"-f",
"json",
])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("leak") || json.to_string().contains("resource"),
"Swift resources (regex fallback) should detect unclosed FileHandle leak"
);
}
#[test]
fn test_resources_ocaml() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.ml",
r#"
let leaky_function path =
let ic = open_in path in
let line = input_line ic in
(* ic is never closed - resource leak *)
line
"#,
);
let output = tldr_cmd()
.args([
"resources",
file.to_str().unwrap(),
"leaky_function",
"-f",
"json",
])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("leak") || json.to_string().contains("resource"),
"OCaml resources should detect unclosed open_in leak"
);
}
#[test]
fn test_resources_lua() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.lua",
r#"
function leaky_function(path)
local f = io.open(path, "r")
local content = f:read("*a")
-- f is never closed - resource leak
return content
end
"#,
);
let output = tldr_cmd()
.args([
"resources",
file.to_str().unwrap(),
"leaky_function",
"-f",
"json",
])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("leak") || json.to_string().contains("resource"),
"Lua resources should detect unclosed io.open leak"
);
}
#[test]
fn test_resources_luau() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.luau",
r#"
local function leaky_function(path: string): string
local f = io.open(path, "r")
local content = f:read("*a")
-- f is never closed - resource leak
return content
end
"#,
);
let output = tldr_cmd()
.args([
"resources",
file.to_str().unwrap(),
"leaky_function",
"-f",
"json",
])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("leak") || json.to_string().contains("resource"),
"Luau resources should detect unclosed io.open leak"
);
}
}
mod contracts_multilang {
use super::*;
#[test]
fn test_contracts_kotlin() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.kt",
r#"
fun processData(x: Int, data: List<Int>): Int {
require(x >= 0) { "x must be non-negative" }
check(data.isNotEmpty()) { "data cannot be empty" }
return data.sum() + x
}
"#,
);
let output = tldr_cmd()
.args([
"contracts",
file.to_str().unwrap(),
"processData",
"-f",
"json",
])
.output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("precondition") || json.to_string().contains("require"),
"Kotlin contracts should detect require() and check() preconditions"
);
}
#[test]
fn test_contracts_swift() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.swift",
r#"
func processData(x: Int, data: [Int]) -> Int {
precondition(x >= 0, "x must be non-negative")
guard !data.isEmpty else {
fatalError("data cannot be empty")
}
return data.reduce(0, +) + x
}
"#,
);
let output = tldr_cmd()
.args([
"contracts",
file.to_str().unwrap(),
"processData",
"-f",
"json",
])
.output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("precondition") || json.to_string().contains("guard"),
"Swift contracts (regex fallback) should detect precondition() and guard clauses"
);
}
#[test]
fn test_contracts_luau() {
let temp = TempDir::new().unwrap();
let file = create_test_file(
&temp,
"test.luau",
r#"
local function processData(x: number, data: {number}): number
assert(x >= 0, "x must be non-negative")
if #data == 0 then
error("data cannot be empty")
end
local sum = 0
for _, v in ipairs(data) do
sum = sum + v
end
return sum + x
end
"#,
);
let output = tldr_cmd()
.args([
"contracts",
file.to_str().unwrap(),
"processData",
"-f",
"json",
])
.output()
.unwrap();
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
let json: Value = serde_json::from_str(&stdout).expect("valid JSON");
assert!(
json.to_string().contains("precondition") || json.to_string().contains("assert"),
"Luau contracts should detect assert() and error() guard preconditions"
);
}
}