e6103dcab1
This PR refactors the command creation in the test suite to remove the
duplication.
**1)** We add the same set of test stubbing args to almost any uv
invocation in the tests:
```rust
command
.arg("--cache-dir")
.arg(self.cache_dir.path())
.env("VIRTUAL_ENV", self.venv.as_os_str())
.env("UV_NO_WRAP", "1")
.env("HOME", self.home_dir.as_os_str())
.env("UV_TOOLCHAIN_DIR", "")
.env("UV_TEST_PYTHON_PATH", &self.python_path())
.current_dir(self.temp_dir.path());
if cfg!(all(windows, debug_assertions)) {
// TODO(konstin): Reduce stack usage in debug mode enough that the tests pass with the
// default windows stack of 1MB
command.env("UV_STACK_SIZE", (8 * 1024 * 1024).to_string());
}
```
Centralizing these into a `TestContext::add_shared_args` method removes
them from everywhere.
**2)** Prefix all `TextContext` methods of the pip interface with
`pip_`. This is now necessary due to `uv sync` vs. `uv pip sync`.
**3)** Move command creation in the various test files into dedicated
functions or methods to avoid repeating the arguments. Except for error
message tests, there should be at most one `Command::new(get_bin())`
call per test file. `EXCLUDE_NEWER` is exclusively used in
`TestContext`.
---
I'm considering adding a `TestCommand` on top of these changes (in
another PR) that holds a reference to the `TextContext`, has
`add_shared_args` as a method and uses `Fn(Self) -> Self` instead of
`Fn(&mut Self) -> Self` for methods to improved chaining.
131 lines
3.4 KiB
Rust
131 lines
3.4 KiB
Rust
#![cfg(all(feature = "python", feature = "pypi"))]
|
|
|
|
use std::process::Command;
|
|
|
|
use anyhow::Result;
|
|
use assert_cmd::prelude::*;
|
|
use assert_fs::prelude::*;
|
|
|
|
use common::uv_snapshot;
|
|
|
|
use crate::common::{get_bin, TestContext};
|
|
|
|
mod common;
|
|
|
|
/// Create a `cache prune` command with options shared across scenarios.
|
|
fn prune_command(context: &TestContext) -> Command {
|
|
let mut command = Command::new(get_bin());
|
|
command.arg("cache").arg("prune");
|
|
context.add_shared_args(&mut command);
|
|
command
|
|
}
|
|
|
|
/// `cache prune` should be a no-op if there's nothing out-of-date in the cache.
|
|
#[test]
|
|
fn prune_no_op() -> Result<()> {
|
|
let context = TestContext::new("3.12");
|
|
|
|
let requirements_txt = context.temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str("anyio")?;
|
|
|
|
// Install a requirement, to populate the cache.
|
|
context
|
|
.pip_sync()
|
|
.arg("requirements.txt")
|
|
.assert()
|
|
.success();
|
|
|
|
uv_snapshot!(context.filters(), prune_command(&context).arg("--verbose"), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
DEBUG uv [VERSION] ([COMMIT] DATE)
|
|
Pruning cache at: [CACHE_DIR]/
|
|
No unused entries found
|
|
"###);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// `cache prune` should remove any stale top-level directories from the cache.
|
|
#[test]
|
|
fn prune_stale_directory() -> Result<()> {
|
|
let context = TestContext::new("3.12");
|
|
|
|
let requirements_txt = context.temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str("anyio")?;
|
|
|
|
// Install a requirement, to populate the cache.
|
|
context
|
|
.pip_sync()
|
|
.arg("requirements.txt")
|
|
.assert()
|
|
.success();
|
|
|
|
// Add a stale directory to the cache.
|
|
let simple = context.cache_dir.child("simple-v4");
|
|
simple.create_dir_all()?;
|
|
|
|
uv_snapshot!(context.filters(), prune_command(&context).arg("--verbose"), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
DEBUG uv [VERSION] ([COMMIT] DATE)
|
|
Pruning cache at: [CACHE_DIR]/
|
|
DEBUG Removing dangling cache entry: [CACHE_DIR]/simple-v4
|
|
Removed 1 directory
|
|
"###);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// `cache prune` should remove any stale symlink from the cache.
|
|
#[test]
|
|
fn prune_stale_symlink() -> Result<()> {
|
|
let context = TestContext::new("3.12");
|
|
|
|
let requirements_txt = context.temp_dir.child("requirements.txt");
|
|
requirements_txt.write_str("anyio")?;
|
|
|
|
// Install a requirement, to populate the cache.
|
|
context
|
|
.pip_sync()
|
|
.arg("requirements.txt")
|
|
.assert()
|
|
.success();
|
|
|
|
// Remove the wheels directory, causing the symlink to become stale.
|
|
let wheels = context.cache_dir.child("wheels-v1");
|
|
fs_err::remove_dir_all(wheels)?;
|
|
|
|
let filters: Vec<_> = context
|
|
.filters()
|
|
.into_iter()
|
|
.chain([
|
|
// The cache entry does not have a stable key, so we filter it out
|
|
(
|
|
r"\[CACHE_DIR\](\\|\/)(.+)(\\|\/).*",
|
|
"[CACHE_DIR]/$2/[ENTRY]",
|
|
),
|
|
])
|
|
.collect();
|
|
|
|
uv_snapshot!(filters, prune_command(&context).arg("--verbose"), @r###"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
DEBUG uv [VERSION] ([COMMIT] DATE)
|
|
Pruning cache at: [CACHE_DIR]/
|
|
DEBUG Removing dangling cache entry: [CACHE_DIR]/archive-v0/[ENTRY]
|
|
Removed 44 files ([SIZE])
|
|
"###);
|
|
|
|
Ok(())
|
|
}
|