chore: harden uv parser, cache panics, test isolation, and temp dir cleanup#410
Conversation
Performance Report (Linux) ➖
Legend
|
Test Coverage Report (Linux)
Coverage increased! Great work! |
Performance Report (macOS)
Legend
|
Performance Report (Windows) ➖
Legend
|
Test Coverage Report (Windows)
Coverage increased! Great work! |
There was a problem hiding this comment.
Pull request overview
This PR batches several hardening and test-quality improvements across PET, mainly to reduce host-environment leakage in tests, improve panic diagnostics, and tighten uv directory parsing.
Changes:
- Harden
pet-uv’s uv-managed Python directory version parsing and add regression tests. - Replace
RwLock.unwrap()s inpet-core’sLocatorCachewith descriptive.expect(...)messages. - Improve test isolation/cleanup by using
env_clear()for the JSONRPC test server process andtempfile::TempDirRAII for temp directories in locator tests.
Show a summary per file
| File | Description |
|---|---|
| crates/pet/tests/jsonrpc_client.rs | Clear inherited environment for the spawned PET server to avoid host tool configuration leakage. |
| crates/pet-windows-registry/src/lib.rs | Switch tests from manual temp dir creation/cleanup to TempDir RAII. |
| crates/pet-windows-registry/Cargo.toml | Add tempfile as a dev-dependency for tests. |
| crates/pet-uv/src/lib.rs | Tighten uv version parsing and add acceptance/rejection tests. |
| crates/pet-pixi/src/lib.rs | Switch tests from manual temp dir creation/cleanup to TempDir RAII. |
| crates/pet-pixi/Cargo.toml | Add tempfile as a dev-dependency for tests. |
| crates/pet-core/src/cache.rs | Improve lock-poison panic diagnostics by using .expect("locator cache lock poisoned"). |
| Cargo.lock | Record new tempfile dev-dependency usage in workspace lockfile. |
Copilot's findings
- Files reviewed: 7/8 changed files
- Comments generated: 2
…ersion validation (PR #410)
There was a problem hiding this comment.
Pull request overview
This PR applies several hardening and test-quality improvements across PET, including stricter uv directory version parsing, improved panic diagnostics for locator caches, more reliable temp dir cleanup in tests, and better JSONRPC test-server environment isolation.
Changes:
- Harden
pet-uv’s uv install directory version parsing and add targeted tests (including prerelease acceptance). - Improve
LocatorCachelock-poisoning panic diagnostics by replacingunwrap()withexpect(...). - Update tests to use
tempfile::TempDirRAII cleanup and clear inherited environment variables for JSONRPC integration tests.
Show a summary per file
| File | Description |
|---|---|
crates/pet/tests/jsonrpc_client.rs |
Clears inherited env vars for spawned test server and restores minimal needed variables. |
crates/pet-uv/src/lib.rs |
Tightens uv directory version parsing and adds new unit tests. |
crates/pet-core/src/cache.rs |
Replaces RwLock .unwrap() calls with .expect(...) for clearer poison diagnostics. |
crates/pet-pixi/src/lib.rs |
Switches tests from manual temp dir management to TempDir RAII cleanup. |
crates/pet-pixi/Cargo.toml |
Adds tempfile as a dev-dependency for tests. |
crates/pet-windows-registry/src/lib.rs |
Switches tests from manual temp dir management to TempDir RAII cleanup. |
crates/pet-windows-registry/Cargo.toml |
Adds tempfile as a dev-dependency for tests. |
Cargo.lock |
Records the new tempfile dev-dependency usage in affected crates. |
Copilot's findings
- Files reviewed: 7/8 changed files
- Comments generated: 2
| // Components before the last must be purely numeric. | ||
| // The last component may have a pre-release suffix (e.g., "0a4", "0rc1"). | ||
| let components: Vec<&str> = version.split('.').collect(); | ||
| if components.len() < 2 { | ||
| return None; | ||
| } | ||
| // All components except the last must be purely numeric. | ||
| let all_but_last = &components[..components.len() - 1]; | ||
| if !all_but_last | ||
| .iter() | ||
| .all(|c| !c.is_empty() && c.chars().all(|ch| ch.is_ascii_digit())) | ||
| { | ||
| return None; | ||
| } | ||
| // The last component must start with a digit (allows pre-release suffix like "0a4"). |
There was a problem hiding this comment.
components validation currently allows non-numeric suffixes on a 2-part version like 3.12abc (because only the major component is in all_but_last, and the last component only has to start with a digit). That seems to undercut the hardening goal and could misidentify directories like cpython-3.12abc-... as valid. Consider requiring the first two components (major+minor) to be digits-only, and only allowing a pre-release suffix on the patch component when a third component exists (and add a test case for the 3.12abc scenario).
| // Components before the last must be purely numeric. | |
| // The last component may have a pre-release suffix (e.g., "0a4", "0rc1"). | |
| let components: Vec<&str> = version.split('.').collect(); | |
| if components.len() < 2 { | |
| return None; | |
| } | |
| // All components except the last must be purely numeric. | |
| let all_but_last = &components[..components.len() - 1]; | |
| if !all_but_last | |
| .iter() | |
| .all(|c| !c.is_empty() && c.chars().all(|ch| ch.is_ascii_digit())) | |
| { | |
| return None; | |
| } | |
| // The last component must start with a digit (allows pre-release suffix like "0a4"). | |
| // Major and minor must always be purely numeric. | |
| // Only the patch component may have a pre-release suffix (e.g., "0a4", "0rc1"). | |
| let components: Vec<&str> = version.split('.').collect(); | |
| if components.len() < 2 { | |
| return None; | |
| } | |
| let is_numeric_component = | |
| |c: &str| !c.is_empty() && c.chars().all(|ch| ch.is_ascii_digit()); | |
| if !is_numeric_component(components[0]) || !is_numeric_component(components[1]) { | |
| return None; | |
| } | |
| if components.len() == 2 { | |
| return Some(version.to_string()); | |
| } | |
| let all_but_last = &components[2..components.len() - 1]; | |
| if !all_but_last.iter().all(|c| is_numeric_component(c)) { | |
| return None; | |
| } | |
| // The patch component may start with a digit and include a pre-release suffix. |
| .env_clear() | ||
| .env("PATH", "") | ||
| .env( | ||
| "SYSTEMROOT", | ||
| std::env::var("SYSTEMROOT").unwrap_or_default(), |
There was a problem hiding this comment.
With .env_clear(), SYSTEMROOT becomes the only restored OS-specific variable here, but unwrap_or_default() will silently set it to an empty string if the parent process doesn't have it. On Windows that can produce confusing downstream failures; it’s better to either (a) only set this on Windows and expect/return an error if missing, or (b) only set it when std::env::var("SYSTEMROOT") succeeds (and omit it otherwise on non-Windows).
…lient (follow-up to #410)
…lient (#411) ## Summary Addresses two unresolved Copilot review comments from merged PR #410. ## Changes - **uv version parser:** Major and minor components are now explicitly validated as purely numeric. Pre-release suffix (e.g., `0a4`, `0rc1`) is only allowed on the patch component (3rd+). Previously `3.12abc` passed validation because the minor was the "last" component and only needed to start with a digit. Added test case for this scenario. - **SYSTEMROOT in test client:** Platform-gated with `#[cfg(windows)]` and only set when `std::env::var("SYSTEMROOT")` succeeds. Previously used `unwrap_or_default()` which silently set it to empty string on non-Windows or when missing. Follow-up to #410
Summary
Batch of four hardening and code quality improvements identified during coverage gap analysis.
Changes
Harden uv version parser to reject non-numeric version components #397 — uv version parser: Validate that version components start with digits, rejecting garbage like
cpython-3.abc.def-linuxwhile still accepting pre-release versions like3.14.0a4. Added tests for both rejection and acceptance cases.LocatorCache uses .unwrap() on RwLock instead of .expect() with messages #402 — LocatorCache
.unwrap()→.expect(): Replaced all 11.unwrap()calls on RwLock operations with.expect("locator cache lock poisoned")for better panic diagnostics.Some tests use manual temp dir cleanup instead of tempfile::TempDir RAII #403 — tempfile::TempDir RAII: Replaced manual temp dir management in
pet-pixiandpet-windows-registrytests withtempfile::TempDir. Directories are now cleaned up automatically even on test panics.JSONRPC test client should clear tool-specific env vars for full isolation #401 — JSONRPC test client isolation: Replaced
.env("PATH", "")with.env_clear()to fully isolate the test server from host environment variables. OnlyPATH(empty) andSYSTEMROOTare restored.Fixes #397, Fixes #402, Fixes #403, Fixes #401