Conversation
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis PR refactors the Ninja test setup to inject a mockable Env trait instead of using std::env directly, defines a helper for creating a MockEnv that returns a consistent PATH, and updates safety documentation around setting the PATH by restoring the original value after tests. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Warning Rate limit exceeded@leynos has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 26 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (6)
Summary by CodeRabbit
WalkthroughReplace ad-hoc PATH management in tests with a PathGuard RAII and mockable Env. Add support modules Changes
Sequence Diagram(s)sequenceDiagram
participant Test as Tester
participant Steps as install_test_ninja
participant Env
participant OS
participant Guard as PathGuard
participant World as CliWorld
Test->>Steps: call (&Env, &mut World, dir, ninja_path)
Steps->>Env: raw("PATH")
Env-->>Steps: original_PATH
Steps->>OS: set PATH = dir + ":" + original_PATH
Steps->>Guard: PathGuard::new(original_PATH)
Steps->>World: store path_guard = Some(Guard), ninja, temp
Note over Guard,OS: On drop (end of scenario) Guard restores PATH to original
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Hey @leynos - I've reviewed your changes - here's some feedback:
- Extract the repeated mocked_path_env() setup into a shared test fixture or helper to avoid duplicating it in every fake_ninja scenario.
- Encapsulate the unsafe std::env::set_var and PATH restoration into a safe RAII helper or scoped-env utility to guarantee cleanup even if tests panic.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Extract the repeated mocked_path_env() setup into a shared test fixture or helper to avoid duplicating it in every fake_ninja scenario.
- Encapsulate the unsafe std::env::set_var and PATH restoration into a safe RAII helper or scoped-env utility to guarantee cleanup even if tests panic.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Actionable comments posted: 5
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
tests/cucumber.rs(1 hunks)tests/runner_tests.rs(1 hunks)tests/steps/process_steps.rs(4 hunks)tests/support/mod.rs(3 hunks)tests/support/path_guard.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit Inference Engine (AGENTS.md)
**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Use functions and composition. Avoid repetition by extracting reusable logic. Prefer generators or comprehensions, and declarative code to imperative repetition when readable.
Small, meaningful functions. Functions must be small, clear in purpose, single responsibility, and obey command/query segregation.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Prefer .expect() over .unwrap().
Use concat!() to combine long string literals rather than escaping newlines with a backslash.
Prefer single line versions of functions where appropriate.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Keep file size manageable. No single code file may be longer than 400 lines. Long switch statements or dispatch tables should be broken up by feature and constituents colocated with targets. Large blocks of test data should be moved to external data files.
Illustrate with clear examples. Function documentation must include clear examples demonstrating the usage and outcome of the function. Test documentation should omit examples where the example serves only to reiterate the test logic.
Prefer semantic error enums. Derive std::error::Error (via the thiserror crate) for any condition the caller might inspect, retry, or map to an HTTP status.
...
Files:
tests/cucumber.rstests/steps/process_steps.rstests/runner_tests.rstests/support/path_guard.rstests/support/mod.rs
⚙️ CodeRabbit Configuration File
**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.
Adhere to single responsibility and CQRS
Place function attributes after doc comments.
Do not use
returnin single-line functions.Move conditionals with >2 branches into a predicate function.
Avoid
unsafeunless absolutely necessary.Every module must begin with a
//!doc comment that explains the module's purpose and utility.Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
Lints must not be silenced except as a last resort.
#[allow]is forbidden.- Only narrowly scoped
#[expect(lint, reason = "...")]is allowed.- No lint groups, no blanket or file-wide suppression.
- Include
FIXME:with link if a fix is expected.Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
Use
rstestfixtures for shared setup and to avoid repetition between tests.Replace duplicated tests with
#[rstest(...)]parameterised cases.Prefer
mockallfor mocks/stubs.Prefer
.expect()over.unwrap()Ensure that any API or behavioural changes are reflected in the documentation in
docs/Ensure that any completed roadmap steps are recorded in the appropriate roadmap in
docs/Files must not exceed 400 lines in length
- Large modules must be decomposed
- Long match statements or dispatch tables should be decomposed by domain and collocated with targets
- Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
Files:
tests/cucumber.rstests/steps/process_steps.rstests/runner_tests.rstests/support/path_guard.rstests/support/mod.rs
🧬 Code Graph Analysis (2)
tests/steps/process_steps.rs (2)
tests/support/path_guard.rs (1)
new(23-25)tests/support/mod.rs (2)
mocked_path_env(95-102)fake_ninja_check_build_file(113-137)
tests/support/mod.rs (1)
tests/support/path_guard.rs (1)
new(23-25)
🔍 MCP Research (1 server)
Deepwiki:
- DeepWiki result (https://deepwiki.com/search/inject-mock-env-for-ninja-test_74bedf4b-ca1e-41d5-acdc-cbab19c7bae3): netsuke uses rstest fixtures to provide controlled test resources (e.g., temp directories) and insta for snapshot testing; injecting a "mock env" for Ninja tests is achieved by controlling the manifest/IR inputs to ninja_gen::generate_ninja rather than mocking the Ninja binary itself.
- DeepWiki result (docs/rust-testing-with-rstest-fixtures.md): shows using rstest fixtures for temporary directories and cleanup semantics useful for isolating tests that touch filesystem or env.
- DeepWiki result (docs/snapshot-testing-in-netsuke-using-insta.md): documents the snapshot-testing workflow for build.ninja output, including use of Settings::set_snapshot_path and the expectation that ninja_gen::generate_ninja must produce deterministic output from a given IR.
🔇 Additional comments (6)
tests/support/path_guard.rs (1)
28-33: Well-documented unsafe usageThe unsafe block is properly justified with a clear comment explaining why setting PATH is safe in this context.
tests/runner_tests.rs (1)
7-8: Good refactoring to centralize PathGuardMoving
PathGuardto the support module improves code reusability across test files.tests/cucumber.rs (1)
22-23: Improved PATH restoration using RAII patternReplacing manual Drop implementation with
PathGuardsimplifies the code and ensures PATH restoration even on panics.tests/support/mod.rs (1)
95-102: Well-structured mock environment fixtureThe
mocked_path_envfixture properly captures the original PATH and provides a clean interface for tests.tests/steps/process_steps.rs (2)
16-29: Excellent dependency injection and safety documentationThe refactored function properly accepts an
Envtrait for better testability, and the unsafe block is well-documented with a clear SAFETY comment explaining the PathGuard restoration mechanism.
33-37: Consistent use of mocked environment across test stepsAll test steps now consistently use
support::mocked_path_env()for PATH management, improving test isolation.Also applies to: 41-45, 53-58
There was a problem hiding this comment.
Code Health Improved
(1 files improve in Code Health)
Gates Passed
6 Quality Gates Passed
See analysis details in CodeScene
View Improvements
| File | Code Health Impact | Categories Improved |
|---|---|---|
| mod.rs | 9.39 → 10.00 | Code Duplication |
Quality Gate Profile: Pay Down Tech Debt
Want more control? Customize Code Health rules or catch issues early with our IDE extension and CLI tool.
| unfulfilled_lint_expectations, | ||
| reason = "used only in some test crates" | ||
| )] | ||
| #[expect(dead_code, reason = "used in PATH tests")] |
There was a problem hiding this comment.
style: The #[expect(dead_code)] attribute is positioned before the function documentation comment, which should be placed after doc comments according to project style guidelines.
| #[expect(dead_code, reason = "used in PATH tests")] | |
| /// Build a valid `PATH` string that contains exactly one entry pointing to | |
| /// `dir` and configure the mock to return it. This avoids lossy conversions | |
| /// and makes the UTF-8 requirement explicit to callers. | |
| /// | |
| /// Note: `MockEnv::raw` returns a `String`, so callers must accept UTF-8. This | |
| /// helper returns an error if the constructed `PATH` cannot be represented as | |
| /// UTF-8. | |
| #[expect(dead_code, reason = "used in PATH tests")] |
Context Used: Rule - Place function attributes after doc comments. (link)
| /// | ||
| /// Returns the temporary directory and the path to the executable. | ||
| #[allow(unfulfilled_lint_expectations, reason = "used only in directory tests")] | ||
| #[expect(dead_code, reason = "used only in directory tests")] |
There was a problem hiding this comment.
style: The #[expect(dead_code)] attribute is positioned before the function documentation comment, which should be placed after doc comments according to project style guidelines.
| #[expect(dead_code, reason = "used only in directory tests")] | |
| /// Create a fake Ninja executable that writes its current directory to the file | |
| /// specified as the first argument. | |
| /// | |
| /// Returns the temporary directory and the path to the executable. | |
| #[expect(dead_code, reason = "used only in directory tests")] |
Context Used: Rule - Place function attributes after doc comments. (link)
There was a problem hiding this comment.
Code Health Improved
(1 files improve in Code Health)
Gates Passed
6 Quality Gates Passed
See analysis details in CodeScene
View Improvements
| File | Code Health Impact | Categories Improved |
|---|---|---|
| mod.rs | 9.39 → 10.00 | Code Duplication |
Quality Gate Profile: Pay Down Tech Debt
Want more control? Customize Code Health rules or catch issues early with our IDE extension and CLI tool.
There was a problem hiding this comment.
Code Health Improved
(1 files improve in Code Health)
Gates Passed
6 Quality Gates Passed
See analysis details in CodeScene
View Improvements
| File | Code Health Impact | Categories Improved |
|---|---|---|
| mod.rs | 9.39 → 10.00 | Code Duplication |
Quality Gate Profile: Pay Down Tech Debt
Want more control? Customize Code Health rules or catch issues early with our IDE extension and CLI tool.
| /// Guard that restores `PATH` to its original value when dropped. | ||
| /// | ||
| /// This uses RAII to ensure the environment is reset even if a test panics. | ||
| #[allow(dead_code, reason = "only some tests mutate PATH")] |
There was a problem hiding this comment.
syntax: The #[allow(dead_code)] attribute conflicts with custom rule e4e7b674 which mandates using #[expect] instead of #[allow] for lint suppression.
| #[allow(dead_code, reason = "only some tests mutate PATH")] | |
| #[expect(dead_code, reason = "only some tests mutate PATH")] |
Context Used: Rule - #[allow] is forbidden. (link)
|
|
||
| use std::sync::{Mutex, MutexGuard}; | ||
|
|
||
| #[allow(dead_code, reason = "only some tests mutate PATH")] |
There was a problem hiding this comment.
style: Using #[allow(dead_code)] instead of #[expect(dead_code)] contradicts the custom rule that forbids #[allow] in favor of #[expect].
| #[allow(dead_code, reason = "only some tests mutate PATH")] | |
| #[expect(dead_code, reason = "only some tests mutate PATH")] |
Context Used: Rule - #[allow] is forbidden. (link)
| } | ||
|
|
||
| impl PathGuard { | ||
| #[allow(dead_code, reason = "only some tests mutate PATH")] |
There was a problem hiding this comment.
syntax: The #[allow(dead_code)] attribute conflicts with custom rule e4e7b674 which mandates using #[expect] instead of #[allow] for lint suppression.
| #[allow(dead_code, reason = "only some tests mutate PATH")] | |
| #[expect(dead_code, reason = "only some tests mutate PATH")] |
Context Used: Rule - #[allow] is forbidden. (link)
Summary
std::env::set_varunsafety and rely on restoringPATHmockable::Envinto test helper instead of readingstd::envMockEnvin process step definitions for dependency-injected PATHsTesting
make fmtmake lintmake testhttps://chatgpt.com/codex/tasks/task_e_689a355dfcdc83228b934a7f060442fd
Summary by Sourcery
Replace direct use of std::env in Ninja CLI tests with a dependency-injected mock environment to improve test isolation and safely manage PATH mutations
Enhancements:
Documentation:
Tests: