• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 extern crate cargo_bazel;
2 extern crate serde_json;
3 extern crate tempfile;
4 
5 use anyhow::{ensure, Context, Result};
6 use cargo_bazel::cli::{splice, SpliceOptions};
7 use serde_json::{json, Value};
8 use std::collections::HashMap;
9 use std::env;
10 use std::fs;
11 use std::path::PathBuf;
12 
setup_cargo_env() -> Result<(PathBuf, PathBuf)>13 fn setup_cargo_env() -> Result<(PathBuf, PathBuf)> {
14     let cargo = std::fs::canonicalize(PathBuf::from(
15         env::var("CARGO").context("CARGO environment variable must be set.")?,
16     ))
17     .unwrap();
18     let rustc = std::fs::canonicalize(PathBuf::from(
19         env::var("RUSTC").context("RUSTC environment variable must be set.")?,
20     ))
21     .unwrap();
22     ensure!(cargo.exists());
23     ensure!(rustc.exists());
24     // If $RUSTC is a relative path it can cause issues with
25     // `cargo_metadata::MetadataCommand`. Just to be on the safe side, we make
26     // both of these env variables absolute paths.
27     if cargo != PathBuf::from(env::var("CARGO").unwrap()) {
28         env::set_var("CARGO", cargo.as_os_str());
29     }
30     if rustc != PathBuf::from(env::var("RUSTC").unwrap()) {
31         env::set_var("RUSTC", rustc.as_os_str());
32     }
33 
34     let cargo_home = PathBuf::from(
35         env::var("TEST_TMPDIR").context("TEST_TMPDIR environment variable must be set.")?,
36     )
37     .join("cargo_home");
38     env::set_var("CARGO_HOME", cargo_home.as_os_str());
39     fs::create_dir_all(&cargo_home)?;
40 
41     println!("$RUSTC={}", rustc.display());
42     println!("$CARGO={}", cargo.display());
43     println!("$CARGO_HOME={}", cargo_home.display());
44 
45     Ok((cargo, rustc))
46 }
47 
run(repository_name: &str, manifests: HashMap<String, String>, lockfile: &str) -> Value48 fn run(repository_name: &str, manifests: HashMap<String, String>, lockfile: &str) -> Value {
49     let (cargo, rustc) = setup_cargo_env().unwrap();
50 
51     let scratch = tempfile::tempdir().unwrap();
52     let runfiles = runfiles::Runfiles::create().unwrap();
53 
54     /*
55     let manifest_path = scratch.path().join("Cargo.toml");
56     fs::copy(
57         runfiles.rlocation(manifest),
58         manifest_path,
59     )
60     .unwrap();
61     */
62 
63     let splicing_manifest = scratch.path().join("splicing_manifest.json");
64     fs::write(
65         &splicing_manifest,
66         serde_json::to_string(&json!({
67             "manifests": manifests,
68             "direct_packages": {},
69             "resolver_version": "2"
70         }))
71         .unwrap(),
72     )
73     .unwrap();
74 
75     let config = scratch.path().join("config.json");
76     fs::write(
77         &config,
78         serde_json::to_string(&json!({
79             "generate_binaries": false,
80             "generate_build_scripts": false,
81             "rendering": {
82                 "repository_name": repository_name,
83                 "regen_command": "//crate_universe:cargo_integration_test"
84             },
85             "supported_platform_triples": [
86                 "x86_64-apple-darwin",
87                 "x86_64-pc-windows-msvc",
88                 "x86_64-unknown-linux-gnu",
89             ]
90         }))
91         .unwrap(),
92     )
93     .unwrap();
94 
95     splice(SpliceOptions {
96         splicing_manifest,
97         cargo_lockfile: Some(runfiles.rlocation(lockfile)),
98         repin: None,
99         workspace_dir: None,
100         output_dir: scratch.path().join("out"),
101         dry_run: false,
102         cargo_config: None,
103         config,
104         cargo,
105         rustc,
106     })
107     .unwrap();
108 
109     let metadata = serde_json::from_str::<Value>(
110         &fs::read_to_string(scratch.path().join("out").join("metadata.json")).unwrap(),
111     )
112     .unwrap();
113 
114     metadata
115 }
116 
117 // See crate_universe/test_data/metadata/target_features/Cargo.toml for input.
118 #[test]
feature_generator()119 fn feature_generator() {
120     // This test case requires network access to build pull crate metadata
121     // so that we can actually run `cargo tree`. However, RBE (and perhaps
122     // other environments) disallow or don't support this. In those cases,
123     // we just skip this test case.
124     use std::net::ToSocketAddrs;
125     if "github.com:443".to_socket_addrs().is_err() {
126         eprintln!("This test case requires network access. Skipping!");
127         return;
128     }
129 
130     let runfiles = runfiles::Runfiles::create().unwrap();
131     let metadata = run(
132         "target_feature_test",
133         HashMap::from([(
134             runfiles
135                 .rlocation(
136                     "rules_rust/crate_universe/test_data/metadata/target_features/Cargo.toml",
137                 )
138                 .to_string_lossy()
139                 .to_string(),
140             "//:test_input".to_string(),
141         )]),
142         "rules_rust/crate_universe/test_data/metadata/target_features/Cargo.lock",
143     );
144 
145     assert_eq!(
146         metadata["metadata"]["cargo-bazel"]["features"]["wgpu-hal 0.14.1"],
147         json!({
148             "selects": {
149                 "x86_64-apple-darwin": [
150                     "block", "foreign-types", "metal",
151                 ],
152                 "x86_64-pc-windows-msvc": [
153                     "ash", "bit-set", "dx11", "dx12", "gpu-alloc",
154                     "gpu-descriptor", "libloading", "native", "range-alloc",
155                     "renderdoc", "renderdoc-sys", "smallvec", "vulkan",
156                 ],
157                 "x86_64-unknown-linux-gnu": [
158                     "ash", "egl", "gles", "glow", "gpu-alloc",
159                     "gpu-descriptor", "libloading", "renderdoc", "renderdoc-sys",
160                     "smallvec", "vulkan",
161                 ],
162             },
163             "common": [
164                 "default",
165             ],
166         })
167     );
168 }
169 
170 // See crate_universe/test_data/metadata/target_cfg_features/Cargo.toml for input.
171 #[test]
feature_generator_cfg_features()172 fn feature_generator_cfg_features() {
173     // This test case requires network access to build pull crate metadata
174     // so that we can actually run `cargo tree`. However, RBE (and perhaps
175     // other environments) disallow or don't support this. In those cases,
176     // we just skip this test case.
177     use std::net::ToSocketAddrs;
178     if "github.com:443".to_socket_addrs().is_err() {
179         eprintln!("This test case requires network access. Skipping!");
180         return;
181     }
182 
183     let runfiles = runfiles::Runfiles::create().unwrap();
184     let metadata = run(
185         "target_cfg_features_test",
186         HashMap::from([(
187             runfiles
188                 .rlocation(
189                     "rules_rust/crate_universe/test_data/metadata/target_cfg_features/Cargo.toml",
190                 )
191                 .to_string_lossy()
192                 .to_string(),
193             "//:test_input".to_string(),
194         )]),
195         "rules_rust/crate_universe/test_data/metadata/target_cfg_features/Cargo.lock",
196     );
197 
198     assert_eq!(
199         metadata["metadata"]["cargo-bazel"]["features"],
200         json!({
201             "target_cfg_features 0.1.0": {
202                 "common": [],
203                 "selects": {}
204             },
205             "autocfg 1.1.0": {
206                 "common": [],
207                 "selects": {}
208             },
209             "pin-project-lite 0.2.9": {
210                 "common": [],
211                 "selects": {}
212             },
213             "tokio 1.25.0": {
214                 "common": ["default"],
215                 "selects": {
216                     // Note: "x86_64-pc-windows-msvc" is *not* here, despite
217                     // being included in `supported_platform_triples` above!
218                     "x86_64-apple-darwin": ["fs"],
219                     "x86_64-unknown-linux-gnu": ["fs"]
220                 }
221             }
222         })
223     );
224 }
225 
226 #[test]
feature_generator_workspace()227 fn feature_generator_workspace() {
228     // This test case requires network access to build pull crate metadata
229     // so that we can actually run `cargo tree`. However, RBE (and perhaps
230     // other environments) disallow or don't support this. In those cases,
231     // we just skip this test case.
232     use std::net::ToSocketAddrs;
233     if "github.com:443".to_socket_addrs().is_err() {
234         eprintln!("This test case requires network access. Skipping!");
235         return;
236     }
237 
238     let runfiles = runfiles::Runfiles::create().unwrap();
239     let metadata = run(
240         "workspace_test",
241         HashMap::from([
242             (
243                 runfiles
244                     .rlocation("rules_rust/crate_universe/test_data/metadata/workspace/Cargo.toml")
245                     .to_string_lossy()
246                     .to_string(),
247                 "//:test_input".to_string(),
248             ),
249             (
250                 runfiles
251                     .rlocation(
252                         "rules_rust/crate_universe/test_data/metadata/workspace/child/Cargo.toml",
253                     )
254                     .to_string_lossy()
255                     .to_string(),
256                 "//crate_universe:test_data/metadata/workspace/child/Cargo.toml".to_string(),
257             ),
258         ]),
259         "rules_rust/crate_universe/test_data/metadata/workspace/Cargo.lock",
260     );
261 
262     assert!(!metadata["metadata"]["cargo-bazel"]["features"]["wgpu 0.14.0"].is_null());
263 }
264 
265 #[test]
feature_generator_crate_combined_features()266 fn feature_generator_crate_combined_features() {
267     // This test case requires network access to build pull crate metadata
268     // so that we can actually run `cargo tree`. However, RBE (and perhaps
269     // other environments) disallow or don't support this. In those cases,
270     // we just skip this test case.
271     use std::net::ToSocketAddrs;
272     if "github.com:443".to_socket_addrs().is_err() {
273         eprintln!("This test case requires network access. Skipping!");
274         return;
275     }
276 
277     let runfiles = runfiles::Runfiles::create().unwrap();
278     let metadata = run(
279         "crate_combined_features",
280         HashMap::from([
281             (
282                 runfiles
283                     .rlocation("rules_rust/crate_universe/test_data/metadata/crate_combined_features/Cargo.toml")
284                     .to_string_lossy()
285                     .to_string(),
286                 "//:test_input".to_string(),
287             )
288         ]),
289         "rules_rust/crate_universe/test_data/metadata/crate_combined_features/Cargo.lock",
290     );
291 
292     // serde appears twice in the list of dependencies, with and without derive features
293     assert_eq!(
294         metadata["metadata"]["cargo-bazel"]["features"]["serde 1.0.158"]["common"],
295         json!(["default", "derive", "serde_derive", "std"])
296     );
297 }
298