Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Commit

Permalink
[cargo-compare] add some comparison testing to CI
Browse files Browse the repository at this point in the history
This works by:
* setting up a real, fairly complex fixture
* generating random queries using proptest
* running them through cargo and guppy
* ensuring that they produce the same results

Not only does this give us high confidence that cargo
and guppy produce the same results, it also gets us
most of the way to #82.

Most of the work in this commit is simply setting up
all the necessary test infrastructure. We piggy-back on
existing proptest infrastructure as much as possible.
  • Loading branch information
sunshowers committed May 1, 2020
1 parent 679f41e commit 5c44f20
Show file tree
Hide file tree
Showing 36 changed files with 538 additions and 25 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ The fixtures are organized into several folders.

* `small`: relatively simple examples that cover basic and some edge case functionality
* `large`: complex examples pulled from real-world Rust repositories, that test a variety of edge cases
* `invalid`: examples that are *representable* as cargo metadata (i.e. they are valid JSON and follow the general
schema) but are *invalid* in some way; `cargo metadata` should never be able to generate these
* `invalid`: examples that are [*representable*](https://oleb.net/blog/2018/03/making-illegal-states-unrepresentable/)
as cargo metadata (i.e. they are valid JSON and follow the general schema) but are *invalid* in some way; `cargo
metadata` should never be able to generate these
* `workspace`: real workspaces, used for comparison testing with Cargo
2 changes: 2 additions & 0 deletions fixtures/workspace/inside-outside/external/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
24 changes: 24 additions & 0 deletions fixtures/workspace/inside-outside/external/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "external"
version = "0.1.0"
authors = ["Fake Author <[email protected]>"]
edition = "2018"

[dependencies]
transitive = { path = "../transitive" }
bytes = { version = "0.5", optional = true }

[dev-dependencies]
transitive = { path = "../transitive", features = ["dev-feature"] }

[build-dependencies]
transitive = { path = "../transitive", features = ["build-feature"] }

[features]
internal-dev-feature = []
internal-build-feature = []
main-dev-feature = []
main-build-feature = []
side-feature = ["bytes"]

[workspace]
7 changes: 7 additions & 0 deletions fixtures/workspace/inside-outside/external/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
2 changes: 2 additions & 0 deletions fixtures/workspace/inside-outside/inactive/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
21 changes: 21 additions & 0 deletions fixtures/workspace/inside-outside/inactive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "inactive"
version = "0.1.0"
authors = ["Fake Author <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
transitive = { path = "../transitive", features = ["inactive-normal"] }

[build-dependencies]
transitive = { path = "../transitive", features = ["inactive-build"] }

[dev-dependencies]
transitive = { path = "../transitive", features = ["inactive-dev"] }

[features]
extra = ["transitive/extra"]

[workspace]
7 changes: 7 additions & 0 deletions fixtures/workspace/inside-outside/inactive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
2 changes: 2 additions & 0 deletions fixtures/workspace/inside-outside/transitive/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
17 changes: 17 additions & 0 deletions fixtures/workspace/inside-outside/transitive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "transitive"
version = "0.1.0"
authors = ["Fake Author <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
build-feature = []
dev-feature = []
inactive-normal = []
inactive-build = []
inactive-dev = []
extra = []

[workspace]
7 changes: 7 additions & 0 deletions fixtures/workspace/inside-outside/transitive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
1 change: 1 addition & 0 deletions fixtures/workspace/inside-outside/workspace/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
66 changes: 66 additions & 0 deletions fixtures/workspace/inside-outside/workspace/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions fixtures/workspace/inside-outside/workspace/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[workspace]
members = ["main", "internal", "side"]
23 changes: 23 additions & 0 deletions fixtures/workspace/inside-outside/workspace/internal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "internal"
version = "0.1.0"
authors = ["Fake Author <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
lazy_static = "1"
external = { path = "../../external" }

[dev-dependencies]
lazy_static = {version = "1", features = ["spin"] }
bytes = "0.5"
external = { path = "../../external", features = ["internal-dev-feature"] }

[build-dependencies]
external = { path = "../../external", features = ["internal-build-feature"] }

[features]
dev-feature = []
build-feature = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
26 changes: 26 additions & 0 deletions fixtures/workspace/inside-outside/workspace/main/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "main"
version = "0.1.0"
authors = ["Fake Author <[email protected]>"]
edition = "2018"
build = "build.rs"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
external = { path = "../../external" }
internal = { path = "../internal" }

[build-dependencies]
external = { path = "../../external", features = ["main-build-feature"] }
internal = { path = "../internal", features = ["build-feature"] }

[dev-dependencies]
external = { path = "../../external", features = ["main-dev-feature"] }
internal = { path = "../internal", features = ["dev-feature"] }

[target.'cfg(all(unix, not(unix)))'.build-dependencies]
inactive = { path = "../../inactive" }

[features]
inactive-extra = ["inactive/extra"]
2 changes: 2 additions & 0 deletions fixtures/workspace/inside-outside/workspace/main/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fn main() {
}
7 changes: 7 additions & 0 deletions fixtures/workspace/inside-outside/workspace/main/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
10 changes: 10 additions & 0 deletions fixtures/workspace/inside-outside/workspace/side/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "side"
version = "0.1.0"
authors = ["Fake Author <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
external = { path = "../../external", features = ["side-feature"] }
7 changes: 7 additions & 0 deletions fixtures/workspace/inside-outside/workspace/side/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
7 changes: 7 additions & 0 deletions fixtures/workspace/inside-outside/workspace/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
4 changes: 4 additions & 0 deletions guppy-cmdlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ edition = "2018"
anyhow = "1.0.28"
guppy = { path = "../guppy" }
structopt = "0.3"
proptest = { version = "0.9", optional = true }

[features]
proptest09 = ["proptest", "guppy/proptest09"]
7 changes: 5 additions & 2 deletions guppy-cmdlib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
//!
//! This library allows translating command-line arguments into guppy's data structures.
#[cfg(feature = "proptest09")]
pub mod proptest;

use anyhow::Result;
use guppy::graph::feature::{
all_filter, default_filter, feature_filter, none_filter, FeatureFilter, FeatureQuery,
Expand Down Expand Up @@ -66,11 +69,11 @@ impl PackagesAndFeatures {
/// Context for invoking the `cargo metadata` command.
///
/// The options mirror Cargo's.
#[derive(Debug, StructOpt)]
#[derive(Clone, Debug, StructOpt)]
pub struct CargoMetadataOptions {
/// Path to Cargo.toml
#[structopt(long = "manifest-path")]
manifest_path: Option<PathBuf>,
pub manifest_path: Option<PathBuf>,
}

impl CargoMetadataOptions {
Expand Down
33 changes: 33 additions & 0 deletions guppy-cmdlib/src/proptest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) The cargo-guppy Contributors
// SPDX-License-Identifier: MIT OR Apache-2.0

//! Proptest support.
use crate::PackagesAndFeatures;
use guppy::graph::PackageGraph;
use proptest::collection::hash_set;
use proptest::prelude::*;

impl PackagesAndFeatures {
pub fn strategy<'g>(graph: &'g PackageGraph) -> impl Strategy<Value = Self> + 'g {
let workspace = graph.workspace();
(
// The lower bound of 0 is important because 0 means the whole workspace.
hash_set(workspace.prop09_name_strategy(), 0..8),
any::<bool>(),
any::<bool>(),
)
.prop_map(move |(packages, all_features, no_default_features)| {
// TODO: select features from these packages (probably requires flat_map :/ )
Self {
packages: packages
.into_iter()
.map(|package| package.to_string())
.collect(),
features: vec![],
all_features,
no_default_features,
}
})
}
}
1 change: 1 addition & 0 deletions guppy/src/graph/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ impl WorkspaceImpl {
root: workspace_root,
members_by_path,
members_by_name,
name_list: OnceCell::new(),
})
}
}
Expand Down
10 changes: 9 additions & 1 deletion guppy/src/graph/graph_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ impl<'g> DependsCache<'g> {
#[derive(Clone, Debug)]
pub struct Workspace<'g> {
graph: &'g PackageGraph,
inner: &'g WorkspaceImpl,
pub(super) inner: &'g WorkspaceImpl,
}

impl<'g> Workspace<'g> {
Expand All @@ -472,6 +472,11 @@ impl<'g> Workspace<'g> {
&self.inner.root
}

/// Returns the number of packages in this workspace.
pub fn member_count(&self) -> usize {
self.inner.members_by_path.len()
}

/// Returns an iterator over workspace paths and package metadatas, sorted by the path
/// they're in.
pub fn members(
Expand Down Expand Up @@ -522,6 +527,9 @@ pub(super) struct WorkspaceImpl {
// This is a BTreeMap to allow presenting data in sorted order.
pub(super) members_by_path: BTreeMap<PathBuf, PackageId>,
pub(super) members_by_name: BTreeMap<Box<str>, PackageId>,
// Cache for members by name (only used for proptests)
#[cfg(feature = "proptest09")]
pub(super) name_list: OnceCell<Vec<Box<str>>>,
}

/// Information about a specific package in a `PackageGraph`.
Expand Down
Loading

0 comments on commit 5c44f20

Please sign in to comment.