Files
dosh/tests/installer_runtime.rs
T
DuProcess 7f8d5711ea
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / macos-client (macos-aarch64, macos-14) (push) Canceled after 0s
ci / macos-client (macos-x86_64, macos-13) (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s
Unify release selection across clients
2026-07-17 18:58:58 -04:00

266 lines
8.3 KiB
Rust

#![cfg(unix)]
use sha2::{Digest, Sha256};
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
use std::process::Command;
use tempfile::TempDir;
const VERSION: &str = "9.8.7-rc3";
fn write_executable(path: &Path, body: &str) {
fs::write(path, body).unwrap();
let mut permissions = fs::metadata(path).unwrap().permissions();
permissions.set_mode(0o755);
fs::set_permissions(path, permissions).unwrap();
}
struct InstallerFixture {
root: TempDir,
fake_bin: PathBuf,
archive: PathBuf,
checksum: PathBuf,
curl_log: PathBuf,
git_log: PathBuf,
version: String,
}
impl InstallerFixture {
fn new(version: &str) -> Self {
let root = tempfile::tempdir().unwrap();
let fake_bin = root.path().join("fake-bin");
let stage = root.path().join("stage/dosh");
fs::create_dir_all(fake_bin.as_path()).unwrap();
fs::create_dir_all(stage.join("bin")).unwrap();
fs::write(stage.join("VERSION"), format!("{version}\n")).unwrap();
write_executable(
&stage.join("bin/dosh-client"),
"#!/bin/sh\nprintf 'fixture dosh\\n'\n",
);
let archive = root.path().join("dosh-macos-aarch64.tar.gz");
let status = Command::new("tar")
.args(["-C", root.path().join("stage").to_str().unwrap(), "-czf"])
.arg(&archive)
.arg("dosh")
.status()
.unwrap();
assert!(status.success());
let digest = Sha256::digest(fs::read(&archive).unwrap());
let checksum = root.path().join("dosh-macos-aarch64.tar.gz.sha256");
fs::write(
&checksum,
format!("{digest:x} dosh-macos-aarch64.tar.gz\n"),
)
.unwrap();
write_executable(
&fake_bin.join("uname"),
"#!/bin/sh\ncase \"${1:-}\" in -s) echo Darwin;; -m) echo arm64;; *) echo Darwin;; esac\n",
);
let curl_log = root.path().join("curl.log");
let git_log = root.path().join("git.log");
write_executable(
&fake_bin.join("curl"),
r#"#!/bin/sh
printf '%s\n' "$*" >>"$TEST_CURL_LOG"
out=
previous=
url=
for arg in "$@"; do
if [ "$previous" = "-o" ]; then out="$arg"; fi
previous="$arg"
case "$arg" in http://*|https://*) url="$arg";; esac
done
case "$url" in
*/raw/branch/main/Cargo.toml)
printf '[package]\nname = "dosh"\nversion = "%s"\n' "$TEST_RELEASE_VERSION"
;;
*.sha256)
cp "$TEST_ARCHIVE_CHECKSUM" "$out"
;;
*/releases/download/*)
[ "${TEST_FAIL_ARCHIVE:-0}" = 1 ] && exit 22
cp "$TEST_ARCHIVE" "$out"
;;
*) exit 22;;
esac
"#,
);
Self {
root,
fake_bin,
archive,
checksum,
curl_log,
git_log,
version: version.to_string(),
}
}
fn command(&self, cwd: &Path) -> Command {
let mut command = Command::new("sh");
command
.arg(format!("{}/install.sh", env!("CARGO_MANIFEST_DIR")))
.args([
"client",
"--repo",
"https://example.invalid/Palav/dosh.git",
"--prefix",
])
.arg(self.root.path().join("prefix"))
.current_dir(cwd)
.env("HOME", self.root.path().join("home"))
.env(
"PATH",
format!(
"{}:{}",
self.fake_bin.display(),
std::env::var("PATH").unwrap_or_default()
),
)
.env("DOSH_BINARY_REQUIRED", "1")
.env("TEST_RELEASE_VERSION", &self.version)
.env("TEST_ARCHIVE", &self.archive)
.env("TEST_ARCHIVE_CHECKSUM", &self.checksum)
.env("TEST_CURL_LOG", &self.curl_log)
.env("TEST_GIT_LOG", &self.git_log);
command
}
fn installed_client(&self) -> PathBuf {
self.root.path().join("prefix/bin/dosh-client")
}
}
#[test]
fn unix_installer_uses_repository_version_even_inside_an_unrelated_rust_project() {
let fixture = InstallerFixture::new(VERSION);
let unrelated = fixture.root.path().join("unrelated");
fs::create_dir_all(&unrelated).unwrap();
fs::write(
unrelated.join("Cargo.toml"),
"[package]\nname = \"not-dosh\"\nversion = \"99.0.0\"\n",
)
.unwrap();
let output = fixture.command(&unrelated).output().unwrap();
assert!(
output.status.success(),
"installer failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(fixture.installed_client().is_file());
let requests = fs::read_to_string(&fixture.curl_log).unwrap();
assert!(requests.contains("/raw/branch/main/Cargo.toml"));
assert!(requests.contains(&format!(
"/releases/download/v{VERSION}/dosh-macos-aarch64.tar.gz"
)));
assert!(!requests.contains("/releases/latest"));
assert!(!requests.contains("99.0.0"));
}
#[test]
fn unix_installer_source_fallback_checks_out_the_same_release_tag() {
let fixture = InstallerFixture::new(VERSION);
write_executable(
&fixture.fake_bin.join("git"),
r#"#!/bin/sh
printf '%s\n' "$*" >>"$TEST_GIT_LOG"
if [ "${1:-}" = clone ]; then
for destination in "$@"; do :; done
mkdir -p "$destination/.git"
fi
"#,
);
write_executable(
&fixture.fake_bin.join("cargo"),
"#!/bin/sh\nmkdir -p target/release\nprintf '#!/bin/sh\\n' >target/release/dosh-client\nchmod +x target/release/dosh-client\n",
);
let cwd = fixture.root.path().join("plain");
fs::create_dir_all(&cwd).unwrap();
let mut command = fixture.command(&cwd);
command
.env("DOSH_BINARY_REQUIRED", "0")
.env("TEST_FAIL_ARCHIVE", "1");
let output = command.output().unwrap();
assert!(
output.status.success(),
"installer failed: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(fixture.installed_client().is_file());
let git = fs::read_to_string(&fixture.git_log).unwrap();
assert!(git.contains(&format!("clone --depth 1 --branch v{VERSION}")));
assert!(!git.contains("--branch main"));
}
#[test]
fn unix_installer_resolves_a_stable_repository_version_without_latest_redirects() {
let version = "1.2.3";
let fixture = InstallerFixture::new(version);
let cwd = fixture.root.path().join("plain");
fs::create_dir_all(&cwd).unwrap();
let output = fixture.command(&cwd).output().unwrap();
assert!(
output.status.success(),
"installer failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let requests = fs::read_to_string(&fixture.curl_log).unwrap();
assert!(requests.contains(&format!(
"/releases/download/v{version}/dosh-macos-aarch64.tar.gz"
)));
assert!(!requests.contains("/releases/latest"));
}
#[test]
fn unix_installer_repairs_a_legacy_updater_that_requests_its_old_tag() {
let fixture = InstallerFixture::new(VERSION);
let cwd = fixture.root.path().join("plain");
fs::create_dir_all(&cwd).unwrap();
let mut command = fixture.command(&cwd);
command.env("DOSH_BINARY_VERSION", "v0.1.17");
let output = command.output().unwrap();
assert!(
output.status.success(),
"installer failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let requests = fs::read_to_string(&fixture.curl_log).unwrap();
assert!(requests.contains(&format!(
"/releases/download/v{VERSION}/dosh-macos-aarch64.tar.gz"
)));
assert!(!requests.contains("/releases/download/v0.1.17/"));
}
#[test]
fn unix_installer_honors_an_explicit_exact_release_pin() {
let pinned = "0.1.17";
let fixture = InstallerFixture::new(pinned);
let cwd = fixture.root.path().join("plain");
fs::create_dir_all(&cwd).unwrap();
let mut command = fixture.command(&cwd);
command
.env("TEST_RELEASE_VERSION", VERSION)
.env("DOSH_BINARY_VERSION", format!("v{pinned}"))
.env("DOSH_BINARY_EXACT", "1");
let output = command.output().unwrap();
assert!(
output.status.success(),
"installer failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let requests = fs::read_to_string(&fixture.curl_log).unwrap();
assert!(requests.contains(&format!(
"/releases/download/v{pinned}/dosh-macos-aarch64.tar.gz"
)));
assert!(!requests.contains(&format!("/releases/download/v{VERSION}/")));
}