Skip to main content

fixtures/
json.rs

1// Copyright (c) The cargo-guppy Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use crate::{
5    details::{FixtureDetails, LinkDetails, PackageDetails, PlatformResults},
6    package_id,
7};
8use ahash::AHashMap;
9use camino::{Utf8Component, Utf8Path, Utf8PathBuf};
10use guppy::{
11    CargoMetadata, DependencyKind,
12    errors::{FeatureBuildStage, FeatureGraphWarning},
13    graph::{BuildTargetId, BuildTargetKind, PackageGraph},
14    platform::{EnabledTernary, Platform, TargetFeatures},
15};
16use once_cell::sync::{Lazy, OnceCell};
17use std::{collections::BTreeMap, fs};
18
19// Metadata along with interesting crate names.
20pub static METADATA1_PATH: &str = "../small/metadata1.json";
21pub static METADATA1_TESTCRATE: &str = "testcrate 0.1.0 (path+file:///fakepath/testcrate)";
22pub static METADATA1_DATATEST: &str =
23    "datatest 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)";
24pub static METADATA1_REGION: &str =
25    "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)";
26pub static METADATA1_DTOA: &str =
27    "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)";
28
29pub static METADATA2_PATH: &str = "../small/metadata2.json";
30pub static METADATA2_TESTCRATE: &str =
31    "testworkspace-crate 0.1.0 (path+file:///Users/fakeuser/local/testworkspace/testcrate)";
32pub static METADATA2_WALKDIR: &str =
33    "walkdir 2.2.9 (path+file:///Users/fakeuser/local/testworkspace/walkdir)";
34pub static METADATA2_QUOTE: &str = "quote 1.0.2 (path+file:///Users/fakeuser/local/quote)";
35
36pub static METADATA_BUILDDEP_PATH: &str = "../small/builddep.json";
37pub static METADATA_BUILDDEP_MAIN: &str =
38    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/main#0.1.0";
39pub static METADATA_BUILDDEP_OPTBUILDDEP: &str =
40    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/optbuilddep#0.1.0";
41pub static METADATA_BUILDDEP_WINBUILDDEP: &str =
42    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/winbuilddep#0.1.0";
43pub static METADATA_BUILDDEP_PLATDEP: &str =
44    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/platdep#0.1.0";
45pub static METADATA_BUILDDEP_NORMALDEP: &str =
46    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/normaldep#0.1.0";
47pub static METADATA_BUILDDEP_REQBUILDDEP: &str =
48    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/reqbuilddep#0.1.0";
49pub static METADATA_BUILDDEP_PMDEP: &str =
50    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/pmdep#0.1.0";
51pub static METADATA_BUILDDEP_HOSTUSER: &str =
52    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/hostuser#0.1.0";
53pub static METADATA_BUILDDEP_TARGETUSER: &str =
54    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/targetuser#0.1.0";
55pub static METADATA_BUILDDEP_DEVDEP: &str =
56    "path+file:///home/fakeuser/dev/tmp/test-workspaces/builddep/devdep#0.1.0";
57
58pub static METADATA_DUPS_PATH: &str = "../small/metadata_dups.json";
59pub static METADATA_DUPS_TESTCRATE: &str =
60    "testcrate-dups 0.1.0 (path+file:///Users/fakeuser/local/testcrates/testcrate-dups)";
61pub static METADATA_DUPS_LAZY_STATIC_1: &str =
62    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)";
63pub static METADATA_DUPS_LAZY_STATIC_02: &str =
64    "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)";
65pub static METADATA_DUPS_BYTES_03: &str =
66    "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)";
67pub static METADATA_DUPS_BYTES_05: &str =
68    "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)";
69
70pub static METADATA_CYCLE1_PATH: &str = "../small/metadata_cycle1.json";
71pub static METADATA_CYCLE1_BASE: &str = "testcycles-base 0.1.0 (path+file:///Users/fakeuser/local/testcrates/testcycles/testcycles-base)";
72pub static METADATA_CYCLE1_HELPER: &str = "testcycles-helper 0.1.0 (path+file:///Users/fakeuser/local/testcrates/testcycles/testcycles-helper)";
73
74pub static METADATA_CYCLE1_WINDOWS_PATH: &str = "../small/metadata_cycle1_windows.json";
75pub static METADATA_CYCLE1_WINDOWS_BASE: &str = "testcycles-base 0.1.0 (path+file:///C:/Users/fakeuser/local/testcrates/testcycles/testcycles-base)";
76pub static METADATA_CYCLE1_WINDOWS_HELPER: &str = "testcycles-helper 0.1.0 (path+file:///C:/Users/fakeuser/local/testcrates/testcycles/testcycles-helper)";
77
78pub static METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_PATH: &str =
79    "../small/metadata_cycle1_windows_different_drives.json";
80pub static METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE: &str = "testcycles-base 0.1.0 (path+file:///C:/Users/fakeuser/local/testcrates/testcycles/testcycles-base)";
81pub static METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER: &str =
82    "testcycles-helper 0.1.0 (path+file:///D:/libs/testcycles-helper)";
83
84pub static METADATA_CYCLE2_PATH: &str = "../small/metadata_cycle2.json";
85pub static METADATA_CYCLE2_UPPER_A: &str =
86    "upper-a 0.1.0 (path+file:///Users/fakeuser/local/testcrates/cycle2/upper-a)";
87pub static METADATA_CYCLE2_UPPER_B: &str =
88    "upper-b 0.1.0 (path+file:///Users/fakeuser/local/testcrates/cycle2/upper-b)";
89pub static METADATA_CYCLE2_LOWER_A: &str =
90    "lower-a 0.1.0 (path+file:///Users/fakeuser/local/testcrates/cycle2/lower-a)";
91pub static METADATA_CYCLE2_LOWER_B: &str =
92    "lower-b 0.1.0 (path+file:///Users/fakeuser/local/testcrates/cycle2/lower-b)";
93
94pub static METADATA_CYCLE_FEATURES_PATH: &str = "../small/metadata_cycle_features.json";
95pub static METADATA_CYCLE_FEATURES_BASE: &str =
96    "testcycles-base 0.1.0 (path+file:///fakepath/testcycles-features/testcycles-base)";
97pub static METADATA_CYCLE_FEATURES_HELPER: &str =
98    "testcycles-helper 0.1.0 (path+file:///fakepath/testcycles-features/testcycles-helper)";
99
100pub static METADATA_SELF_DEV_CYCLE_PATH: &str = "../small/metadata_self_dev_cycle.json";
101pub static METADATA_SELF_DEV_CYCLE_BASE: &str =
102    "self-dev-cycle-base 0.1.0 (path+file:///Users/fakeuser/local/testcrates/self-dev-cycle/base)";
103pub static METADATA_SELF_DEV_CYCLE_HELPER: &str = "self-dev-cycle-helper 0.1.0 (path+file:///Users/fakeuser/local/testcrates/self-dev-cycle/helper)";
104pub static METADATA_SELF_DEV_CYCLE_CYCLE_A: &str = "self-dev-cycle-cycle-a 0.1.0 (path+file:///Users/fakeuser/local/testcrates/self-dev-cycle/cycle-a)";
105pub static METADATA_SELF_DEV_CYCLE_CYCLE_B: &str = "self-dev-cycle-cycle-b 0.1.0 (path+file:///Users/fakeuser/local/testcrates/self-dev-cycle/cycle-b)";
106
107pub static METADATA_HAKARI_REVERSE_DEP_PATH: &str = "../small/metadata_hakari_reverse_dep.json";
108pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-features#hrd-member-features@0.1.0";
109pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-published#hrd-member-published@0.1.0";
110pub static METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_PUBLISHED: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/via-member-published#hrd-via-member-published@0.1.0";
111pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-dev#hrd-member-dev@0.1.0";
112pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_UNLINKED: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-unlinked#hrd-member-unlinked@0.1.0";
113pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_NORMAL: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-normal#hrd-member-normal@0.1.0";
114pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_BUILD: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-build#hrd-member-build@0.1.0";
115pub static METADATA_HAKARI_REVERSE_DEP_MEMBER_CFG: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/member-cfg#hrd-member-cfg@0.1.0";
116pub static METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/workspace/workspace-hack#hrd-workspace-hack@0.1.0";
117pub static METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/normal-on-hack#hrd-normal-on-hack@0.1.0";
118pub static METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/via-member-dev#hrd-via-member-dev@0.1.0";
119pub static METADATA_HAKARI_REVERSE_DEP_LEAF: &str =
120    "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/leaf#hrd-leaf@0.1.0";
121pub static METADATA_HAKARI_REVERSE_DEP_VIA_NORMAL_ON_HACK: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/via-normal-on-hack#hrd-via-normal-on-hack@0.1.0";
122pub static METADATA_HAKARI_REVERSE_DEP_BUILD_ON_HACK: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/build-on-hack#hrd-build-on-hack@0.1.0";
123pub static METADATA_HAKARI_REVERSE_DEP_CFG_ON_HACK: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/cfg-on-hack#hrd-cfg-on-hack@0.1.0";
124pub static METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_UNLINKED: &str = "path+file:///Users/fakeuser/local/testcrates/hakari-reverse-dep/via-member-unlinked#hrd-via-member-unlinked@0.1.0";
125
126pub static METADATA_TARGETS1_PATH: &str = "../small/metadata_targets1.json";
127pub static METADATA_TARGETS1_TESTCRATE: &str =
128    "testcrate-targets 0.1.0 (path+file:///Users/fakeuser/local/testcrates/testcrate-targets)";
129pub static METADATA_TARGETS1_LAZY_STATIC_1: &str =
130    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)";
131pub static METADATA_TARGETS1_LAZY_STATIC_02: &str =
132    "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)";
133pub static METADATA_TARGETS1_LAZY_STATIC_01: &str =
134    "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)";
135pub static METADATA_TARGETS1_BYTES: &str =
136    "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)";
137pub static METADATA_TARGETS1_DEP_A: &str =
138    "dep-a 0.1.0 (path+file:///Users/fakeuser/local/testcrates/dep-a)";
139
140pub static METADATA_BUILD_TARGETS1_PATH: &str = "../small/metadata_build_targets1.json";
141pub static METADATA_BUILD_TARGETS1_TESTCRATE: &str =
142    "testcrate 0.1.0 (path+file:///Users/fakeuser/local/testcrates/test-build-targets)";
143
144pub static METADATA_PROC_MACRO1_PATH: &str = "../small/metadata_proc_macro1.json";
145pub static METADATA_PROC_MACRO1_MACRO: &str =
146    "macro 0.1.0 (path+file:///Users/fakeuser/local/testcrates/proc-macro/macro)";
147pub static METADATA_PROC_MACRO1_NORMAL_USER: &str =
148    "normal-user 0.1.0 (path+file:///Users/fakeuser/local/testcrates/proc-macro/normal-user)";
149pub static METADATA_PROC_MACRO1_BUILD_USER: &str =
150    "build-user 0.1.0 (path+file:///Users/fakeuser/local/testcrates/proc-macro/build-user)";
151pub static METADATA_PROC_MACRO1_DEV_USER: &str =
152    "dev-user 0.1.0 (path+file:///Users/fakeuser/local/testcrates/proc-macro/dev-user)";
153
154pub static METADATA_ALTERNATE_REGISTRIES_PATH: &str = "../small/alternate-registries.json";
155pub static METADATA_ALTERNATE_REGISTRY_URL: &str = "https://github.com/fakeorg/crates.io-index";
156
157pub static METADATA_WEAK_NAMESPACED_FEATURES_PATH: &str = "../small/weak-namespaced-features.json";
158pub static METADATA_WEAK_NAMESPACED_ID: &str =
159    "namespaced-weak 0.1.0 (path+file:///home/fakeuser/dev/tmp/test-workspaces/namespaced-weak)";
160pub static METADATA_WEAK_NAMESPACED_SMALLVEC: &str =
161    "smallvec 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)";
162pub static METADATA_WEAK_NAMESPACED_ARRAYVEC: &str =
163    "arrayvec 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)";
164pub static METADATA_WEAK_NAMESPACED_TINYVEC: &str =
165    "tinyvec 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)";
166
167pub static METADATA_LIBRA_PATH: &str = "../large/metadata_libra.json";
168pub static METADATA_LIBRA_ADMISSION_CONTROL_SERVICE: &str = "admission-control-service 0.1.0 (path+file:///Users/fakeuser/local/libra/admission_control/admission-control-service)";
169pub static METADATA_LIBRA_COMPILER: &str =
170    "compiler 0.1.0 (path+file:///Users/fakeuser/local/libra/language/compiler)";
171pub static METADATA_LIBRA_E2E_TESTS: &str =
172    "language-e2e-tests 0.1.0 (path+file:///Users/fakeuser/local/libra/language/e2e-tests)";
173pub static METADATA_LIBRA_EXECUTOR: &str =
174    "executor 0.1.0 (path+file:///Users/fakeuser/local/libra/execution/executor)";
175pub static METADATA_LIBRA_EXECUTOR_UTILS: &str =
176    "executor-utils 0.1.0 (path+file:///Users/fakeuser/local/libra/execution/executor-utils)";
177pub static METADATA_LIBRA_COST_SYNTHESIS: &str =
178    "cost-synthesis 0.1.0 (path+file:///Users/fakeuser/local/libra/language/tools/cost-synthesis)";
179pub static METADATA_LIBRA_FUNCTIONAL_TESTS: &str =
180    "functional_tests 0.1.0 (path+file:///Users/fakeuser/local/libra/language/functional_tests)";
181pub static METADATA_LIBRA_FUNCTIONAL_HYPHEN_TESTS: &str =
182    "functional-tests 0.1.0 (path+file:///Users/fakeuser/local/libra/language/functional-tests)";
183pub static METADATA_LIBRA_LIBRA_VM: &str =
184    "libra-vm 0.1.0 (path+file:///Users/fakeuser/local/libra/language/libra-vm)";
185pub static METADATA_LIBRA_MOVE_LANG: &str =
186    "move-lang 0.0.1 (path+file:///Users/fakeuser/local/libra/language/move-lang)";
187pub static METADATA_LIBRA_MOVE_LANG_STDLIB: &str =
188    "move-lang-stdlib 0.1.0 (path+file:///Users/fakeuser/local/libra/language/move-lang/stdlib)";
189pub static METADATA_LIBRA_MOVE_VM_RUNTIME: &str =
190    "move-vm-runtime 0.1.0 (path+file:///Users/fakeuser/local/libra/language/move-vm/runtime)";
191pub static METADATA_LIBRA_STDLIB: &str =
192    "stdlib 0.1.0 (path+file:///Users/fakeuser/local/libra/language/stdlib)";
193pub static METADATA_LIBRA_TEST_GENERATION: &str = "test-generation 0.1.0 (path+file:///Users/fakeuser/local/libra/language/tools/test-generation)";
194pub static METADATA_LIBRA_TRANSACTION_BUILDER: &str = "transaction-builder 0.1.0 (path+file:///Users/fakeuser/local/libra/language/transaction-builder)";
195pub static METADATA_LIBRA_VM_GENESIS: &str =
196    "vm-genesis 0.1.0 (path+file:///Users/fakeuser/local/libra/language/tools/vm-genesis)";
197pub static METADATA_LIBRA_LANGUAGE_BENCHMARKS: &str =
198    "language_benchmarks 0.1.0 (path+file:///Users/fakeuser/local/libra/language/benchmarks)";
199pub static METADATA_LIBRA_TREE_HEAP: &str = "tree_heap 0.1.0 (path+file:///Users/fakeuser/local/libra/language/stackless-bytecode/tree_heap)";
200pub static METADATA_LIBRA_LAZY_STATIC: &str =
201    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)";
202pub static METADATA_LIBRA_BACKTRACE: &str =
203    "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)";
204pub static METADATA_LIBRA_CFG_IF: &str =
205    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)";
206
207pub static METADATA_LIBRA_F0091A4_PATH: &str = "../large/metadata_libra_f0091a4.json";
208
209pub static METADATA_LIBRA_9FFD93B_PATH: &str = "../large/metadata_libra_9ffd93b.json";
210
211pub static MNEMOS_B3B4DA9_PATH: &str = "../large/mnemos_b3b4da9.json";
212
213pub static HYPER_UTIL_7AFB1ED_PATH: &str = "../large/hyper_util_7afb1ed.json";
214
215pub static METADATA_GUPPY_78CB7E8_PATH: &str = "../guppy/metadata_guppy_78cb7e8.json";
216
217pub static METADATA_GUPPY_869476C_PATH: &str = "../guppy/metadata_guppy_869476c.json";
218
219pub static METADATA_GUPPY_C9B4F76_PATH: &str = "../guppy/metadata_guppy_c9b4f76.json";
220
221pub static METADATA_GUPPY_44B62FA_PATH: &str = "../guppy/metadata_guppy_44b62fa.json";
222pub static METADATA_GUPPY_CARGO_GUPPY: &str =
223    "cargo-guppy 0.1.0 (path+file:///home/fakeuser/dev/cargo-guppy/cargo-guppy)";
224
225pub static FAKE_AUTHOR: &str = "Fake Author <fakeauthor@example.com>";
226
227/// Fixtures that should be excluded from fixture-manager output generation.
228/// These are Windows-specific fixtures that don't need summary/hakari outputs.
229const FIXTURE_MANAGER_EXCLUDES: &[&str] = &[
230    "metadata_cycle1_windows",
231    "metadata_cycle1_windows_different_drives",
232];
233
234macro_rules! define_fixtures {
235    ($($name: ident => $json_path: ident,)*) => {
236        impl JsonFixture {
237            // Access all fixtures.
238            pub fn all_fixtures() -> &'static BTreeMap<&'static str, JsonFixture> {
239                // Provide a list of all fixtures.
240                static ALL_FIXTURES: Lazy<BTreeMap<&'static str, JsonFixture>> = Lazy::new(|| {
241                    let mut map = BTreeMap::new();
242
243                    $(map.insert(
244                        stringify!($name),
245                        JsonFixture::new(stringify!($name), $json_path, FixtureDetails::$name()),
246                    );)*
247
248                    map
249                });
250
251                &*ALL_FIXTURES
252            }
253
254            /// Returns fixtures used by fixture-manager for output generation.
255            /// Excludes Windows-specific fixtures that don't need summary/hakari
256            /// outputs.
257            pub fn fixture_manager_fixtures() -> impl Iterator<Item = &'static JsonFixture> {
258                Self::all_fixtures()
259                    .iter()
260                    .filter(|(name, _)| !FIXTURE_MANAGER_EXCLUDES.contains(name))
261                    .map(|(_, fixture)| fixture)
262            }
263
264            // Access individual fixtures if the name is known.
265            $(pub fn $name() -> &'static Self {
266                &JsonFixture::all_fixtures()[stringify!($name)]
267            })*
268        }
269    };
270}
271
272define_fixtures! {
273    metadata1 => METADATA1_PATH,
274    metadata2 => METADATA2_PATH,
275    metadata_builddep => METADATA_BUILDDEP_PATH,
276    metadata_dups => METADATA_DUPS_PATH,
277    metadata_cycle1 => METADATA_CYCLE1_PATH,
278    metadata_cycle1_windows => METADATA_CYCLE1_WINDOWS_PATH,
279    metadata_cycle1_windows_different_drives => METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_PATH,
280    metadata_cycle2 => METADATA_CYCLE2_PATH,
281    metadata_cycle_features => METADATA_CYCLE_FEATURES_PATH,
282    metadata_self_dev_cycle => METADATA_SELF_DEV_CYCLE_PATH,
283    metadata_hakari_reverse_dep => METADATA_HAKARI_REVERSE_DEP_PATH,
284    metadata_targets1 => METADATA_TARGETS1_PATH,
285    metadata_build_targets1 => METADATA_BUILD_TARGETS1_PATH,
286    metadata_proc_macro1 => METADATA_PROC_MACRO1_PATH,
287    metadata_alternate_registries => METADATA_ALTERNATE_REGISTRIES_PATH,
288    metadata_weak_namespaced_features => METADATA_WEAK_NAMESPACED_FEATURES_PATH,
289    metadata_libra => METADATA_LIBRA_PATH,
290    metadata_libra_f0091a4 => METADATA_LIBRA_F0091A4_PATH,
291    metadata_libra_9ffd93b => METADATA_LIBRA_9FFD93B_PATH,
292    mnemos_b3b4da9 => MNEMOS_B3B4DA9_PATH,
293    hyper_util_7afb1ed => HYPER_UTIL_7AFB1ED_PATH,
294    metadata_guppy_78cb7e8 => METADATA_GUPPY_78CB7E8_PATH,
295    metadata_guppy_869476c => METADATA_GUPPY_869476C_PATH,
296    metadata_guppy_c9b4f76 => METADATA_GUPPY_C9B4F76_PATH,
297    metadata_guppy_44b62fa => METADATA_GUPPY_44B62FA_PATH,
298}
299
300pub struct JsonFixture {
301    name: &'static str,
302    workspace_path: Utf8PathBuf,
303    abs_path: Utf8PathBuf,
304    json_graph: OnceCell<(String, PackageGraph)>,
305    details: FixtureDetails,
306}
307
308impl JsonFixture {
309    fn new(name: &'static str, rel_path: &'static str, details: FixtureDetails) -> Self {
310        let rel_path = Utf8Path::new(rel_path);
311        let fixtures_dir = Utf8Path::new(env!("CARGO_MANIFEST_DIR"));
312        // rel_path is relative to this dir.
313        let mut abs_path = fixtures_dir.join("src");
314        abs_path.push(rel_path);
315        let abs_path = Utf8PathBuf::from_path_buf(
316            abs_path
317                .canonicalize()
318                .expect("fixture path canonicalization succeeded"),
319        )
320        .expect("valid UTF-8 path");
321
322        let workspace_root = fixtures_dir.parent().expect("up to workspace root");
323        let workspace_path = Utf8PathBuf::from_path_buf(
324            pathdiff::diff_paths(&abs_path, workspace_root)
325                .expect("both abs_path and workspace root are absolute"),
326        )
327        .expect("diff of UTF-8 paths is UTF-8");
328
329        // No symlinks in this repo, so normalize this path.
330        let workspace_path = normalize_assuming_no_symlinks(workspace_path);
331
332        Self {
333            name,
334            workspace_path,
335            abs_path,
336            json_graph: OnceCell::new(),
337            details,
338        }
339    }
340
341    /// Lookup a fixture by name, or `None` if the name wasn't found.
342    pub fn by_name(name: &str) -> Option<&'static Self> {
343        Self::all_fixtures().get(name)
344    }
345
346    /// Returns the name of this fixture.
347    pub fn name(&self) -> &'static str {
348        self.name
349    }
350
351    /// Returns the absolute path of this fixture.
352    pub fn abs_path(&self) -> &Utf8Path {
353        &self.abs_path
354    }
355
356    /// Returns the path of this fixture, relative to the workspace root.
357    pub fn workspace_path(&self) -> &Utf8Path {
358        &self.workspace_path
359    }
360
361    /// Returns the unparsed JSON string for this fixture.
362    pub fn json(&self) -> &str {
363        self.init_graph().0
364    }
365
366    /// Returns the package graph for this fixture.
367    pub fn graph(&self) -> &PackageGraph {
368        self.init_graph().1
369    }
370
371    /// Returns the test details for this fixture.
372    pub fn details(&self) -> &FixtureDetails {
373        &self.details
374    }
375
376    /// Verifies that the parsed metadata matches known details.
377    pub fn verify(&self) {
378        let graph = self.graph();
379
380        graph.verify().expect("graph verification should succeed");
381
382        // Check that all external sources parse correctly in all graphs.
383        for package in graph.packages() {
384            let source = package.source();
385            if source.is_external() {
386                let external = source
387                    .parse_external()
388                    .unwrap_or_else(|| panic!("cannot parse external source {source}"));
389                assert_eq!(
390                    format!("{external}"),
391                    source.external_source().expect("is_external is true"),
392                    "roundtrip with ExternalSource"
393                );
394            }
395        }
396
397        self.details.assert_cycles(graph, "cycles");
398
399        self.details.assert_workspace(graph.workspace());
400        self.details.assert_topo(graph);
401
402        for id in self.details.known_ids() {
403            let msg = format!("error while verifying package '{id}'");
404            let metadata = graph.metadata(id).expect(&msg);
405            self.details.assert_metadata(id, metadata, &msg);
406
407            // Check for build targets.
408            if self.details.has_build_targets(id) {
409                self.details.assert_build_targets(metadata, &msg);
410            }
411
412            // Check for direct dependency queries.
413            if self.details.has_deps(id) {
414                self.details.assert_deps(graph, id, &msg);
415            }
416            if self.details.has_reverse_deps(id) {
417                self.details.assert_reverse_deps(graph, id, &msg);
418            }
419
420            // Check for transitive dependency queries. Use both ID based and edge-based queries.
421            if self.details.has_transitive_deps(id) {
422                self.details
423                    .assert_transitive_deps(graph, id, &format!("{msg} (transitive deps)"));
424            }
425            if self.details.has_transitive_reverse_deps(id) {
426                self.details.assert_transitive_reverse_deps(
427                    graph,
428                    id,
429                    &format!("{msg} (transitive reverse deps)"),
430                );
431            }
432
433            // Check for named features.
434            if self.details.has_named_features(id) {
435                self.details
436                    .assert_named_features(graph, id, &format!("{msg} (named features)"));
437            }
438        }
439
440        self.details.assert_link_details(graph, "link details");
441
442        // Tests for the feature graph.
443        self.details
444            .assert_feature_graph_warnings(graph, "feature graph warnings");
445        self.details
446            .assert_conditional_link_package_links(graph, "conditional link package links");
447    }
448
449    fn init_graph(&self) -> (&str, &PackageGraph) {
450        let (json, package_graph) = self.json_graph.get_or_init(|| {
451            let json = fs::read_to_string(&self.abs_path)
452                .unwrap_or_else(|err| panic!("reading file '{}' failed: {}", self.abs_path, err));
453            let graph = Self::parse_graph(&json);
454            (json, graph)
455        });
456        (json.as_str(), package_graph)
457    }
458
459    fn parse_graph(json: &str) -> PackageGraph {
460        let metadata =
461            CargoMetadata::parse_json(json).expect("parsing metadata JSON should succeed");
462        PackageGraph::from_metadata(metadata).expect("constructing package graph should succeed")
463    }
464}
465
466// Thanks to @porglezomp on Twitter for this simple normalization method.
467fn normalize_assuming_no_symlinks(p: impl AsRef<Utf8Path>) -> Utf8PathBuf {
468    let mut out = Utf8PathBuf::new();
469    for c in p.as_ref().components() {
470        match c {
471            Utf8Component::ParentDir => {
472                out.pop();
473            }
474            c => out.push(c),
475        }
476    }
477    out
478}
479
480// Some clones in here make the code more uniform overall.
481#[allow(clippy::redundant_clone)]
482impl FixtureDetails {
483    // Specific fixtures follow.
484
485    pub(crate) fn metadata1() -> Self {
486        let mut details = AHashMap::new();
487
488        PackageDetails::new(
489            METADATA1_TESTCRATE,
490            "testcrate",
491            "0.1.0",
492            vec![FAKE_AUTHOR],
493            None,
494            None,
495        )
496        .with_workspace_path("")
497        .with_build_targets(vec![(
498            BuildTargetId::Binary("testcrate"),
499            BuildTargetKind::Binary,
500            "src/main.rs",
501        )])
502        .with_deps(vec![("datatest", METADATA1_DATATEST)])
503        .with_reverse_deps(vec![])
504        .insert_into(&mut details);
505
506        #[rustfmt::skip]
507        let datatest_deps =
508            vec![
509                ("ctor", "ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)"),
510                ("datatest-derive", "datatest-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)"),
511                ("regex", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)"),
512                ("region", "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)"),
513                ("serde", "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)"),
514                ("serde_yaml", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)"),
515                ("version_check", "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)"),
516                // walkdir was replaced with [replace] (see metadata1.toml) -- ensure that the
517                // *replaced* version shows up here, not the regular one.
518                ("walkdir", "walkdir 2.2.9 (git+https://github.com/BurntSushi/walkdir?tag=2.2.9#7c7013259eb9db400b3e5c7bc60330ca08068826)"),
519                ("yaml-rust", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)")
520            ];
521
522        static LIB_TYPE: Lazy<Vec<String>> = Lazy::new(|| vec!["lib".into()]);
523
524        PackageDetails::new(
525            METADATA1_DATATEST,
526            "datatest",
527            "0.4.2",
528            vec!["Ivan Dubrov <ivan@commure.com>"],
529            Some("Data-driven tests in Rust\n"),
530            Some("MIT/Apache-2.0"),
531        )
532        .with_crates_io()
533        .with_build_targets(vec![
534            (
535                BuildTargetId::Library,
536                BuildTargetKind::LibraryOrExample(&LIB_TYPE),
537                "src/lib.rs",
538            ),
539            (
540                BuildTargetId::BuildScript,
541                BuildTargetKind::Binary,
542                "build.rs",
543            ),
544            (
545                BuildTargetId::Test("bench"),
546                BuildTargetKind::Binary,
547                "tests/bench.rs",
548            ),
549            (
550                BuildTargetId::Test("datatest"),
551                BuildTargetKind::Binary,
552                "tests/datatest.rs",
553            ),
554            (
555                BuildTargetId::Test("datatest_stable"),
556                BuildTargetKind::Binary,
557                "tests/datatest_stable.rs",
558            ),
559            (
560                BuildTargetId::Test("datatest_stable_unsafe"),
561                BuildTargetKind::Binary,
562                "tests/datatest_stable_unsafe.rs",
563            ),
564            (
565                BuildTargetId::Test("unicode"),
566                BuildTargetKind::Binary,
567                "tests/unicode.rs",
568            ),
569        ])
570        .with_deps(datatest_deps)
571        .with_reverse_deps(vec![("datatest", METADATA1_TESTCRATE)])
572        .insert_into(&mut details);
573
574        Self::new(details).with_workspace_members(vec![("", METADATA1_TESTCRATE)])
575    }
576
577    pub(crate) fn metadata2() -> Self {
578        let mut details = AHashMap::new();
579
580        PackageDetails::new(
581            METADATA2_TESTCRATE,
582            "testworkspace-crate",
583            "0.1.0",
584            vec![FAKE_AUTHOR],
585            None,
586            None,
587        )
588        .with_workspace_path("testcrate")
589        .with_deps(vec![
590            (
591                "datatest",
592                "datatest 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
593            ),
594            // There are three instances of walkdir in the dependencies -- ensure they all
595            // link up correctly.
596            ("walkdir", METADATA2_WALKDIR),
597            (
598                "walkdir-crates-io",
599                "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
600            ),
601            (
602                "walkdir-nuevo",
603                "walkdir 0.1.0 (path+file:///Users/fakeuser/local/walkdir)",
604            ),
605        ])
606        .with_reverse_deps(vec![])
607        .insert_into(&mut details);
608
609        PackageDetails::new(
610            METADATA2_WALKDIR,
611            "walkdir",
612            "2.2.9",
613            vec![FAKE_AUTHOR],
614            None,
615            None,
616        )
617        .with_workspace_path("walkdir")
618        .with_deps(vec![])
619        .with_reverse_deps(vec![("walkdir", METADATA2_TESTCRATE)])
620        .insert_into(&mut details);
621
622        // quote was replaced with [patch].
623        PackageDetails::new(
624            METADATA2_QUOTE,
625            "quote",
626            "1.0.2",
627            vec!["David Tolnay <dtolnay@gmail.com>"],
628            Some("Quasi-quoting macro quote!(...)"),
629            Some("MIT OR Apache-2.0"),
630        )
631        .with_local_path("../quote")
632        .with_deps(vec![(
633            "proc-macro2",
634            "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
635        )])
636        .with_reverse_deps(vec![
637            (
638                "quote",
639                "ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
640            ),
641            (
642                "quote",
643                "datatest-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
644            ),
645            (
646                "quote",
647                "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
648            ),
649        ])
650        .with_named_features(vec!["default", "proc-macro"])
651        .insert_into(&mut details);
652
653        Self::new(details).with_workspace_members(vec![
654            ("testcrate", METADATA2_TESTCRATE),
655            ("walkdir", METADATA2_WALKDIR),
656        ])
657    }
658
659    pub(crate) fn metadata_builddep() -> Self {
660        let details = AHashMap::new();
661
662        Self::new(details)
663    }
664
665    pub(crate) fn metadata_dups() -> Self {
666        let mut details = AHashMap::new();
667
668        PackageDetails::new(
669            METADATA_DUPS_TESTCRATE,
670            "testcrate-dups",
671            "0.1.0",
672            vec![FAKE_AUTHOR],
673            None,
674            None,
675        )
676        .with_workspace_path("")
677        .with_deps(vec![
678            ("lazy_static", METADATA_DUPS_LAZY_STATIC_1),
679            ("lazy_static", METADATA_DUPS_LAZY_STATIC_02),
680            ("bytes-package", METADATA_DUPS_BYTES_03),
681            ("bytes-package", METADATA_DUPS_BYTES_05),
682        ])
683        .insert_into(&mut details);
684
685        Self::new(details).with_workspace_members(vec![("", METADATA_DUPS_TESTCRATE)])
686    }
687
688    pub(crate) fn metadata_cycle1() -> Self {
689        let mut details = AHashMap::new();
690
691        PackageDetails::new(
692            METADATA_CYCLE1_BASE,
693            "testcycles-base",
694            "0.1.0",
695            vec![FAKE_AUTHOR],
696            None,
697            None,
698        )
699        .with_workspace_path("")
700        .with_deps(vec![("testcycles-helper", METADATA_CYCLE1_HELPER)])
701        .with_transitive_deps(vec![METADATA_CYCLE1_BASE, METADATA_CYCLE1_HELPER])
702        .with_transitive_reverse_deps(vec![METADATA_CYCLE1_BASE, METADATA_CYCLE1_HELPER])
703        .insert_into(&mut details);
704
705        PackageDetails::new(
706            METADATA_CYCLE1_HELPER,
707            "testcycles-helper",
708            "0.1.0",
709            vec![FAKE_AUTHOR],
710            None,
711            None,
712        )
713        .with_local_path("../testcycles-helper")
714        .with_deps(vec![("testcycles-base", METADATA_CYCLE1_BASE)])
715        .with_transitive_deps(vec![METADATA_CYCLE1_BASE, METADATA_CYCLE1_HELPER])
716        .with_transitive_reverse_deps(vec![METADATA_CYCLE1_BASE, METADATA_CYCLE1_HELPER])
717        .insert_into(&mut details);
718
719        Self::new(details)
720            .with_workspace_members(vec![("", METADATA_CYCLE1_BASE)])
721            .with_cycles(vec![vec![METADATA_CYCLE1_HELPER, METADATA_CYCLE1_BASE]])
722    }
723
724    pub(crate) fn metadata_cycle1_windows() -> Self {
725        let mut details = AHashMap::new();
726
727        PackageDetails::new(
728            METADATA_CYCLE1_WINDOWS_BASE,
729            "testcycles-base",
730            "0.1.0",
731            vec![FAKE_AUTHOR],
732            None,
733            None,
734        )
735        .with_workspace_path("")
736        .with_deps(vec![("testcycles-helper", METADATA_CYCLE1_WINDOWS_HELPER)])
737        .with_transitive_deps(vec![
738            METADATA_CYCLE1_WINDOWS_BASE,
739            METADATA_CYCLE1_WINDOWS_HELPER,
740        ])
741        .with_transitive_reverse_deps(vec![
742            METADATA_CYCLE1_WINDOWS_BASE,
743            METADATA_CYCLE1_WINDOWS_HELPER,
744        ])
745        .insert_into(&mut details);
746
747        PackageDetails::new(
748            METADATA_CYCLE1_WINDOWS_HELPER,
749            "testcycles-helper",
750            "0.1.0",
751            vec![FAKE_AUTHOR],
752            None,
753            None,
754        )
755        .with_local_path("../testcycles-helper")
756        .with_deps(vec![("testcycles-base", METADATA_CYCLE1_WINDOWS_BASE)])
757        .with_transitive_deps(vec![
758            METADATA_CYCLE1_WINDOWS_BASE,
759            METADATA_CYCLE1_WINDOWS_HELPER,
760        ])
761        .with_transitive_reverse_deps(vec![
762            METADATA_CYCLE1_WINDOWS_BASE,
763            METADATA_CYCLE1_WINDOWS_HELPER,
764        ])
765        .insert_into(&mut details);
766
767        Self::new(details)
768            .with_workspace_members(vec![("", METADATA_CYCLE1_WINDOWS_BASE)])
769            .with_cycles(vec![vec![
770                METADATA_CYCLE1_WINDOWS_HELPER,
771                METADATA_CYCLE1_WINDOWS_BASE,
772            ]])
773    }
774
775    pub(crate) fn metadata_cycle1_windows_different_drives() -> Self {
776        let mut details = AHashMap::new();
777
778        PackageDetails::new(
779            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
780            "testcycles-base",
781            "0.1.0",
782            vec![FAKE_AUTHOR],
783            None,
784            None,
785        )
786        .with_workspace_path("")
787        .with_deps(vec![(
788            "testcycles-helper",
789            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
790        )])
791        .with_transitive_deps(vec![
792            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
793            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
794        ])
795        .with_transitive_reverse_deps(vec![
796            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
797            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
798        ])
799        .insert_into(&mut details);
800
801        // The path is normalized to forward slashes on Unix but not on Windows.
802        #[cfg(windows)]
803        let helper_path = r"D:\libs\testcycles-helper";
804        #[cfg(not(windows))]
805        let helper_path = "D:/libs/testcycles-helper";
806
807        PackageDetails::new(
808            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
809            "testcycles-helper",
810            "0.1.0",
811            vec![FAKE_AUTHOR],
812            None,
813            None,
814        )
815        .with_local_path(helper_path)
816        .with_deps(vec![(
817            "testcycles-base",
818            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
819        )])
820        .with_transitive_deps(vec![
821            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
822            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
823        ])
824        .with_transitive_reverse_deps(vec![
825            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
826            METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
827        ])
828        .insert_into(&mut details);
829
830        Self::new(details)
831            .with_workspace_members(vec![("", METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE)])
832            .with_cycles(vec![vec![
833                METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_HELPER,
834                METADATA_CYCLE1_WINDOWS_DIFFERENT_DRIVES_BASE,
835            ]])
836    }
837
838    pub(crate) fn metadata_cycle2() -> Self {
839        // upper-a <-> upper-b
840        //                |
841        //                v
842        //             lower-a <-> lower-b
843        let mut details = AHashMap::new();
844
845        // upper-a
846        PackageDetails::new(
847            METADATA_CYCLE2_UPPER_A,
848            "upper-a",
849            "0.1.0",
850            vec![FAKE_AUTHOR],
851            None,
852            None,
853        )
854        .with_workspace_path("upper-a")
855        .with_deps(vec![("upper-b", METADATA_CYCLE2_UPPER_B)])
856        .with_reverse_deps(vec![("upper-a", METADATA_CYCLE2_UPPER_B)])
857        .with_transitive_deps(vec![
858            METADATA_CYCLE2_UPPER_A,
859            METADATA_CYCLE2_UPPER_B,
860            METADATA_CYCLE2_LOWER_A,
861            METADATA_CYCLE2_LOWER_B,
862        ])
863        .with_transitive_reverse_deps(vec![METADATA_CYCLE2_UPPER_A, METADATA_CYCLE2_UPPER_B])
864        .insert_into(&mut details);
865
866        // upper-b
867        PackageDetails::new(
868            METADATA_CYCLE2_UPPER_B,
869            "upper-b",
870            "0.1.0",
871            vec![FAKE_AUTHOR],
872            None,
873            None,
874        )
875        .with_workspace_path("upper-b")
876        .with_deps(vec![
877            ("upper-a", METADATA_CYCLE2_UPPER_A),
878            ("lower-a", METADATA_CYCLE2_LOWER_A),
879        ])
880        .with_reverse_deps(vec![("upper-b", METADATA_CYCLE2_UPPER_A)])
881        .with_transitive_deps(vec![
882            METADATA_CYCLE2_UPPER_A,
883            METADATA_CYCLE2_UPPER_B,
884            METADATA_CYCLE2_LOWER_A,
885            METADATA_CYCLE2_LOWER_B,
886        ])
887        .with_transitive_reverse_deps(vec![METADATA_CYCLE2_UPPER_A, METADATA_CYCLE2_UPPER_B])
888        .insert_into(&mut details);
889
890        // lower-a
891        PackageDetails::new(
892            METADATA_CYCLE2_LOWER_A,
893            "lower-a",
894            "0.1.0",
895            vec![FAKE_AUTHOR],
896            None,
897            None,
898        )
899        .with_workspace_path("lower-a")
900        .with_deps(vec![("lower-b", METADATA_CYCLE2_LOWER_B)])
901        .with_reverse_deps(vec![
902            ("lower-a", METADATA_CYCLE2_UPPER_B),
903            ("lower-a", METADATA_CYCLE2_LOWER_B),
904        ])
905        .with_transitive_deps(vec![METADATA_CYCLE2_LOWER_A, METADATA_CYCLE2_LOWER_B])
906        .with_transitive_reverse_deps(vec![
907            METADATA_CYCLE2_UPPER_A,
908            METADATA_CYCLE2_UPPER_B,
909            METADATA_CYCLE2_LOWER_A,
910            METADATA_CYCLE2_LOWER_B,
911        ])
912        .insert_into(&mut details);
913
914        // lower-b
915        PackageDetails::new(
916            METADATA_CYCLE2_LOWER_B,
917            "lower-b",
918            "0.1.0",
919            vec![FAKE_AUTHOR],
920            None,
921            None,
922        )
923        .with_workspace_path("lower-b")
924        .with_deps(vec![("lower-a", METADATA_CYCLE2_LOWER_A)])
925        .with_reverse_deps(vec![("lower-b", METADATA_CYCLE2_LOWER_A)])
926        .with_transitive_deps(vec![METADATA_CYCLE2_LOWER_A, METADATA_CYCLE2_LOWER_B])
927        .with_transitive_reverse_deps(vec![
928            METADATA_CYCLE2_UPPER_A,
929            METADATA_CYCLE2_UPPER_B,
930            METADATA_CYCLE2_LOWER_A,
931            METADATA_CYCLE2_LOWER_B,
932        ])
933        .insert_into(&mut details);
934
935        Self::new(details)
936            .with_workspace_members(vec![
937                ("upper-a", METADATA_CYCLE2_UPPER_A),
938                ("upper-b", METADATA_CYCLE2_UPPER_B),
939                ("lower-a", METADATA_CYCLE2_LOWER_A),
940                ("lower-b", METADATA_CYCLE2_LOWER_B),
941            ])
942            .with_cycles(vec![
943                // upper-b dev-depends on upper-a, and upper-a normal-depends on upper-b.
944                vec![METADATA_CYCLE2_UPPER_A, METADATA_CYCLE2_UPPER_B],
945                // lower-b dev-depends on lower-a, and lower-a normal-depends on lower-b.
946                vec![METADATA_CYCLE2_LOWER_A, METADATA_CYCLE2_LOWER_B],
947            ])
948    }
949
950    pub(crate) fn metadata_self_dev_cycle() -> Self {
951        let mut details = AHashMap::new();
952
953        PackageDetails::new(
954            METADATA_SELF_DEV_CYCLE_BASE,
955            "self-dev-cycle-base",
956            "0.1.0",
957            vec![FAKE_AUTHOR],
958            None,
959            Some("MIT OR Apache-2.0"),
960        )
961        .with_workspace_path("base")
962        .with_deps(vec![
963            // The normal edge to `helper`, plus the self-dev edge.
964            ("self-dev-cycle-base", METADATA_SELF_DEV_CYCLE_BASE),
965            ("self-dev-cycle-helper", METADATA_SELF_DEV_CYCLE_HELPER),
966        ])
967        .with_reverse_deps(vec![("self-dev-cycle-base", METADATA_SELF_DEV_CYCLE_BASE)])
968        .with_transitive_deps(vec![
969            METADATA_SELF_DEV_CYCLE_BASE,
970            METADATA_SELF_DEV_CYCLE_HELPER,
971        ])
972        .with_transitive_reverse_deps(vec![METADATA_SELF_DEV_CYCLE_BASE])
973        .with_named_features(vec!["extra"])
974        .insert_into(&mut details);
975
976        PackageDetails::new(
977            METADATA_SELF_DEV_CYCLE_HELPER,
978            "self-dev-cycle-helper",
979            "0.1.0",
980            vec![FAKE_AUTHOR],
981            None,
982            Some("MIT OR Apache-2.0"),
983        )
984        .with_workspace_path("helper")
985        .with_reverse_deps(vec![(
986            "self-dev-cycle-helper",
987            METADATA_SELF_DEV_CYCLE_BASE,
988        )])
989        .with_named_features(vec!["extra"])
990        .insert_into(&mut details);
991
992        // `cycle-a` <-> `cycle-b` form a classic 2-node multi-SCC: a
993        // non-dev edge `cycle-a -> cycle-b` together with a dev edge
994        // `cycle-b -> cycle-a` closes the cycle. Disconnected from
995        // base/helper, so it's a second cycle alongside `base`'s
996        // self-loop.
997        PackageDetails::new(
998            METADATA_SELF_DEV_CYCLE_CYCLE_A,
999            "self-dev-cycle-cycle-a",
1000            "0.1.0",
1001            vec![FAKE_AUTHOR],
1002            None,
1003            Some("MIT OR Apache-2.0"),
1004        )
1005        .with_workspace_path("cycle-a")
1006        .with_deps(vec![(
1007            "self-dev-cycle-cycle-b",
1008            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1009        )])
1010        .with_reverse_deps(vec![(
1011            "self-dev-cycle-cycle-a",
1012            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1013        )])
1014        .with_transitive_deps(vec![
1015            METADATA_SELF_DEV_CYCLE_CYCLE_A,
1016            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1017        ])
1018        .with_transitive_reverse_deps(vec![
1019            METADATA_SELF_DEV_CYCLE_CYCLE_A,
1020            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1021        ])
1022        .insert_into(&mut details);
1023
1024        PackageDetails::new(
1025            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1026            "self-dev-cycle-cycle-b",
1027            "0.1.0",
1028            vec![FAKE_AUTHOR],
1029            None,
1030            Some("MIT OR Apache-2.0"),
1031        )
1032        .with_workspace_path("cycle-b")
1033        .with_deps(vec![(
1034            "self-dev-cycle-cycle-a",
1035            METADATA_SELF_DEV_CYCLE_CYCLE_A,
1036        )])
1037        .with_reverse_deps(vec![(
1038            "self-dev-cycle-cycle-b",
1039            METADATA_SELF_DEV_CYCLE_CYCLE_A,
1040        )])
1041        .with_transitive_deps(vec![
1042            METADATA_SELF_DEV_CYCLE_CYCLE_A,
1043            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1044        ])
1045        .with_transitive_reverse_deps(vec![
1046            METADATA_SELF_DEV_CYCLE_CYCLE_A,
1047            METADATA_SELF_DEV_CYCLE_CYCLE_B,
1048        ])
1049        .insert_into(&mut details);
1050
1051        // The fixture exercises both kinds of cycles at once:
1052        //
1053        // * `base`'s path-self dev-dependency is a single-node SCC with
1054        //   a self-loop, i.e., a cycle of length 1. The feature graph
1055        //   does *not* emit a self-loop warning here: the loop comes
1056        //   from `[dev-dependencies]`, not from a `[features]`
1057        //   declaration, and is a legitimate Cargo construct.
1058        // * `cycle-a` <-> `cycle-b` form a 2-node SCC via a regular
1059        //   forward edge and a dev back-edge.
1060        //
1061        // `cycles().all_cycles()` reports both, in topological order.
1062        Self::new(details)
1063            .with_workspace_members(vec![
1064                ("base", METADATA_SELF_DEV_CYCLE_BASE),
1065                ("helper", METADATA_SELF_DEV_CYCLE_HELPER),
1066                ("cycle-a", METADATA_SELF_DEV_CYCLE_CYCLE_A),
1067                ("cycle-b", METADATA_SELF_DEV_CYCLE_CYCLE_B),
1068            ])
1069            .with_cycles(vec![
1070                vec![METADATA_SELF_DEV_CYCLE_BASE],
1071                vec![
1072                    METADATA_SELF_DEV_CYCLE_CYCLE_A,
1073                    METADATA_SELF_DEV_CYCLE_CYCLE_B,
1074                ],
1075            ])
1076    }
1077
1078    pub(crate) fn metadata_hakari_reverse_dep() -> Self {
1079        // This fixture tests guppy-rs/guppy#499: hakari must not unify a
1080        // package that already depends on the workspace-hack, directly or
1081        // transitively, since adding it to the workspace-hack would form a
1082        // cycle.
1083        //
1084        // Legend:
1085        //
1086        // * [x] = workspace member
1087        // * (x) = non-workspace path package, standing in for a crates.io
1088        //         package redirected into the tree via [patch].
1089        //
1090        // Arrows point from dependent to dependency; unlabeled arrows are
1091        // unconditional normal dependencies. Every crate has an "hrd-" prefix
1092        // that isn't shown here. Names describe each package's path to the
1093        // hack: members are named after their own link to it, third-party
1094        // packages with a direct link are <link>-on-hack, and third-party
1095        // packages that reach the hack through something else are
1096        // via-<that package>.
1097        //
1098        // Third-party packages that must be excluded. Each one reaches the
1099        // workspace-hack, or a member that hakari manages, through a
1100        // different kind of path:
1101        //
1102        //   (normal-on-hack) -------------------------------> [workspace-hack]
1103        //   (via-normal-on-hack) --> (normal-on-hack) ------> [workspace-hack]
1104        //   (build-on-hack) -- build -----------------------> [workspace-hack]
1105        //   (cfg-on-hack) -- cfg(windows) ------------------> [workspace-hack]
1106        //   (via-member-published) --> [member-published] --> [workspace-hack]
1107        //   (via-member-dev) --> [member-dev] -- dev -------> [workspace-hack]
1108        //   (via-member-unlinked) --> [member-unlinked]
1109        //
1110        // * via-normal-on-hack and via-member-published show that the path
1111        //   may be indirect. via-member-published is the canonical [patch]
1112        //   shape: a published workspace member redirected back into the
1113        //   workspace.
1114        // * build-on-hack and cfg-on-hack show that build-only and
1115        //   cfg(windows)-only edges count just like unconditional ones.
1116        // * via-member-dev and via-member-unlinked have no normal or build
1117        //   path to the hack at all: member-dev's edge is dev-only and
1118        //   member-unlinked has no dependencies. They are excluded anyway,
1119        //   because hakari manages both members and manage-deps would give
1120        //   each one a normal dependency on the hack. Once those members are
1121        //   no longer managed, both packages are unified.
1122        //
1123        // Third-party packages that must be unified:
1124        //
1125        //   (leaf) has no dependencies and is the only package that ends up
1126        //   in the hack's output. [workspace-hack] and (normal-on-hack)
1127        //   depend on it, as do [member-features] and [member-published].
1128        //
1129        // [workspace-hack] also depends on (via-member-dev), closing a cycle
1130        // through [member-dev]'s dev-only edge. Cargo permits that cycle.
1131        //
1132        // Workspace members:
1133        //
1134        // * [member-features] depends on every (x) above and on
1135        //   [workspace-hack]. [member-published] does too, except for
1136        //   (via-member-published). member-features enables features on each
1137        //   (x) while member-published enables none, so every (x) would be
1138        //   unified if it weren't excluded: extra on normal-on-hack and
1139        //   via-member-dev, feat1 on leaf, and f1 on the rest.
1140        // * [member-normal] depends on (via-member-published) and
1141        //   [workspace-hack].
1142        // * [member-unlinked] has no dependencies.
1143        // * [member-dev], [member-build] and [member-cfg] each have a single
1144        //   link to [workspace-hack] that isn't an unconditional normal
1145        //   dependency: dev-only, build-only and cfg(windows)-only
1146        //   respectively. They exercise how manage-deps treats members that
1147        //   already have some link to the hack.
1148        let mut details = AHashMap::new();
1149
1150        PackageDetails::new(
1151            METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1152            "hrd-workspace-hack",
1153            "0.1.0",
1154            vec![FAKE_AUTHOR],
1155            None,
1156            None,
1157        )
1158        .with_workspace_path("workspace-hack")
1159        .with_deps(vec![
1160            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_LEAF),
1161            (
1162                "hrd-via-member-dev",
1163                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV,
1164            ),
1165        ])
1166        .with_reverse_deps(vec![
1167            (
1168                "hrd-workspace-hack",
1169                METADATA_HAKARI_REVERSE_DEP_BUILD_ON_HACK,
1170            ),
1171            (
1172                "hrd-workspace-hack",
1173                METADATA_HAKARI_REVERSE_DEP_CFG_ON_HACK,
1174            ),
1175            (
1176                "hrd-workspace-hack",
1177                METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK,
1178            ),
1179            (
1180                "hrd-workspace-hack",
1181                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1182            ),
1183            (
1184                "hrd-workspace-hack",
1185                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1186            ),
1187            ("hrd-workspace-hack", METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV),
1188            (
1189                "hrd-workspace-hack",
1190                METADATA_HAKARI_REVERSE_DEP_MEMBER_NORMAL,
1191            ),
1192            (
1193                "hrd-workspace-hack",
1194                METADATA_HAKARI_REVERSE_DEP_MEMBER_BUILD,
1195            ),
1196            ("hrd-workspace-hack", METADATA_HAKARI_REVERSE_DEP_MEMBER_CFG),
1197        ])
1198        .with_named_features(vec![])
1199        .insert_into(&mut details);
1200
1201        PackageDetails::new(
1202            METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK,
1203            "hrd-normal-on-hack",
1204            "0.1.0",
1205            vec![FAKE_AUTHOR],
1206            None,
1207            None,
1208        )
1209        .with_local_path("../normal-on-hack")
1210        .with_deps(vec![
1211            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_LEAF),
1212            (
1213                "hrd-workspace-hack",
1214                METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1215            ),
1216        ])
1217        .with_reverse_deps(vec![
1218            (
1219                "hrd-normal-on-hack",
1220                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1221            ),
1222            (
1223                "hrd-normal-on-hack",
1224                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1225            ),
1226            (
1227                "hrd-normal-on-hack",
1228                METADATA_HAKARI_REVERSE_DEP_VIA_NORMAL_ON_HACK,
1229            ),
1230        ])
1231        .with_named_features(vec!["extra"])
1232        .insert_into(&mut details);
1233
1234        PackageDetails::new(
1235            METADATA_HAKARI_REVERSE_DEP_VIA_NORMAL_ON_HACK,
1236            "hrd-via-normal-on-hack",
1237            "0.1.0",
1238            vec![FAKE_AUTHOR],
1239            None,
1240            None,
1241        )
1242        .with_local_path("../via-normal-on-hack")
1243        .with_deps(vec![(
1244            "hrd-normal-on-hack",
1245            METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK,
1246        )])
1247        .with_reverse_deps(vec![
1248            (
1249                "hrd-via-normal-on-hack",
1250                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1251            ),
1252            (
1253                "hrd-via-normal-on-hack",
1254                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1255            ),
1256        ])
1257        .with_named_features(vec!["f1"])
1258        .insert_into(&mut details);
1259
1260        PackageDetails::new(
1261            METADATA_HAKARI_REVERSE_DEP_BUILD_ON_HACK,
1262            "hrd-build-on-hack",
1263            "0.1.0",
1264            vec![FAKE_AUTHOR],
1265            None,
1266            None,
1267        )
1268        .with_local_path("../build-on-hack")
1269        .with_deps(vec![(
1270            "hrd-workspace-hack",
1271            METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1272        )])
1273        .with_reverse_deps(vec![
1274            (
1275                "hrd-build-on-hack",
1276                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1277            ),
1278            (
1279                "hrd-build-on-hack",
1280                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1281            ),
1282        ])
1283        .with_named_features(vec!["f1"])
1284        .insert_into(&mut details);
1285
1286        PackageDetails::new(
1287            METADATA_HAKARI_REVERSE_DEP_CFG_ON_HACK,
1288            "hrd-cfg-on-hack",
1289            "0.1.0",
1290            vec![FAKE_AUTHOR],
1291            None,
1292            None,
1293        )
1294        .with_local_path("../cfg-on-hack")
1295        .with_deps(vec![(
1296            "hrd-workspace-hack",
1297            METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1298        )])
1299        .with_reverse_deps(vec![
1300            (
1301                "hrd-cfg-on-hack",
1302                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1303            ),
1304            (
1305                "hrd-cfg-on-hack",
1306                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1307            ),
1308        ])
1309        .with_named_features(vec!["f1"])
1310        .insert_into(&mut details);
1311
1312        PackageDetails::new(
1313            METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV,
1314            "hrd-via-member-dev",
1315            "0.1.0",
1316            vec![FAKE_AUTHOR],
1317            None,
1318            None,
1319        )
1320        .with_local_path("../via-member-dev")
1321        .with_deps(vec![(
1322            "hrd-member-dev",
1323            METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV,
1324        )])
1325        .with_reverse_deps(vec![
1326            (
1327                "hrd-via-member-dev",
1328                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1329            ),
1330            (
1331                "hrd-via-member-dev",
1332                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1333            ),
1334            (
1335                "hrd-via-member-dev",
1336                METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1337            ),
1338        ])
1339        .with_named_features(vec!["extra"])
1340        .insert_into(&mut details);
1341
1342        PackageDetails::new(
1343            METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_UNLINKED,
1344            "hrd-via-member-unlinked",
1345            "0.1.0",
1346            vec![FAKE_AUTHOR],
1347            None,
1348            None,
1349        )
1350        .with_local_path("../via-member-unlinked")
1351        .with_deps(vec![(
1352            "hrd-member-unlinked",
1353            METADATA_HAKARI_REVERSE_DEP_MEMBER_UNLINKED,
1354        )])
1355        .with_reverse_deps(vec![
1356            (
1357                "hrd-via-member-unlinked",
1358                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1359            ),
1360            (
1361                "hrd-via-member-unlinked",
1362                METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1363            ),
1364        ])
1365        .with_named_features(vec!["f1"])
1366        .insert_into(&mut details);
1367
1368        PackageDetails::new(
1369            METADATA_HAKARI_REVERSE_DEP_MEMBER_UNLINKED,
1370            "hrd-member-unlinked",
1371            "0.1.0",
1372            vec![FAKE_AUTHOR],
1373            None,
1374            None,
1375        )
1376        .with_workspace_path("member-unlinked")
1377        .with_deps(vec![])
1378        .with_reverse_deps(vec![(
1379            "hrd-member-unlinked",
1380            METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_UNLINKED,
1381        )])
1382        .with_named_features(vec![])
1383        .insert_into(&mut details);
1384
1385        PackageDetails::new(
1386            METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1387            "hrd-member-features",
1388            "0.1.0",
1389            vec![FAKE_AUTHOR],
1390            None,
1391            None,
1392        )
1393        .with_workspace_path("member-features")
1394        .with_deps(vec![
1395            (
1396                "hrd-build-on-hack",
1397                METADATA_HAKARI_REVERSE_DEP_BUILD_ON_HACK,
1398            ),
1399            ("hrd-cfg-on-hack", METADATA_HAKARI_REVERSE_DEP_CFG_ON_HACK),
1400            (
1401                "hrd-normal-on-hack",
1402                METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK,
1403            ),
1404            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_LEAF),
1405            (
1406                "hrd-via-member-published",
1407                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_PUBLISHED,
1408            ),
1409            (
1410                "hrd-via-member-dev",
1411                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV,
1412            ),
1413            (
1414                "hrd-via-normal-on-hack",
1415                METADATA_HAKARI_REVERSE_DEP_VIA_NORMAL_ON_HACK,
1416            ),
1417            (
1418                "hrd-via-member-unlinked",
1419                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_UNLINKED,
1420            ),
1421            (
1422                "hrd-workspace-hack",
1423                METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1424            ),
1425        ])
1426        .with_reverse_deps(vec![])
1427        .with_named_features(vec![])
1428        .insert_into(&mut details);
1429
1430        PackageDetails::new(
1431            METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_PUBLISHED,
1432            "hrd-via-member-published",
1433            "0.1.0",
1434            vec![FAKE_AUTHOR],
1435            None,
1436            None,
1437        )
1438        .with_local_path("../via-member-published")
1439        .with_deps(vec![(
1440            "hrd-member-published",
1441            METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1442        )])
1443        .with_reverse_deps(vec![
1444            (
1445                "hrd-via-member-published",
1446                METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1447            ),
1448            (
1449                "hrd-via-member-published",
1450                METADATA_HAKARI_REVERSE_DEP_MEMBER_NORMAL,
1451            ),
1452        ])
1453        .with_named_features(vec!["f1"])
1454        .insert_into(&mut details);
1455
1456        PackageDetails::new(
1457            METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1458            "hrd-member-published",
1459            "0.1.0",
1460            vec![FAKE_AUTHOR],
1461            None,
1462            None,
1463        )
1464        .with_workspace_path("member-published")
1465        .with_deps(vec![
1466            (
1467                "hrd-build-on-hack",
1468                METADATA_HAKARI_REVERSE_DEP_BUILD_ON_HACK,
1469            ),
1470            ("hrd-cfg-on-hack", METADATA_HAKARI_REVERSE_DEP_CFG_ON_HACK),
1471            (
1472                "hrd-normal-on-hack",
1473                METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK,
1474            ),
1475            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_LEAF),
1476            (
1477                "hrd-via-member-dev",
1478                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV,
1479            ),
1480            (
1481                "hrd-via-normal-on-hack",
1482                METADATA_HAKARI_REVERSE_DEP_VIA_NORMAL_ON_HACK,
1483            ),
1484            (
1485                "hrd-via-member-unlinked",
1486                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_UNLINKED,
1487            ),
1488            (
1489                "hrd-workspace-hack",
1490                METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1491            ),
1492        ])
1493        .with_reverse_deps(vec![(
1494            "hrd-member-published",
1495            METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_PUBLISHED,
1496        )])
1497        .with_named_features(vec![])
1498        .insert_into(&mut details);
1499
1500        PackageDetails::new(
1501            METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV,
1502            "hrd-member-dev",
1503            "0.1.0",
1504            vec![FAKE_AUTHOR],
1505            None,
1506            None,
1507        )
1508        .with_workspace_path("member-dev")
1509        .with_deps(vec![(
1510            "hrd-workspace-hack",
1511            METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1512        )])
1513        .with_reverse_deps(vec![(
1514            "hrd-member-dev",
1515            METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV,
1516        )])
1517        .with_named_features(vec![])
1518        .insert_into(&mut details);
1519
1520        PackageDetails::new(
1521            METADATA_HAKARI_REVERSE_DEP_MEMBER_NORMAL,
1522            "hrd-member-normal",
1523            "0.1.0",
1524            vec![FAKE_AUTHOR],
1525            None,
1526            None,
1527        )
1528        .with_workspace_path("member-normal")
1529        .with_deps(vec![
1530            (
1531                "hrd-via-member-published",
1532                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_PUBLISHED,
1533            ),
1534            (
1535                "hrd-workspace-hack",
1536                METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1537            ),
1538        ])
1539        .with_reverse_deps(vec![])
1540        .with_named_features(vec![])
1541        .insert_into(&mut details);
1542
1543        PackageDetails::new(
1544            METADATA_HAKARI_REVERSE_DEP_MEMBER_BUILD,
1545            "hrd-member-build",
1546            "0.1.0",
1547            vec![FAKE_AUTHOR],
1548            None,
1549            None,
1550        )
1551        .with_workspace_path("member-build")
1552        .with_deps(vec![(
1553            "hrd-workspace-hack",
1554            METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1555        )])
1556        .with_reverse_deps(vec![])
1557        .with_named_features(vec![])
1558        .insert_into(&mut details);
1559
1560        PackageDetails::new(
1561            METADATA_HAKARI_REVERSE_DEP_MEMBER_CFG,
1562            "hrd-member-cfg",
1563            "0.1.0",
1564            vec![FAKE_AUTHOR],
1565            None,
1566            None,
1567        )
1568        .with_workspace_path("member-cfg")
1569        .with_deps(vec![(
1570            "hrd-workspace-hack",
1571            METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1572        )])
1573        .with_reverse_deps(vec![])
1574        .with_named_features(vec![])
1575        .insert_into(&mut details);
1576
1577        PackageDetails::new(
1578            METADATA_HAKARI_REVERSE_DEP_LEAF,
1579            "hrd-leaf",
1580            "0.1.0",
1581            vec![FAKE_AUTHOR],
1582            None,
1583            None,
1584        )
1585        .with_local_path("../leaf")
1586        .with_deps(vec![])
1587        .with_reverse_deps(vec![
1588            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK),
1589            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES),
1590            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED),
1591            ("hrd-leaf", METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1592        ])
1593        .with_named_features(vec!["feat1", "feat2"])
1594        .insert_into(&mut details);
1595
1596        let x86_64_linux =
1597            Platform::new("x86_64-unknown-linux-gnu", TargetFeatures::Unknown).unwrap();
1598        let x86_64_windows =
1599            Platform::new("x86_64-pc-windows-msvc", TargetFeatures::Unknown).unwrap();
1600
1601        let mut link_details = AHashMap::new();
1602
1603        use EnabledTernary::*;
1604
1605        // hrd-normal-on-hack -> hrd-workspace-hack.
1606        // An ordinary, unconditional normal dependency: a control for the
1607        // edges below.
1608        LinkDetails::new(
1609            package_id(METADATA_HAKARI_REVERSE_DEP_NORMAL_ON_HACK),
1610            package_id(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1611        )
1612        .with_platform_status(
1613            DependencyKind::Normal,
1614            x86_64_linux.clone(),
1615            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1616        )
1617        .with_platform_status(
1618            DependencyKind::Normal,
1619            x86_64_windows.clone(),
1620            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1621        )
1622        .with_platform_status(
1623            DependencyKind::Build,
1624            x86_64_linux.clone(),
1625            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1626        )
1627        .with_platform_status(
1628            DependencyKind::Development,
1629            x86_64_linux.clone(),
1630            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1631        )
1632        .insert_into(&mut link_details);
1633
1634        // hrd-member-dev -> hrd-workspace-hack.
1635        // A dev-only dependency: the cycle through this edge is permitted.
1636        LinkDetails::new(
1637            package_id(METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV),
1638            package_id(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1639        )
1640        .with_platform_status(
1641            DependencyKind::Development,
1642            x86_64_linux.clone(),
1643            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1644        )
1645        .with_platform_status(
1646            DependencyKind::Development,
1647            x86_64_windows.clone(),
1648            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1649        )
1650        .with_platform_status(
1651            DependencyKind::Normal,
1652            x86_64_linux.clone(),
1653            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1654        )
1655        .with_platform_status(
1656            DependencyKind::Build,
1657            x86_64_linux.clone(),
1658            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1659        )
1660        .insert_into(&mut link_details);
1661
1662        // hrd-build-on-hack -> hrd-workspace-hack.
1663        // A build-only dependency.
1664        LinkDetails::new(
1665            package_id(METADATA_HAKARI_REVERSE_DEP_BUILD_ON_HACK),
1666            package_id(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1667        )
1668        .with_platform_status(
1669            DependencyKind::Build,
1670            x86_64_linux.clone(),
1671            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1672        )
1673        .with_platform_status(
1674            DependencyKind::Build,
1675            x86_64_windows.clone(),
1676            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1677        )
1678        .with_platform_status(
1679            DependencyKind::Normal,
1680            x86_64_linux.clone(),
1681            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1682        )
1683        .with_platform_status(
1684            DependencyKind::Development,
1685            x86_64_linux.clone(),
1686            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1687        )
1688        .insert_into(&mut link_details);
1689
1690        // hrd-cfg-on-hack -> hrd-workspace-hack.
1691        // A normal dependency, but only on cfg(windows).
1692        LinkDetails::new(
1693            package_id(METADATA_HAKARI_REVERSE_DEP_CFG_ON_HACK),
1694            package_id(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1695        )
1696        .with_platform_status(
1697            DependencyKind::Normal,
1698            x86_64_linux.clone(),
1699            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1700        )
1701        .with_platform_status(
1702            DependencyKind::Normal,
1703            x86_64_windows.clone(),
1704            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1705        )
1706        .with_platform_status(
1707            DependencyKind::Build,
1708            x86_64_windows.clone(),
1709            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1710        )
1711        .with_platform_status(
1712            DependencyKind::Development,
1713            x86_64_windows.clone(),
1714            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1715        )
1716        .insert_into(&mut link_details);
1717        // hrd-member-build -> hrd-workspace-hack.
1718        // A build-only dependency from a workspace member.
1719        LinkDetails::new(
1720            package_id(METADATA_HAKARI_REVERSE_DEP_MEMBER_BUILD),
1721            package_id(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1722        )
1723        .with_platform_status(
1724            DependencyKind::Build,
1725            x86_64_linux.clone(),
1726            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1727        )
1728        .with_platform_status(
1729            DependencyKind::Build,
1730            x86_64_windows.clone(),
1731            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1732        )
1733        .with_platform_status(
1734            DependencyKind::Normal,
1735            x86_64_linux.clone(),
1736            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1737        )
1738        .with_platform_status(
1739            DependencyKind::Development,
1740            x86_64_linux.clone(),
1741            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1742        )
1743        .insert_into(&mut link_details);
1744        // hrd-member-cfg -> hrd-workspace-hack.
1745        // A normal dependency from a workspace member, but only on
1746        // cfg(windows).
1747        LinkDetails::new(
1748            package_id(METADATA_HAKARI_REVERSE_DEP_MEMBER_CFG),
1749            package_id(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1750        )
1751        .with_platform_status(
1752            DependencyKind::Normal,
1753            x86_64_linux.clone(),
1754            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1755        )
1756        .with_platform_status(
1757            DependencyKind::Normal,
1758            x86_64_windows.clone(),
1759            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1760        )
1761        .with_platform_status(
1762            DependencyKind::Build,
1763            x86_64_windows.clone(),
1764            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1765        )
1766        .with_platform_status(
1767            DependencyKind::Development,
1768            x86_64_windows.clone(),
1769            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1770        )
1771        .insert_into(&mut link_details);
1772
1773        Self::new(details)
1774            .with_workspace_members(vec![
1775                (
1776                    "member-features",
1777                    METADATA_HAKARI_REVERSE_DEP_MEMBER_FEATURES,
1778                ),
1779                (
1780                    "member-published",
1781                    METADATA_HAKARI_REVERSE_DEP_MEMBER_PUBLISHED,
1782                ),
1783                ("member-dev", METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV),
1784                (
1785                    "member-unlinked",
1786                    METADATA_HAKARI_REVERSE_DEP_MEMBER_UNLINKED,
1787                ),
1788                ("member-normal", METADATA_HAKARI_REVERSE_DEP_MEMBER_NORMAL),
1789                ("member-build", METADATA_HAKARI_REVERSE_DEP_MEMBER_BUILD),
1790                ("member-cfg", METADATA_HAKARI_REVERSE_DEP_MEMBER_CFG),
1791                ("workspace-hack", METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK),
1792            ])
1793            .with_hakari_package(METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK)
1794            .with_link_details(link_details)
1795            .with_cycles(vec![vec![
1796                METADATA_HAKARI_REVERSE_DEP_WORKSPACE_HACK,
1797                METADATA_HAKARI_REVERSE_DEP_VIA_MEMBER_DEV,
1798                METADATA_HAKARI_REVERSE_DEP_MEMBER_DEV,
1799            ]])
1800    }
1801
1802    pub(crate) fn metadata_cycle_features() -> Self {
1803        let details = AHashMap::new();
1804
1805        Self::new(details)
1806            .with_workspace_members(vec![
1807                ("testcycles-base", METADATA_CYCLE_FEATURES_BASE),
1808                ("testcycles-helper", METADATA_CYCLE_FEATURES_HELPER),
1809            ])
1810            .with_cycles(vec![vec![
1811                METADATA_CYCLE_FEATURES_HELPER,
1812                METADATA_CYCLE_FEATURES_BASE,
1813            ]])
1814    }
1815
1816    pub(crate) fn metadata_targets1() -> Self {
1817        // In the testcrate:
1818        //
1819        // ```
1820        // [dependencies]
1821        // lazy_static = "1"
1822        // bytes = { version = "0.5", default-features = false, features = ["serde"] }
1823        // dep-a = { path = "../dep-a", optional = true }
1824        //
1825        // [target.'cfg(not(windows))'.dependencies]
1826        // lazy_static = "0.2"
1827        // dep-a = { path = "../dep-a", features = ["foo"] }
1828        //
1829        // [target.'cfg(windows)'.dev-dependencies]
1830        // lazy_static = "0.1"
1831        //
1832        // [target.'cfg(target_arch = "x86")'.dependencies]
1833        // bytes = { version = "=0.5.3", optional = false }
1834        // dep-a = { path = "../dep-a", features = ["bar"] }
1835        //
1836        // [target.x86_64-unknown-linux-gnu.build-dependencies]
1837        // bytes = { version = "0.5.2", optional = true, default-features = false, features = ["std"] }
1838        //
1839        // # Platform-specific dev-dependencies.
1840        //
1841        // [target.'cfg(any(target_feature = "sse2", target_feature = "atomics"))'.dev-dependencies]
1842        // dep-a = { path = "../dep-a", default-features = false, features = ["baz"] }
1843        //
1844        // [target.'cfg(all(unix, not(target_feature = "sse")))'.dev-dependencies]
1845        // dep-a = { path = "../dep-a" }
1846        //
1847        // [target.'cfg(any(unix, target_feature = "sse"))'.dev-dependencies]
1848        // dep-a = { path = "../dep-a", default-features = false, features = ["quux"] }
1849        //
1850        // # Platform-specific build dependencies.
1851        //
1852        // [target.'cfg(target_feature = "sse")'.build-dependencies]
1853        // dep-a = { path = "../dep-a", default-features = false, features = ["foo"] }
1854        //
1855        // # any -- evaluates to true for unix.
1856        // [target.'cfg(any(unix, target_feature = "sse"))'.build-dependencies]
1857        // dep-a = { path = "../dep-a", optional = true, default-features = true }
1858        //
1859        // # all -- evaluates to unknown on unixes if the target features are unknown.
1860        // # Evaluates to false on Windows whether target features are known or not.
1861        // [target.'cfg(all(unix, target_feature = "sse"))'.build-dependencies]
1862        // dep-a = { path = "../dep-a", optional = true, default-features = false, features = ["bar"] }
1863        // ```
1864        let mut details = AHashMap::new();
1865
1866        PackageDetails::new(
1867            METADATA_TARGETS1_TESTCRATE,
1868            "testcrate-targets",
1869            "0.1.0",
1870            vec![FAKE_AUTHOR],
1871            None,
1872            None,
1873        )
1874        .with_workspace_path("")
1875        .with_deps(vec![
1876            ("lazy_static", METADATA_TARGETS1_LAZY_STATIC_1),
1877            ("lazy_static", METADATA_TARGETS1_LAZY_STATIC_02),
1878            ("lazy_static", METADATA_TARGETS1_LAZY_STATIC_01),
1879            ("bytes", METADATA_TARGETS1_BYTES),
1880            ("dep-a", METADATA_TARGETS1_DEP_A),
1881        ])
1882        .insert_into(&mut details);
1883
1884        let x86_64_linux =
1885            Platform::new("x86_64-unknown-linux-gnu", TargetFeatures::Unknown).unwrap();
1886        let i686_windows = Platform::new(
1887            "i686-pc-windows-msvc",
1888            TargetFeatures::features(["sse", "sse2"].iter().copied()),
1889        )
1890        .unwrap();
1891        let x86_64_windows =
1892            Platform::new("x86_64-pc-windows-msvc", TargetFeatures::Unknown).unwrap();
1893
1894        let mut link_details = AHashMap::new();
1895
1896        use EnabledTernary::*;
1897
1898        // testcrate -> lazy_static 1.
1899        LinkDetails::new(
1900            package_id(METADATA_TARGETS1_TESTCRATE),
1901            package_id(METADATA_TARGETS1_LAZY_STATIC_1),
1902        )
1903        .with_platform_status(
1904            DependencyKind::Normal,
1905            x86_64_linux.clone(),
1906            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1907        )
1908        .with_platform_status(
1909            DependencyKind::Normal,
1910            i686_windows.clone(),
1911            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1912        )
1913        .insert_into(&mut link_details);
1914
1915        // testcrate -> lazy_static 0.2.
1916        // Included on not-Windows.
1917        LinkDetails::new(
1918            package_id(METADATA_TARGETS1_TESTCRATE),
1919            package_id(METADATA_TARGETS1_LAZY_STATIC_02),
1920        )
1921        .with_platform_status(
1922            DependencyKind::Normal,
1923            x86_64_linux.clone(),
1924            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1925        )
1926        .with_platform_status(
1927            DependencyKind::Normal,
1928            i686_windows.clone(),
1929            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1930        )
1931        .insert_into(&mut link_details);
1932
1933        // testcrate -> lazy_static 0.1.
1934        // Included as a dev-dependency on Windows.
1935        LinkDetails::new(
1936            package_id(METADATA_TARGETS1_TESTCRATE),
1937            package_id(METADATA_TARGETS1_LAZY_STATIC_01),
1938        )
1939        .with_platform_status(
1940            DependencyKind::Development,
1941            x86_64_linux.clone(),
1942            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled)),
1943        )
1944        .with_platform_status(
1945            DependencyKind::Development,
1946            i686_windows.clone(),
1947            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled)),
1948        )
1949        .insert_into(&mut link_details);
1950
1951        // testcrate -> bytes.
1952        // As a normal dependency, this is always built but default-features varies.
1953        // As a build dependency, it is only present on Linux.
1954        LinkDetails::new(
1955            package_id(METADATA_TARGETS1_TESTCRATE),
1956            package_id(METADATA_TARGETS1_BYTES),
1957        )
1958        .with_platform_status(
1959            DependencyKind::Normal,
1960            x86_64_linux.clone(),
1961            PlatformResults::new((Enabled, Enabled), (Disabled, Disabled))
1962                .with_feature_status("serde", (Enabled, Enabled))
1963                .with_feature_status("std", (Disabled, Disabled)),
1964        )
1965        .with_platform_status(
1966            DependencyKind::Normal,
1967            i686_windows.clone(),
1968            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled))
1969                .with_feature_status("serde", (Enabled, Enabled))
1970                .with_feature_status("std", (Disabled, Disabled)),
1971        )
1972        .with_features(DependencyKind::Normal, vec!["serde"])
1973        .with_platform_status(
1974            DependencyKind::Build,
1975            x86_64_linux.clone(),
1976            PlatformResults::new((Disabled, Enabled), (Disabled, Disabled))
1977                .with_feature_status("serde", (Disabled, Disabled))
1978                .with_feature_status("std", (Disabled, Enabled)),
1979        )
1980        .with_platform_status(
1981            DependencyKind::Build,
1982            i686_windows.clone(),
1983            PlatformResults::new((Disabled, Disabled), (Disabled, Disabled))
1984                .with_feature_status("serde", (Disabled, Disabled))
1985                .with_feature_status("std", (Disabled, Disabled)),
1986        )
1987        .with_features(DependencyKind::Build, vec!["std"])
1988        .insert_into(&mut link_details);
1989
1990        // testcrate -> dep-a.
1991        // As a normal dependency, this is optionally built by default, but on not-Windows or on x86
1992        // it is required.
1993        // As a dev dependency, it is present if sse2 or atomics are turned on.
1994        LinkDetails::new(
1995            package_id(METADATA_TARGETS1_TESTCRATE),
1996            package_id(METADATA_TARGETS1_DEP_A),
1997        )
1998        .with_platform_status(
1999            DependencyKind::Normal,
2000            x86_64_linux.clone(),
2001            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled))
2002                .with_feature_status("foo", (Enabled, Enabled))
2003                .with_feature_status("bar", (Disabled, Disabled))
2004                .with_feature_status("baz", (Disabled, Disabled))
2005                .with_feature_status("quux", (Disabled, Disabled)),
2006        )
2007        .with_platform_status(
2008            DependencyKind::Normal,
2009            i686_windows.clone(),
2010            PlatformResults::new((Enabled, Enabled), (Enabled, Enabled))
2011                .with_feature_status("foo", (Disabled, Disabled))
2012                .with_feature_status("bar", (Enabled, Enabled))
2013                .with_feature_status("baz", (Disabled, Disabled))
2014                .with_feature_status("quux", (Disabled, Disabled)),
2015        )
2016        .with_platform_status(
2017            DependencyKind::Normal,
2018            x86_64_windows.clone(),
2019            PlatformResults::new((Disabled, Enabled), (Disabled, Enabled))
2020                .with_feature_status("foo", (Disabled, Disabled))
2021                .with_feature_status("bar", (Disabled, Disabled))
2022                .with_feature_status("baz", (Disabled, Disabled))
2023                .with_feature_status("quux", (Disabled, Disabled)),
2024        )
2025        .with_platform_status(
2026            DependencyKind::Development,
2027            x86_64_linux.clone(),
2028            // x86_64_linux uses TargetFeature::Unknown.
2029            PlatformResults::new((Enabled, Enabled), (Unknown, Unknown))
2030                .with_feature_status("foo", (Disabled, Disabled))
2031                .with_feature_status("bar", (Disabled, Disabled))
2032                .with_feature_status("baz", (Unknown, Unknown))
2033                .with_feature_status("quux", (Enabled, Enabled)),
2034        )
2035        .with_platform_status(
2036            DependencyKind::Development,
2037            i686_windows.clone(),
2038            // i686_windows turns on sse and sse2.
2039            PlatformResults::new((Enabled, Enabled), (Disabled, Disabled))
2040                .with_feature_status("foo", (Disabled, Disabled))
2041                .with_feature_status("bar", (Disabled, Disabled))
2042                .with_feature_status("baz", (Enabled, Enabled))
2043                .with_feature_status("quux", (Enabled, Enabled)),
2044        )
2045        .with_platform_status(
2046            DependencyKind::Development,
2047            x86_64_windows.clone(),
2048            // x86_64_windows uses TargetFeatures::Unknown.
2049            PlatformResults::new((Unknown, Unknown), (Disabled, Disabled))
2050                .with_feature_status("foo", (Disabled, Disabled))
2051                .with_feature_status("bar", (Disabled, Disabled))
2052                .with_feature_status("baz", (Unknown, Unknown))
2053                .with_feature_status("quux", (Unknown, Unknown)),
2054        )
2055        .with_platform_status(
2056            DependencyKind::Build,
2057            x86_64_linux.clone(),
2058            // x86_64_linux uses TargetFeature::Unknown.
2059            PlatformResults::new((Unknown, Enabled), (Disabled, Enabled))
2060                .with_feature_status("foo", (Unknown, Unknown))
2061                .with_feature_status("bar", (Disabled, Unknown))
2062                .with_feature_status("baz", (Disabled, Disabled))
2063                .with_feature_status("quux", (Disabled, Disabled)),
2064        )
2065        .with_platform_status(
2066            DependencyKind::Build,
2067            i686_windows.clone(),
2068            // i686_windows turns on sse and sse2.
2069            PlatformResults::new((Enabled, Enabled), (Disabled, Enabled))
2070                .with_feature_status("foo", (Enabled, Enabled))
2071                .with_feature_status("bar", (Disabled, Disabled))
2072                .with_feature_status("baz", (Disabled, Disabled))
2073                .with_feature_status("quux", (Disabled, Disabled)),
2074        )
2075        .with_platform_status(
2076            DependencyKind::Build,
2077            x86_64_windows.clone(),
2078            // x86_64_windows uses TargetFeatures::Unknown.
2079            PlatformResults::new((Unknown, Unknown), (Disabled, Unknown))
2080                .with_feature_status("foo", (Unknown, Unknown))
2081                .with_feature_status("bar", (Disabled, Disabled))
2082                .with_feature_status("baz", (Disabled, Disabled))
2083                .with_feature_status("quux", (Disabled, Disabled)),
2084        )
2085        .insert_into(&mut link_details);
2086
2087        Self::new(details)
2088            .with_workspace_members(vec![("", METADATA_TARGETS1_TESTCRATE)])
2089            .with_link_details(link_details)
2090    }
2091
2092    pub(crate) fn metadata_build_targets1() -> Self {
2093        // [package]
2094        // name = "testcrate"
2095        // version = "0.1.0"
2096        // authors = ["Fake Author <fakeauthor@example.com>"]
2097        // edition = "2018"
2098        // build = "build.rs"
2099        //
2100        // [lib]
2101        // name = "bench1"
2102        // crate-type = ["cdylib", "bin"]
2103        //
2104        // [[bench]]
2105        // name = "bench1"
2106        // path = "src/main.rs"
2107        //
2108        // [[bench]]
2109        // name = "bench2"
2110        // path = "src/main2.rs"
2111        //
2112        // [[example]]
2113        // name = "example1"
2114        // path = "src/lib.rs"
2115        // crate-type = ["rlib", "dylib"]
2116
2117        let mut details = AHashMap::new();
2118
2119        static BIN_CDYLIB_TYPES: Lazy<Vec<String>> =
2120            Lazy::new(|| vec!["bin".into(), "cdylib".into()]);
2121        static DYLIB_RLIB_TYPES: Lazy<Vec<String>> =
2122            Lazy::new(|| vec!["dylib".into(), "rlib".into()]);
2123
2124        PackageDetails::new(
2125            METADATA_BUILD_TARGETS1_TESTCRATE,
2126            "testcrate",
2127            "0.1.0",
2128            vec![FAKE_AUTHOR],
2129            None,
2130            None,
2131        )
2132        .with_workspace_path("")
2133        .with_build_targets(vec![
2134            (
2135                BuildTargetId::Library,
2136                BuildTargetKind::LibraryOrExample(&BIN_CDYLIB_TYPES),
2137                "src/lib.rs",
2138            ),
2139            (
2140                BuildTargetId::BuildScript,
2141                BuildTargetKind::Binary,
2142                "build.rs",
2143            ),
2144            (
2145                BuildTargetId::Binary("testcrate"),
2146                BuildTargetKind::Binary,
2147                "src/main.rs",
2148            ),
2149            (
2150                BuildTargetId::Example("example1"),
2151                BuildTargetKind::LibraryOrExample(&DYLIB_RLIB_TYPES),
2152                "src/lib.rs",
2153            ),
2154            (
2155                BuildTargetId::Benchmark("bench1"),
2156                BuildTargetKind::Binary,
2157                "src/main.rs",
2158            ),
2159            (
2160                BuildTargetId::Benchmark("bench2"),
2161                BuildTargetKind::Binary,
2162                "src/main2.rs",
2163            ),
2164        ])
2165        .insert_into(&mut details);
2166
2167        Self::new(details)
2168    }
2169
2170    pub(crate) fn metadata_proc_macro1() -> Self {
2171        let mut details = AHashMap::new();
2172
2173        PackageDetails::new(
2174            METADATA_PROC_MACRO1_MACRO,
2175            "macro",
2176            "0.1.0",
2177            vec![FAKE_AUTHOR],
2178            None,
2179            None,
2180        )
2181        .with_workspace_path("macro")
2182        .with_reverse_deps(vec![
2183            ("macro", METADATA_PROC_MACRO1_NORMAL_USER),
2184            ("macro", METADATA_PROC_MACRO1_BUILD_USER),
2185            ("macro", METADATA_PROC_MACRO1_DEV_USER),
2186        ])
2187        .insert_into(&mut details);
2188
2189        Self::new(details)
2190    }
2191
2192    pub(crate) fn metadata_alternate_registries() -> Self {
2193        let details = AHashMap::new();
2194        Self::new(details)
2195    }
2196
2197    pub(crate) fn metadata_weak_namespaced_features() -> Self {
2198        let details = AHashMap::new();
2199        Self::new(details)
2200    }
2201
2202    pub(crate) fn metadata_libra() -> Self {
2203        let mut details = AHashMap::new();
2204
2205        PackageDetails::new(
2206            METADATA_LIBRA_E2E_TESTS,
2207            "language-e2e-tests",
2208            "0.1.0",
2209            vec!["Libra Association <opensource@libra.org>"],
2210            Some("Libra language e2e tests"),
2211            Some("Apache-2.0"),
2212        )
2213        .with_workspace_path("language/e2e-tests")
2214        .with_transitive_reverse_deps(vec![
2215            METADATA_LIBRA_E2E_TESTS,
2216            METADATA_LIBRA_COST_SYNTHESIS,
2217            METADATA_LIBRA_FUNCTIONAL_TESTS,
2218            METADATA_LIBRA_TEST_GENERATION,
2219            METADATA_LIBRA_LANGUAGE_BENCHMARKS,
2220            METADATA_LIBRA_TREE_HEAP,
2221        ])
2222        .insert_into(&mut details);
2223
2224        PackageDetails::new(
2225            METADATA_LIBRA_LAZY_STATIC,
2226            "lazy_static",
2227            "1.4.0",
2228            vec!["Marvin Löbel <loebel.marvin@gmail.com>"],
2229            Some("A macro for declaring lazily evaluated statics in Rust."),
2230            Some("MIT/Apache-2.0"),
2231        )
2232        .with_crates_io()
2233        .with_transitive_deps(vec![
2234            METADATA_LIBRA_LAZY_STATIC,
2235            "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
2236            // lazy_static also has doc-comment as a dev-dependency, but that isn't part of the
2237            // resolved graph so it won't appear here.
2238        ])
2239        .insert_into(&mut details);
2240
2241        #[rustfmt::skip]
2242        let workspace_members = vec![
2243            ("admission_control/admission-control-proto", "admission-control-proto 0.1.0 (path+file:///Users/fakeuser/local/libra/admission_control/admission-control-proto)"),
2244            ("admission_control/admission-control-service", METADATA_LIBRA_ADMISSION_CONTROL_SERVICE),
2245            ("benchmark", "benchmark 0.1.0 (path+file:///Users/fakeuser/local/libra/benchmark)"),
2246            ("client", "client 0.1.0 (path+file:///Users/fakeuser/local/libra/client)"),
2247            ("client/libra_wallet", "libra-wallet 0.1.0 (path+file:///Users/fakeuser/local/libra/client/libra_wallet)"),
2248            ("common/bounded-executor", "bounded-executor 0.1.0 (path+file:///Users/fakeuser/local/libra/common/bounded-executor)"),
2249            ("common/channel", "channel 0.1.0 (path+file:///Users/fakeuser/local/libra/common/channel)"),
2250            ("common/crash-handler", "crash-handler 0.1.0 (path+file:///Users/fakeuser/local/libra/common/crash-handler)"),
2251            ("common/datatest-stable", "datatest-stable 0.1.0 (path+file:///Users/fakeuser/local/libra/common/datatest-stable)"),
2252            ("common/debug-interface", "debug-interface 0.1.0 (path+file:///Users/fakeuser/local/libra/common/debug-interface)"),
2253            ("common/executable-helpers", "executable-helpers 0.1.0 (path+file:///Users/fakeuser/local/libra/common/executable-helpers)"),
2254            ("common/failure-ext", "libra-failure-ext 0.1.0 (path+file:///Users/fakeuser/local/libra/common/failure-ext)"),
2255            ("common/failure-ext/failure-macros", "libra-failure-macros 0.1.0 (path+file:///Users/fakeuser/local/libra/common/failure-ext/failure-macros)"),
2256            ("common/futures-semaphore", "futures-semaphore 0.1.0 (path+file:///Users/fakeuser/local/libra/common/futures-semaphore)"),
2257            ("common/grpc-helpers", "grpc-helpers 0.1.0 (path+file:///Users/fakeuser/local/libra/common/grpc-helpers)"),
2258            ("common/lcs", "libra-canonical-serialization 0.1.0 (path+file:///Users/fakeuser/local/libra/common/lcs)"),
2259            ("common/logger", "libra-logger 0.1.0 (path+file:///Users/fakeuser/local/libra/common/logger)"),
2260            ("common/metrics", "libra-metrics 0.1.0 (path+file:///Users/fakeuser/local/libra/common/metrics)"),
2261            ("common/nibble", "libra-nibble 0.1.0 (path+file:///Users/fakeuser/local/libra/common/nibble)"),
2262            ("common/proptest-helpers", "libra-proptest-helpers 0.1.0 (path+file:///Users/fakeuser/local/libra/common/proptest-helpers)"),
2263            ("common/prost-ext", "libra-prost-ext 0.1.0 (path+file:///Users/fakeuser/local/libra/common/prost-ext)"),
2264            ("common/tools", "libra-tools 0.1.0 (path+file:///Users/fakeuser/local/libra/common/tools)"),
2265            ("config", "libra-config 0.1.0 (path+file:///Users/fakeuser/local/libra/config)"),
2266            ("config/config-builder", "config-builder 0.1.0 (path+file:///Users/fakeuser/local/libra/config/config-builder)"),
2267            ("config/generate-keypair", "generate-keypair 0.1.0 (path+file:///Users/fakeuser/local/libra/config/generate-keypair)"),
2268            ("consensus", "consensus 0.1.0 (path+file:///Users/fakeuser/local/libra/consensus)"),
2269            ("consensus/consensus-types", "consensus-types 0.1.0 (path+file:///Users/fakeuser/local/libra/consensus/consensus-types)"),
2270            ("consensus/safety-rules", "safety-rules 0.1.0 (path+file:///Users/fakeuser/local/libra/consensus/safety-rules)"),
2271            ("crypto/crypto", "libra-crypto 0.1.0 (path+file:///Users/fakeuser/local/libra/crypto/crypto)"),
2272            ("crypto/crypto-derive", "libra-crypto-derive 0.1.0 (path+file:///Users/fakeuser/local/libra/crypto/crypto-derive)"),
2273            ("crypto/secret-service", "secret-service 0.1.0 (path+file:///Users/fakeuser/local/libra/crypto/secret-service)"),
2274            ("executor", "executor 0.1.0 (path+file:///Users/fakeuser/local/libra/executor)"),
2275            ("language/benchmarks", METADATA_LIBRA_LANGUAGE_BENCHMARKS),
2276            ("language/bytecode-verifier", "bytecode-verifier 0.1.0 (path+file:///Users/fakeuser/local/libra/language/bytecode-verifier)"),
2277            ("language/bytecode-verifier/bytecode_verifier_tests", "bytecode_verifier_tests 0.1.0 (path+file:///Users/fakeuser/local/libra/language/bytecode-verifier/bytecode_verifier_tests)"),
2278            ("language/bytecode-verifier/invalid-mutations", "invalid-mutations 0.1.0 (path+file:///Users/fakeuser/local/libra/language/bytecode-verifier/invalid-mutations)"),
2279            ("language/compiler", METADATA_LIBRA_COMPILER),
2280            ("language/compiler/bytecode-source-map", "bytecode-source-map 0.1.0 (path+file:///Users/fakeuser/local/libra/language/compiler/bytecode-source-map)"),
2281            ("language/compiler/ir-to-bytecode", "ir-to-bytecode 0.1.0 (path+file:///Users/fakeuser/local/libra/language/compiler/ir-to-bytecode)"),
2282            ("language/compiler/ir-to-bytecode/syntax", "ir-to-bytecode-syntax 0.1.0 (path+file:///Users/fakeuser/local/libra/language/compiler/ir-to-bytecode/syntax)"),
2283            ("language/e2e-tests", METADATA_LIBRA_E2E_TESTS),
2284            ("language/functional_tests", METADATA_LIBRA_FUNCTIONAL_TESTS),
2285            ("language/stackless-bytecode/bytecode-to-boogie", "bytecode-to-boogie 0.1.0 (path+file:///Users/fakeuser/local/libra/language/stackless-bytecode/bytecode-to-boogie)"),
2286            ("language/stackless-bytecode/generator", "stackless-bytecode-generator 0.1.0 (path+file:///Users/fakeuser/local/libra/language/stackless-bytecode/generator)"),
2287            ("language/stackless-bytecode/tree_heap", METADATA_LIBRA_TREE_HEAP),
2288            ("language/stdlib", METADATA_LIBRA_STDLIB),
2289            ("language/tools/cost-synthesis", METADATA_LIBRA_COST_SYNTHESIS),
2290            ("language/tools/test-generation", METADATA_LIBRA_TEST_GENERATION),
2291            ("language/transaction-builder", METADATA_LIBRA_TRANSACTION_BUILDER),
2292            ("language/vm", "vm 0.1.0 (path+file:///Users/fakeuser/local/libra/language/vm)"),
2293            ("language/vm/serializer_tests", "serializer_tests 0.1.0 (path+file:///Users/fakeuser/local/libra/language/vm/serializer_tests)"),
2294            ("language/vm/vm-genesis", "vm-genesis 0.1.0 (path+file:///Users/fakeuser/local/libra/language/vm/vm-genesis)"),
2295            ("language/vm/vm-runtime", "vm-runtime 0.1.0 (path+file:///Users/fakeuser/local/libra/language/vm/vm-runtime)"),
2296            ("language/vm/vm-runtime/vm-cache-map", "vm-cache-map 0.1.0 (path+file:///Users/fakeuser/local/libra/language/vm/vm-runtime/vm-cache-map)"),
2297            ("language/vm/vm-runtime/vm-runtime-types", "vm-runtime-types 0.1.0 (path+file:///Users/fakeuser/local/libra/language/vm/vm-runtime/vm-runtime-types)"),
2298            ("libra-node", "libra-node 0.1.0 (path+file:///Users/fakeuser/local/libra/libra-node)"),
2299            ("libra-swarm", "libra-swarm 0.1.0 (path+file:///Users/fakeuser/local/libra/libra-swarm)"),
2300            ("mempool", "libra-mempool 0.1.0 (path+file:///Users/fakeuser/local/libra/mempool)"),
2301            ("mempool/mempool-shared-proto", "libra-mempool-shared-proto 0.1.0 (path+file:///Users/fakeuser/local/libra/mempool/mempool-shared-proto)"),
2302            ("network", "network 0.1.0 (path+file:///Users/fakeuser/local/libra/network)"),
2303            ("network/memsocket", "memsocket 0.1.0 (path+file:///Users/fakeuser/local/libra/network/memsocket)"),
2304            ("network/netcore", "netcore 0.1.0 (path+file:///Users/fakeuser/local/libra/network/netcore)"),
2305            ("network/noise", "noise 0.1.0 (path+file:///Users/fakeuser/local/libra/network/noise)"),
2306            ("network/socket-bench-server", "socket-bench-server 0.1.0 (path+file:///Users/fakeuser/local/libra/network/socket-bench-server)"),
2307            ("state-synchronizer", "state-synchronizer 0.1.0 (path+file:///Users/fakeuser/local/libra/state-synchronizer)"),
2308            ("storage/accumulator", "accumulator 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/accumulator)"),
2309            ("storage/jellyfish-merkle", "jellyfish-merkle 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/jellyfish-merkle)"),
2310            ("storage/libradb", "libradb 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/libradb)"),
2311            ("storage/schemadb", "schemadb 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/schemadb)"),
2312            ("storage/scratchpad", "scratchpad 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/scratchpad)"),
2313            ("storage/state-view", "libra-state-view 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/state-view)"),
2314            ("storage/storage-client", "storage-client 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/storage-client)"),
2315            ("storage/storage-proto", "storage-proto 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/storage-proto)"),
2316            ("storage/storage-service", "storage-service 0.1.0 (path+file:///Users/fakeuser/local/libra/storage/storage-service)"),
2317            ("testsuite", "testsuite 0.1.0 (path+file:///Users/fakeuser/local/libra/testsuite)"),
2318            ("testsuite/cluster-test", "cluster-test 0.1.0 (path+file:///Users/fakeuser/local/libra/testsuite/cluster-test)"),
2319            ("testsuite/libra-fuzzer", "libra-fuzzer 0.1.0 (path+file:///Users/fakeuser/local/libra/testsuite/libra-fuzzer)"),
2320            ("types", "libra-types 0.1.0 (path+file:///Users/fakeuser/local/libra/types)"),
2321            ("vm-validator", "vm-validator 0.1.0 (path+file:///Users/fakeuser/local/libra/vm-validator)"),
2322            ("x", "x 0.1.0 (path+file:///Users/fakeuser/local/libra/x)"),
2323        ];
2324
2325        Self::new(details)
2326            .with_workspace_members(workspace_members)
2327            .with_feature_graph_warnings(vec![
2328                // See https://github.com/alexcrichton/cfg-if/issues/22 for more.
2329                FeatureGraphWarning::MissingFeature {
2330                    stage: FeatureBuildStage::AddNamedFeatureEdges {
2331                        package_id: package_id(METADATA_LIBRA_BACKTRACE),
2332                        from_feature: "rustc-dep-of-std".to_string(),
2333                    },
2334                    package_id: package_id(METADATA_LIBRA_CFG_IF),
2335                    feature_name: "rustc-dep-of-std".to_string(),
2336                },
2337            ])
2338    }
2339
2340    pub(crate) fn metadata_libra_f0091a4() -> Self {
2341        let details = AHashMap::new();
2342
2343        Self::new(details).with_cycles(vec![vec![
2344            METADATA_LIBRA_FUNCTIONAL_HYPHEN_TESTS,
2345            METADATA_LIBRA_E2E_TESTS,
2346            METADATA_LIBRA_VM_GENESIS,
2347            METADATA_LIBRA_MOVE_LANG_STDLIB,
2348            METADATA_LIBRA_MOVE_LANG,
2349        ]])
2350    }
2351
2352    pub(crate) fn metadata_libra_9ffd93b() -> Self {
2353        let details = AHashMap::new();
2354
2355        Self::new(details).with_cycles(vec![
2356            vec![METADATA_LIBRA_EXECUTOR_UTILS, METADATA_LIBRA_EXECUTOR],
2357            vec![
2358                METADATA_LIBRA_FUNCTIONAL_HYPHEN_TESTS,
2359                METADATA_LIBRA_E2E_TESTS,
2360                METADATA_LIBRA_VM_GENESIS,
2361                METADATA_LIBRA_TRANSACTION_BUILDER,
2362                METADATA_LIBRA_LIBRA_VM,
2363                METADATA_LIBRA_MOVE_VM_RUNTIME,
2364                METADATA_LIBRA_COMPILER,
2365                METADATA_LIBRA_STDLIB,
2366                METADATA_LIBRA_MOVE_LANG,
2367            ],
2368        ])
2369    }
2370
2371    pub(crate) fn mnemos_b3b4da9() -> Self {
2372        let details = AHashMap::new();
2373
2374        Self::new(details)
2375    }
2376
2377    pub(crate) fn hyper_util_7afb1ed() -> Self {
2378        let details = AHashMap::new();
2379
2380        Self::new(details)
2381    }
2382
2383    pub(crate) fn metadata_guppy_78cb7e8() -> Self {
2384        let details = AHashMap::new();
2385
2386        Self::new(details)
2387    }
2388
2389    pub(crate) fn metadata_guppy_869476c() -> Self {
2390        let details = AHashMap::new();
2391
2392        Self::new(details)
2393    }
2394
2395    pub(crate) fn metadata_guppy_c9b4f76() -> Self {
2396        let details = AHashMap::new();
2397
2398        Self::new(details)
2399    }
2400
2401    pub(crate) fn metadata_guppy_44b62fa() -> Self {
2402        let details = AHashMap::new();
2403
2404        Self::new(details)
2405    }
2406}