use splice::ingest::imports::{extract_cpp_imports, ImportKind};
use std::path::Path;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_system_include() {
let source = b"#include <stdio.h>\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["stdio.h"]);
assert_eq!(imports[0].imported_names, vec!["stdio.h"]);
assert!(!imports[0].is_glob);
}
#[test]
fn test_extract_local_include() {
let source = b"#include \"myheader.h\"\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppLocalInclude);
assert_eq!(imports[0].path, vec!["myheader.h"]);
assert_eq!(imports[0].imported_names, vec!["myheader.h"]);
assert!(!imports[0].is_glob);
}
#[test]
fn test_extract_nested_system_include() {
let source = b"#include <boost/filesystem.hpp>\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.cpp"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["boost", "filesystem.hpp"]);
assert_eq!(imports[0].imported_names, vec!["boost/filesystem.hpp"]);
assert!(!imports[0].is_glob);
}
#[test]
fn test_extract_nested_local_include() {
let source = b"#include \"utils/helper.h\"\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.cpp"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppLocalInclude);
assert_eq!(imports[0].path, vec!["utils", "helper.h"]);
assert_eq!(imports[0].imported_names, vec!["utils/helper.h"]);
assert!(!imports[0].is_glob);
}
#[test]
fn test_extract_multiple_includes() {
let source = b"
#include <stdio.h>
#include \"local.h\"
#include <vector>
#include \"utils/helper.h\"
";
let imports =
extract_cpp_imports(Path::new("/tmp/test.cpp"), source).expect("Failed to parse");
assert_eq!(imports.len(), 4);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["stdio.h"]);
assert_eq!(imports[1].import_kind, ImportKind::CppLocalInclude);
assert_eq!(imports[1].path, vec!["local.h"]);
assert_eq!(imports[2].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[2].path, vec!["vector"]);
assert_eq!(imports[3].import_kind, ImportKind::CppLocalInclude);
assert_eq!(imports[3].path, vec!["utils", "helper.h"]);
}
#[test]
fn test_extract_include_with_whitespace() {
let source = b"#include < stdio.h >\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert!(imports[0].path.last().is_some_and(|p| p.contains("stdio")));
}
#[test]
fn test_extract_include_in_conditional() {
let source = b"
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 2);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["windows.h"]);
assert_eq!(imports[1].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[1].path, vec!["unistd.h"]);
}
#[test]
fn test_empty_source() {
let source = b"int main() { return 0; }\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 0);
}
#[test]
fn test_include_with_code_after() {
let source = b"#include <stdio.h>\nint main() { return 0; }\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["stdio.h"]);
}
#[test]
fn test_cpp_system_include_has_byte_span() {
let source = b"#include <stdio.h>\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].byte_span, (0, 19));
}
#[test]
fn test_cpp_local_include_has_byte_span() {
let source = b"#include \"myheader.h\"\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].byte_span, (0, 22));
}
#[test]
fn test_deeply_nested_include_path() {
let source = b"#include \"project/internal/utils/helper.h\"\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.cpp"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppLocalInclude);
assert_eq!(
imports[0].path,
vec!["project", "internal", "utils", "helper.h"]
);
assert_eq!(
imports[0].imported_names,
vec!["project/internal/utils/helper.h"]
);
}
#[test]
fn test_include_no_newline() {
let source = b"#include <stdio.h>";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["stdio.h"]);
}
#[test]
fn test_include_with_comment_before() {
let source = b"// Standard I/O\n#include <stdio.h>\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.c"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["stdio.h"]);
}
#[test]
fn test_angle_bracket_include_windows_style() {
let source = b"#include <Windows.h>\n";
let imports =
extract_cpp_imports(Path::new("/tmp/test.cpp"), source).expect("Failed to parse");
assert_eq!(imports.len(), 1);
assert_eq!(imports[0].import_kind, ImportKind::CppSystemInclude);
assert_eq!(imports[0].path, vec!["Windows.h"]);
}
}