use cmake_file_api::{objects, reply};
#[test]
fn test_missing_api() {
let tmp_dir = tempdir::TempDir::new("test_cmake").unwrap();
let empty_dir = tmp_dir.path();
assert_eq!(reply::is_available(&empty_dir), false);
assert!(reply::index_file(&empty_dir).is_none());
assert!(matches!(
reply::Reader::from_build_dir(&empty_dir),
Err(reply::ReaderError::FileApiNotGenerated)
));
}
#[test]
fn test_json_parser_error() {
let tmp_dir = tempdir::TempDir::new("test_cmake").unwrap();
let build_dir = tmp_dir.path();
std::fs::create_dir_all(&reply::dir(&build_dir)).unwrap();
let broken_index_file = reply::dir(&build_dir).join("index-broken.json");
std::fs::write(&broken_index_file, "broken").unwrap();
assert_eq!(reply::is_available(&build_dir), true);
assert_eq!(
reply::index_file(&build_dir),
Some(broken_index_file.clone())
);
assert!(matches!(
reply::Reader::from_build_dir(&build_dir),
Err(reply::ReaderError::Parse(_))
));
}
#[test]
fn test_valid_api() {
let tmp_dir = tempdir::TempDir::new("test_cmake").unwrap();
let project_dir = tmp_dir.path();
{
let main_cpp = project_dir.join("main.cpp");
std::fs::write(&main_cpp, "int main() { return 0; }").expect("Failed to write main.cpp");
}
{
let libfoo_dir = project_dir.join("libfoo");
std::fs::create_dir(&libfoo_dir).unwrap();
let libfoo_cpp = libfoo_dir.join("libfoo.cpp");
std::fs::write(
libfoo_cpp,
r#"
extern int foo();
"#,
)
.expect("Failed to write libfoo.cpp");
let libfoo_h = libfoo_dir.join("libfoo.h");
std::fs::write(
libfoo_h,
r#"
#include <libfoo.cpp>
int foo() { return 42; }
"#,
)
.expect("Failed to write libfoo.h");
let cmake_lists = libfoo_dir.join("CMakeLists.txt");
std::fs::write(
cmake_lists,
r#"
add_library(foo libfoo.cpp libfoo.h)
target_include_directories(foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
"#,
)
.expect("Failed to write CMakeLists.txt");
}
{
let cmake_lists = project_dir.join("CMakeLists.txt");
std::fs::write(
cmake_lists,
r#"
cmake_minimum_required(VERSION 3.10)
project(test_cmake)
add_subdirectory(libfoo)
add_executable(test_cmake main.cpp)
target_link_libraries(test_cmake foo)
"#,
)
.expect("Failed to write CMakeLists.txt");
}
let build_dir = tmp_dir.path().join("build");
cmake_file_api::query::Writer::default()
.request_all_objects()
.write_stateless(&build_dir)
.expect("Failed to write query");
assert!(std::process::Command::new("cmake")
.arg("-S")
.arg(&project_dir)
.arg("-B")
.arg(&build_dir)
.status()
.expect("Failed to run cmake")
.success());
assert!(reply::is_available(&build_dir));
assert!(reply::index_file(&build_dir).is_some());
let reader =
reply::Reader::from_build_dir(&build_dir).expect("Reply reader should be available");
assert!(reader.has_object::<cmake_file_api::objects::CodeModelV2>());
assert!(reader.has_object::<cmake_file_api::objects::ConfigureLogV1>());
assert!(reader.has_object::<cmake_file_api::objects::CacheV2>());
assert!(reader.has_object::<cmake_file_api::objects::ToolchainsV1>());
assert!(reader.has_object::<cmake_file_api::objects::CMakeFilesV1>());
let codemodel: objects::CodeModelV2 = reader.read_object().expect("codemodel should be available");
assert!(codemodel.configurations.len() > 0);
assert!(codemodel.configurations[0].targets.len() > 0);
assert_eq!(
codemodel.configurations[0].targets.len(),
codemodel.configurations[0].target_refs.len()
);
assert!(codemodel.configurations[0].directories.len() > 0);
assert_eq!(
codemodel.configurations[0].directories.len(),
codemodel.configurations[0].directory_refs.len()
);
}