guarantee serde is in lockstep with serde_derive

This commit is contained in:
soqb 2023-08-21 00:53:22 +01:00
parent 3c7dd6fc1e
commit 2ea7e1300f
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
7 changed files with 149 additions and 0 deletions

View File

@ -156,3 +156,12 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/install@cargo-outdated
- run: cargo outdated --workspace --exit-code 1
lockstep:
name: Lockstep
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- run: cd test_suite/assert_lockstep && cargo run -- dummy_dependant

View File

@ -4,6 +4,7 @@ members = [
"serde_derive",
"serde_derive_internals",
"test_suite",
"test_suite/assert_lockstep",
]
[patch.crates-io]

View File

@ -31,6 +31,10 @@ features = ["derive"]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
# Even though this `cfg` can never be enabled, it still forces cargo to keep `serde_derive` in lockstep with `serde`.
[target.'cfg(any())'.dependencies]
serde_derive = { version = "=1.0.185", path = "../serde_derive" }
### FEATURES #################################################################

View File

@ -0,0 +1,12 @@
[package]
name = "assert_lockstep"
version = "0.1.0"
edition = "2018"
rust-version = "1.70"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cargo-lock = "8.0.0"
toml = "0.5"
thiserror = "1.0.39"

View File

@ -0,0 +1,12 @@
[package]
name = "dummy_dependant"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { path = "../../../serde" }
# `workspace.exclude` does not seem to work with doubly nested paths.
[workspace]

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,110 @@
use cargo_lock::{Lockfile, Package, Version};
use std::convert::Infallible;
use std::fmt;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::str::FromStr;
use thiserror::Error;
#[derive(Debug, Error)]
enum TestError {
#[error("Package \"{name}\" not found in the lockfile")]
NoPackageFound { name: String },
#[error("Package \"{first}\" and \"{second}\" had different versions in the lockfile")]
VersionMismatch { first: PackageId, second: PackageId },
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("Error parsing lockfile: {0}")]
Lock(#[from] cargo_lock::Error),
}
impl From<Infallible> for TestError {
fn from(value: Infallible) -> Self {
match value {}
}
}
#[derive(Debug)]
struct PackageId {
name: String,
version: Version,
}
impl PackageId {
fn new(package: &Package) -> Self {
Self {
name: package.name.to_string(),
version: package.version.clone(),
}
}
}
impl fmt::Display for PackageId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{name}@{version}",
name = self.name,
version = self.version,
)
}
}
fn find_package<'a>(lockfile: &'a Lockfile, package_name: &str) -> Result<&'a Package, TestError> {
lockfile
.packages
.iter()
.find(|package| package.name.as_str() == package_name)
.ok_or_else(|| TestError::NoPackageFound {
name: package_name.to_owned(),
})
}
fn main() {
if let Err(error) = main_inner() {
panic!("{}", error);
}
}
fn main_inner() -> Result<(), TestError> {
let path = PathBuf::from_str(&std::env::args().nth(1).unwrap())?;
Command::new("cargo")
.arg("clean")
.current_dir(&path)
.stdout(Stdio::inherit())
.output()?;
Command::new("cargo")
.arg("update")
.current_dir(&path)
.stdout(Stdio::inherit())
.output()?;
let lockfile = Lockfile::load(path.join("Cargo.lock"))?;
let serde = find_package(&lockfile, "serde")?;
println!("packages should match {id}", id = PackageId::new(&serde));
let package_names = &["serde_derive"];
let packages = package_names
.iter()
.map(|name| find_package(&lockfile, name));
for package in packages {
let package = package?;
println!("discovered package {id}", id = PackageId::new(&package));
if package.version != serde.version {
return Err(TestError::VersionMismatch {
first: PackageId::new(&serde),
second: PackageId::new(&package),
});
}
}
Ok(())
}