1ef40d7f6Sopenharmony_ci#[cfg(test)]
2ef40d7f6Sopenharmony_cimod tidy;
3ef40d7f6Sopenharmony_ci
4ef40d7f6Sopenharmony_ciuse std::time::Instant;
5ef40d7f6Sopenharmony_ci
6ef40d7f6Sopenharmony_ciuse xshell::{cmd, Shell};
7ef40d7f6Sopenharmony_ci
8ef40d7f6Sopenharmony_ciconst MSRV: &str = "1.56.0";
9ef40d7f6Sopenharmony_ci
10ef40d7f6Sopenharmony_cifn main() -> xshell::Result<()> {
11ef40d7f6Sopenharmony_ci    let sh = Shell::new()?;
12ef40d7f6Sopenharmony_ci
13ef40d7f6Sopenharmony_ci    let _e = push_toolchain(&sh, "stable")?;
14ef40d7f6Sopenharmony_ci    let _e = sh.push_env("CARGO", "");
15ef40d7f6Sopenharmony_ci
16ef40d7f6Sopenharmony_ci    {
17ef40d7f6Sopenharmony_ci        let _s = section("BUILD");
18ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo test --workspace --no-run").run()?;
19ef40d7f6Sopenharmony_ci    }
20ef40d7f6Sopenharmony_ci
21ef40d7f6Sopenharmony_ci    {
22ef40d7f6Sopenharmony_ci        let _s = section("TEST");
23ef40d7f6Sopenharmony_ci
24ef40d7f6Sopenharmony_ci        for &release in &[None, Some("--release")] {
25ef40d7f6Sopenharmony_ci            cmd!(sh, "cargo test --features unstable {release...}").run()?;
26ef40d7f6Sopenharmony_ci            cmd!(
27ef40d7f6Sopenharmony_ci                sh,
28ef40d7f6Sopenharmony_ci                "cargo test --no-default-features --features unstable,std,parking_lot {release...}"
29ef40d7f6Sopenharmony_ci            )
30ef40d7f6Sopenharmony_ci            .run()?;
31ef40d7f6Sopenharmony_ci        }
32ef40d7f6Sopenharmony_ci
33ef40d7f6Sopenharmony_ci        // Skip doctests for no_std tests as those don't work
34ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo test --no-default-features --features unstable --test it").run()?;
35ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo test --no-default-features --features unstable,alloc --test it").run()?;
36ef40d7f6Sopenharmony_ci
37ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo test --no-default-features --features critical-section").run()?;
38ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo test --features critical-section").run()?;
39ef40d7f6Sopenharmony_ci    }
40ef40d7f6Sopenharmony_ci
41ef40d7f6Sopenharmony_ci    {
42ef40d7f6Sopenharmony_ci        let _s = section("TEST_BETA");
43ef40d7f6Sopenharmony_ci        let _e = push_toolchain(&sh, "beta")?;
44ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo test --features unstable").run()?;
45ef40d7f6Sopenharmony_ci    }
46ef40d7f6Sopenharmony_ci
47ef40d7f6Sopenharmony_ci    {
48ef40d7f6Sopenharmony_ci        let _s = section("TEST_MSRV");
49ef40d7f6Sopenharmony_ci        let _e = push_toolchain(&sh, MSRV)?;
50ef40d7f6Sopenharmony_ci        sh.copy_file("Cargo.lock.msrv", "Cargo.lock")?;
51ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo build").run()?;
52ef40d7f6Sopenharmony_ci    }
53ef40d7f6Sopenharmony_ci
54ef40d7f6Sopenharmony_ci    {
55ef40d7f6Sopenharmony_ci        let _s = section("TEST_MIRI");
56ef40d7f6Sopenharmony_ci        let miri_nightly= cmd!(sh, "curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri").read()?;
57ef40d7f6Sopenharmony_ci        let _e = push_toolchain(&sh, &format!("nightly-{}", miri_nightly))?;
58ef40d7f6Sopenharmony_ci
59ef40d7f6Sopenharmony_ci        sh.remove_path("./target")?;
60ef40d7f6Sopenharmony_ci
61ef40d7f6Sopenharmony_ci        cmd!(sh, "rustup component add miri").run()?;
62ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo miri setup").run()?;
63ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo miri test --features unstable").run()?;
64ef40d7f6Sopenharmony_ci    }
65ef40d7f6Sopenharmony_ci
66ef40d7f6Sopenharmony_ci    {
67ef40d7f6Sopenharmony_ci        let _s = section("PUBLISH");
68ef40d7f6Sopenharmony_ci
69ef40d7f6Sopenharmony_ci        let version = cmd!(sh, "cargo pkgid").read()?.rsplit_once('#').unwrap().1.to_string();
70ef40d7f6Sopenharmony_ci        let tag = format!("v{version}");
71ef40d7f6Sopenharmony_ci
72ef40d7f6Sopenharmony_ci        let current_branch = cmd!(sh, "git branch --show-current").read()?;
73ef40d7f6Sopenharmony_ci        let has_tag = cmd!(sh, "git tag --list").read()?.lines().any(|it| it.trim() == tag);
74ef40d7f6Sopenharmony_ci        let dry_run = sh.var("CI").is_err() || has_tag || current_branch != "master";
75ef40d7f6Sopenharmony_ci        eprintln!("Publishing{}!", if dry_run { " (dry run)" } else { "" });
76ef40d7f6Sopenharmony_ci
77ef40d7f6Sopenharmony_ci        let dry_run_arg = if dry_run { Some("--dry-run") } else { None };
78ef40d7f6Sopenharmony_ci        cmd!(sh, "cargo publish {dry_run_arg...}").run()?;
79ef40d7f6Sopenharmony_ci        if dry_run {
80ef40d7f6Sopenharmony_ci            eprintln!("{}", cmd!(sh, "git tag {tag}"));
81ef40d7f6Sopenharmony_ci            eprintln!("{}", cmd!(sh, "git push --tags"));
82ef40d7f6Sopenharmony_ci        } else {
83ef40d7f6Sopenharmony_ci            cmd!(sh, "git tag {tag}").run()?;
84ef40d7f6Sopenharmony_ci            cmd!(sh, "git push --tags").run()?;
85ef40d7f6Sopenharmony_ci        }
86ef40d7f6Sopenharmony_ci    }
87ef40d7f6Sopenharmony_ci    Ok(())
88ef40d7f6Sopenharmony_ci}
89ef40d7f6Sopenharmony_ci
90ef40d7f6Sopenharmony_cifn push_toolchain<'a>(
91ef40d7f6Sopenharmony_ci    sh: &'a xshell::Shell,
92ef40d7f6Sopenharmony_ci    toolchain: &str,
93ef40d7f6Sopenharmony_ci) -> xshell::Result<xshell::PushEnv<'a>> {
94ef40d7f6Sopenharmony_ci    cmd!(sh, "rustup toolchain install {toolchain} --no-self-update").run()?;
95ef40d7f6Sopenharmony_ci    let res = sh.push_env("RUSTUP_TOOLCHAIN", toolchain);
96ef40d7f6Sopenharmony_ci    cmd!(sh, "rustc --version").run()?;
97ef40d7f6Sopenharmony_ci    Ok(res)
98ef40d7f6Sopenharmony_ci}
99ef40d7f6Sopenharmony_ci
100ef40d7f6Sopenharmony_cifn section(name: &'static str) -> impl Drop {
101ef40d7f6Sopenharmony_ci    println!("::group::{name}");
102ef40d7f6Sopenharmony_ci    let start = Instant::now();
103ef40d7f6Sopenharmony_ci    defer(move || {
104ef40d7f6Sopenharmony_ci        let elapsed = start.elapsed();
105ef40d7f6Sopenharmony_ci        eprintln!("{name}: {elapsed:.2?}");
106ef40d7f6Sopenharmony_ci        println!("::endgroup::");
107ef40d7f6Sopenharmony_ci    })
108ef40d7f6Sopenharmony_ci}
109ef40d7f6Sopenharmony_ci
110ef40d7f6Sopenharmony_cifn defer<F: FnOnce()>(f: F) -> impl Drop {
111ef40d7f6Sopenharmony_ci    struct D<F: FnOnce()>(Option<F>);
112ef40d7f6Sopenharmony_ci    impl<F: FnOnce()> Drop for D<F> {
113ef40d7f6Sopenharmony_ci        fn drop(&mut self) {
114ef40d7f6Sopenharmony_ci            if let Some(f) = self.0.take() {
115ef40d7f6Sopenharmony_ci                f()
116ef40d7f6Sopenharmony_ci            }
117ef40d7f6Sopenharmony_ci        }
118ef40d7f6Sopenharmony_ci    }
119ef40d7f6Sopenharmony_ci    D(Some(f))
120ef40d7f6Sopenharmony_ci}
121