1use std::process::Command;
2
3#[test]
4fn test_backends() {
5    // Pick an arbitrary platform where linux_raw is enabled by default and
6    // ensure that the use-default crate uses it.
7    #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
8    {
9        assert!(
10            has_dependency(
11                "test-crates/use-default",
12                &[],
13                &[],
14                &["RUSTFLAGS"],
15                "linux-raw-sys"
16            ),
17            "use-default does not depend on linux-raw-sys"
18        );
19    }
20
21    // Pick an arbitrary platform where linux_raw is enabled by default and
22    // ensure that the use-rustix-auxv crate uses it, and does not use libc.
23    #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
24    {
25        // TODO: Re-enable this test once io-lifetimes can depend on Rust 1.63
26        // and always use std, so it can drop its libc dependency.
27        /*
28        assert!(
29            !has_dependency(
30                "test-crates/use-rustix-auxv",
31                &[],
32                &[],
33                &["RUSTFLAGS"],
34                "libc"
35            ),
36            "use-rustix-auxv depends on libc"
37        );
38        */
39
40        assert!(
41            has_dependency(
42                "test-crates/use-rustix-auxv",
43                &[],
44                &[],
45                &["RUSTFLAGS"],
46                "linux-raw-sys"
47            ),
48            "use-rustix-auxv does not depend on linux-raw-sys"
49        );
50    }
51
52    #[cfg(windows)]
53    let libc_dep = "windows-sys";
54    #[cfg(unix)]
55    let libc_dep = "libc";
56
57    // Test the use-libc crate, which enables the "use-libc" cargo feature.
58    assert!(
59        has_dependency("test-crates/use-libc", &[], &[], &["RUSTFLAGS"], libc_dep),
60        "use-libc doesn't depend on {}",
61        libc_dep
62    );
63
64    // Test the use-default crate with `--cfg=rustix_use_libc`.
65    assert!(
66        has_dependency(
67            "test-crates/use-default",
68            &[],
69            &[("RUSTFLAGS", "--cfg=rustix_use_libc")],
70            &[],
71            libc_dep
72        ),
73        "use-default with --cfg=rustix_use_libc does not depend on {}",
74        libc_dep
75    );
76
77    // Test the use-default crate with `--features=rustix/use-libc`.
78    assert!(
79        has_dependency(
80            "test-crates/use-default",
81            &["--features=rustix/use-libc"],
82            &[],
83            &[],
84            libc_dep
85        ),
86        "use-default with --features=rustix/use-libc does not depend on {}",
87        libc_dep
88    );
89}
90
91/// Test whether the crate at directory `dir` has a dependency on `dependency`,
92/// setting the environment variables `envs` and unsetting the environment
93/// variables `remove_envs` when running `cargo`.
94fn has_dependency(
95    dir: &str,
96    args: &[&str],
97    envs: &[(&str, &str)],
98    remove_envs: &[&str],
99    dependency: &str,
100) -> bool {
101    let mut command = Command::new("cargo");
102
103    command
104        .arg("tree")
105        .arg("--quiet")
106        .arg("--edges=normal")
107        .arg(&format!("--invert={}", dependency))
108        .current_dir(dir);
109
110    command.args(args);
111    for (key, value) in envs {
112        command.env(key, value);
113    }
114    for key in remove_envs {
115        command.env_remove(key);
116    }
117
118    let child = command.output().unwrap();
119
120    // `cargo tree --invert=foo` can fail in two different ways: it exits with
121    // a non-zero status if the dependency is not present in the Cargo.toml
122    // configuration, and it exists with a zero status and prints nothing if
123    // the dependency is present but optional and not enabled. So we check for
124    // both here.
125    child.status.success() && !child.stdout.is_empty()
126}
127