Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/vp_cli_snapshots/tests/cli_snapshots/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ cwd = "packages/app" # optional, relative to the fixture root
skip-platforms = ["windows"] # or { os = "linux", libc = "musl" }
requires = ["bash"] # "sh" | "bash" | "zsh" | "cmd" | "fish" | "nu" | "pwsh"
ignore = false # true: only runs with `-- --ignored`
serial = false # true: run alone across cargo test/nextest workers
seed-runtime = true # false: start from an empty VP_HOME
link-node-modules = false # true: expose the run-root node_modules as
# the workspace's parent-dir node_modules,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_add_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "add", "--help"], comment = "should show help", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_add_npm10_with_workspace"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "add", "testnpm2", "-D", "-w", "--", "--no-audit"], comment = "should add package to workspace root" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_cache_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "pm", "cache", "dir"], comment = "should show cache directory (uses npm config get cache)", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_config_npm10"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "pm", "config", "--help"], comment = "should show help", continue-on-failure = true },
{ argv = ["vp", "pm", "config", "get", "vite-plus-pm-config-test-key", "--location", "project"], comment = "should get config value from project scope", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_dedupe_npm10"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "dedupe"], comment = "should dedupe dependencies" },
{ argv = ["vpt", "print-file", "package.json"], continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_dlx_no_package_json"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "dlx", "-s", "cowsay", "hello"], comment = "should work without package.json", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_dlx_npm10"
vp = "global"
serial = true
local-registry = true
skip-platforms = ["windows", { os = "linux", libc = "musl" }]
steps = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_link_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vpt", "mkdir", "-p", "../test-lib-npm"], comment = "create test library" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_list_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "install"], comment = "should install packages first", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_list_npm10_with_workspace"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "install"], comment = "should install packages first", continue-on-failure = true },
{ argv = ["vp", "pm", "list", "--json"], comment = "should list current workspace root dependencies", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_outdated_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "install"], comment = "should install packages first", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_outdated_npm10_with_workspace"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "install"], continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_owner_npm10"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "pm", "owner", "list", "testnpm2"], comment = "should list package owners", continue-on-failure = true },
]
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_pack_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "pm", "pack", "--json"], comment = "should pack current package" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_pack_npm10_with_workspace"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "pm", "pack", "--json"], comment = "should pack current workspace root", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_prune_npm10"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "install"], comment = "should install packages first", continue-on-failure = true },
{ argv = ["vp", "pm", "prune", "--help"], comment = "should show help", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_publish_npm10"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "pm", "publish", "--help"], comment = "should show help", continue-on-failure = true },
{ argv = ["vp", "pm", "publish", "--dry-run", "--", "--loglevel", "error"], comment = "should preview publish without actually publishing (uses npm publish --dry-run)", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_remove_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "remove", "testnpm2", "-D", "--", "--no-audit"], comment = "should pass when remove not exists package" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_remove_npm10_with_workspace"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "add", "testnpm2", "-D", "-w", "--filter=*", "--", "--no-audit"], comment = "prepare packages" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_unlink_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vpt", "mkdir", "-p", "../unlink-test-lib-npm"], comment = "create test library" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_update_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "update", "testnpm2", "--", "--no-audit"], comment = "should update package within semver range" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_update_npm10_with_workspace"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "update", "testnpm2", "-w", "--", "--no-audit"], comment = "should update in workspace root" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_view_npm10"
vp = "global"
serial = true
steps = [
{ argv = ["vp", "pm", "view", "testnpm2", "dist.tarball"], comment = "should view testnpm2 package information", continue-on-failure = true },
{ argv = ["vp", "pm", "info", "testnpm2", "dist.tarball"], comment = "should info alias to view", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_vpx_no_package_json"
vp = "global"
serial = true
local-registry = true
skip-platforms = ["windows"]
steps = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_why_npm10"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "install"], comment = "should install packages first", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "command_why_npm10_with_workspace"
vp = "global"
serial = true
skip-platforms = ["windows"]
steps = [
{ argv = ["vp", "install"], continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"vite": "^7.0.0",
"vitest": "^4.0.0"
},
"packageManager": "npm@10.9.2"
"packageManager": "npm@11.13.0"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "migration_standalone_npm"
vp = "global"
serial = true
skip-platforms = ["windows"]
unset-env = ["CI", "VP_SKIP_INSTALL"]
local-registry = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ check package.json has overrides field (not pnpm.overrides)
"overrides": {
"vite": "npm:@voidzero-dev/vite-plus-core@<version>"
},
"packageManager": "npm@10.9.2"
"packageManager": "npm@11.13.0"
}
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "npm_install_with_options"
vp = "local"
serial = true
steps = [
{ argv = ["vp", "install", "--help"], comment = "print help message", continue-on-failure = true },
{ argv = ["vp", "run", "install"], comment = "https://docs.npmjs.com/cli/v10/commands/npm-install", continue-on-failure = true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[[case]]
name = "pm_audit_bun"
vp = "global"
serial = true
cwd = "bun"
steps = [
{ argv = ["vp", "install", "--", "--silent"], comment = "should install packages first", continue-on-failure = true },
Expand Down
57 changes: 41 additions & 16 deletions crates/vp_cli_snapshots/tests/cli_snapshots/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ mod flavor;
mod redact;

use std::{
collections::BTreeMap,
collections::{BTreeMap, hash_map::DefaultHasher},
ffi::OsString,
fs::{File, OpenOptions},
hash::{Hash, Hasher},
io::Write,
path::{Path, PathBuf},
sync::{Arc, Mutex, mpsc},
Expand Down Expand Up @@ -1530,33 +1532,56 @@ fn run_case(
/// on Linux: only the few signal-sensitive cases pay for serialization, while
/// the rest parallelize as they already do on macOS and Windows.
///
/// This coordinates threads within a single `cargo test` process, which is the
/// Linux and macOS snapshot jobs and the only place the parallel-PTY
/// signal-routing flakiness occurs. The Windows job runs the suite under
/// `cargo nextest`, which executes each trial in its own process; there the
/// gate is a no-op, but isolation is stronger for free — a signal-sensitive
/// case already has its own process, PTY, and process group, which is exactly
/// what this gate reconstructs for the shared-process case.
/// The in-process lock coordinates the threads used by `cargo test`. A matching
/// file lock coordinates the separate trial processes used by `cargo nextest`
/// on Windows. The lock file name includes the checkout path so independent
/// worktrees do not block each other.
static EXECUTION_GATE: std::sync::RwLock<()> = std::sync::RwLock::new(());

/// Held for a case's whole run: either a shared read lease (parallel) or the
/// exclusive write lease (isolated). Poisoning is ignored — a case that
/// panicked already failed, and its neighbours should still run.
enum GateLease {
Shared(
#[expect(dead_code, reason = "held for its Drop")] std::sync::RwLockReadGuard<'static, ()>,
),
Exclusive(
#[expect(dead_code, reason = "held for its Drop")] std::sync::RwLockWriteGuard<'static, ()>,
),
Shared {
#[expect(dead_code, reason = "held for its Drop")]
thread: std::sync::RwLockReadGuard<'static, ()>,
#[expect(dead_code, reason = "held for its Drop")]
process: File,
},
Exclusive {
#[expect(dead_code, reason = "held for its Drop")]
thread: std::sync::RwLockWriteGuard<'static, ()>,
#[expect(dead_code, reason = "held for its Drop")]
process: File,
},
}

fn execution_gate_file() -> File {
let mut hasher = DefaultHasher::new();
flavor::repo_root().hash(&mut hasher);
let path = std::env::temp_dir()
.join(format!("vp-cli-snapshots-execution-{:016x}.lock", hasher.finish()));
OpenOptions::new()
.create(true)
.read(true)
.write(true)
.truncate(false)
.open(&path)
.unwrap_or_else(|error| panic!("failed to open execution gate {}: {error}", path.display()))
}

fn acquire_gate(isolated: bool) -> GateLease {
use std::sync::PoisonError;
if isolated {
GateLease::Exclusive(EXECUTION_GATE.write().unwrap_or_else(PoisonError::into_inner))
let thread = EXECUTION_GATE.write().unwrap_or_else(PoisonError::into_inner);
let process = execution_gate_file();
File::lock(&process).expect("failed to lock the cross-process execution gate");
GateLease::Exclusive { thread, process }
} else {
GateLease::Shared(EXECUTION_GATE.read().unwrap_or_else(PoisonError::into_inner))
let thread = EXECUTION_GATE.read().unwrap_or_else(PoisonError::into_inner);
let process = execution_gate_file();
File::lock_shared(&process).expect("failed to lock the cross-process execution gate");
GateLease::Shared { thread, process }
}
}

Expand Down
Loading