Skip to content

Refactor PathGuard for injectable env and add mock test#105

Closed
leynos wants to merge 4 commits intomainfrom
codex/clarify-unsafe-usage-and-add-tests-for-pathguard
Closed

Refactor PathGuard for injectable env and add mock test#105
leynos wants to merge 4 commits intomainfrom
codex/clarify-unsafe-usage-and-add-tests-for-pathguard

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Aug 12, 2025

Summary

  • document std::env::set_var unsafety and wrap it via a generic Env trait
  • allow injecting an environment in PathGuard
  • add unit test verifying PATH restoration with a mock environment

Testing

  • make lint
  • make test

https://chatgpt.com/codex/tasks/task_e_689a8d0b78888322aee8b2405a5e74af

Summary by Sourcery

Introduce an Env trait to encapsulate unsafe environment mutations and refactor PathGuard to be generic over an environment implementation, adding constructors for injection and an env_mut accessor; consolidate unsafe std::env::set_var calls into the Env trait and a restore method on drop; add the mockall dependency and a unit test using a mock Env to verify that PATH is correctly restored without touching the real environment.

New Features:

  • Define an Env trait and RealEnv implementation for setting environment variables.
  • Make PathGuard generic over Env with with_env and env_mut to support injectable environments.

Enhancements:

  • Wrap unsafe std::env::set_var calls behind the Env trait and move restoration logic into a restore method on drop.

Build:

  • Add the mockall crate to Cargo.toml.

Tests:

  • Add a mock-based unit test in tests/path_guard_tests.rs to verify PATH restoration using a MockEnv.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Aug 12, 2025

Reviewer's Guide

This PR refactors PathGuard to abstract environment mutation behind an Env trait with a real implementation, makes PathGuard generic over this trait (enabling injection), encapsulates the unsafe restore logic in a dedicated method/Drop impl, and adds a mock-based unit test verifying PATH restoration without touching the real environment.

Sequence diagram for PATH restoration with mock environment in unit test

sequenceDiagram
    participant Test as actor Test
    participant MockEnv
    participant PathGuard
    Test->>MockEnv: set_var("PATH", "test_path")
    Test->>PathGuard: new("new_path", MockEnv)
    PathGuard->>MockEnv: get_var("PATH")
    PathGuard->>MockEnv: set_var("PATH", "new_path")
    Test-->>PathGuard: drop()
    PathGuard->>MockEnv: set_var("PATH", "test_path")
Loading

Class diagram for refactored PathGuard and Env trait

classDiagram
    class Env {
        <<trait>>
        +get_var(key: &str) -> Option<String>
        +set_var(key: &str, value: &str)
    }
    class RealEnv {
        +get_var(key: &str) -> Option<String>
        +set_var(key: &str, value: &str)
    }
    Env <|.. RealEnv
    class PathGuard~E: Env~ {
        -env: E
        -original_path: Option<String>
        +new(path: &str, env: E) -> PathGuard<E>
        +drop()
    }
    PathGuard o-- Env
    RealEnv <|-- PathGuard
    class MockEnv {
        +get_var(key: &str) -> Option<String>
        +set_var(key: &str, value: &str)
    }
    Env <|.. MockEnv
    MockEnv <|-- PathGuard
Loading

File-Level Changes

Change Details Files
Abstract std::env::set_var behind an Env trait and inject into PathGuard
  • Define Env trait with unsafe set_var method
  • Implement RealEnv delegating to std::env::set_var
  • Make PathGuard generic over Env, defaulting to RealEnv
  • Add with_env constructor and env_mut accessor
tests/support/path_guard.rs
Encapsulate drop logic into restore method and generic Drop implementation
  • Extract drop logic into private restore()
  • Replace previous Drop impl with a generic Drop for PathGuard
  • Use EnvLock around unsafe set_var call
tests/support/path_guard.rs
Add mock-driven unit test and dependency for Env injection
  • Add mockall dependency in Cargo.toml
  • Create tests/path_guard_tests.rs using MockEnv to assert set_var calls
  • Write test restoring PATH without touching real environment
Cargo.toml
tests/path_guard_tests.rs

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 12, 2025

Note

Other AI code review bot(s) detected

CodeRabbit 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 1 minutes and 41 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 1c50f23 and bf17dd2.

📒 Files selected for processing (3)
  • tests/path_guard_tests.rs (1 hunks)
  • tests/support/mod.rs (2 hunks)
  • tests/support/path_guard.rs (1 hunks)

Summary by CodeRabbit

  • New Features

    • None.
  • Bug Fixes

    • None.
  • Tests

    • Added comprehensive tests for PATH override behaviour using a mock environment.
    • Enhanced test utilities to support configurable environments and custom compile-time configurations, improving reliability without affecting the real system environment.
  • Refactor

    • Reworked test helper to allow injectable environments and automatic restoration on scope exit.
  • Chores

    • Added a development-only mocking dependency to support new test scenarios.

Walkthrough

Add dev-dependency mockall; introduce an Env trait and RealEnv, make PathGuard generic over Env with with_env and env_mut APIs and Drop-based restore; add tests using a mocked Env; adjust test-support lint attributes.

Changes

Cohort / File(s) Summary
Dependencies
Cargo.toml
Add dev-dependency mockall = "0.11".
Test support lint adjustments
tests/support/mod.rs
Add crate-level expect(unexpected_cfgs) attribute and annotate fake_ninja with expect/allow(dead_code) via cfg_attr.
PathGuard & Env abstraction
tests/support/path_guard.rs
Add public Env trait (unsafe fn set_var(&mut self, key: &str, val: &OsStr)), RealEnv impl, make PathGuard generic PathGuard<E: Env = RealEnv>; add with_env, new delegating to with_env, env_mut, restore, generic Drop, and import OsStr/OsString.
PATH guard tests
tests/path_guard_tests.rs
Add test using a mock Env (via mockall) asserting ordered set_var("PATH", ...) calls: temporary set to "/tmp" then restored to "/orig"; avoid touching real environment.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test
    participant MockEnv as Env (mock)
    participant Guard as PathGuard<Env>

    Test->>Guard: PathGuard::with_env("/orig", MockEnv)
    Test->>Guard: guard.env_mut().set_var("PATH", "/tmp") (unsafe)
    Note right of Guard: PATH temporarily "/tmp"
    Test-->>Guard: guard drops (scope end)
    Guard->>MockEnv: restore -> set_var("PATH", "/orig") (unsafe)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related issues

Possibly related PRs

Poem

A path set, a mock takes stage, then yields,
A guard returns the road to former fields.
Tests sing softly: "/tmp", then "/orig" again,
Rust drops the curtain, tidy as a pen.
Env well-protected — cheers and confetti rain 🎉

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/clarify-unsafe-usage-and-add-tests-for-pathguard

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 1 comment

Edit Code Review Bot Settings | Greptile

Comment thread tests/support/path_guard.rs Outdated
pub struct RealEnv;

impl Env for RealEnv {
#[allow(unsafe_op_in_unsafe_fn, reason = "delegates to std::env")]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

style: using #[allow] instead of #[expect] violates the custom lint rule requiring narrowly scoped expectations

Context Used: Rule - Only narrowly scoped #[expect(lint, reason = "...")] is allowed. (link)

sourcery-ai[bot]

This comment was marked as resolved.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Aug 12, 2025

@coderabbitai please create new GitHub issues for the following:

  • Consider adding a zero-argument constructor for PathGuard that captures the current PATH automatically, so callers using the real environment don’t have to fetch and pass it manually.
  • The unsafe Env::set_var API forces unsafe blocks in user code and tests—consider providing a safe helper on PathGuard to set PATH values internally and hide the unsafety from consumers.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 12, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@leynos I'll create GitHub issues for both of those suggestions.


🏁 Script executed:

#!/bin/bash

# Create first issue for zero-argument constructor
gh issue create \
  --title "Add zero-argument constructor to PathGuard for automatic PATH capture" \
  --body "## Description
Consider adding a zero-argument constructor for PathGuard that captures the current PATH automatically, so callers using the real environment don't have to fetch and pass it manually.

This would improve the ergonomics of the API for common use cases where users just want to temporarily modify the PATH and have it restored automatically.

## Context
This suggestion came up during the review of PR #105 which refactored PathGuard for injectable env and added mock testing.

## Backlinks
- PR: https://github.com/leynos/netsuke/pull/105
- Comment: https://github.com/leynos/netsuke/pull/105#discussion_r1

Requested by: @leynos" \
  --assignee leynos

# Create second issue for safe helper API
gh issue create \
  --title "Provide safe helper on PathGuard to hide unsafe Env::set_var API from consumers" \
  --body "## Description
The unsafe Env::set_var API forces unsafe blocks in user code and tests. Consider providing a safe helper on PathGuard to set PATH values internally and hide the unsafety from consumers.

This would improve the API design by encapsulating the unsafe operations within PathGuard itself, rather than exposing them to consumers of the API.

## Context
This suggestion came up during the review of PR #105 which refactored PathGuard for injectable env and added mock testing.

## Backlinks
- PR: https://github.com/leynos/netsuke/pull/105
- Comment: https://github.com/leynos/netsuke/pull/105#discussion_r1

Requested by: @leynos" \
  --assignee leynos

Length of output: 1637


@leynos I've successfully created both GitHub issues for your suggestions:

  1. Issue Add zero-argument constructor to PathGuard for automatic PATH capture #110: Add zero-argument constructor to PathGuard for automatic PATH capture
  2. Issue Provide safe helper on PathGuard to hide unsafe Env::set_var API from consumers #111: Provide safe helper on PathGuard to hide unsafe Env::set_var API from consumers

Both issues have been assigned to you and include the relevant context from this PR review.

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, no comments

Edit Code Review Bot Settings | Greptile

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Aug 12, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 12, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

♻️ Duplicate comments (3)
tests/support/mod.rs (1)

6-6: Use #[expect] instead of #[allow]

Replace #[allow] with #[expect] to comply with the coding guidelines. The guidelines explicitly forbid #[allow] and require narrowly scoped #[expect(lint, reason = "...")].

-#![allow(unexpected_cfgs, reason = "test utilities use custom cfg")]
+#![expect(unexpected_cfgs, reason = "test utilities use custom cfg")]
tests/support/path_guard.rs (2)

6-6: Use #[expect] instead of #[allow]

Replace #[allow] with #[expect] to comply with the coding guidelines that explicitly forbid #[allow].

-#![allow(unexpected_cfgs, reason = "test utilities use custom cfg")]
+#![expect(unexpected_cfgs, reason = "test utilities use custom cfg")]

65-66: Remove redundant attribute

Remove the #[allow(dead_code)] attribute.

     #[cfg_attr(expect, expect(dead_code, reason = "used in env injection tests"))]
-    #[allow(dead_code, reason = "used in env injection tests")]
     pub fn env_mut(&mut self) -> &mut E {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fed9793 and d3430ba.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml (1 hunks)
  • tests/path_guard_tests.rs (1 hunks)
  • tests/support/mod.rs (2 hunks)
  • tests/support/path_guard.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.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 return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless 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 rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for 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/path_guard_tests.rs
  • tests/support/mod.rs
  • tests/support/path_guard.rs
🧬 Code Graph Analysis (2)
tests/path_guard_tests.rs (1)
tests/support/path_guard.rs (4)
  • set_var (19-19)
  • set_var (28-30)
  • new (48-50)
  • with_env (57-62)
tests/support/path_guard.rs (1)
tests/support/env_lock.rs (1)
  • acquire (19-21)
🔍 MCP Research (1 server)

Deepwiki:

  • Document [Developer Guide]: the listed test dependencies mention rstest, cucumber, and insta as the project's testing frameworks but do not mention mockall (docs referencing Cargo.toml under "Testing Framework" and "Dependency Architecture").
  • Document [Testing Framework]: the testing-stack description explicitly details rstest, cucumber-rs, and insta for unit/BDD/snapshot testing; no reference to mockall appears in that page.
🔇 Additional comments (3)
tests/support/path_guard.rs (2)

13-20: Well-designed abstraction for environment mutation

The Env trait provides a clean abstraction over environment mutations, properly documenting the safety concerns introduced in Rust 2024. The unsafe marker correctly signals the process-wide state mutation risk.


71-81: Proper restoration logic with appropriate safety documentation

The restore method correctly uses EnvLock to serialise access and includes comprehensive safety documentation explaining the Rust 2024 requirements and mitigation strategy.

tests/path_guard_tests.rs (1)

15-34: Well-structured test with proper mocking

The test effectively verifies PATH restoration using a mock environment, avoiding real environment mutations. The sequence enforcement ensures the correct order of operations, and the test properly exercises both the mutation and restoration paths.

Comment thread Cargo.toml
Comment thread tests/path_guard_tests.rs Outdated
Comment thread tests/support/mod.rs Outdated
Comment thread tests/support/path_guard.rs Outdated
Comment thread tests/support/path_guard.rs Outdated
Comment on lines 45 to 46
#[cfg_attr(expect, expect(dead_code, reason = "only some tests mutate PATH"))]
#[allow(dead_code, reason = "only some tests mutate PATH")]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove redundant attribute

Remove the #[allow(dead_code)] attribute as #[cfg_attr(expect, expect(dead_code))] already handles this conditionally.

     #[cfg_attr(expect, expect(dead_code, reason = "only some tests mutate PATH"))]
-    #[allow(dead_code, reason = "only some tests mutate PATH")]
     /// Create a guard capturing the current `PATH` using the real environment.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[cfg_attr(expect, expect(dead_code, reason = "only some tests mutate PATH"))]
#[allow(dead_code, reason = "only some tests mutate PATH")]
#[cfg_attr(expect, expect(dead_code, reason = "only some tests mutate PATH"))]
/// Create a guard capturing the current `PATH` using the real environment.
🤖 Prompt for AI Agents
In tests/support/path_guard.rs around lines 45 to 46, remove the redundant
#[allow(dead_code, reason = "only some tests mutate PATH")] attribute because
the conditional #[cfg_attr(expect, expect(dead_code, reason = "only some tests
mutate PATH"))] already covers the case; delete the #[allow(...)] line and keep
the cfg_attr(expect, expect(...)) attribute only so the dead_code lint is
handled conditionally.

Comment thread tests/support/path_guard.rs Outdated
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, no comments

Edit Code Review Bot Settings | Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

♻️ Duplicate comments (1)
tests/support/mod.rs (1)

22-23: Remove #[allow(...)] and use #[expect(...)] to comply with lint policy

Do not use #[allow]. The project policy permits only narrowly-scoped #[expect(..., reason = "...")]. Apply a single, direct expectation on the item.

Apply this diff:

-#[cfg_attr(expect, expect(dead_code, reason = "used in PATH tests"))]
-#[cfg_attr(not(expect), allow(dead_code, reason = "used in PATH tests"))]
+#[expect(dead_code, reason = "used in PATH tests")]
 pub fn fake_ninja(exit_code: i32) -> (TempDir, PathBuf) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3430ba and 1c50f23.

📒 Files selected for processing (3)
  • tests/path_guard_tests.rs (1 hunks)
  • tests/support/mod.rs (2 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/path_guard_tests.rs
  • tests/support/path_guard.rs
  • tests/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 return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless 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 rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for 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/path_guard_tests.rs
  • tests/support/path_guard.rs
  • tests/support/mod.rs
🧬 Code Graph Analysis (2)
tests/path_guard_tests.rs (1)
tests/support/path_guard.rs (4)
  • set_var (21-21)
  • set_var (32-34)
  • new (52-54)
  • with_env (61-66)
tests/support/path_guard.rs (1)
tests/support/env_lock.rs (1)
  • acquire (19-21)
🔍 MCP Research (1 server)

Deepwiki:

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-test
🔇 Additional comments (9)
tests/support/mod.rs (3)

6-7: Accept the narrowly-scoped lint expectation

Keep this crate-level expectation. It documents intent and stays within the “expect with reason” policy.


82-83: Accept the narrowly-scoped lint expectation

The item-level #[expect(dead_code, ...)] is compliant and scoped correctly.


55-76: Retain mock_path_to: MockEnv and expect_raw exist
Remove the suggestion to delete this helper. mockable::MockEnv and its expect_raw method are defined in tests/support/env.rs, so mock_path_to compiles without errors.

Likely an incorrect or invalid review comment.

tests/support/path_guard.rs (4)

6-7: Accept the crate-level lint expectation

Keep this; it explains the custom cfg usage and remains within the “expect with reason” rule.


8-9: Import OsStr/OsString explicitly

This is the right place to introduce Os types for the public API surface.


43-45: Store Env alongside original PATH

This addition is necessary for injection and is well-scoped.


89-93: LGTM: Drop delegates to restore

This keeps the RAII guarantee tight and readable.

tests/path_guard_tests.rs (2)

1-5: Good module-level documentation

Keep this. It satisfies the requirement for a leading //! and clarifies test intent.


19-39: LGTM: Verify PATH is set then restored via mock sequence without touching real env

The ordered expectations on set_var coupled with the RAII scope validate restoration behaviour cleanly.

Comment thread tests/path_guard_tests.rs
Comment on lines +12 to +17
mock! {
pub Env {}
impl Env for Env {
unsafe fn set_var(&mut self, key: &str, val: &OsStr);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Prefer rstest fixtures for reusable mocks per repository testing guidance

Adopt rstest fixtures for the mock environment to align with the repo’s testing standards and reduce duplication as tests grow.

According to the team’s guidance (DeepWiki), tests should use rstest fixtures for injectable environments with mockall. I can sketch a fixture like:

use rstest::fixture;

#[fixture]
fn mock_env() -> MockEnv {
    let mut env = MockEnv::new();
    // set common expectations here if needed
    env
}

Would you like me to refactor the tests to use rstest and extract a reusable mock_env fixture?

🤖 Prompt for AI Agents
In tests/path_guard_tests.rs around lines 12 to 17, the mocked Env is declared
inline with mockall; replace that pattern with an rstest fixture so tests can
reuse the mock per the repo guideline. Create a #[fixture] fn mock_env() ->
MockEnv that constructs MockEnv::new(), configures any common expectations, and
returns it; update tests to accept mock_env: MockEnv as a parameter instead of
creating local mocks; add the rstest::fixture import and any necessary mockall
imports to the test module and ensure visibility (pub if needed) so existing
tests compile.

Comment thread tests/support/path_guard.rs
Comment thread tests/support/path_guard.rs
Comment thread tests/support/path_guard.rs
Comment thread tests/support/path_guard.rs
Comment thread tests/support/path_guard.rs
Comment thread tests/support/path_guard.rs
Comment thread tests/support/path_guard.rs
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 1 comment

Edit Code Review Bot Settings | Greptile

Comment thread tests/support/mod.rs
//! This module provides helpers for creating fake executables along with
//! logging utilities used in behavioural tests.

#![allow(unexpected_cfgs, reason = "test utilities use custom cfg")]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

style: violates custom rule forbidding #[allow] - should use #[expect(unexpected_cfgs, reason = "...")] instead

Suggested change
#![allow(unexpected_cfgs, reason = "test utilities use custom cfg")]
#![expect(unexpected_cfgs, reason = "test utilities use custom cfg")]

Context Used: Rule - #[allow] is forbidden. (link)

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Aug 12, 2025

Superseded

@leynos leynos closed this Aug 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant