fn test_PORTABILITY_001_detect_bashisms() {
let makefile = r#"
test:
if [[ -f file.txt ]]; then echo "found"; fi
result=$$((1 + 2))
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("bashism") || r.contains("[[") || r.contains("POSIX")),
"Should detect bashisms like [[ and $(())"
);
}
#[test]
fn test_PORTABILITY_002_detect_gnu_make_extensions() {
let makefile = r#"
%.o: %.c
gcc -c $< -o $@
build: $(wildcard *.c)
gcc -o app $^
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
let _ = result.transformations_applied; }
#[test]
fn test_PORTABILITY_003_detect_platform_specific_commands() {
let makefile = r#"
detect:
uname -s
cat /proc/cpuinfo
ifconfig
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("platform") || r.contains("portable") || r.contains("uname")),
"Should detect platform-specific commands like uname, /proc, ifconfig"
);
}
#[test]
fn test_PORTABILITY_004_detect_shell_specific_features() {
let makefile = r#"
build:
echo $$RANDOM
source setup.sh
declare -a array=(1 2 3)
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("source") || r.contains("declare") || r.contains("bash")),
"Should detect bash-specific features like source and declare"
);
}
#[test]
fn test_PORTABILITY_005_detect_path_separator_issues() {
let makefile = r#"
build:
gcc -I/usr/local/include -L/usr/local/lib app.c
install -m 755 app /usr/local/bin/app
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
let _ = result.transformations_applied; }
#[test]
fn test_PORTABILITY_006_preserve_portable_constructs() {
let makefile = r#"
build:
if [ -f file.txt ]; then echo "found"; fi
result=`expr 1 + 2`
. setup.sh
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
let _ = result.transformations_applied; }
#[test]
fn test_PORTABILITY_007_detect_non_portable_flags() {
let makefile = r#"
build:
cp --preserve=all src dest
ls --color=auto
grep --color=always pattern file
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("--") || r.contains("GNU") || r.contains("portable")),
"Should detect GNU-specific long flags like --preserve, --color"
);
}
#[test]
fn test_PORTABILITY_008_detect_echo_flags() {
let makefile = r#"
build:
echo -e "Line1\nLine2"
echo -n "No newline"
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("echo") || r.contains("printf") || r.contains("portable")),
"Should detect non-portable echo -e and echo -n (recommend printf)"
);
}
#[test]
fn test_PORTABILITY_009_detect_sed_in_place() {
let makefile = r#"
build:
sed -i 's/old/new/g' file.txt
sed -i.bak 's/foo/bar/' data.txt
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("sed") || r.contains("portable") || r.contains("-i")),
"Should detect sed -i as non-portable GNU extension"
);
}
#[test]
fn test_PORTABILITY_010_comprehensive_portability_check() {
let makefile = r#"
build:
if [[ -f file.txt ]]; then echo -e "Found\n"; fi
uname -s
source env.sh
cp --preserve=all src dest
sed -i 's/old/new/' file
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result.transformations_applied >= 1,
"Should detect multiple portability issues ([[, echo -e, uname, source, --, sed -i)"
);
}
#[test]
fn test_PROPERTY_001_idempotency() {
let makefile = r#"
FILES = $(wildcard *.c)
build:
mkdir build
gcc -c main.c
echo "Done"
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result1 = purify_makefile(&ast);
let result2 = purify_makefile(&ast);
assert_eq!(
result1.report.len(),
result2.report.len(),
"Purification should be idempotent - same recommendations"
);
assert_eq!(
result1.transformations_applied, result2.transformations_applied,
"Purification should apply same number of transformations"
);
}
#[test]
fn test_PROPERTY_002_parallel_safety_preserved() {
let makefile = r#"
all: build test
build:
gcc -c main.c -o main.o
test:
./test.sh
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
let _ = result.transformations_applied; }
#[test]
fn test_PROPERTY_003_reproducibility_enforced() {
let makefile = r#"
VERSION = $(shell date +%s)
build:
echo "Version: $$RANDOM"
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("date") || r.contains("RANDOM") || r.contains("deterministic")),
"Should detect non-deterministic patterns"
);
}
#[test]
fn test_PROPERTY_004_performance_optimizations() {
let makefile = r#"
VAR = $(shell echo test)
FILES = $(wildcard *.c)
build:
gcc -c file1.c
gcc -c file2.c
gcc -c file3.c
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result.transformations_applied >= 1,
"Should recommend performance optimizations"
);
}
#[test]
fn test_PROPERTY_005_error_handling_completeness() {
let makefile = r#"
build:
mkdir build
gcc -c main.c
cp main.o build/
"#;
let ast = crate::make_parser::parser::parse_makefile(makefile).unwrap();
let result = purify_makefile(&ast);
assert!(
result
.report
.iter()
.any(|r| r.contains("error") || r.contains("exit") || r.contains("DELETE_ON_ERROR")),
"Should recommend error handling improvements"
);
}
include!("tests_tests_INTEGRATION.rs");