From 7e63ff937fbafa47a881ad22105e84a361c6c641 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Tue, 26 Nov 2019 23:48:57 +0900 Subject: [PATCH 1/2] Improve `dep-tests` --- dep-tests.toml | 18 +- dep-tests/Cargo.toml | 2 + dep-tests/src/main.rs | 407 ++++++++++++++++++++++++++++-------------- 3 files changed, 292 insertions(+), 135 deletions(-) diff --git a/dep-tests.toml b/dep-tests.toml index 1b86cdb..6dce855 100644 --- a/dep-tests.toml +++ b/dep-tests.toml @@ -1,17 +1,25 @@ +# See `cargo help pkgid` + +# **`-p`, `--package`が指定されていないとき**、記述したSPECに対応するpackageを除外する。 exclude = [ "c2-chacha:0.2.3", # よくわからない理由でビルドに失敗する "derive_more:0.99.2", # 必要なファイルがexcludeされている - "jemallocator:0.3.2", # よくわからない理由でビルドに失敗する "libm:0.1.4", # `#![deny(warnings)]` "mac:0.1.1", # `#![deny(warnings)]` "nom:5.0.1", # 必要なファイルがexcludeされている "num-rational:0.2.2", # よくわからない理由でビルドに失敗する - "petgraph:0.4.13", # よくわからない理由で実行時に失敗する - "primal:0.2.3", # 最終リリース日が古すぎて"normalizing"が行なわれておらず、workspace membersが相対パスのまま - "primal-estimate:0.2.1", # 最終リリース日が古すぎて"normalizing"が行なわれておらず、workspace membersが相対パスのまま + "primal-estimate:0.2.1", # 古すぎて"normalizing"が行なわれておらず、workspace membersが相対パスのまま + "primal:0.2.3", # 古すぎて"normalizing"が行なわれておらず、workspace membersが相対パスのまま "proc-macro2:1.0.6", # よくわからない理由でビルドに失敗する + "rand:0.6.5", # 現状同一の`name`のpackageは一つのworkspace内で共存できない "rand_core:0.3.1", # よくわからない理由でビルドに失敗する - # "smallvec:1.0.0", # 成功はするが謎のエラーが表示される + "rand_pcg:0.1.2", # 現状同一の`name`のpackageは一つのworkspace内で共存できない "syn:0.15.44", # よくわからない理由でビルドに失敗する "syn:1.0.8", # よくわからない理由でビルドに失敗する + "smallvec:0.6.13", # 現状同一の`name`のpackageは一つのworkspace内で共存できない ] + +# key部分でSPECを指定すると、そのSPECの対象のpackageはvalue部分で指定したtargetのみ実行する。 +[filter] +"smallvec:1.0.0" = { lib = true } # doc-testでエラーが表示され、成功はするしおそらく実害は無いが見た目がよろしくない +"text_io:0.1.7" = { doc = true, lib = true, test = ["module", "read_str"] } # `"tuple"`が`target/`下の実行ファイルを実行(しかもexamplesの)という行儀の悪いことをやっている diff --git a/dep-tests/Cargo.toml b/dep-tests/Cargo.toml index 2ddde99..1f0d542 100644 --- a/dep-tests/Cargo.toml +++ b/dep-tests/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] cargo = "0.40.0" +either = "1.5.3" failure = "0.1.6" fs_extra = "1.1.0" itertools = "0.8.2" @@ -16,3 +17,4 @@ once_cell = "1.2.0" serde = { version = "1.0.103", features = ["derive"] } structopt = "0.3.5" toml = "0.5.5" +toml_edit = "0.1.5" diff --git a/dep-tests/src/main.rs b/dep-tests/src/main.rs index 8d1c591..3d53718 100644 --- a/dep-tests/src/main.rs +++ b/dep-tests/src/main.rs @@ -1,12 +1,13 @@ use cargo::core::compiler::{self, CompileMode, TargetInfo}; -use cargo::core::dependency; +use cargo::core::dependency::{self, Dependency}; use cargo::core::package::{Package, PackageSet}; use cargo::core::resolver::ResolveOpts; use cargo::core::shell::{Shell, Verbosity}; -use cargo::core::{PackageId, PackageIdSpec, Resolve, Workspace}; -use cargo::ops::{Packages, TestOptions}; +use cargo::core::{PackageIdSpec, Resolve, Workspace}; +use cargo::ops::{CompileFilter, CompileOptions, FilterRule, LibRule, Packages, TestOptions}; use cargo::util::command_prelude::{App, AppExt as _, AppSettings, ArgMatchesExt as _}; use cargo::{CliError, CliResult}; +use either::Either; use failure::{format_err, Fail as _, Fallible}; use itertools::Itertools as _; use maplit::btreeset; @@ -14,9 +15,10 @@ use once_cell::sync::Lazy; use serde::Deserialize; use structopt::StructOpt; +use std::borrow::Borrow; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::env; -use std::fmt::{Display, Write as _}; +use std::fmt::Display; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::process::ExitStatus; @@ -65,7 +67,7 @@ struct Opt { value_name("SPEC"), number_of_values(1), parse(try_from_str = PackageIdSpec::parse), - help("**Dependency** to run test for") + help("Package to run test for") )] package: Vec, #[structopt( @@ -84,8 +86,6 @@ struct Opt { help("How deep in the dependency chain to search") )] depth: Option, - #[structopt(long, value_name("N"), help("Skips the first N packages"))] - skip: Option, #[structopt( default_value_os({ static DEFAULT: Lazy = @@ -110,14 +110,14 @@ impl Opt { &[], )?; - let DepTestsConfig { exclude } = DepTestsConfig::load(config)?; + let DepTestsConfig { exclude, filter } = DepTestsConfig::load(config)?; let ws = Workspace::new(&config.cwd().join(MANIFEST_PATH), config)?; let (packages, resolve) = cargo::ops::resolve_ws_with_opts( &ws, ResolveOpts::new( - false, + true, &self.features, self.all_features, self.no_default_features, @@ -125,34 +125,35 @@ impl Opt { &Packages::Default.to_package_id_specs(&ws)?, )?; - let (normal_deps, packages) = ( - find_normal_deps(&ws, &resolve, self.depth)?, - filter_packages(&packages, &self.package, &exclude)?, - ); - - let wss = setup_workspaces(config, &self.dir, &normal_deps, &packages)?; - for (i, (id, ws)) in wss.iter().enumerate().skip(self.skip()) { - let mut msg = format!("Testing `{}` ({}/{})", id, i + 1, wss.len()); - if let Some(skip) = self.skip { - write!(msg, " (skipping the first {} package(s))", skip).unwrap(); - } - config.shell().info(msg)?; - run_tests(&resolve, *id, ws)?; - } - + let dev_pkgs = filter_packages(&ws, &packages, &resolve, None, |_| true)?; + let (dev_deps_free_pkgs, target_pkgs) = + filter_packages(&ws, &packages, &resolve, self.depth, |d| { + d.kind() == dependency::Kind::Normal + })? + .iter() + .copied() + .filter(|pkg| { + let (id, include) = (pkg.package_id(), &self.package); + include.iter().any(|s| s.matches(id)) + || include.is_empty() && !exclude.iter().any(|s| s.matches(id)) + }) + .partition(|pkg| pkg.dependencies().iter().all(|d| d.is_transitive())); + + let new_ws = setup_workspace(config, &self.dir, &dev_pkgs, &target_pkgs, &resolve)?; + + run_tests(&ws, dev_deps_free_pkgs, &filter)?; + run_tests(&new_ws, new_ws.members(), &filter)?; config.shell().info("Successful!").map_err(Into::into) } - - fn skip(&self) -> usize { - self.skip.map(NonZeroUsize::get).unwrap_or_default() - } } -fn find_normal_deps( - ws: &Workspace, +fn filter_packages<'a>( + ws: &'a Workspace, + packages: &'a PackageSet, resolve: &Resolve, depth: Option, -) -> Fallible> { + extra_pred: fn(&Dependency) -> bool, +) -> Fallible> { let rustc = ws.config().load_global_rustc(Some(&ws))?; let host_triple = &rustc.host; let target_info = TargetInfo::new( @@ -162,21 +163,21 @@ fn find_normal_deps( compiler::Kind::Host, )?; - let member = ws.current()?.package_id(); - let mut normal_deps = btreeset!(member); - let mut cur = btreeset!(member); + let mut outcome = btreeset!(ws.current()?); + let mut cur = outcome.clone(); let mut depth = depth.map(NonZeroUsize::get); while !cur.is_empty() && depth.map_or(true, |d| d > 0) { let mut next = btreeset!(); for from in cur { - for (to, deps) in resolve.deps(from) { + for (to, deps) in resolve.deps(from.package_id()) { + let to = packages.get_one(to)?; for dep in deps { - if dep.kind() == dependency::Kind::Normal // `dep` may be a build-dependency. - && dep - .platform() - .as_ref() - .map_or(true, |p| p.matches(host_triple, target_info.cfg())) - && normal_deps.insert(to) + if dep + .platform() + .as_ref() + .map_or(true, |p| p.matches(host_triple, target_info.cfg())) + && extra_pred(dep) + && outcome.insert(to) { next.insert(to); } @@ -187,116 +188,229 @@ fn find_normal_deps( depth = depth.map(|d| d - 1); } for member in ws.members() { - normal_deps.remove(&member.package_id()); + outcome.remove(member); } - Ok(normal_deps) -} - -fn filter_packages<'a>( - packages: &'a PackageSet, - include: &[PackageIdSpec], - exclude: &HashSet, -) -> Fallible> { - let packages = packages.get_many(packages.package_ids())?; - Ok(packages - .into_iter() - .map(|p| (p.package_id(), p)) - .filter(|&(id, _)| { - (include.is_empty() || include.iter().any(|s| s.matches(id))) - && !exclude.iter().any(|s| s.matches(id)) - }) - .collect::>()) + Ok(outcome) } -fn setup_workspaces<'cfg>( +fn setup_workspace<'cfg>( config: &'cfg cargo::Config, root: &Path, - normal_deps: &BTreeSet, - packages: &HashMap, -) -> Fallible>> { - let wss = normal_deps + pkgs_to_build: &BTreeSet<&Package>, + pkgs_to_test: &BTreeSet<&Package>, + resolve: &Resolve, +) -> Fallible> { + let deps = pkgs_to_build .iter() - .flat_map(|d| packages.get(d)) .map(|dep| { - let src = dep.root(); - let dst = root.join(src.file_name().unwrap_or_default()); - let dst = cargo::util::paths::normalize_path(&if dst.is_relative() { - config.cwd().join(dst) + let path_or_version = if pkgs_to_test.contains(dep) { + let src = dep.root(); + let dst = root.join(src.file_name().unwrap_or_default()); + let dst = cargo::util::paths::normalize_path(&if dst.is_relative() { + config.cwd().join(dst) + } else { + dst + }); + + config + .shell() + .info(format!("Copying {} to {}", src.display(), dst.display()))?; + + fs_extra::dir::copy( + src, + &dst, + &fs_extra::dir::CopyOptions { + skip_exist: true, + copy_inside: true, + ..fs_extra::dir::CopyOptions::new() + }, + )?; + + Either::Left(format!( + "./{}", + dst.file_name() + .unwrap_or_default() + .to_str() + .expect("the directory names should be -") + )) } else { - dst - }); + Either::Right(dep.package_id().version()) + }; + let features = resolve.features_sorted(dep.package_id()); + Ok((dep.package_id(), (path_or_version, features))) + }) + .collect::>>()?; + for (path_or_version, _) in deps.values() { + if let Either::Left(path) = path_or_version { + let manifest_path = root.join(path).join("Cargo.toml"); + let manifest_path = cargo::util::paths::normalize_path(&manifest_path); + let mut cargo_toml = + cargo::util::paths::read(&manifest_path)?.parse::()?; + cargo_toml.as_table_mut().remove("profile"); + cargo::util::paths::write(&manifest_path, cargo_toml.to_string().as_ref())?; config .shell() - .info(&format!("Copying {} to {}", src.display(), dst.display()))?; - - fs_extra::dir::copy( - src, - &dst, - &fs_extra::dir::CopyOptions { - skip_exist: true, - copy_inside: true, - ..fs_extra::dir::CopyOptions::new() - }, - )?; - - let ws = Workspace::new(&dst.join("Cargo.toml"), config)?; - Ok((dep.package_id(), ws)) - }) - .collect::>>()?; + .info(format!("Modified {}", manifest_path.display()))?; + } + } - for ws in wss.values() { - let src = cargo::util::paths::normalize_path(&config.cwd().join("Cargo.lock")); - let dst = ws.root().join("Cargo.lock"); + let src = cargo::util::paths::normalize_path(&config.cwd().join("Cargo.lock")); + let dst = root.join("Cargo.lock"); - config - .shell() - .info(&format!("Copying {} to {}", src.display(), dst.display()))?; + config + .shell() + .info(&format!("Copying {} to {}", src.display(), dst.display()))?; - fs_extra::file::copy( - src, - dst, - &fs_extra::file::CopyOptions { - overwrite: true, - ..fs_extra::file::CopyOptions::new() - }, - )?; + fs_extra::file::copy( + src, + dst, + &fs_extra::file::CopyOptions { + overwrite: true, + ..fs_extra::file::CopyOptions::new() + }, + )?; + + let mut cargo_toml = r#"[package] +name = "atcoder-rust-base-dep-tests" +version = "0.0.0" +edition = "2018" +publish = false + +[workspace] +members = [] + +[patch.crates-io] +"# + .parse::() + .unwrap(); + + cargo_toml["workspace"]["members"] = { + let mut workspace = toml_edit::Array::default(); + for (path_or_version, _) in deps.values() { + if let Either::Left(path) = path_or_version { + workspace.push(&**path); + } + } + toml_edit::value(workspace) + }; + + for (id, (path_or_version, _)) in &deps { + if let Either::Left(path) = path_or_version { + cargo_toml["patch"]["crates-io"][&*id.name()]["path"] = toml_edit::value(&**path); + } + } + + cargo_toml["dependencies"] = toml_edit::table(); + for (i, (id, (path_or_version, features))) in deps.iter().enumerate() { + let dummy_extern_crate_name = format!("_{}", i); + let mut val = toml_edit::InlineTable::default(); + val.get_or_insert("package", &*id.name()); + match path_or_version { + Either::Left(path) => val.get_or_insert("path", &**path), + Either::Right(version) => val.get_or_insert("version", format!("={}", version)), + }; + val.get_or_insert("default-features", false); + let mut val_features = toml_edit::Array::default(); + for &feature in features { + val_features.push(feature); + } + val.get_or_insert("features", val_features); + cargo_toml["dependencies"][&dummy_extern_crate_name] = toml_edit::value(val); } - Ok(wss) -} -fn run_tests(resolve: &Resolve, id: PackageId, ws: &Workspace) -> CliResult { - // `ws.current()?.package_id().source_id()` differs to `id.source_id()`. + let manifest_path = root.join("Cargo.toml"); + cargo::util::paths::write(&manifest_path, cargo_toml.to_string().as_ref())?; + config + .shell() + .info(format!("Wrote {}", manifest_path.display()))?; + + let src_dir = root.join("src"); + cargo::util::paths::create_dir_all(&src_dir)?; + let src_path = src_dir.join("lib.rs"); + cargo::util::paths::write(&src_path, b"")?; + config + .shell() + .info(format!("Wrote {}", src_path.display()))?; + + Workspace::new(&manifest_path, config) +} - let compile_opts = { - let features = resolve.features(id); - let mut args = vec!["".to_owned(), "--no-default-features".to_owned()]; - if !features.is_empty() { - args.push("--features".to_owned()); - args.push(features.iter().join(" ")); +fn run_tests, P: Borrow>( + ws: &Workspace, + pkgs: I, + filter: &HashMap, +) -> CliResult { + fn run_tests( + ws: &Workspace, + pkg: &Package, + modify_compile_opts: impl FnOnce(&mut CompileOptions), + ) -> CliResult { + let spec = PackageIdSpec::from_package_id(pkg.package_id()).to_string(); + let mut compile_opts = App::new("") + .arg_package("") + .get_matches_from_safe(&["", "-p", &spec])? + .compile_options(ws.config(), CompileMode::Test, Some(ws))?; + modify_compile_opts(&mut compile_opts); + + let test_opts = TestOptions { + compile_opts, + no_run: false, + no_fail_fast: false, + }; + + if let Some(err) = cargo::ops::run_tests(&ws, &test_opts, &[])? { + return Err(match err.exit.as_ref().and_then(ExitStatus::code) { + Some(code) => { + let hint = format_err!("{}", err.hint(&ws, &test_opts.compile_opts)); + CliError::new(err.context(hint).into(), code) + } + None => CliError::new(err.into(), 101), + }); } - App::new("") - .arg_features() - .get_matches_from_safe(args)? - .compile_options(ws.config(), CompileMode::Test, Some(ws))? - }; + Ok(()) + } - let test_opts = TestOptions { - compile_opts, - no_run: false, - no_fail_fast: false, - }; + fn default_compile_filter() -> CompileFilter { + CompileFilter::new( + LibRule::True, + FilterRule::none(), + FilterRule::none(), + FilterRule::none(), + FilterRule::none(), + ) + } - match cargo::ops::run_tests(&ws, &test_opts, &[])? { - None => Ok(()), - Some(err) => Err(match err.exit.as_ref().and_then(ExitStatus::code) { - Some(code) => { - let hint = format_err!("{}", err.hint(&ws, &test_opts.compile_opts)); - CliError::new(err.context(hint).into(), code) - } - None => CliError::new(err.into(), 101), - }), + for pkg in pkgs { + let pkg = pkg.borrow(); + let filter = match filter + .iter() + .filter(|(k, _)| k.matches(pkg.package_id())) + .map(|(_, v)| v.clone()) + .exactly_one() + { + Ok(filter) => Some(filter), + Err(err) => match err.count() { + 0 => None, + n => return Err(format_err!("`{}` matches {} specs", pkg, n).into()), + }, + }; + + run_tests(ws, pkg, |mut compile_opts| { + compile_opts.filter = filter + .as_ref() + .map(DepTestsConfigFilter::compile_filter) + .unwrap_or_else(default_compile_filter); + })?; + + if filter.map_or(true, |DepTestsConfigFilter { doc, .. }| doc) { + run_tests(ws, pkg, |mut compile_opts| { + compile_opts.build_config.mode = CompileMode::Doctest; + compile_opts.filter = default_compile_filter(); + })?; + } } + Ok(()) } trait ShellExt { @@ -324,6 +438,7 @@ impl ShellExt for Shell { #[derive(Deserialize, Debug)] struct DepTestsConfig { exclude: HashSet, + filter: HashMap, } impl DepTestsConfig { @@ -335,3 +450,35 @@ impl DepTestsConfig { Ok(this) } } + +#[derive(Deserialize, Default, Debug, Clone, PartialEq)] +struct DepTestsConfigFilter { + #[serde(default)] + doc: bool, + #[serde(default)] + lib: bool, + #[serde(default)] + bin: BTreeSet, + #[serde(default)] + example: BTreeSet, + #[serde(default)] + test: BTreeSet, + #[serde(default)] + bench: BTreeSet, +} + +impl DepTestsConfigFilter { + fn compile_filter(&self) -> CompileFilter { + CompileFilter::new( + if self.lib { + LibRule::True + } else { + LibRule::False + }, + FilterRule::new(self.bin.iter().cloned().collect(), false), + FilterRule::new(self.test.iter().cloned().collect(), false), + FilterRule::new(self.example.iter().cloned().collect(), false), + FilterRule::new(self.bench.iter().cloned().collect(), false), + ) + } +} From 83e1465dfff3c98140549efbeb9f335c9dcef8ba Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Wed, 27 Nov 2019 23:41:35 +0900 Subject: [PATCH 2/2] Merge the `dep-tests` job with the `build` jobs --- .github/workflows/ci.yml | 109 +++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d881bde..050c120 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,56 +35,20 @@ jobs: uses: actions-rs/cargo@v1 with: command: fmt - args: --all -- --check + args: -- --check - dep-tests: - strategy: - fail-fast: false - - name: dep-tests - runs-on: ubuntu-18.04 - - steps: - - name: Checkout - uses: actions/checkout@v1 - - - name: rust-toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: 1.38.0-x86_64-unknown-linux-gnu - override: true - profile: default - - - name: '`cargo fmt --all --manifest-path ./dep-tests/Cargo.toml -- --check`' + - name: '`cargo fmt --manifest-path ./dep-tests/Cargo.toml -- --check`' uses: actions-rs/cargo@v1 with: command: fmt - args: --all --manifest-path ./dep-tests/Cargo.toml -- --check - - - name: '`cargo clippy --manifest-path ./dep-tests/Cargo.toml -- -D warnings`' - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --manifest-path ./dep-tests/Cargo.toml -- -D warnings - - - name: '`cargo test --no-fail-fast --manifest-path ./dep-tests/Cargo.toml`' - uses: actions-rs/cargo@v1 - with: - command: test - args: --no-fail-fast --manifest-path ./dep-tests/Cargo.toml - - - name: '`cargo dep-tests --all-features -d 1`' - uses: actions-rs/cargo@v1 - with: - command: dep-tests - args: --all-features -d 1 + args: --manifest-path ./dep-tests/Cargo.toml -- --check build: strategy: fail-fast: false matrix: toolchain: - # `x86_64-pc-windows-msvc` is tier 1 **for now**. + # `x86_64-pc-windows-gnu` is tier 1 **for now**. - 1.38.0-x86_64-pc-windows-msvc - 1.38.0-x86_64-pc-windows-gnu - 1.38.0-x86_64-apple-darwin @@ -99,28 +63,52 @@ jobs: - beta-x86_64-unknown-linux-gnu include: - toolchain: 1.38.0-x86_64-pc-windows-msvc + features: --no-default-features + dep_tests: true os: windows-latest - toolchain: 1.38.0-x86_64-pc-windows-gnu + features: --no-default-features + dep_tests: false os: windows-latest - toolchain: 1.38.0-x86_64-apple-darwin + features: --all-features + dep_tests: true os: macOS-latest - toolchain: 1.38.0-x86_64-unknown-linux-gnu + features: --all-features + dep_tests: true os: ubuntu-18.04 - toolchain: stable-x86_64-pc-windows-msvc + features: --no-default-features + dep_tests: true os: windows-latest - toolchain: stable-x86_64-pc-windows-gnu + features: --no-default-features + dep_tests: false os: windows-latest - toolchain: stable-x86_64-apple-darwin + features: --all-features + dep_tests: true os: macOS-latest - toolchain: stable-x86_64-unknown-linux-gnu + features: --all-features + dep_tests: true os: ubuntu-18.04 - toolchain: beta-x86_64-pc-windows-msvc + features: --no-default-features + dep_tests: true os: windows-latest - toolchain: beta-x86_64-pc-windows-gnu + features: --no-default-features + dep_tests: false os: windows-latest - toolchain: beta-x86_64-apple-darwin + features: --all-features + dep_tests: true os: macOS-latest - toolchain: beta-x86_64-unknown-linux-gnu + features: --all-features + dep_tests: true os: ubuntu-18.04 name: ${{ matrix.toolchain }} @@ -141,30 +129,41 @@ jobs: override: true profile: default - - name: Determine features - id: features - run: | - if ${{ matrix.os == 'windows-latest' }}; then - echo '::set-output name=features::--no-default-features' - else - echo '::set-output name=features::--all-features' - fi - shell: bash - - - name: '`cargo clippy`' + - name: '`cargo clippy ${{ matrix.features }} -- -D warnings`' uses: actions-rs/cargo@v1 with: command: clippy - args: ${{ steps.features.outputs.features }} -- -D warnings + args: ${{ matrix.features }} -- -D warnings - - name: '`cargo test`' + - name: '`cargo test ${{ matrix.features }} --no-fail-fast`' uses: actions-rs/cargo@v1 with: command: test - args: ${{ steps.features.outputs.features }} --no-fail-fast + args: ${{ matrix.features }} --no-fail-fast - name: '`cargo run --release`' uses: actions-rs/cargo@v1 with: command: run - args: ${{ steps.features.outputs.features }} --release + args: ${{ matrix.features }} --release + + - name: '`cargo clippy ${{ matrix.features }} --manifest-path ./dep-tests/Cargo.toml -- -D warnings`' + uses: actions-rs/cargo@v1 + with: + command: clippy + args: ${{ matrix.features }} --manifest-path ./dep-tests/Cargo.toml -- -D warnings + if: matrix.dep_tests + + - name: '`cargo test ${{ matrix.features }} --manifest-path ./dep-tests/Cargo.toml --no-fail-fast`' + uses: actions-rs/cargo@v1 + with: + command: test + args: ${{ matrix.features }} --manifest-path ./dep-tests/Cargo.toml --no-fail-fast + if: matrix.dep_tests + + - name: '`cargo dep-tests --all-features -d 1`' + uses: actions-rs/cargo@v1 + with: + command: dep-tests + args: --all-features -d 1 + if: matrix.dep_tests