Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/fensu-cli/src/check/_helpers/evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ pub(crate) fn render_results(
mut results: Vec<CheckResult>,
root: &Path,
color: bool,
show_warnings: bool,
(show_warnings, incomplete): (bool, bool),
) -> (String, i32) {
let selected = results.iter().map(|result| result.selected).sum::<usize>();
let excluded = results.iter().map(|result| result.excluded).sum::<usize>();
Expand Down Expand Up @@ -1009,6 +1009,7 @@ pub(crate) fn render_results(
evaluation_summary: summary.as_deref(),
applied_exceptions,
threshold_uses: &threshold_uses,
incomplete,
});
(output, i32::from(!faults.is_empty()))
}
Expand Down
3 changes: 2 additions & 1 deletion crates/fensu-cli/src/check/_helpers/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pub(crate) fn render_check(
let cacheable = results
.iter()
.all(|result| result.cacheable.unwrap_or(true));
let (output, exit_code) = render_results(results, &plan.root, plan.color, options.warn);
let (output, exit_code) =
render_results(results, &plan.root, plan.color, (options.warn, false));
let mut stderr = String::new();
stderr.push_str(&freshness(&plan));
if options.cache_stats {
Expand Down
11 changes: 8 additions & 3 deletions crates/fensu-cli/src/check/main/render_check_results.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Render one aggregate set of analyzer check results.
//! Render one aggregate set of analyzer check results, marked incomplete when a target could not run.

use std::path::Path;

Expand All @@ -8,7 +8,12 @@ pub(crate) fn render_check_results(
results: Vec<CheckResult>,
root: &Path,
color: bool,
show_warnings: bool,
(show_warnings, incomplete): (bool, bool),
) -> (String, i32) {
crate::check::_helpers::evaluation::render_results(results, root, color, show_warnings)
crate::check::_helpers::evaluation::render_results(
results,
root,
color,
(show_warnings, incomplete),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ fn structured_check(request: StructuredCheckRequest<'_>) -> CliOutput {
let (stdout, report_exit_code) = if command_error && results.is_empty() {
(String::new(), 0)
} else {
render_check_results(results, &root, color, show_warnings)
render_check_results(results, &root, color, (show_warnings, command_error))
};
let mut stderr = String::new();
if show_cache_stats {
Expand Down
11 changes: 9 additions & 2 deletions crates/fensu-cli/src/reporting/main/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ pub(crate) fn report(request: ReportRequest<'_>) -> String {
} else {
"faults"
};
let mut summary = format!("Found {} {noun}", request.faults.len());
let mut summary = if request.incomplete {
format!(
"Check incomplete: found {} {noun} in the targets that ran",
request.faults.len()
)
} else {
format!("Found {} {noun}", request.faults.len())
};
if request.show_warnings {
let noun = if request.warnings.len() == 1 {
"warning"
Expand All @@ -24,7 +31,7 @@ pub(crate) fn report(request: ReportRequest<'_>) -> String {
summary.push_str(&format!(" and {} {noun}", request.warnings.len()));
}
if request.color {
let style = if request.faults.is_empty() {
let style = if request.faults.is_empty() && !request.incomplete {
GREEN
} else {
ORANGE
Expand Down
2 changes: 2 additions & 0 deletions crates/fensu-cli/src/reporting/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ pub(crate) struct ReportRequest<'a> {
pub(crate) evaluation_summary: Option<&'a str>,
pub(crate) applied_exceptions: usize,
pub(crate) threshold_uses: &'a [ThresholdUse],
/// Whether a target could not run, so the faults cover only the targets that did.
pub(crate) incomplete: bool,
}
1 change: 1 addition & 0 deletions crates/fensu-cli/src/tests/test_render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fn given_colored_faults_when_rendering_then_uses_historical_orange_styles() {
evaluation_summary: None,
applied_exceptions: 0,
threshold_uses: &[],
incomplete: false,
});

assert_eq!(
Expand Down
55 changes: 55 additions & 0 deletions crates/fensu-cli/tests/command/test_check_mixed_targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,58 @@ fn given_custom_python_rust_and_web_rules_when_checking_then_native_and_hosted_t
}
}
}

#[test]
fn given_custom_python_and_rust_targets_without_cargo_when_checking_then_the_summary_says_incomplete(
) {
let test_cases = [crate::test_types::RustMixedTargetUnavailableTestCase {
description: "a Rust target that cannot run fails the check, and the summary of the \
Python findings says the check is incomplete",
expected_exit_code: 2,
expected_error: "FPRSL902 Rust analysis cannot run: cargo not found",
expected_summary: "Check incomplete: found 1 fault in the targets that ran",
}];
for test_case in test_cases {
let repository = tempfile::tempdir().expect("temporary repository");
write(
repository.path().join("Cargo.toml"),
"[package]\nname = \"example\"\nversion = \"0.1.0\"\nedition = \"2021\"\n",
);
write(
repository.path().join("src/lib.rs"),
"pub fn sum(left: usize, right: usize) -> usize { left + right }\n",
);
write(
repository.path().join("python/value.py"),
"def value(item):\n return item\n",
);
write(repository.path().join("rules/custom.py"), "import ast\nfrom fensu import Family, Fault, RuleContext, rule\n@rule(code='XMIX001', family=Family.CUSTOM, slug='mixed-python', message='mixed Python')\ndef mixed_python(module: ast.Module, ctx: RuleContext) -> list[Fault]:\n return []\n");
write(repository.path().join("fensu.toml"), "[targets.python]\nanalyzer = \"python\"\nroots = [\"python\"]\ntests = []\ntooling = []\nselect = [\"FFA001\", \"XMIX001\"]\nrule_paths = [\"rules/custom.py\"]\n[targets.rust]\nanalyzer = \"rust\"\nroots = [\"src\"]\ntests = []\ntooling = []\nrule_packs = [\"rust\"]\nselect = [\"FPRSS010\"]\n");
let output = std::process::Command::new(env!("CARGO_BIN_EXE_fensu"))
.args(["check", "--no-color", "--no-cache"])
.current_dir(repository.path())
.env("FENSU_PYTHON", crate::helpers::workspace_python())
.env("CARGO", "/cargo-does-not-exist/cargo")
.env("PATH", "/cargo-does-not-exist")
.output()
.expect("mixed check runs");
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
assert_eq!(
output.status.code(),
Some(test_case.expected_exit_code),
"{}: {stdout} {stderr}",
test_case.description
);
assert!(
stderr.contains(test_case.expected_error),
"{}: {stderr}",
test_case.description
);
assert!(
stdout.contains(test_case.expected_summary) && !stdout.contains("Found "),
"{}: {stdout}",
test_case.description
);
}
}
7 changes: 7 additions & 0 deletions crates/fensu-cli/tests/command/test_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ pub(crate) struct RustMixedTargetTestCase {
pub(crate) expected_codes: &'static [&'static str],
}

pub(crate) struct RustMixedTargetUnavailableTestCase {
pub(crate) description: &'static str,
pub(crate) expected_exit_code: i32,
pub(crate) expected_error: &'static str,
pub(crate) expected_summary: &'static str,
}

pub(crate) struct RepositoryRuleTestCase {
pub(crate) description: &'static str,
pub(crate) expected_exit_code: i32,
Expand Down
8 changes: 8 additions & 0 deletions docs/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ FPRSL902 Rust analysis cannot run: cargo not found; install the Rust toolchain (

`FPRSL901` remains the code for a manifest that cannot be read, parsed, or accepted by a working
`cargo`.

When other targets did run, their faults are still printed, and the summary says the check is
incomplete instead of reporting a count for the whole repository:

```text
Check incomplete: found 1 fault in the targets that ran
```

## File placement and embedded resources

The `rust` pack enables `FPRSR311` (`rust-rsr311`) and `FPRSL106` (`rust-rsl106`)
Expand Down
Loading