aboutsummaryrefslogtreecommitdiffstats
path: root/tests/pipe.rs
blob: e09334bc93b37573c4b25854bcb3972ee0b64cd1 (plain) (blame)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#[test]
fn test_pipe_basic() {
    use std::os::unix::io::FromRawFd as _;

    let (read_fd, write_fd) =
        nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();

    let mut child_from = std::process::Command::new("seq");
    child_from.args(["1", "10"]);
    child_from.stdout(unsafe { std::process::Stdio::from_raw_fd(write_fd) });

    let mut child_to = std::process::Command::new("tac");
    child_to.stdin(unsafe { std::process::Stdio::from_raw_fd(read_fd) });
    child_to.stdout(std::process::Stdio::piped());

    assert!(child_from.status().unwrap().success());
    drop(child_from);
    let output = child_to.output().unwrap();
    assert!(output.status.success());
    assert_eq!(output.stdout, b"10\n9\n8\n7\n6\n5\n4\n3\n2\n1\n");
}

#[test]
fn test_pipe_blocking() {
    use std::io::Read as _;
    use std::os::unix::io::FromRawFd as _;

    let (read_fd, write_fd) =
        nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();

    let pty_from = pty_process::blocking::Pty::new().unwrap();
    let pts_from = pty_from.pts().unwrap();
    pty_from.resize(pty_process::Size::new(24, 80)).unwrap();
    let mut cmd_from = pty_process::blocking::Command::new("seq");
    cmd_from.args(["1", "10"]);
    cmd_from.stdout(unsafe { std::process::Stdio::from_raw_fd(write_fd) });
    let mut child_from = cmd_from.spawn(&pts_from).unwrap();

    let mut pty_to = pty_process::blocking::Pty::new().unwrap();
    let pts_to = pty_to.pts().unwrap();
    let mut cmd_to = pty_process::blocking::Command::new("tac");
    cmd_to.stdin(unsafe { std::process::Stdio::from_raw_fd(read_fd) });
    let mut child_to = cmd_to.spawn(&pts_to).unwrap();

    assert!(child_from.wait().unwrap().success());
    drop(cmd_from);

    // wait for the `tac` process to finish generating output (we don't really
    // have a good way to detect when that happens)
    std::thread::sleep(std::time::Duration::from_millis(100));

    let mut buf = [0u8; 1024];
    let bytes = pty_to.read(&mut buf).unwrap();
    assert_eq!(
        &buf[..bytes],
        b"10\r\n9\r\n8\r\n7\r\n6\r\n5\r\n4\r\n3\r\n2\r\n1\r\n"
    );

    assert!(child_to.wait().unwrap().success());
}

#[cfg(feature = "async")]
#[test]
fn test_pipe_async() {
    use std::os::unix::io::FromRawFd as _;
    use tokio::io::AsyncReadExt as _;

    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            let (read_fd, write_fd) =
                nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();

            let pty_from = pty_process::Pty::new().unwrap();
            let pts_from = pty_from.pts().unwrap();
            pty_from.resize(pty_process::Size::new(24, 80)).unwrap();
            let mut cmd_from = pty_process::Command::new("seq");
            cmd_from.args(["1", "10"]);
            cmd_from.stdout(unsafe {
                std::process::Stdio::from_raw_fd(write_fd)
            });
            let mut child_from = cmd_from.spawn(&pts_from).unwrap();

            let mut pty_to = pty_process::Pty::new().unwrap();
            let pts_to = pty_to.pts().unwrap();
            let mut cmd_to = pty_process::Command::new("tac");
            cmd_to
                .stdin(unsafe { std::process::Stdio::from_raw_fd(read_fd) });
            let mut child_to = cmd_to.spawn(&pts_to).unwrap();

            assert!(child_from.wait().await.unwrap().success());
            drop(cmd_from);

            // wait for the `tac` process to finish generating output (we
            // don't really have a good way to detect when that happens)
            tokio::time::sleep(std::time::Duration::from_millis(100)).await;

            let mut buf = [0u8; 1024];
            let bytes = pty_to.read(&mut buf).await.unwrap();
            assert_eq!(
                &buf[..bytes],
                b"10\r\n9\r\n8\r\n7\r\n6\r\n5\r\n4\r\n3\r\n2\r\n1\r\n"
            );

            assert!(child_to.wait().await.unwrap().success());
        });
}