Skip to content

Commit

Permalink
Allow excluding packages from verification with --exclude (#2399)
Browse files Browse the repository at this point in the history
  • Loading branch information
adpaco-aws authored Apr 21, 2023
1 parent e1bc7bf commit c7b38c2
Show file tree
Hide file tree
Showing 30 changed files with 309 additions and 11 deletions.
6 changes: 6 additions & 0 deletions kani-driver/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ pub struct CargoArgs {
/// Do not activate the `default` feature
#[arg(long)]
pub no_default_features: bool,

// This tolerates spaces too, but we say "comma" only because this is the least error-prone approach...
/// Comma separated list of features to activate
#[arg(short = 'F', long)]
Expand All @@ -314,9 +315,14 @@ pub struct CargoArgs {
/// Build all packages in the workspace
#[arg(long)]
pub workspace: bool,

/// Run Kani on the specified packages.
#[arg(long, short, conflicts_with("workspace"), num_args(1..))]
pub package: Vec<String>,

/// Exclude the specified packages
#[arg(long, short, requires("workspace"), conflicts_with("package"), num_args(1..))]
pub exclude: Vec<String>,
}

impl CargoArgs {
Expand Down
44 changes: 33 additions & 11 deletions kani-driver/src/call_cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl KaniSession {
pkg_args.extend(["--".to_string(), self.reachability_arg()]);

let mut found_target = false;
let packages = packages_to_verify(&self.args, &metadata);
let packages = packages_to_verify(&self.args, &metadata)?;
let mut artifacts = vec![];
let mut failed_targets = vec![];
for package in packages {
Expand Down Expand Up @@ -261,35 +261,57 @@ fn print_msg(diagnostic: &Diagnostic, use_rendered: bool) -> Result<()> {
Ok(())
}

/// Check that all package names are present in the workspace, otherwise return which aren't.
fn validate_package_names(package_names: &[String], packages: &[Package]) -> Result<()> {
let package_list: Vec<String> = packages.iter().map(|pkg| pkg.name.clone()).collect();
let unknown_packages: Vec<&String> =
package_names.iter().filter(|pkg_name| !package_list.contains(pkg_name)).collect();

// Some packages aren't in the workspace. Return an error which includes their names.
if !unknown_packages.is_empty() {
let fmt_packages: Vec<String> =
unknown_packages.iter().map(|pkg| format!("`{pkg}`")).collect();
let error_msg = if unknown_packages.len() == 1 {
format!("couldn't find package {}", fmt_packages[0])
} else {
format!("couldn't find packages {}", fmt_packages.join(", "))
};
bail!(error_msg);
};
Ok(())
}

/// Extract the packages that should be verified.
/// If `--package <pkg>` is given, return the list of packages selected.
/// If `--exclude <pkg>` is given, return the list of packages not excluded.
/// If `--workspace` is given, return the list of workspace members.
/// If no argument provided, return the root package if there's one or all members.
/// - I.e.: Do whatever cargo does when there's no `default_members`.
/// - This is because `default_members` is not available in cargo metadata.
/// See <https://github.com/rust-lang/cargo/issues/8033>.
fn packages_to_verify<'b>(args: &KaniArgs, metadata: &'b Metadata) -> Vec<&'b Package> {
debug!(package_selection=?args.cargo.package, workspace=args.cargo.workspace, "packages_to_verify args");
/// In addition, if either `--package <pkg>` or `--exclude <pkg>` is given,
/// validate that `<pkg>` is a package name in the workspace, or return an error
/// otherwise.
fn packages_to_verify<'b>(args: &KaniArgs, metadata: &'b Metadata) -> Result<Vec<&'b Package>> {
debug!(package_selection=?args.cargo.package, package_exclusion=?args.cargo.exclude, workspace=args.cargo.workspace, "packages_to_verify args");
let packages = if !args.cargo.package.is_empty() {
validate_package_names(&args.cargo.package, &metadata.packages)?;
args.cargo
.package
.iter()
.map(|pkg_name| {
metadata
.packages
.iter()
.find(|pkg| pkg.name == *pkg_name)
.expect(&format!("Cannot find package '{pkg_name}'"))
})
.map(|pkg_name| metadata.packages.iter().find(|pkg| pkg.name == *pkg_name).unwrap())
.collect()
} else if !args.cargo.exclude.is_empty() {
validate_package_names(&args.cargo.exclude, &metadata.packages)?;
metadata.packages.iter().filter(|pkg| !args.cargo.exclude.contains(&pkg.name)).collect()
} else {
match (args.cargo.workspace, metadata.root_package()) {
(true, _) | (_, None) => metadata.workspace_packages(),
(_, Some(root_pkg)) => vec![root_pkg],
}
};
trace!(?packages, "packages_to_verify result");
packages
Ok(packages)
}

/// Extract Kani artifact that might've been generated from a given rustc artifact.
Expand Down
17 changes: 17 additions & 0 deletions tests/cargo-ui/ws-package-exclude-unknown/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

# This workspace test checks that the `--exclude` option prints a user-friendly
# error when the package isn't found in the workspace.

[package]
name = "ws-package-exclude"
version = "0.1.0"
edition = "2021"

[workspace]
members = ["lib_package", "bin_package"]

[workspace.metadata.kani.flags]
workspace = true
exclude = ["unknown_package"]
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-exclude-unknown/bin_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "bin_package"
version = "0.1.0"
edition = "2021"

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

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_bin_package() {
assert!(1 + 1 == 2);
}
1 change: 1 addition & 0 deletions tests/cargo-ui/ws-package-exclude-unknown/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
error: couldn't find package `unknown_package`
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-exclude-unknown/lib_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "lib_package"
version = "0.1.0"
edition = "2021"

[lib]
name = "lib_package"
path = "src/lib.rs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

pub fn api() {}

#[kani::proof]
fn harness_in_lib_package() {
assert!(1 + 1 == 2);
}
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-exclude-unknown/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_ws_package() {
assert!(1 + 1 == 3);
}
17 changes: 17 additions & 0 deletions tests/cargo-ui/ws-package-exclude/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

# This workspace test checks that the `--exclude` option removes the
# `ws-package-exclude` package from the packages to verify.

[package]
name = "ws-package-exclude"
version = "0.1.0"
edition = "2021"

[workspace]
members = ["lib_package", "bin_package"]

[workspace.metadata.kani.flags]
workspace = true
exclude = ["ws-package-exclude"]
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-exclude/bin_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "bin_package"
version = "0.1.0"
edition = "2021"

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

[dependencies]
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-exclude/bin_package/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_bin_package() {
assert!(1 + 1 == 2);
}
3 changes: 3 additions & 0 deletions tests/cargo-ui/ws-package-exclude/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Checking harness harness_in_bin_package...
Checking harness harness_in_lib_package...
Complete - 2 successfully verified harnesses, 0 failures, 2 total.
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-exclude/lib_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "lib_package"
version = "0.1.0"
edition = "2021"

[lib]
name = "lib_package"
path = "src/lib.rs"
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-exclude/lib_package/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

pub fn api() {}

#[kani::proof]
fn harness_in_lib_package() {
assert!(1 + 1 == 2);
}
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-exclude/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_ws_package() {
assert!(1 + 1 == 2);
}
16 changes: 16 additions & 0 deletions tests/cargo-ui/ws-package-select-unknown/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

# This workspace test checks that the `--package` option prints a user-friendly
# error when the package isn't found in the workspace.

[package]
name = "ws-package-select"
version = "0.1.0"
edition = "2021"

[workspace]
members = ["lib_package", "bin_package"]

[workspace.metadata.kani.flags]
package = ["unknown_package"]
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-select-unknown/bin_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "bin_package"
version = "0.1.0"
edition = "2021"

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

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_bin_package() {
assert!(1 + 1 == 2);
}
1 change: 1 addition & 0 deletions tests/cargo-ui/ws-package-select-unknown/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
error: couldn't find package `unknown_package`
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-select-unknown/lib_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "lib_package"
version = "0.1.0"
edition = "2021"

[lib]
name = "lib_package"
path = "src/lib.rs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

pub fn api() {}

#[kani::proof]
fn harness_in_lib_package() {
assert!(1 + 1 == 2);
}
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-select-unknown/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_ws_package() {
assert!(1 + 1 == 2);
}
16 changes: 16 additions & 0 deletions tests/cargo-ui/ws-package-select/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

# This workspace test checks that the `--package` option only includes the
# `lib_package` and `bin_package` packages as the packages to verify.

[package]
name = "ws-package-select"
version = "0.1.0"
edition = "2021"

[workspace]
members = ["lib_package", "bin_package"]

[workspace.metadata.kani.flags]
package = ["lib_package", "bin_package"]
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-select/bin_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "bin_package"
version = "0.1.0"
edition = "2021"

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

[dependencies]
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-select/bin_package/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_bin_package() {
assert!(1 + 1 == 2);
}
3 changes: 3 additions & 0 deletions tests/cargo-ui/ws-package-select/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Checking harness harness_in_bin_package...
Checking harness harness_in_lib_package...
Complete - 2 successfully verified harnesses, 0 failures, 2 total.
11 changes: 11 additions & 0 deletions tests/cargo-ui/ws-package-select/lib_package/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright Kani Contributors
# SPDX-License-Identifier: Apache-2.0 OR MIT

[package]
name = "lib_package"
version = "0.1.0"
edition = "2021"

[lib]
name = "lib_package"
path = "src/lib.rs"
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-select/lib_package/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

pub fn api() {}

#[kani::proof]
fn harness_in_lib_package() {
assert!(1 + 1 == 2);
}
9 changes: 9 additions & 0 deletions tests/cargo-ui/ws-package-select/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

fn main() {}

#[kani::proof]
fn harness_in_ws_package() {
assert!(1 + 1 == 3);
}

0 comments on commit c7b38c2

Please sign in to comment.