Skip to content

Commit cf893c1

Browse files
Xaeroxeweihanglo
authored andcommitted
test(freshness_checksum): verify cargo depinfo is properly encoded
1 parent c0e550e commit cf893c1

File tree

3 files changed

+152
-84
lines changed

3 files changed

+152
-84
lines changed

crates/cargo-test-support/src/lib.rs

+79
Original file line numberDiff line numberDiff line change
@@ -1582,3 +1582,82 @@ where
15821582
let thread = std::thread::spawn(|| f());
15831583
thread_wait_timeout(n, thread)
15841584
}
1585+
1586+
// Helper for testing dep-info files in the fingerprint dir.
1587+
#[track_caller]
1588+
pub fn assert_deps(project: &Project, fingerprint: &str, test_cb: impl Fn(&Path, &[(u8, &str)])) {
1589+
let mut files = project
1590+
.glob(fingerprint)
1591+
.map(|f| f.expect("unwrap glob result"))
1592+
// Filter out `.json` entries.
1593+
.filter(|f| f.extension().is_none());
1594+
let info_path = files
1595+
.next()
1596+
.unwrap_or_else(|| panic!("expected 1 dep-info file at {}, found 0", fingerprint));
1597+
assert!(files.next().is_none(), "expected only 1 dep-info file");
1598+
let dep_info = fs::read(&info_path).unwrap();
1599+
let dep_info = &mut &dep_info[..];
1600+
let deps = (0..read_usize(dep_info))
1601+
.map(|_| {
1602+
let ty = read_u8(dep_info);
1603+
let path = std::str::from_utf8(read_bytes(dep_info)).unwrap();
1604+
let checksum_present = read_bool(dep_info);
1605+
if checksum_present {
1606+
// Read out the checksum info without using it
1607+
let _file_len = read_u64(dep_info);
1608+
let _checksum = read_bytes(dep_info);
1609+
}
1610+
(ty, path)
1611+
})
1612+
.collect::<Vec<_>>();
1613+
test_cb(&info_path, &deps);
1614+
1615+
fn read_usize(bytes: &mut &[u8]) -> usize {
1616+
let ret = &bytes[..4];
1617+
*bytes = &bytes[4..];
1618+
1619+
u32::from_le_bytes(ret.try_into().unwrap()) as usize
1620+
}
1621+
1622+
fn read_u8(bytes: &mut &[u8]) -> u8 {
1623+
let ret = bytes[0];
1624+
*bytes = &bytes[1..];
1625+
ret
1626+
}
1627+
1628+
fn read_bool(bytes: &mut &[u8]) -> bool {
1629+
read_u8(bytes) != 0
1630+
}
1631+
1632+
fn read_u64(bytes: &mut &[u8]) -> u64 {
1633+
let ret = &bytes[..8];
1634+
*bytes = &bytes[8..];
1635+
1636+
u64::from_le_bytes(ret.try_into().unwrap())
1637+
}
1638+
1639+
fn read_bytes<'a>(bytes: &mut &'a [u8]) -> &'a [u8] {
1640+
let n = read_usize(bytes);
1641+
let ret = &bytes[..n];
1642+
*bytes = &bytes[n..];
1643+
ret
1644+
}
1645+
}
1646+
1647+
pub fn assert_deps_contains(project: &Project, fingerprint: &str, expected: &[(u8, &str)]) {
1648+
assert_deps(project, fingerprint, |info_path, entries| {
1649+
for (e_kind, e_path) in expected {
1650+
let pattern = glob::Pattern::new(e_path).unwrap();
1651+
let count = entries
1652+
.iter()
1653+
.filter(|(kind, path)| kind == e_kind && pattern.matches(path))
1654+
.count();
1655+
if count != 1 {
1656+
panic!(
1657+
"Expected 1 match of {} {} in {:?}, got {}:\n{:#?}",
1658+
e_kind, e_path, info_path, count, entries
1659+
);
1660+
}
1661+
}
1662+
})
1663+
}

tests/testsuite/dep_info.rs

+2-84
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,17 @@
11
//! Tests for dep-info files. This includes the dep-info file Cargo creates in
22
//! the output directory, and the ones stored in the fingerprint.
33
4-
use std::fs;
54
use std::path::Path;
6-
use std::str;
75

86
use cargo_test_support::compare::assert_e2e;
97
use cargo_test_support::paths;
108
use cargo_test_support::prelude::*;
119
use cargo_test_support::registry::Package;
1210
use cargo_test_support::str;
13-
use cargo_test_support::{
14-
basic_bin_manifest, basic_manifest, main_file, project, rustc_host, Project,
15-
};
11+
use cargo_test_support::{assert_deps, assert_deps_contains};
12+
use cargo_test_support::{basic_bin_manifest, basic_manifest, main_file, project, rustc_host};
1613
use filetime::FileTime;
1714

18-
// Helper for testing dep-info files in the fingerprint dir.
19-
#[track_caller]
20-
fn assert_deps(project: &Project, fingerprint: &str, test_cb: impl Fn(&Path, &[(u8, &str)])) {
21-
let mut files = project
22-
.glob(fingerprint)
23-
.map(|f| f.expect("unwrap glob result"))
24-
// Filter out `.json` entries.
25-
.filter(|f| f.extension().is_none());
26-
let info_path = files
27-
.next()
28-
.unwrap_or_else(|| panic!("expected 1 dep-info file at {}, found 0", fingerprint));
29-
assert!(files.next().is_none(), "expected only 1 dep-info file");
30-
let dep_info = fs::read(&info_path).unwrap();
31-
let dep_info = &mut &dep_info[..];
32-
let deps = (0..read_usize(dep_info))
33-
.map(|_| {
34-
let ty = read_u8(dep_info);
35-
let path = str::from_utf8(read_bytes(dep_info)).unwrap();
36-
let checksum_present = read_bool(dep_info);
37-
if checksum_present {
38-
// Read out the checksum info without using it
39-
let _file_len = read_u64(dep_info);
40-
let _checksum = read_bytes(dep_info);
41-
}
42-
(ty, path)
43-
})
44-
.collect::<Vec<_>>();
45-
test_cb(&info_path, &deps);
46-
47-
fn read_usize(bytes: &mut &[u8]) -> usize {
48-
let ret = &bytes[..4];
49-
*bytes = &bytes[4..];
50-
51-
u32::from_le_bytes(ret.try_into().unwrap()) as usize
52-
}
53-
54-
fn read_u8(bytes: &mut &[u8]) -> u8 {
55-
let ret = bytes[0];
56-
*bytes = &bytes[1..];
57-
ret
58-
}
59-
60-
fn read_bool(bytes: &mut &[u8]) -> bool {
61-
read_u8(bytes) != 0
62-
}
63-
64-
fn read_u64(bytes: &mut &[u8]) -> u64 {
65-
let ret = &bytes[..8];
66-
*bytes = &bytes[8..];
67-
68-
u64::from_le_bytes(ret.try_into().unwrap())
69-
}
70-
71-
fn read_bytes<'a>(bytes: &mut &'a [u8]) -> &'a [u8] {
72-
let n = read_usize(bytes);
73-
let ret = &bytes[..n];
74-
*bytes = &bytes[n..];
75-
ret
76-
}
77-
}
78-
79-
fn assert_deps_contains(project: &Project, fingerprint: &str, expected: &[(u8, &str)]) {
80-
assert_deps(project, fingerprint, |info_path, entries| {
81-
for (e_kind, e_path) in expected {
82-
let pattern = glob::Pattern::new(e_path).unwrap();
83-
let count = entries
84-
.iter()
85-
.filter(|(kind, path)| kind == e_kind && pattern.matches(path))
86-
.count();
87-
if count != 1 {
88-
panic!(
89-
"Expected 1 match of {} {} in {:?}, got {}:\n{:#?}",
90-
e_kind, e_path, info_path, count, entries
91-
);
92-
}
93-
}
94-
})
95-
}
96-
9715
#[cargo_test]
9816
fn build_dep_info() {
9917
let p = project()

tests/testsuite/freshness_checksum.rs

+71
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::net::TcpListener;
66
use std::process::Stdio;
77
use std::thread;
88

9+
use cargo_test_support::assert_deps_contains;
910
use cargo_test_support::prelude::*;
1011
use cargo_test_support::registry::Package;
1112
use cargo_test_support::{
@@ -129,6 +130,76 @@ fn same_size_different_content() {
129130
.run();
130131
}
131132

133+
#[cargo_test(
134+
nightly,
135+
reason = "-Zbinary-dep-depinfo is unstable, also requires -Zchecksum-hash-algorithm"
136+
)]
137+
fn binary_depinfo_correctly_encoded() {
138+
Package::new("regdep", "0.1.0")
139+
.file("src/lib.rs", "pub fn f() {}")
140+
.publish();
141+
142+
let p = project()
143+
.file(
144+
"Cargo.toml",
145+
r#"
146+
[package]
147+
name = "foo"
148+
version = "0.1.0"
149+
edition = "2018"
150+
151+
[dependencies]
152+
regdep = "0.1"
153+
bar = {path = "./bar"}
154+
"#,
155+
)
156+
.file(
157+
"src/main.rs",
158+
r#"
159+
fn main() {
160+
regdep::f();
161+
bar::f();
162+
}
163+
"#,
164+
)
165+
/*********** Path Dependency `bar` ***********/
166+
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
167+
.file("bar/src/lib.rs", "pub fn f() {}")
168+
.build();
169+
170+
let host = rustc_host();
171+
p.cargo("build -Zbinary-dep-depinfo -Zchecksum-freshness --target")
172+
.arg(&host)
173+
.masquerade_as_nightly_cargo(&["binary-dep-depinfo", "checksum-freshness"])
174+
.with_stderr_data(str![[r#"
175+
...
176+
[COMPILING] foo v0.1.0 ([ROOT]/foo)
177+
...
178+
179+
"#]])
180+
.run();
181+
182+
assert_deps_contains(
183+
&p,
184+
&format!("target/{}/debug/.fingerprint/foo-*/dep-bin-foo", host),
185+
&[
186+
(0, "src/main.rs"),
187+
(1, &format!("{}/debug/deps/libbar-*.rlib", host)),
188+
(1, &format!("{}/debug/deps/libregdep-*.rlib", host)),
189+
],
190+
);
191+
192+
// Make sure it stays fresh.
193+
p.cargo("build -Zbinary-dep-depinfo -Zchecksum-freshness --target")
194+
.arg(&host)
195+
.masquerade_as_nightly_cargo(&["binary-dep-depinfo", "checksum-freshness"])
196+
.with_stderr_data(str![[r#"
197+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
198+
199+
"#]])
200+
.run();
201+
}
202+
132203
#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")]
133204
fn modifying_and_moving() {
134205
let p = project()

0 commit comments

Comments
 (0)