1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use std::{ffi::OsStr, process::Stdio, time::Duration};
use tokio::{
    io::{AsyncBufReadExt, BufReader},
    process::{Child, Command},
    time::timeout,
};

pub struct Engine {
    pub token: String,
    command: Command,
    child: Option<Child>,
}

impl Engine {
    pub fn new<I, S>(program: &str, args: I) -> Self
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        let secret: String = thread_rng().sample_iter(&Alphanumeric).take(8).collect();
        let token = format!("token:{}", secret);
        let mut command = Command::new(program);
        command
            .arg("--enable-rpc=true")
            .arg(format!("--rpc-secret={}", secret))
            .args(args)
            .stdin(Stdio::null())
            .stderr(Stdio::null())
            .stdout(Stdio::piped());
        Engine {
            token,
            command,
            child: None,
        }
    }
    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
        self.command.arg(arg);
        self
    }
    pub async fn start(&mut self) {
        let mut child = self.command.spawn().unwrap();
        let output = child.stdout.take().unwrap();
        let reader = BufReader::new(output);
        let mut lines = reader.lines();
        let mut result = false;
        timeout(Duration::from_secs(10), async {
            while let Some(line) = lines.next_line().await.unwrap() {
                if line.contains("[ERROR]") {
                    panic!();
                };
                if line.contains("IPv4 RPC: listening on TCP port 6800") {
                    result = true;
                    break;
                }
            }
        })
        .await
        .unwrap();
        if result == false {
            panic!();
        }
        self.child = Some(child);
    }
    pub fn stop(&mut self) {
        if let Some(child) = &mut self.child {
            child.kill().unwrap();
        }
    }
}