Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 4aece51

Browse files
committed
Fix extraction of package dir from package ID
After rust-lang/cargo#12914, the format of the package ID changed to be path+file:///path/crate_name#version See https://doc.rust-lang.org/cargo/reference/pkgid-spec.html for details on the format. The test files were regenerated with `cargo metadata`. This procedure is now documented in a `README.md` file for future generations. Bug: 333808266 Test: atest --host cargo_embargo.test Test: Ran `cargo_embargo generate cargo_embargo.json` on chrono Change-Id: I055d19baf6e78f30b708296434082121762573af
1 parent af4bdc3 commit 4aece51

File tree

15 files changed

+31559
-15802
lines changed

15 files changed

+31559
-15802
lines changed

tools/cargo_embargo/Android.bp

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ rust_binary_host {
4343
rust_test_host {
4444
name: "cargo_embargo.test",
4545
defaults: ["cargo_embargo.defaults"],
46+
rustlibs: ["libgoogletest_rust"],
4647
test_config: "AndroidTest.xml",
4748
data: ["testdata/**/*"],
4849
}

tools/cargo_embargo/src/cargo/metadata.rs

+51-12
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
1717
use super::{Crate, CrateType, Extern, ExternType};
1818
use crate::config::VariantConfig;
19-
use anyhow::{anyhow, bail, Context, Result};
19+
use anyhow::{bail, Context, Result};
2020
use serde::Deserialize;
2121
use std::collections::BTreeMap;
2222
use std::ops::Deref;
@@ -268,14 +268,22 @@ fn make_extern(packages: &[PackageMetadata], dependency: &DependencyMetadata) ->
268268
Ok(Extern { name, lib_name, extern_type })
269269
}
270270

271-
/// Given a package ID like
272-
/// `"either 1.8.1 (path+file:///usr/local/google/home/qwandor/aosp/external/rust/crates/either)"`,
273-
/// returns the path to the package, e.g.
274-
/// `"/usr/local/google/home/qwandor/aosp/external/rust/crates/either"`.
271+
/// Given a Cargo package ID, returns the path.
272+
///
273+
/// Extracts `"/path/to/crate"` from
274+
/// `"path+file:///path/to/crate#1.2.3"`. See
275+
/// https://doc.rust-lang.org/cargo/reference/pkgid-spec.html for
276+
/// information on Cargo package ID specifications.
275277
fn package_dir_from_id(id: &str) -> Result<PathBuf> {
276-
const URI_MARKER: &str = "(path+file://";
277-
let uri_start = id.find(URI_MARKER).ok_or_else(|| anyhow!("Invalid package ID {}", id))?;
278-
Ok(PathBuf::from(id[uri_start + URI_MARKER.len()..id.len() - 1].to_string()))
278+
const PREFIX: &str = "path+file://";
279+
const SEPARATOR: char = '#';
280+
let Some(stripped) = id.strip_prefix(PREFIX) else {
281+
bail!("Invalid package ID {id:?}, expected it to start with {PREFIX:?}");
282+
};
283+
let Some(idx) = stripped.rfind(SEPARATOR) else {
284+
bail!("Invalid package ID {id:?}, expected it to contain {SEPARATOR:?}");
285+
};
286+
Ok(PathBuf::from(stripped[..idx].to_string()))
279287
}
280288

281289
fn split_src_path<'a>(src_path: &'a Path, package_dir: &Path) -> &'a Path {
@@ -344,8 +352,19 @@ mod tests {
344352
use super::*;
345353
use crate::config::Config;
346354
use crate::tests::testdata_directories;
355+
use googletest::matchers::eq;
356+
use googletest::prelude::assert_that;
347357
use std::fs::{read_to_string, File};
348358

359+
#[test]
360+
fn extract_package_dir_from_id() -> Result<()> {
361+
assert_eq!(
362+
package_dir_from_id("path+file:///path/to/crate#1.2.3")?,
363+
PathBuf::from("/path/to/crate")
364+
);
365+
Ok(())
366+
}
367+
349368
#[test]
350369
fn resolve_multi_level_feature_dependencies() {
351370
let chosen = vec!["default".to_string(), "extra".to_string(), "on_by_default".to_string()];
@@ -419,6 +438,20 @@ mod tests {
419438

420439
#[test]
421440
fn parse_metadata() {
441+
/// Remove anything before "external/rust/crates/" from the
442+
/// `package_dir` field. This makes the test robust since you
443+
/// can use `cargo metadata` to regenerate the test files and
444+
/// you don't have to care about where your AOSP checkout
445+
/// lives.
446+
fn normalize_package_dir(mut c: Crate) -> Crate {
447+
const EXTERNAL_RUST_CRATES: &str = "external/rust/crates/";
448+
let package_dir = c.package_dir.to_str().unwrap();
449+
if let Some(idx) = package_dir.find(EXTERNAL_RUST_CRATES) {
450+
c.package_dir = PathBuf::from(format!(".../{}", &package_dir[idx..]));
451+
}
452+
c
453+
}
454+
422455
for testdata_directory_path in testdata_directories() {
423456
let cfg = Config::from_json_str(
424457
&read_to_string(testdata_directory_path.join("cargo_embargo.json"))
@@ -432,10 +465,13 @@ mod tests {
432465
)
433466
.unwrap();
434467
let cargo_metadata_path = testdata_directory_path.join("cargo.metadata");
435-
let expected_crates: Vec<Vec<Crate>> = serde_json::from_reader(
468+
let expected_crates: Vec<Vec<Crate>> = serde_json::from_reader::<_, Vec<Vec<Crate>>>(
436469
File::open(testdata_directory_path.join("crates.json")).unwrap(),
437470
)
438-
.unwrap();
471+
.unwrap()
472+
.into_iter()
473+
.map(|crates: Vec<Crate>| crates.into_iter().map(normalize_package_dir).collect())
474+
.collect();
439475

440476
let crates = cfg
441477
.variants
@@ -448,9 +484,12 @@ mod tests {
448484
variant_cfg,
449485
)
450486
.unwrap()
487+
.into_iter()
488+
.map(normalize_package_dir)
489+
.collect::<Vec<Crate>>()
451490
})
452-
.collect::<Vec<_>>();
453-
assert_eq!(crates, expected_crates);
491+
.collect::<Vec<Vec<Crate>>>();
492+
assert_that!(format!("{crates:#?}"), eq(format!("{expected_crates:#?}")));
454493
}
455494
}
456495
}

tools/cargo_embargo/src/main.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,8 @@ fn crate_to_bp_modules(
911911
#[cfg(test)]
912912
mod tests {
913913
use super::*;
914+
use googletest::matchers::eq;
915+
use googletest::prelude::assert_that;
914916
use std::env::{current_dir, set_current_dir};
915917
use std::fs::{self, read_to_string};
916918
use std::path::PathBuf;
@@ -992,7 +994,7 @@ mod tests {
992994
.unwrap();
993995
}
994996

995-
assert_eq!(output, expected_output);
997+
assert_that!(output, eq(expected_output));
996998

997999
set_current_dir(old_current_dir).unwrap();
9981000
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Test data for `cargo_embargo`
2+
3+
The files here are used for `cargo_embargo` integration tests. Run the tests with
4+
5+
```shell
6+
atest --host cargo_embargo.test
7+
```
8+
9+
## Handling changes in Cargo output
10+
11+
When the output of `cargo metadata` changes, you need to update the
12+
`cargo.metadata` files found in the subdirectories here. Do this with:
13+
14+
```
15+
for crate in aho-corasick async-trait either plotters rustc-demangle-capi; do
16+
pushd $ANDROID_BUILD_TOP/external/rust/crates/$crate
17+
cargo metadata --format-version 1 | jq --sort-keys \
18+
> $ANDROID_BUILD_TOP/development/tools/cargo_embargo/testdata/$crate/cargo.metadata
19+
popd
20+
done
21+
```
22+
23+
Run the integration tests again after updating the crate metadata.
24+
25+
Some tests will likely fail because of outdated information in the other test
26+
files:
27+
28+
- `expected_Android.bp`: Adjust the version numbers to match the current version
29+
from `cargo.metadata`.
30+
- `crates.json`: Adjust version numbers and `package_dir` as necessary.
31+
- `cargo_embargo.json`: Adjust the list of Cargo features if this has changed
32+
since the file was last touched.

0 commit comments

Comments
 (0)