Skip to content

Fix/post grep rtk cleanups - #5

Closed
isink17 wants to merge 3 commits into
feat/grep-agent-safe-jsonfrom
fix/post-grep-rtk-cleanups
Closed

Fix/post grep rtk cleanups#5
isink17 wants to merge 3 commits into
feat/grep-agent-safe-jsonfrom
fix/post-grep-rtk-cleanups

Conversation

@isink17

@isink17 isink17 commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

Test plan

  • cargo fmt --all && cargo clippy --all-targets && cargo test
  • Manual testing: rtk <command> output inspected

Important: All PRs must target the develop branch (not master).
See CONTRIBUTING.md for details.

Ivan Sinkovic and others added 3 commits May 7, 2026 18:43
… blocks + failed summaries, drops passing-test noise, handles ctest -V prefixes, and filters combined stdout/stderr.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new ctest command and output filter to display compact GoogleTest failure summaries, updates git argument parsing to treat filenames with extensions as paths if they exist, and fixes log truncation to use character counts instead of byte lengths. The review feedback highlights a logic bug in the ctest summary line parser that causes dead code, an O(N^2) performance bottleneck in the line compaction helper, and opportunities to optimize string length checks from O(N) to O(1) in the log analyzer.

Comment on lines +176 to +188
fn is_gtest_failed_summary_line(line: &str) -> bool {
// Summary/listing:
// "[ FAILED ] 1 test, listed below:"
// "[ FAILED ] Foo.Fail"
// "[ PASSED ] 2 tests."
if line.starts_with("[ FAILED ]") {
return true;
}
if line.starts_with("[ PASSED ]") && line.contains("tests") {
return true;
}
false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The is_gtest_failed_summary_line function returns true for any line starting with [ FAILED ]. However, individual test failure lines (e.g., [ FAILED ] Foo.Fail (0 ms)) also start with this prefix. Because is_gtest_failed_summary_line is checked before emitting_failure_block in the main loop, individual test failure lines will match the summary check first. This makes the is_gtest_failed_test_line check dead code and prevents current_test from being reset to None.

To fix this, ensure that is_gtest_failed_summary_line excludes lines containing ( (which indicate individual test failure lines).

Suggested change
fn is_gtest_failed_summary_line(line: &str) -> bool {
// Summary/listing:
// "[ FAILED ] 1 test, listed below:"
// "[ FAILED ] Foo.Fail"
// "[ PASSED ] 2 tests."
if line.starts_with("[ FAILED ]") {
return true;
}
if line.starts_with("[ PASSED ]") && line.contains("tests") {
return true;
}
false
}
fn is_gtest_failed_summary_line(line: &str) -> bool {
// Summary/listing:
// "[ FAILED ] 1 test, listed below:"
// "[ FAILED ] Foo.Fail"
// "[ PASSED ] 2 tests."
if line.starts_with("[ FAILED ]") && !line.contains('(') {
return true;
}
if line.starts_with("[ PASSED ]") && line.contains("tests") {
return true;
}
false
}

Comment on lines +218 to +225
fn compact_lines(mut lines: Vec<String>) -> Vec<String> {
// Trim leading/trailing empties, collapse multiple blank lines.
while lines.first().is_some_and(|l| l.trim().is_empty()) {
lines.remove(0);
}
while lines.last().is_some_and(|l| l.trim().is_empty()) {
lines.pop();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using lines.remove(0) in a loop is highly inefficient because it shifts all remaining elements in the vector on each iteration, resulting in $O(N^2)$ time complexity.

We can optimize this to $O(N)$ by finding the first and last non-empty indices using position and rposition, and then draining the range directly.

fn compact_lines(mut lines: Vec<String>) -> Vec<String> {
    // Trim leading/trailing empties, collapse multiple blank lines.
    let first_non_empty = lines.iter().position(|l| !l.trim().is_empty()).unwrap_or(lines.len());
    let last_non_empty = lines.iter().rposition(|l| !l.trim().is_empty()).map(|idx| idx + 1).unwrap_or(0);
    if first_non_empty >= last_non_empty {
        return Vec::new();
    }

    let mut out: Vec<String> = Vec::with_capacity(last_non_empty - first_non_empty);
    let mut last_blank = false;
    for l in lines.drain(first_non_empty..last_non_empty) {
        let blank = l.trim().is_empty();
        if blank {
            if last_blank {
                continue;
            }
            last_blank = true;
            out.push(String::new());
        } else { 
            last_blank = false;
            out.push(l);
        }
    }
    out
}

Comment on lines +143 to 146
let truncated = if original.chars().count() > 100 {
let t: String = original.chars().take(97).collect();
format!("{}...", t)
} else {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Calling original.chars().count() traverses the entire string, which is an $O(N)$ operation. If a log line is extremely long (e.g., several megabytes), this can cause a severe performance bottleneck.

Since we only need to check if the character count exceeds 100, we can optimize this to $O(1)$ by using .take(101).count().

Suggested change
let truncated = if original.chars().count() > 100 {
let t: String = original.chars().take(97).collect();
format!("{}...", t)
} else {
let truncated = if original.chars().take(101).count() > 100 {
let t: String = original.chars().take(97).collect();
format!("{}...", t)
} else {

Comment on lines +183 to 186
let truncated = if original.chars().count() > 100 {
let t: String = original.chars().take(97).collect();
format!("{}...", t)
} else {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Calling original.chars().count() traverses the entire string, which is an $O(N)$ operation. If a log line is extremely long (e.g., several megabytes), this can cause a severe performance bottleneck.

Since we only need to check if the character count exceeds 100, we can optimize this to $O(1)$ by using .take(101).count().

Suggested change
let truncated = if original.chars().count() > 100 {
let t: String = original.chars().take(97).collect();
format!("{}...", t)
} else {
let truncated = if original.chars().take(101).count() > 100 {
let t: String = original.chars().take(97).collect();
format!("{}...", t)
} else {

@isink17 isink17 closed this May 28, 2026
isink17 pushed a commit that referenced this pull request Aug 6, 2026
The comment was previously added in response to review point #5. Removed
per follow-up feedback — the arm itself is self-explanatory in context
alongside the other Host variants.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant