char/avril

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

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

Charlotte Somsnapshot: embed shared main and worker startup in the CLI688e96e

main
2.1 KiB70 linesraw
1#![allow(dead_code)]
2// Shared across test targets; each uses only part of this module.
3use std::fs;
4use std::io::{Read, Write};
5use std::process::{Child, Command, Output, Stdio};
6use std::time::{Duration, Instant};
7
8pub fn spawn(source: &str) -> (tempfile::TempDir, Child) {
9    let dir = tempfile::tempdir().unwrap();
10    let path = dir.path().join("main.js");
11    fs::write(&path, source).unwrap();
12    let child = Command::new(env!("CARGO_BIN_EXE_avril"))
13        .arg("run")
14        .arg(path)
15        .stdin(Stdio::piped())
16        .stdout(Stdio::piped())
17        .stderr(Stdio::piped())
18        .spawn()
19        .unwrap();
20    (dir, child)
21}
22
23fn capture(mut pipe: impl Read + Send + 'static) -> std::thread::JoinHandle<Vec<u8>> {
24    std::thread::spawn(move || {
25        let mut bytes = Vec::new();
26        pipe.read_to_end(&mut bytes).unwrap();
27        bytes
28    })
29}
30
31pub fn wait(mut child: Child) -> Output {
32    let stdout = child.stdout.take().map(capture);
33    let stderr = child.stderr.take().map(capture);
34    let deadline = Instant::now() + Duration::from_secs(5);
35    let status = loop {
36        if let Some(status) = child.try_wait().unwrap() {
37            break status;
38        }
39        if Instant::now() >= deadline {
40            child.kill().unwrap();
41            child.wait().unwrap();
42            panic!("Runtime did not exit within five seconds");
43        }
44        std::thread::sleep(Duration::from_millis(10));
45    };
46    Output {
47        status,
48        stdout: stdout
49            .map(|thread| thread.join().unwrap())
50            .unwrap_or_default(),
51        stderr: stderr
52            .map(|thread| thread.join().unwrap())
53            .unwrap_or_default(),
54    }
55}
56
57pub fn run(source: &str, input: &[u8]) -> Output {
58    let (_dir, mut child) = spawn(source);
59    let mut stdin = child.stdin.take().unwrap();
60    let input = input.to_vec();
61    let writer = std::thread::spawn(move || stdin.write_all(&input));
62    let output = wait(child);
63    writer.join().unwrap().unwrap();
64    assert!(
65        output.status.success(),
66        "{}",
67        String::from_utf8_lossy(&output.stderr)
68    );
69    output
70}