#![cfg(feature = "mutation-testing")]
#![cfg(not(feature = "skip-slow-tests"))]
use pmat::cli::commands::MutateArgs;
use pmat::cli::handlers::mutate::handle;
use pmat::stateless_server::StatelessTemplateServer;
use std::fs;
use std::sync::Arc;
use tempfile::tempdir;
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_rust_mutation_full_workflow() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.rs");
fs::write(
&file_path,
r#"
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn multiply(a: i32, b: i32) -> i32 {
a * b
}
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_multiply() {
assert_eq!(multiply(2, 3), 6);
}
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: None, timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok(),
"Rust mutation workflow should complete successfully"
);
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_python_mutation_full_workflow() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.py");
fs::write(
&file_path,
r#"
def add(a, b):
return a + b
def multiply(a, b):
return a * b
def test_add():
assert add(2, 3) == 5
def test_multiply():
assert multiply(2, 3) == 6
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: Some("python".to_string()),
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("Python")
|| msg.contains("not supported")
|| msg.contains("No mutants"),
"Error should be related to Python support: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_typescript_mutation_full_workflow() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.ts");
fs::write(
&file_path,
r#"
function add(a: number, b: number): number {
return a + b;
}
function multiply(a: number, b: number): number {
return a * b;
}
describe('Math functions', () => {
it('should add numbers', () => {
expect(add(2, 3)).toBe(5);
});
it('should multiply numbers', () => {
expect(multiply(2, 3)).toBe(6);
});
});
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: Some("typescript".to_string()),
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("TypeScript")
|| msg.contains("not supported")
|| msg.contains("No mutants"),
"Error should be related to TypeScript support: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_javascript_mutation_full_workflow() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.js");
fs::write(
&file_path,
r#"
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
describe('Math functions', () => {
it('should add numbers', () => {
expect(add(2, 3)).toBe(5);
});
it('should multiply numbers', () => {
expect(multiply(2, 3)).toBe(6);
});
});
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: Some("javascript".to_string()),
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("JavaScript")
|| msg.contains("not supported")
|| msg.contains("No mutants"),
"Error should be related to JavaScript support: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_go_mutation_full_workflow() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.go");
fs::write(
&file_path,
r#"
package main
func Add(a, b int) int {
return a + b
}
func Multiply(a, b int) int {
return a * b
}
func main() {
result := Add(2, 3)
println(result)
}
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: Some("go".to_string()),
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("Go") || msg.contains("not supported") || msg.contains("No mutants"),
"Error should be related to Go support: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_cpp_mutation_full_workflow() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test.cpp");
fs::write(
&file_path,
r#"
#include <iostream>
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
int main() {
int result = add(2, 3);
std::cout << result << std::endl;
return 0;
}
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: Some("cpp".to_string()),
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("C++") || msg.contains("not supported") || msg.contains("No mutants"),
"Error should be related to C++ support: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_multi_file_mutation_testing() {
let temp_dir = tempdir().unwrap();
let lib_path = temp_dir.path().join("lib.rs");
fs::write(
&lib_path,
r#"
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
"#,
)
.unwrap();
let utils_path = temp_dir.path().join("utils.rs");
fs::write(
&utils_path,
r#"
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
pub fn divide(a: i32, b: i32) -> i32 {
a / b
}
"#,
)
.unwrap();
for file_path in [lib_path, utils_path] {
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok(),
"Multi-file mutation should handle each file: {:?}",
file_path
);
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_workspace_level_mutation() {
let temp_dir = tempdir().unwrap();
let src_dir = temp_dir.path().join("src");
fs::create_dir(&src_dir).unwrap();
let main_path = src_dir.join("main.rs");
fs::write(
&main_path,
r#"
fn main() {
let result = add(2, 3);
println!("{}", result);
}
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
"#,
)
.unwrap();
let args = MutateArgs {
target: main_path.clone(),
language: None,
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(result.is_ok(), "Workspace-level mutation should succeed");
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_large_file_mutation() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("large_file.rs");
let mut code = String::new();
for i in 0..200 {
code.push_str(&format!(
r#"
fn function_{}(a: i32, b: i32) -> i32 {{
a + b + {}
}}
"#,
i, i
));
}
fs::write(&file_path, code).unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 60, jobs: Some(4), output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: true, use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("No mutants") || msg.contains("timeout") || msg.contains("Too many"),
"Error should be acceptable for large file: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_many_mutants_handling() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("many_mutants.rs");
let mut code = String::from("fn process(x: i32) -> i32 {\n");
code.push_str(" let mut result = x;\n");
for i in 0..50 {
code.push_str(&format!(
" result = result + {} - {} * {} / {};\n",
i,
i + 1,
i + 2,
i + 3
));
}
code.push_str(" result\n}\n");
fs::write(&file_path, code).unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 60,
jobs: Some(4),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: true,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("No mutants") || msg.contains("timeout"),
"Error should be acceptable: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_parallel_execution_scaling() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("parallel_test.rs");
fs::write(
&file_path,
r#"
fn add(a: i32, b: i32) -> i32 { a + b }
fn sub(a: i32, b: i32) -> i32 { a - b }
fn mul(a: i32, b: i32) -> i32 { a * b }
fn div(a: i32, b: i32) -> i32 { a / b }
"#,
)
.unwrap();
for jobs in [1, 2, 4, 8] {
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 30,
jobs: Some(jobs),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok()
|| result
.as_ref()
.err()
.map(|e| e.to_string().contains("No mutants"))
.unwrap_or(false),
"Parallel execution with {} jobs should work",
jobs
);
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_timeout_handling() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("timeout_test.rs");
fs::write(
&file_path,
r#"
fn compute(n: i32) -> i32 {
let mut sum = 0;
for i in 0..n {
sum += i;
}
sum
}
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 1, jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
match result {
Ok(_) => {
}
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("timeout") || msg.contains("No mutants") || msg.contains("Timed out"),
"Error should be timeout-related or no mutants: {}",
msg
);
}
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_memory_usage_bounds() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("memory_test.rs");
let mut code = String::new();
for i in 0..100 {
code.push_str(&format!("fn func_{}(x: i32) -> i32 {{ x + {} }}\n", i, i));
}
fs::write(&file_path, code).unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 30,
jobs: Some(2),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: true, use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok()
|| result
.as_ref()
.err()
.map(|e| !e.to_string().contains("out of memory"))
.unwrap_or(true),
"Should not run out of memory"
);
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_execution_time_bounds() {
use std::time::Instant;
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("time_test.rs");
fs::write(
&file_path,
r#"
fn add(a: i32, b: i32) -> i32 { a + b }
fn sub(a: i32, b: i32) -> i32 { a - b }
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 30,
jobs: Some(2),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let start = Instant::now();
let _result = handle(args, server).await;
let duration = start.elapsed();
assert!(
duration.as_secs() < 60,
"Small file mutation should complete within 60 seconds, took {:?}",
duration
);
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_parallel_mutant_execution_correctness() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("parallel.rs");
fs::write(
&file_path,
"fn add(a: i32, b: i32) -> i32 { a + b }\nfn sub(a: i32, b: i32) -> i32 { a - b }",
)
.unwrap();
let args = MutateArgs {
target: file_path,
language: None,
timeout: 30,
jobs: Some(4),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok()
|| result
.as_ref()
.err()
.map(|e| e.to_string().contains("No mutants"))
.unwrap_or(false)
);
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_race_condition_handling() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("race.rs");
fs::write(&file_path, "fn compute(x: i32) -> i32 { x * 2 + 1 }").unwrap();
for _ in 0..3 {
let args = MutateArgs {
target: file_path.clone(),
language: None,
timeout: 30,
jobs: Some(8),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let _ = handle(args, server).await;
}
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_resource_contention() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("contention.rs");
fs::write(&file_path, "fn process(n: i32) -> i32 { (0..n).sum() }").unwrap();
let args = MutateArgs {
target: file_path,
language: None,
timeout: 30,
jobs: Some(16),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: true,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok()
|| result
.as_ref()
.err()
.map(|e| !e.to_string().contains("panic"))
.unwrap_or(true)
);
}
#[tokio::test]
async fn test_graceful_shutdown_on_error() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("shutdown.rs");
fs::write(&file_path, "fn invalid syntax here").unwrap();
let args = MutateArgs {
target: file_path,
language: None,
timeout: 5,
jobs: Some(4),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(result.is_err() || result.as_ref().ok().is_some());
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_mutation_of_actual_pmat_code() {
use std::path::Path;
let pmat_file = Path::new("src/utils/path_validator.rs");
if !pmat_file.exists() {
return;
}
let args = MutateArgs {
target: pmat_file.to_path_buf(),
language: None,
timeout: 60,
jobs: Some(2),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: true,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok()
|| result
.as_ref()
.err()
.map(|e| e.to_string().contains("No mutants"))
.unwrap_or(false)
);
}
#[tokio::test]
async fn test_mutation_with_failing_tests() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("failing.rs");
fs::write(
&file_path,
r#"
fn buggy_add(a: i32, b: i32) -> i32 { a - b }
#[test]
fn test_add() { assert_eq!(buggy_add(2, 3), 5); }
"#,
)
.unwrap();
let args = MutateArgs {
target: file_path,
language: None,
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let _ = handle(args, server).await;
}
#[tokio::test]
#[ignore = "slow mutation test - run manually"]
async fn test_mutation_with_no_tests() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("notests.rs");
fs::write(&file_path, "fn add(a: i32, b: i32) -> i32 { a + b }").unwrap();
let args = MutateArgs {
target: file_path,
language: None,
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: false,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let result = handle(args, server).await;
assert!(
result.is_ok()
|| result
.as_ref()
.err()
.map(|e| e.to_string().contains("No mutants"))
.unwrap_or(false)
);
}
#[tokio::test]
async fn test_mutation_with_flaky_tests() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("flaky.rs");
fs::write(&file_path, r#"
use std::time::SystemTime;
fn time_dependent() -> bool { SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() % 2 == 0 }
#[test]
fn test_flaky() { assert!(time_dependent() || !time_dependent()); }
"#).unwrap();
let args = MutateArgs {
target: file_path,
language: None,
timeout: 30,
jobs: Some(1),
output_format: "json".to_string(),
output: None,
threshold: None,
failures_only: true,
use_cargo_mutants: false,
features: None,
all_features: false,
no_default_features: false,
no_shuffle: false,
};
let server = Arc::new(StatelessTemplateServer::new().unwrap());
let _ = handle(args, server).await;
}