use crate::util; use std::path::PathBuf; use anyhow::Result; use assert_fs::prelude::*; use indoc::{formatdoc, indoc}; use predicates::prelude::*; #[test] fn cyclic_includes() -> Result<()> { for handling in [None, Some("error"), Some("warn"), Some("ignore")] { let builder = util::builder() .source_file("#include ")? .search_dir( "-d", [("a.hpp", "#include "), ("b.hpp", "#include ")], )?; let mut command = builder.command(); if let Some(handling) = handling { command.args(["--cyclic-include", handling]); } let mut assert = command.assert(); let handling = handling.unwrap_or("error"); if handling == "error" { assert = assert.failure(); } else { assert = assert.success().stdout("#include "); } if handling != "ignore" { assert.stderr(predicate::str::is_empty().not()); } } Ok(()) } #[test] fn cyclic_include_back_to_source_file() -> Result<()> { let mut a_path = PathBuf::new(); util::builder() .search_dir_setup("-d", |dir| { dir.child("a.hpp").write_str("#include ")?; dir.child("b.hpp").write_str("#include ")?; a_path = dir.child("a.hpp").to_path_buf(); Ok(()) })? .command() .arg(a_path) .assert() .failure(); Ok(()) } #[test] fn already_included_source_file() -> Result<()> { let mut include_path = PathBuf::new(); util::builder() .source_file("#include ")? .search_dir_setup("-d", |dir| { dir.child("a.hpp").write_str("arst")?; include_path = dir.child("a.hpp").to_path_buf(); Ok(()) })? .command() .arg(include_path) .assert() .success() .stdout("arst"); Ok(()) } #[test] fn include_headers_at_most_once() -> Result<()> { util::builder() .source_file(indoc! {" #include #include "})? .search_dir("-d", [("a.hpp", "#include "), ("b.hpp", "arst\n")])? .command() .assert() .success() .stdout("arst\n"); Ok(()) } #[test] fn file_identity_considers_symlinks() -> Result<()> { util::builder() .source_file(indoc! {" #include #include "})? .search_dir_setup("-d", |dir| { dir.child("a.hpp").write_str("arst\n")?; dir.child("b.hpp").symlink_to_file(dir.child("a.hpp"))?; Ok(()) })? .command() .assert() .success() .stdout("arst\n"); Ok(()) } #[test] fn weird_include_statements() -> Result<()> { util::builder() .source_file("# \t include \t \t ")? .search_dir("-d", [("a.hpp", "arst")])? .command() .assert() .success() .stdout("arst"); Ok(()) } #[test] fn line_directives() -> Result<()> { let builder = util::builder() .source_file(indoc! {" arst #include arst #include arst "})? .search_dir("-d", [("a.hpp", "#include \n"), ("b.hpp", "qwfp\n")])?; let src_file = builder.source_files[0].to_path_buf().canonicalize()?; let dir = &builder.search_dirs[0].1; let b_hpp = dir.child("b.hpp").to_path_buf().canonicalize()?; builder .command() .arg("--line-directives") .assert() .success() .stdout(formatdoc! {r#" #line 1 "{src_file}" arst #line 1 "{b_hpp}" qwfp #line 3 "{src_file}" arst #line 6 "{src_file}" arst "#, src_file=src_file.display(), b_hpp=b_hpp.display() }); Ok(()) } #[test] fn pragma_once_removal() -> Result<()> { util::builder() .source_file(indoc! {" #include #include "})? .search_dir( "-d", [ ("a.hpp", "#pragma once\n"), ("b.hpp", "# \tpragma\t once \t\n"), ], )? .command() .assert() .success() .stdout(""); Ok(()) }