Skip to content

Commit 72f5c8d

Browse files
committed
tmp
1 parent e2716a0 commit 72f5c8d

8 files changed

Lines changed: 1935 additions & 29 deletions

File tree

Cargo.lock

Lines changed: 1030 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ tracing = "0.1.41"
1919
tracing-appender = "0.2.3"
2020
tracing-subscriber = { version = "0.3.20", features = ["json"] }
2121

22+
[dev-dependencies]
23+
cargo-test-macro = "0.4.5"
24+
cargo-test-support = "=0.8.0" # Pinned to avoid pulling in breaking changes
25+
snapbox = "0.6.21"
26+
2227
[target.'cfg(not(target_os = "windows"))'.dependencies]
2328
pprof = { version = "0.15.0", features = ["flamegraph"] }
2429

src/graph.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
util::{FilePath, FilePathBuf},
99
};
1010

11+
#[derive(Debug)]
1112
pub struct CrateGraph {
1213
pub inner: HashMap<PackageId, PackageNode>,
1314
}
@@ -227,7 +228,7 @@ impl CrateGraph {
227228
}
228229

229230
/// Represents one target of a single package
230-
#[derive(Clone)]
231+
#[derive(Clone, Debug)]
231232
pub struct PackageNode {
232233
pub name: String,
233234
pub targets: Vec<Target>,
@@ -241,13 +242,13 @@ pub struct PackageNode {
241242
pub proc_macro_dylib: Option<FilePathBuf>,
242243
}
243244

244-
#[derive(Clone)]
245+
#[derive(Clone, Debug, Eq, PartialEq)]
245246
pub struct Dependency {
246247
pub id: PackageId,
247248
pub name: String,
248249
}
249250

250-
#[derive(Clone)]
251+
#[derive(Clone, Debug)]
251252
pub struct Target {
252253
pub name: String,
253254
pub edition: Edition,

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod cli;
2-
mod discover;
3-
mod graph;
4-
mod rust_project;
2+
pub mod discover;
3+
pub mod graph;
4+
pub mod rust_project;
55
pub mod util;
66

77
use std::path::PathBuf;

tests/check.rs

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
mod utils;
2+
3+
use cargo_subspace::graph::Dependency;
4+
use utils::prelude::*;
5+
6+
use crate::utils::{DiscoverRunnerExt, bin, discover, discover_path_builder, lib, workspace};
7+
8+
// TEST STRATEGY
9+
// - Snapshot testing (output doesn't change and is in expected format)
10+
// - want to be able to inspect crate graph
11+
//
12+
// need to test
13+
// - output format is expected (snapshot testing)
14+
// - inspect crate graph for specific inputs
15+
// - (stretch) RA returns correct diagnostics for specific inputs
16+
//
17+
// TODOS
18+
// - make CARGO_HOME dynamic based on home (or something)
19+
// - move move functionality into lib crate with public functions for discover_path,
20+
// discover_buildfile that return pruned DepGraph
21+
22+
#[cargo_test]
23+
fn standalone_crate() {
24+
let p = bin("foo")
25+
.file(
26+
"src/main.rs",
27+
stringify! {
28+
fn main() {
29+
println!("hi!");
30+
}
31+
},
32+
)
33+
.build();
34+
35+
let crate_graph = discover(p.file("Cargo.toml"));
36+
37+
assert_eq!(crate_graph.len(), 1);
38+
39+
crate_graph.get(&p);
40+
}
41+
42+
#[cargo_test]
43+
fn test_workspace_with_independent_members() {
44+
let bar = lib("bar");
45+
let foo = lib("foo");
46+
let w = workspace().member(foo).member(bar).build();
47+
48+
let crate_graph = discover(w.file("bar/Cargo.toml"));
49+
50+
// We only ran discover on bar, so foo should not be in the graph
51+
assert_eq!(crate_graph.len(), 1);
52+
53+
let bar = w.member("bar");
54+
let pkg = crate_graph.get(bar);
55+
assert!(pkg.dependencies.is_empty());
56+
57+
let crate_graph = discover(w.file("foo/Cargo.toml"));
58+
59+
// We only ran discover on foo, so bar should not be in the graph
60+
assert_eq!(crate_graph.graph.inner.len(), 1);
61+
62+
let foo = w.member("foo");
63+
let pkg = crate_graph.get(foo);
64+
assert!(pkg.dependencies.is_empty());
65+
}
66+
67+
#[cargo_test]
68+
fn test_workspace_with_dependent_members() {
69+
// foo --> bar
70+
let bar = lib("bar");
71+
let foo = lib("foo").path_dependency(&bar);
72+
let w = workspace().member(foo).member(bar).build();
73+
74+
let crate_graph = discover(w.file("bar/Cargo.toml"));
75+
76+
// We only ran discover on bar, so foo should not be in the graph
77+
assert_eq!(crate_graph.len(), 1);
78+
79+
let bar = w.member("bar");
80+
let pkg = crate_graph.get(bar);
81+
assert!(pkg.dependencies.is_empty());
82+
83+
let crate_graph = discover(w.file("foo/Cargo.toml"));
84+
85+
// We ran discover on foo, so both foo AND bar should be in the graph
86+
assert_eq!(crate_graph.graph.inner.len(), 2);
87+
88+
let bar = w.member("bar");
89+
let pkg = crate_graph.get(bar);
90+
assert!(pkg.dependencies.is_empty());
91+
92+
let foo = w.member("foo");
93+
let pkg = crate_graph.get(foo);
94+
assert_eq!(pkg.dependencies, vec![bar.as_dependency()]);
95+
}
96+
97+
#[cargo_test]
98+
fn test_workspace_with_shared_dependencies() {
99+
// c1 --> c3
100+
// c2 --> c3
101+
let c3 = lib("c3");
102+
let c2 = lib("c2").path_dependency(&c3);
103+
let c1 = lib("c1").path_dependency(&c3);
104+
let w = workspace().member(c1).member(c2).member(c3).build();
105+
106+
let crate_graph = discover(w.file("c3/Cargo.toml"));
107+
108+
// We only ran discover on c3, so c1 and c2 should not be in the graph
109+
assert_eq!(crate_graph.len(), 1);
110+
111+
let c3 = w.member("c3");
112+
let pkg = crate_graph.get(c3);
113+
assert!(pkg.dependencies.is_empty());
114+
115+
let crate_graph = discover(w.file("c1/Cargo.toml"));
116+
117+
// We ran discover on c1, so both c1 AND c3 should be in the graph
118+
assert_eq!(crate_graph.graph.inner.len(), 2);
119+
120+
let c3 = w.member("c3");
121+
let pkg = crate_graph.get(c3);
122+
assert!(pkg.dependencies.is_empty());
123+
124+
let c1 = w.member("c1");
125+
let pkg = crate_graph.get(c1);
126+
assert_eq!(pkg.dependencies, vec![c3.as_dependency()]);
127+
128+
let crate_graph = discover(w.file("c2/Cargo.toml"));
129+
130+
// We ran discover on c2, so both c2 AND c3 should be in the graph
131+
assert_eq!(crate_graph.graph.inner.len(), 2);
132+
133+
let c3 = w.member("c3");
134+
let pkg = crate_graph.get(c3);
135+
assert!(pkg.dependencies.is_empty());
136+
137+
let c2 = w.member("c2");
138+
let pkg = crate_graph.get(c2);
139+
assert_eq!(pkg.dependencies, vec![c3.as_dependency()]);
140+
}
141+
142+
#[cargo_test]
143+
fn standalone_crate_with_external_dependency() {
144+
let mut builder = bin("foo");
145+
let hashbrown_id = builder.dependency("hashbrown", "0.16.0", true);
146+
let foo = builder.build();
147+
148+
let crate_graph = discover_path_builder(foo.file("Cargo.toml"))
149+
.with_no_default_features()
150+
.build();
151+
152+
assert_eq!(crate_graph.len(), 2);
153+
154+
let hashbrown = crate_graph.get_pkg(&hashbrown_id);
155+
assert_eq!(hashbrown.name, "hashbrown");
156+
assert_eq!(hashbrown.version.to_string(), "0.16.0");
157+
assert!(hashbrown.dependencies.is_empty());
158+
159+
let foo = crate_graph.get(&foo);
160+
assert_eq!(
161+
foo.dependencies,
162+
vec![Dependency {
163+
id: hashbrown_id,
164+
name: "hashbrown".into(),
165+
}]
166+
)
167+
}
168+
169+
#[cargo_test]
170+
fn workspace_with_external_dependency() {
171+
// foo --> hashbrown
172+
// bar
173+
let mut foo = lib("foo");
174+
let hashbrown_id = foo.dependency("hashbrown", "0.16.0", true);
175+
let bar = lib("bar");
176+
let w = workspace().member(foo).member(bar).build();
177+
178+
let crate_graph = discover_path_builder(w.file("foo/Cargo.toml"))
179+
.with_no_default_features()
180+
.build();
181+
182+
assert_eq!(crate_graph.len(), 2);
183+
184+
let hashbrown = crate_graph.get_pkg(&hashbrown_id);
185+
assert_eq!(hashbrown.name, "hashbrown");
186+
assert_eq!(hashbrown.version.to_string(), "0.16.0");
187+
assert!(hashbrown.dependencies.is_empty());
188+
189+
let foo = crate_graph.get(w.member("foo"));
190+
assert_eq!(
191+
foo.dependencies,
192+
vec![Dependency {
193+
id: hashbrown_id,
194+
name: "hashbrown".into(),
195+
}]
196+
);
197+
198+
let crate_graph = discover_path_builder(w.file("bar/Cargo.toml"))
199+
.with_no_default_features()
200+
.build();
201+
202+
assert_eq!(crate_graph.len(), 1);
203+
204+
let foo = crate_graph.get(w.member("bar"));
205+
assert!(foo.dependencies.is_empty());
206+
}
207+
208+
#[cargo_test]
209+
fn workspace_with_path_and_external_dependency() {
210+
// foo --> hashbrown, bar
211+
// bar
212+
let bar = lib("bar");
213+
let mut foo = lib("foo").path_dependency(&bar);
214+
let hashbrown_id = foo.dependency("hashbrown", "0.16.0", true);
215+
let w = workspace().member(foo).member(bar).build();
216+
217+
let crate_graph = discover_path_builder(w.file("bar/Cargo.toml"))
218+
.with_no_default_features()
219+
.build();
220+
221+
assert_eq!(crate_graph.len(), 1);
222+
223+
let foo = crate_graph.get(w.member("bar"));
224+
assert!(foo.dependencies.is_empty());
225+
226+
let crate_graph = discover_path_builder(w.file("foo/Cargo.toml"))
227+
.with_no_default_features()
228+
.build();
229+
230+
assert_eq!(crate_graph.len(), 3);
231+
232+
let hashbrown = crate_graph.get_pkg(&hashbrown_id);
233+
assert_eq!(hashbrown.name, "hashbrown");
234+
assert_eq!(hashbrown.version.to_string(), "0.16.0");
235+
assert!(hashbrown.dependencies.is_empty());
236+
237+
let foo = crate_graph.get(w.member("foo"));
238+
239+
assert_eq!(foo.dependencies.len(), 2);
240+
assert!(foo.dependencies.contains(&Dependency {
241+
id: hashbrown_id,
242+
name: "hashbrown".into(),
243+
}));
244+
assert!(foo.dependencies.contains(&w.member("bar").as_dependency()));
245+
}
246+
247+
#[cargo_test]
248+
fn external_dependency_proc_macro_dylib() {
249+
let mut builder = bin("foo");
250+
let serde_derive_id = builder.dependency("serde_derive", "1.0.228", true);
251+
let foo = builder.build();
252+
253+
let crate_graph = discover_path_builder(foo.file("Cargo.toml"))
254+
.with_no_default_features()
255+
.build();
256+
257+
let serde_derive = crate_graph.get_pkg(&serde_derive_id);
258+
259+
#[cfg(target_os = "macos")]
260+
assert_eq!(
261+
serde_derive.proc_macro_dylib.as_ref().unwrap().as_str(),
262+
foo.root
263+
.join("target/debug/deps/libserde_derive-1793a7b2113a3756.dylib")
264+
.display()
265+
.to_string()
266+
);
267+
268+
#[cfg(target_os = "windows")]
269+
assert_eq!(
270+
serde_derive.proc_macro_dylib.as_ref().unwrap().as_str(),
271+
foo.root
272+
.join("target/debug/deps/libserde_derive-1793a7b2113a3756.dll")
273+
.display()
274+
.to_string()
275+
);
276+
277+
#[cfg(target_os = "linux")]
278+
assert_eq!(
279+
serde_derive.proc_macro_dylib.as_ref().unwrap().as_str(),
280+
foo.root
281+
.join("target/debug/deps/libserde_derive-1793a7b2113a3756.so")
282+
.display()
283+
.to_string()
284+
);
285+
}
286+
287+
#[cargo_test]
288+
fn internal_dependency_proc_macro_dylib() {
289+
todo!()
290+
}
291+
292+
// standalone crate, workspace, external dep for proc macros and build scripts
293+
#[cargo_test]
294+
fn external_dependency_build_script() {
295+
todo!()
296+
}
297+
298+
#[cargo_test]
299+
fn internal_dependency_build_script() {
300+
todo!()
301+
}
302+
303+
// All the existing tests but with external dependencies
304+
// A standalone crate nested under the root of a workspace from which it's excluded
305+
// Multiple build targets in a single crate
306+
// Intra-crate target dependencies
307+
// Feature flags (both ws + external deps)

tests/discover.rs

Whitespace-only changes.

0 commit comments

Comments
 (0)