hakari/
proptest_helpers.rs1use crate::{
5 hakari::{DepFormatVersion, WorkspaceHackLineStyle},
6 HakariBuilder, UnifyTargetHost,
7};
8use guppy::{
9 graph::{cargo::CargoResolverVersion, PackageGraph},
10 platform::{Platform, TargetFeatures},
11 PackageId,
12};
13use proptest::{
14 collection::{hash_set, vec},
15 prelude::*,
16};
17
18impl<'g> HakariBuilder<'g> {
25 pub fn proptest1_strategy(
35 graph: &'g PackageGraph,
36 hakari_id_strategy: impl Strategy<Value = Option<&'g PackageId>> + 'g,
37 ) -> impl Strategy<Value = HakariBuilder<'g>> + 'g {
38 (
39 hakari_id_strategy,
40 vec(Platform::strategy(any::<TargetFeatures>()), 0..4),
41 any::<CargoResolverVersion>(),
42 hash_set(graph.proptest1_id_strategy(), 0..8),
43 hash_set(graph.proptest1_id_strategy(), 0..8),
44 any::<UnifyTargetHost>(),
45 any::<bool>(),
46 any::<DepFormatVersion>(),
47 any::<WorkspaceHackLineStyle>(),
48 )
49 .prop_map(
50 move |(
51 hakari_id,
52 platforms,
53 version,
54 traversal_excludes,
55 final_excludes,
56 unify_target_host,
57 output_single_feature,
58 dep_format_version,
59 line_style,
60 )| {
61 let mut builder = HakariBuilder::new(graph, hakari_id)
62 .expect("HakariBuilder::new returned an error");
63 let platforms: Vec<_> = platforms
64 .iter()
65 .map(|platform| platform.triple_str().to_owned())
66 .collect();
67 builder
68 .set_platforms(platforms)
69 .expect("all platforms are known")
70 .set_resolver(version)
71 .add_traversal_excludes(traversal_excludes)
72 .expect("traversal excludes obtained from PackageGraph should work")
73 .add_final_excludes(final_excludes)
74 .expect("final excludes obtained from PackageGraph should work")
75 .set_unify_target_host(unify_target_host)
76 .set_dep_format_version(dep_format_version)
77 .set_workspace_hack_line_style(line_style)
78 .set_output_single_feature(output_single_feature);
79 builder
80 },
81 )
82 }
83}
84
85#[cfg(all(test, feature = "cli-support"))]
86mod test {
87 use super::*;
88 use fixtures::json::JsonFixture;
89 use proptest::option;
90 use std::collections::HashSet;
91
92 #[test]
94 fn builder_summary_roundtrip() {
95 for (&name, fixture) in JsonFixture::all_fixtures() {
96 let graph = fixture.graph();
97 let workspace = graph.workspace();
98 let strategy = HakariBuilder::proptest1_strategy(
99 graph,
100 option::of(workspace.proptest1_id_strategy()),
101 );
102 proptest!(|(builder in strategy)| {
103 let summary = builder.to_summary().unwrap_or_else(|err| {
104 panic!("for fixture {}, builder -> summary conversion failed: {}", name, err);
105 });
106 let builder2 = summary.to_hakari_builder(graph).unwrap_or_else(|err| {
107 panic!("for fixture {}, summary -> builder conversion failed: {}", name, err);
108 });
109 let summary2 = builder2.to_summary().unwrap_or_else(|err| {
110 panic!("for fixture {}, second builder -> summary conversion failed: {}", name, err);
111 });
112 assert_eq!(summary, summary2, "summary roundtripped correctly");
113 });
114 }
115 }
116
117 #[test]
119 fn traversal_excludes() {
120 for (&name, fixture) in JsonFixture::all_fixtures() {
121 let graph = fixture.graph();
122 let workspace = graph.workspace();
123 let strategy = HakariBuilder::proptest1_strategy(
124 graph,
125 option::of(workspace.proptest1_id_strategy()),
126 );
127 proptest!(|(builder in strategy, queries in vec(graph.proptest1_id_strategy(), 0..64))| {
128 if let Some(package) = builder.hakari_package() {
130 assert!(
131 builder.is_traversal_excluded(package.id()).expect("valid package ID"),
132 "for fixture {}, hakari package is excluded from traversals",
133 name,
134 );
135 }
136 let traversal_excludes: HashSet<_> = builder.traversal_excludes().collect();
138 for query_id in queries {
139 assert_eq!(
140 traversal_excludes.contains(query_id),
141 builder.is_traversal_excluded(query_id).expect("valid package ID"),
142 "for fixture {}, traversal_excludes and is_traversal_excluded match",
143 name,
144 );
145 }
146 });
147 }
148 }
149}