char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somsnapshot: prepare typed ops and static/live bootstrap711e4d5

main
2.2 KiB65 linesraw
1//! Snapshot tests run their bodies in child processes: V8 shares one read-only heap
2//! between all live isolates of a process, so tests sharing a process would race on it.
3
4#![allow(dead_code)]
5
6use std::path::PathBuf;
7use std::process::{Command, Stdio};
8use std::time::{Duration, Instant};
9
10const ROLE: &str = "AVRIL_CORE_TEST_ROLE";
11const DIRECTORY: &str = "AVRIL_CORE_TEST_DIRECTORY";
12
13/// The role this process was spawned for, if it is a test child.
14pub fn role() -> Option<String> {
15    std::env::var(ROLE).ok()
16}
17
18/// The parent's scratch directory, shared by every role of one test.
19pub fn directory() -> PathBuf {
20    PathBuf::from(std::env::var_os(DIRECTORY).unwrap())
21}
22
23/// Run `test` in a child process with `role`, and return its output.
24pub fn child(test: &str, role: &str, directory: &std::path::Path) -> String {
25    let log = tempfile::NamedTempFile::new().unwrap();
26    let mut child = Command::new(std::env::current_exe().unwrap())
27        .args(["--exact", test, "--nocapture", "--test-threads=1"])
28        .env(ROLE, role)
29        .env(DIRECTORY, directory)
30        .stdin(Stdio::null())
31        .stdout(log.as_file().try_clone().unwrap())
32        .stderr(log.as_file().try_clone().unwrap())
33        .spawn()
34        .unwrap();
35    let deadline = Instant::now() + Duration::from_secs(60);
36    let status = loop {
37        if let Some(status) = child.try_wait().unwrap() {
38            break status;
39        }
40        if Instant::now() >= deadline {
41            child.kill().unwrap();
42            child.wait().unwrap();
43            panic!(
44                "{test} {role} timed out:\n{}",
45                std::fs::read_to_string(log.path()).unwrap()
46            );
47        }
48        std::thread::sleep(Duration::from_millis(10));
49    };
50    let output = std::fs::read_to_string(log.path()).unwrap();
51    assert!(status.success(), "{test} {role}: {status}\n{output}");
52    assert!(
53        output.contains("1 passed; 0 failed"),
54        "{test} {role}: child filter did not run its test:\n{output}"
55    );
56    output
57}
58
59/// Run each role of `test` in its own child process, in order.
60pub fn roles(test: &str, roles: &[&str]) {
61    let directory = tempfile::tempdir().unwrap();
62    for role in roles {
63        child(test, role, directory.path());
64    }
65}