Skip to content
Merged
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
97 changes: 70 additions & 27 deletions tests/packaging.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! The crates.io package: it carries the sources and the Factory skills the
//! binary embeds, and none of the repository's own agent tooling, docs, site
//! or tests. And the binary's dependencies: HTTPS through rustls, never
//! OpenSSL (ADR 0003).
//! or tests. And the binary's dependencies, as the lockfile names them: HTTPS
//! through rustls, never OpenSSL (ADR 0003).

use std::fs;
use std::path::Path;
use std::process::Command;

/// The paths `cargo package` would put in the crate.
Expand All @@ -24,6 +26,29 @@ fn package_list() -> Vec<String> {
.collect()
}

/// The packages in a lockfile that would link OpenSSL, as `name version`.
///
/// The lockfile names every package for every target without touching the
/// registry, where `cargo tree --target all --offline` fails unless every
/// platform's crates are already in the cargo cache. It also names the
/// dev-dependencies, so this is stricter than the binary's own normal and
/// build dependencies, which is all ADR 0003 needs: a test-only OpenSSL is
/// caught too.
fn openssl_packages(lockfile: &str) -> Vec<String> {
let lockfile: toml::Table = lockfile.parse().expect("the lockfile is not TOML");
lockfile["package"]
.as_array()
.expect("the lockfile has no packages")
.iter()
.filter_map(|package| {
let name = package["name"].as_str().unwrap();
["openssl-sys", "openssl", "native-tls"]
.contains(&name)
.then(|| format!("{name} {}", package["version"].as_str().unwrap()))
})
.collect()
}

#[test]
fn package_leaves_out_the_repository_tooling() {
for path in package_list() {
Expand Down Expand Up @@ -60,30 +85,48 @@ fn package_carries_the_factory_skills_with_their_license_and_credits() {

#[test]
fn the_binary_never_links_openssl() {
let output = Command::new(env!("CARGO"))
.args([
"tree",
"--edges",
"normal,build",
"--prefix",
"none",
"--format",
"{p}",
"--target",
"all",
"--offline",
])
.current_dir(env!("CARGO_MANIFEST_DIR"))
.output()
.expect("could not run cargo tree");
assert!(
output.status.success(),
"stderr: {}",
String::from_utf8_lossy(&output.stderr)
let lockfile = fs::read_to_string(Path::new(env!("CARGO_MANIFEST_DIR")).join("Cargo.lock"))
.expect("could not read Cargo.lock");
let linked = openssl_packages(&lockfile);
assert!(linked.is_empty(), "{linked:?} are dependencies");
}

#[test]
fn a_lockfile_with_openssl_or_native_tls_in_it_is_caught() {
let lockfile = r#"
version = 4

[[package]]
name = "native-tls"
version = "0.2.14"
dependencies = [
"openssl",
"openssl-probe",
"openssl-sys",
]

[[package]]
name = "openssl"
version = "0.10.73"

[[package]]
name = "openssl-probe"
version = "0.2.1"

[[package]]
name = "openssl-sys"
version = "0.9.109"

[[package]]
name = "rustls"
version = "0.23.31"
"#;
assert_eq!(
openssl_packages(lockfile),
[
"native-tls 0.2.14",
"openssl 0.10.73",
"openssl-sys 0.9.109"
]
);
for package in String::from_utf8(output.stdout).unwrap().lines() {
for linked in ["openssl-sys ", "openssl ", "native-tls "] {
assert!(!package.starts_with(linked), "{package} is a dependency");
}
}
}
Loading