]> git.proxmox.com Git - rustc.git/blame - vendor/cargo_metadata/tests/test_samples.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / vendor / cargo_metadata / tests / test_samples.rs
CommitLineData
3c0e092e
XL
1extern crate cargo_metadata;
2extern crate semver;
3#[macro_use]
4extern crate serde_json;
5
6use camino::Utf8PathBuf;
781aab86 7use cargo_metadata::{
ed00b5ec
FG
8 workspace_default_members_is_missing, ArtifactDebuginfo, CargoOpt, DependencyKind, Edition,
9 Message, Metadata, MetadataCommand,
781aab86 10};
3c0e092e 11
ed00b5ec
FG
12/// Output from oldest version ever supported (1.24).
13///
14/// This intentionally has as many null fields as possible.
15/// 1.8 is when metadata was introduced.
16/// Older versions not supported because the following are required:
17/// - `workspace_members` added in 1.13
18/// - `target_directory` added in 1.19
19/// - `workspace_root` added in 1.24
20const JSON_OLD_MINIMAL: &str = r#"
3c0e092e
XL
21{
22 "packages": [
23 {
24 "name": "foo",
25 "version": "0.1.0",
26 "id": "foo 0.1.0 (path+file:///foo)",
27 "license": null,
28 "license_file": null,
29 "description": null,
30 "source": null,
31 "dependencies": [
32 {
33 "name": "somedep",
34 "source": null,
35 "req": "^1.0",
36 "kind": null,
37 "optional": false,
38 "uses_default_features": true,
39 "features": [],
40 "target": null
41 }
42 ],
43 "targets": [
44 {
45 "kind": [
46 "bin"
47 ],
48 "crate_types": [
49 "bin"
50 ],
51 "name": "foo",
52 "src_path": "/foo/src/main.rs"
53 }
54 ],
55 "features": {},
56 "manifest_path": "/foo/Cargo.toml"
57 }
58 ],
59 "workspace_members": [
60 "foo 0.1.0 (path+file:///foo)"
61 ],
62 "resolve": null,
63 "target_directory": "/foo/target",
64 "version": 1,
65 "workspace_root": "/foo"
66}
67"#;
ed00b5ec
FG
68
69#[test]
70fn old_minimal() {
71 let meta: Metadata = serde_json::from_str(JSON_OLD_MINIMAL).unwrap();
3c0e092e
XL
72 assert_eq!(meta.packages.len(), 1);
73 let pkg = &meta.packages[0];
74 assert_eq!(pkg.name, "foo");
75 assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap());
76 assert_eq!(pkg.authors.len(), 0);
77 assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)");
78 assert_eq!(pkg.description, None);
79 assert_eq!(pkg.license, None);
80 assert_eq!(pkg.license_file, None);
81 assert_eq!(pkg.default_run, None);
82 assert_eq!(pkg.rust_version, None);
83 assert_eq!(pkg.dependencies.len(), 1);
84 let dep = &pkg.dependencies[0];
85 assert_eq!(dep.name, "somedep");
86 assert_eq!(dep.source, None);
87 assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap());
88 assert_eq!(dep.kind, DependencyKind::Normal);
064997fb
FG
89 assert!(!dep.optional);
90 assert!(dep.uses_default_features);
3c0e092e
XL
91 assert_eq!(dep.features.len(), 0);
92 assert!(dep.target.is_none());
93 assert_eq!(dep.rename, None);
94 assert_eq!(dep.registry, None);
95 assert_eq!(pkg.targets.len(), 1);
96 let target = &pkg.targets[0];
97 assert_eq!(target.name, "foo");
98 assert_eq!(target.kind, vec!["bin"]);
99 assert_eq!(target.crate_types, vec!["bin"]);
100 assert_eq!(target.required_features.len(), 0);
101 assert_eq!(target.src_path, "/foo/src/main.rs");
064997fb
FG
102 assert_eq!(target.edition, Edition::E2015);
103 assert!(target.doctest);
104 assert!(target.test);
105 assert!(target.doc);
3c0e092e
XL
106 assert_eq!(pkg.features.len(), 0);
107 assert_eq!(pkg.manifest_path, "/foo/Cargo.toml");
108 assert_eq!(pkg.categories.len(), 0);
109 assert_eq!(pkg.keywords.len(), 0);
110 assert_eq!(pkg.readme, None);
111 assert_eq!(pkg.repository, None);
112 assert_eq!(pkg.homepage, None);
113 assert_eq!(pkg.documentation, None);
064997fb 114 assert_eq!(pkg.edition, Edition::E2015);
3c0e092e
XL
115 assert_eq!(pkg.metadata, serde_json::Value::Null);
116 assert_eq!(pkg.links, None);
117 assert_eq!(pkg.publish, None);
118 assert_eq!(meta.workspace_members.len(), 1);
119 assert_eq!(
120 meta.workspace_members[0].to_string(),
121 "foo 0.1.0 (path+file:///foo)"
122 );
123 assert!(meta.resolve.is_none());
124 assert_eq!(meta.workspace_root, "/foo");
125 assert_eq!(meta.workspace_metadata, serde_json::Value::Null);
126 assert_eq!(meta.target_directory, "/foo/target");
ed00b5ec
FG
127
128 assert!(workspace_default_members_is_missing(
129 &meta.workspace_default_members
130 ));
131 let serialized = serde_json::to_value(meta).unwrap();
132 assert!(!serialized
133 .as_object()
134 .unwrap()
135 .contains_key("workspace_default_members"));
3c0e092e
XL
136}
137
138macro_rules! sorted {
139 ($e:expr) => {{
140 let mut v = $e.clone();
141 v.sort();
142 v
143 }};
144}
145
146fn cargo_version() -> semver::Version {
147 let output = std::process::Command::new("cargo")
148 .arg("-V")
149 .output()
150 .expect("Failed to exec cargo.");
151 let out = std::str::from_utf8(&output.stdout)
152 .expect("invalid utf8")
153 .trim();
154 let split: Vec<&str> = out.split_whitespace().collect();
155 assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out);
156 let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed");
157 // Don't care about metadata, it is awkward to compare.
158 ver.pre = semver::Prerelease::EMPTY;
159 ver.build = semver::BuildMetadata::EMPTY;
160 ver
161}
162
163#[derive(serde::Deserialize, PartialEq, Eq, Debug)]
164struct WorkspaceMetadata {
165 testobject: TestObject,
166}
167
168#[derive(serde::Deserialize, PartialEq, Eq, Debug)]
169struct TestObject {
170 myvalue: String,
171}
172
173#[test]
174fn all_the_fields() {
5e7ed085 175 // All the fields currently generated as of 1.60. This tries to exercise as
3c0e092e
XL
176 // much as possible.
177 let ver = cargo_version();
178 let minimum = semver::Version::parse("1.56.0").unwrap();
179 if ver < minimum {
180 // edition added in 1.30
181 // rename added in 1.31
182 // links added in 1.33
183 // doctest added in 1.37
184 // publish added in 1.39
185 // dep_kinds added in 1.41
186 // test added in 1.47
187 // homepage added in 1.49
188 // documentation added in 1.49
189 // doc added in 1.50
190 // path added in 1.51
191 // default_run added in 1.55
192 // rust_version added in 1.58
ed00b5ec 193 // workspace_default_members added in 1.71
3c0e092e
XL
194 eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver);
195 return;
196 }
197 let meta = MetadataCommand::new()
198 .manifest_path("tests/all/Cargo.toml")
199 .exec()
200 .unwrap();
201 assert_eq!(meta.workspace_root.file_name().unwrap(), "all");
202 assert_eq!(
ed00b5ec 203 serde_json::from_value::<WorkspaceMetadata>(meta.workspace_metadata.clone()).unwrap(),
3c0e092e
XL
204 WorkspaceMetadata {
205 testobject: TestObject {
206 myvalue: "abc".to_string()
207 }
208 }
209 );
210 assert_eq!(meta.workspace_members.len(), 1);
211 assert!(meta.workspace_members[0].to_string().starts_with("all"));
ed00b5ec
FG
212 if ver >= semver::Version::parse("1.71.0").unwrap() {
213 assert_eq!(&*meta.workspace_default_members, &meta.workspace_members);
214 }
3c0e092e
XL
215
216 assert_eq!(meta.packages.len(), 9);
217 let all = meta.packages.iter().find(|p| p.name == "all").unwrap();
218 assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap());
219 assert_eq!(all.authors, vec!["Jane Doe <user@example.com>"]);
220 assert!(all.id.to_string().starts_with("all"));
221 assert_eq!(all.description, Some("Package description.".to_string()));
222 assert_eq!(all.license, Some("MIT/Apache-2.0".to_string()));
223 assert_eq!(all.license_file, Some(Utf8PathBuf::from("LICENSE")));
224 assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE"));
225 assert_eq!(all.publish, Some(vec![]));
226 assert_eq!(all.links, Some("foo".to_string()));
227 assert_eq!(all.default_run, Some("otherbin".to_string()));
228 if ver >= semver::Version::parse("1.58.0").unwrap() {
229 assert_eq!(
230 all.rust_version,
781aab86 231 Some(semver::Version::parse("1.56.0").unwrap())
3c0e092e
XL
232 );
233 }
234
235 assert_eq!(all.dependencies.len(), 8);
236 let bitflags = all
237 .dependencies
238 .iter()
239 .find(|d| d.name == "bitflags")
240 .unwrap();
241 assert_eq!(
242 bitflags.source,
243 Some("registry+https://github.com/rust-lang/crates.io-index".to_string())
244 );
064997fb 245 assert!(bitflags.optional);
3c0e092e
XL
246 assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap());
247
248 let path_dep = all
249 .dependencies
250 .iter()
251 .find(|d| d.name == "path-dep")
252 .unwrap();
253 assert_eq!(path_dep.source, None);
254 assert_eq!(path_dep.kind, DependencyKind::Normal);
255 assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap());
256 assert_eq!(
257 path_dep.path.as_ref().map(|p| p.ends_with("path-dep")),
258 Some(true),
259 );
260
261 all.dependencies
262 .iter()
263 .find(|d| d.name == "namedep")
264 .unwrap();
265
266 let featdep = all
267 .dependencies
268 .iter()
269 .find(|d| d.name == "featdep")
270 .unwrap();
271 assert_eq!(featdep.features, vec!["i128"]);
064997fb 272 assert!(!featdep.uses_default_features);
3c0e092e
XL
273
274 let renamed = all
275 .dependencies
276 .iter()
277 .find(|d| d.name == "oldname")
278 .unwrap();
279 assert_eq!(renamed.rename, Some("newname".to_string()));
280
281 let devdep = all
282 .dependencies
283 .iter()
284 .find(|d| d.name == "devdep")
285 .unwrap();
286 assert_eq!(devdep.kind, DependencyKind::Development);
287
288 let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap();
289 assert_eq!(bdep.kind, DependencyKind::Build);
290
291 let windep = all
292 .dependencies
293 .iter()
294 .find(|d| d.name == "windep")
295 .unwrap();
296 assert_eq!(
297 windep.target.as_ref().map(|x| x.to_string()),
298 Some("cfg(windows)".to_string())
299 );
300
301 macro_rules! get_file_name {
302 ($v:expr) => {
303 all.targets
304 .iter()
305 .find(|t| t.src_path.file_name().unwrap() == $v)
306 .unwrap()
307 };
308 }
309 assert_eq!(all.targets.len(), 8);
310 let lib = get_file_name!("lib.rs");
311 assert_eq!(lib.name, "all");
5e7ed085 312 assert_eq!(sorted!(lib.kind), vec!["cdylib", "rlib", "staticlib"]);
3c0e092e
XL
313 assert_eq!(
314 sorted!(lib.crate_types),
5e7ed085 315 vec!["cdylib", "rlib", "staticlib"]
3c0e092e
XL
316 );
317 assert_eq!(lib.required_features.len(), 0);
064997fb
FG
318 assert_eq!(lib.edition, Edition::E2018);
319 assert!(lib.doctest);
320 assert!(lib.test);
321 assert!(lib.doc);
3c0e092e
XL
322
323 let main = get_file_name!("main.rs");
324 assert_eq!(main.crate_types, vec!["bin"]);
325 assert_eq!(main.kind, vec!["bin"]);
064997fb
FG
326 assert!(!main.doctest);
327 assert!(main.test);
328 assert!(main.doc);
3c0e092e
XL
329
330 let otherbin = get_file_name!("otherbin.rs");
064997fb
FG
331 assert_eq!(otherbin.edition, Edition::E2015);
332 assert!(!otherbin.doc);
3c0e092e
XL
333
334 let reqfeat = get_file_name!("reqfeat.rs");
335 assert_eq!(reqfeat.required_features, vec!["feat2"]);
336
337 let ex1 = get_file_name!("ex1.rs");
338 assert_eq!(ex1.kind, vec!["example"]);
064997fb 339 assert!(!ex1.test);
3c0e092e
XL
340
341 let t1 = get_file_name!("t1.rs");
342 assert_eq!(t1.kind, vec!["test"]);
343
344 let b1 = get_file_name!("b1.rs");
345 assert_eq!(b1.kind, vec!["bench"]);
346
347 let build = get_file_name!("build.rs");
348 assert_eq!(build.kind, vec!["custom-build"]);
349
5e7ed085
FG
350 if ver >= semver::Version::parse("1.60.0").unwrap() {
351 // 1.60 now reports optional dependencies within the features table
352 assert_eq!(all.features.len(), 4);
353 assert_eq!(all.features["bitflags"], vec!["dep:bitflags"]);
354 } else {
355 assert_eq!(all.features.len(), 3);
356 }
3c0e092e
XL
357 assert_eq!(all.features["feat1"].len(), 0);
358 assert_eq!(all.features["feat2"].len(), 0);
359 assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]);
360
361 assert!(all.manifest_path.ends_with("all/Cargo.toml"));
362 assert_eq!(all.categories, vec!["command-line-utilities"]);
363 assert_eq!(all.keywords, vec!["cli"]);
364 assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md")));
9ffffee4 365 assert!(all.readme().unwrap().ends_with("tests/all/README.md"));
3c0e092e
XL
366 assert_eq!(
367 all.repository,
368 Some("https://github.com/oli-obk/cargo_metadata/".to_string())
369 );
370 assert_eq!(
371 all.homepage,
372 Some("https://github.com/oli-obk/cargo_metadata/".to_string())
373 );
374 assert_eq!(
375 all.documentation,
376 Some("https://docs.rs/cargo_metadata/".to_string())
377 );
064997fb 378 assert_eq!(all.edition, Edition::E2018);
3c0e092e
XL
379 assert_eq!(
380 all.metadata,
381 json!({
382 "docs": {
383 "rs": {
384 "all-features": true,
385 "default-target": "x86_64-unknown-linux-gnu",
386 "rustc-args": ["--example-rustc-arg"]
387 }
388 }
389 })
390 );
391
392 let resolve = meta.resolve.as_ref().unwrap();
393 assert!(resolve
394 .root
395 .as_ref()
396 .unwrap()
397 .to_string()
398 .starts_with("all"));
399
400 assert_eq!(resolve.nodes.len(), 9);
401 let path_dep = resolve
402 .nodes
403 .iter()
404 .find(|n| n.id.to_string().starts_with("path-dep"))
405 .unwrap();
406 assert_eq!(path_dep.deps.len(), 0);
407 assert_eq!(path_dep.dependencies.len(), 0);
408 assert_eq!(path_dep.features.len(), 0);
409
410 let bitflags = resolve
411 .nodes
412 .iter()
413 .find(|n| n.id.to_string().starts_with("bitflags"))
414 .unwrap();
415 assert_eq!(bitflags.features, vec!["default"]);
416
417 let featdep = resolve
418 .nodes
419 .iter()
420 .find(|n| n.id.to_string().starts_with("featdep"))
421 .unwrap();
422 assert_eq!(featdep.features, vec!["i128"]);
423
424 let all = resolve
425 .nodes
426 .iter()
427 .find(|n| n.id.to_string().starts_with("all"))
428 .unwrap();
429 assert_eq!(all.dependencies.len(), 8);
430 assert_eq!(all.deps.len(), 8);
431 let newname = all.deps.iter().find(|d| d.name == "newname").unwrap();
432 assert!(newname.pkg.to_string().starts_with("oldname"));
433 // Note the underscore here.
434 let path_dep = all.deps.iter().find(|d| d.name == "path_dep").unwrap();
435 assert!(path_dep.pkg.to_string().starts_with("path-dep"));
436 assert_eq!(path_dep.dep_kinds.len(), 1);
437 let kind = &path_dep.dep_kinds[0];
438 assert_eq!(kind.kind, DependencyKind::Normal);
439 assert!(kind.target.is_none());
440
441 let namedep = all
442 .deps
443 .iter()
444 .find(|d| d.name == "different_name")
445 .unwrap();
446 assert!(namedep.pkg.to_string().starts_with("namedep"));
447 assert_eq!(sorted!(all.features), vec!["bitflags", "default", "feat1"]);
448
449 let bdep = all.deps.iter().find(|d| d.name == "bdep").unwrap();
450 assert_eq!(bdep.dep_kinds.len(), 1);
451 let kind = &bdep.dep_kinds[0];
452 assert_eq!(kind.kind, DependencyKind::Build);
453 assert!(kind.target.is_none());
454
455 let devdep = all.deps.iter().find(|d| d.name == "devdep").unwrap();
456 assert_eq!(devdep.dep_kinds.len(), 1);
457 let kind = &devdep.dep_kinds[0];
458 assert_eq!(kind.kind, DependencyKind::Development);
459 assert!(kind.target.is_none());
460
461 let windep = all.deps.iter().find(|d| d.name == "windep").unwrap();
462 assert_eq!(windep.dep_kinds.len(), 1);
463 let kind = &windep.dep_kinds[0];
464 assert_eq!(kind.kind, DependencyKind::Normal);
465 assert_eq!(
466 kind.target.as_ref().map(|x| x.to_string()),
467 Some("cfg(windows)".to_string())
468 );
ed00b5ec
FG
469
470 let serialized = serde_json::to_value(meta).unwrap();
471 if ver >= semver::Version::parse("1.71.0").unwrap() {
472 assert!(serialized.as_object().unwrap()["workspace_default_members"]
473 .as_array()
474 .is_some());
475 } else {
476 assert!(!serialized
477 .as_object()
478 .unwrap()
479 .contains_key("workspace_default_members"));
480 }
3c0e092e
XL
481}
482
483#[test]
484fn alt_registry() {
485 // This is difficult to test (would need to set up a custom index).
486 // Just manually check the JSON is handled.
487 let json = r#"
488{
489 "packages": [
490 {
491 "name": "alt",
492 "version": "0.1.0",
493 "id": "alt 0.1.0 (path+file:///alt)",
494 "source": null,
495 "dependencies": [
496 {
497 "name": "alt2",
498 "source": "registry+https://example.com",
499 "req": "^0.1",
500 "kind": null,
501 "rename": null,
502 "optional": false,
503 "uses_default_features": true,
504 "features": [],
505 "target": null,
506 "registry": "https://example.com"
507 }
508 ],
509 "targets": [
510 {
511 "kind": [
512 "lib"
513 ],
514 "crate_types": [
515 "lib"
516 ],
517 "name": "alt",
518 "src_path": "/alt/src/lib.rs",
519 "edition": "2018"
520 }
521 ],
522 "features": {},
523 "manifest_path": "/alt/Cargo.toml",
524 "metadata": null,
525 "authors": [],
526 "categories": [],
527 "keywords": [],
528 "readme": null,
529 "repository": null,
530 "edition": "2018",
531 "links": null
532 }
533 ],
534 "workspace_members": [
535 "alt 0.1.0 (path+file:///alt)"
536 ],
537 "resolve": null,
538 "target_directory": "/alt/target",
539 "version": 1,
540 "workspace_root": "/alt"
541}
542"#;
543 let meta: Metadata = serde_json::from_str(json).unwrap();
544 assert_eq!(meta.packages.len(), 1);
545 let alt = &meta.packages[0];
546 let deps = &alt.dependencies;
547 assert_eq!(deps.len(), 1);
548 let dep = &deps[0];
549 assert_eq!(dep.registry, Some("https://example.com".to_string()));
550}
551
552#[test]
553fn current_dir() {
554 let meta = MetadataCommand::new()
555 .current_dir("tests/all/namedep")
556 .exec()
557 .unwrap();
558 let namedep = meta.packages.iter().find(|p| p.name == "namedep").unwrap();
559 assert!(namedep.name.starts_with("namedep"));
560}
561
562#[test]
563fn parse_stream_is_robust() {
564 // Proc macros can print stuff to stdout, which naturally breaks JSON messages.
565 // Let's check that we don't die horribly in this case, and report an error.
9ffffee4 566 let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false}
3c0e092e 567Evil proc macro was here!
9ffffee4 568{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false}
3c0e092e
XL
569"##;
570 let mut n_messages = 0;
571 let mut text = String::new();
572 for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) {
573 let message = message.unwrap();
574 match message {
575 cargo_metadata::Message::TextLine(line) => text = line,
576 _ => n_messages += 1,
577 }
578 }
579 assert_eq!(n_messages, 2);
580 assert_eq!(text, "Evil proc macro was here!");
581}
582
583#[test]
584fn advanced_feature_configuration() {
585 fn build_features<F: FnOnce(&mut MetadataCommand) -> &mut MetadataCommand>(
586 func: F,
587 ) -> Vec<String> {
588 let mut meta = MetadataCommand::new();
589 let meta = meta.manifest_path("tests/all/Cargo.toml");
590
591 let meta = func(meta);
592 let meta = meta.exec().unwrap();
593
594 let resolve = meta.resolve.as_ref().unwrap();
595
596 let all = resolve
597 .nodes
598 .iter()
599 .find(|n| n.id.to_string().starts_with("all"))
600 .unwrap();
601
602 all.features.clone()
603 }
604
605 // Default behavior; tested above
606 let default_features = build_features(|meta| meta);
607 assert_eq!(
608 sorted!(default_features),
609 vec!["bitflags", "default", "feat1"]
610 );
611
612 // Manually specify the same default features
613 let manual_features = build_features(|meta| {
614 meta.features(CargoOpt::NoDefaultFeatures)
615 .features(CargoOpt::SomeFeatures(vec![
616 "feat1".into(),
617 "bitflags".into(),
618 ]))
619 });
620 assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]);
621
622 // Multiple SomeFeatures is same as one longer SomeFeatures
623 let manual_features = build_features(|meta| {
624 meta.features(CargoOpt::NoDefaultFeatures)
625 .features(CargoOpt::SomeFeatures(vec!["feat1".into()]))
626 .features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
627 });
628 assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]);
629
630 // No features + All features == All features
631 let all_features = build_features(|meta| {
632 meta.features(CargoOpt::AllFeatures)
633 .features(CargoOpt::NoDefaultFeatures)
634 });
635 assert_eq!(
636 sorted!(all_features),
637 vec!["bitflags", "default", "feat1", "feat2"]
638 );
639
640 // The '--all-features' flag supersedes other feature flags
641 let all_flag_variants = build_features(|meta| {
642 meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
643 .features(CargoOpt::NoDefaultFeatures)
644 .features(CargoOpt::AllFeatures)
645 });
646 assert_eq!(sorted!(all_flag_variants), sorted!(all_features));
647}
648
649#[test]
650fn depkind_to_string() {
651 assert_eq!(DependencyKind::Normal.to_string(), "normal");
652 assert_eq!(DependencyKind::Development.to_string(), "dev");
653 assert_eq!(DependencyKind::Build.to_string(), "build");
654 assert_eq!(DependencyKind::Unknown.to_string(), "Unknown");
655}
9ffffee4
FG
656
657#[test]
658fn basic_workspace_root_package_exists() {
659 // First try with dependencies
660 let meta = MetadataCommand::new()
661 .manifest_path("tests/basic_workspace/Cargo.toml")
662 .exec()
663 .unwrap();
664 assert_eq!(meta.root_package().unwrap().name, "ex_bin");
665 // Now with no_deps, it should still work exactly the same
666 let meta = MetadataCommand::new()
667 .manifest_path("tests/basic_workspace/Cargo.toml")
668 .no_deps()
669 .exec()
670 .unwrap();
671 assert_eq!(
672 meta.root_package()
673 .expect("workspace root still exists when no_deps used")
674 .name,
675 "ex_bin"
676 );
677}
781aab86
FG
678
679#[test]
680fn debuginfo_variants() {
681 // Checks behavior for the different debuginfo variants.
682 let variants = [
683 ("0", ArtifactDebuginfo::None),
684 ("1", ArtifactDebuginfo::Limited),
685 ("2", ArtifactDebuginfo::Full),
686 (
687 "\"line-directives-only\"",
688 ArtifactDebuginfo::LineDirectivesOnly,
689 ),
690 ("\"line-tables-only\"", ArtifactDebuginfo::LineTablesOnly),
691 ("3", ArtifactDebuginfo::UnknownInt(3)),
692 (
693 "\"abc\"",
694 ArtifactDebuginfo::UnknownString("abc".to_string()),
695 ),
696 ("null", ArtifactDebuginfo::None),
697 ];
698 for (value, expected) in variants {
699 let s = r#"{"reason":"compiler-artifact","package_id":"cargo_metadata 0.16.0 (path+file:////cargo_metadata)","manifest_path":"/cargo_metadata/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cargo_metadata","src_path":"/cargo_metadata/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":DEBUGINFO,"debug_assertions":true,"overflow_checks":true,"test":false},"features":["default"],"filenames":["/cargo_metadata/target/debug/deps/libcargo_metadata-27f582f7187b9a2c.rmeta"],"executable":null,"fresh":false}"#;
700 let message: Message = serde_json::from_str(&s.replace("DEBUGINFO", value)).unwrap();
701 match message {
702 Message::CompilerArtifact(artifact) => {
703 assert_eq!(artifact.profile.debuginfo, expected);
704 let de_s = serde_json::to_string(&artifact.profile.debuginfo).unwrap();
705 // Note: Roundtrip does not retain null value.
706 if value == "null" {
707 assert_eq!(artifact.profile.debuginfo.to_string(), "0");
708 assert_eq!(de_s, "0");
709 } else {
710 assert_eq!(
711 artifact.profile.debuginfo.to_string(),
712 value.trim_matches('"')
713 );
714 assert_eq!(de_s, value);
715 }
716 }
717 _ => panic!("unexpected {:?}", message),
718 }
719 }
720}
ed00b5ec
FG
721
722#[test]
723#[should_panic = "WorkspaceDefaultMembers should only be dereferenced on Cargo versions >= 1.71"]
724fn missing_workspace_default_members() {
725 let meta: Metadata = serde_json::from_str(JSON_OLD_MINIMAL).unwrap();
726 let _ = &*meta.workspace_default_members;
727}