File: test_lwt_process.ml

package info (click to toggle)
lwt 5.9.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,284 kB
  • sloc: ml: 22,030; ansic: 7,167; makefile: 92; python: 62
file content (107 lines) | stat: -rw-r--r-- 3,476 bytes parent folder | download | duplicates (3)
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
(* This file is part of Lwt, released under the MIT license. See LICENSE.md for
   details, or visit https://github.com/ocsigen/lwt/blob/master/LICENSE.md. *)



open Test
open Lwt.Infix

let expected_str = "the quick brown fox jumps over the lazy dog"
let expected = Bytes.of_string expected_str
let expected_len = Bytes.length expected

let check_status ?(status=(=) 0) = function
  | Unix.WEXITED n when status n -> Lwt.return_true
  | Unix.WEXITED n ->
    Printf.eprintf "exited with code %d" n;
    Lwt.return_false
  | Unix.WSIGNALED x ->
    Printf.eprintf "failed with signal %d" x;
    Lwt.return_false
  | Unix.WSTOPPED x ->
    Printf.eprintf "stopped with signal %d" x;
    Lwt.return_false

let pwrite ~stdin pout =
  let args = [|"dummy.exe"; "read"|] in
  let proc = Lwt_process.exec ~stdin ("./dummy.exe", args) in
  let write = Lwt.finalize
                (fun () -> Lwt_unix.write pout expected 0 expected_len)
                (fun () -> Lwt_unix.close pout) in
  proc >>= fun r ->
  write >>= fun n ->
  assert (n = expected_len);
  check_status r

let pread ?stdout ?stderr pin =
  let buf = Bytes.create expected_len in
  let proc = match stdout, stderr with
    | Some stdout, None ->
       let args = [|"dummy.exe"; "write"|] in
       Lwt_process.exec ~stdout ("./dummy.exe", args)
    | None, Some stderr ->
       let args = [|"dummy.exe"; "errwrite"|] in
       Lwt_process.exec ~stderr ("./dummy.exe", args)
    | _ -> assert false
  in
  let read = Lwt_unix.read pin buf 0 expected_len in
  proc >>= fun r ->
  read >>= fun n ->
  assert (n = expected_len);
  assert (Bytes.equal buf expected);
  Lwt_unix.read pin buf 0 1 >>= fun n ->
  assert (n = 0);
  check_status r

let suite = suite "lwt_process" [
  (* The sleep command is not available on Win32. *)
  test "lazy_undefined" ~only_if:(fun () -> not Sys.win32)
    (fun () ->
      Lwt_process.with_process_in
        ~timeout:1. ("sleep", [| "sleep"; "2" |])
          (fun p ->
            Lwt.catch
              (fun () -> Lwt_io.read p#stdout)
              (fun _ -> Lwt.return ""))
        >>= fun _ -> Lwt.return_true);

  test "subproc stdout can be redirected to null"
    (fun () ->
      let args = [|"dummy.exe"; "write"|] in
      Lwt_process.exec ~stdout:`Dev_null ("./dummy.exe", args)
      >>= check_status);

  test "subproc stderr can be redirected to null"
    (fun () ->
      let args = [|"dummy.exe"; "errwrite"|] in
      Lwt_process.exec ~stderr:`Dev_null ("./dummy.exe", args)
      >>= check_status);

  test "subproc cannot write on closed stdout"
    (fun () ->
      let args = [|"dummy.exe"; "write"|] in
      let stderr = `Dev_null    (* mask subproc stderr *) in
      Lwt_process.exec ~stdout:`Close ~stderr ("./dummy.exe", args)
      >>= check_status ~status:((<>) 0));

  test "subproc cannot write on closed stderr"
    (fun () ->
      let args = [|"dummy.exe"; "errwrite"|] in
      Lwt_process.exec ~stderr:`Close ("./dummy.exe", args)
      >>= check_status ~status:((<>) 0));

  test "can write to subproc stdin"
    (fun () ->
      let pin, pout = Lwt_unix.pipe_out ~cloexec:true () in
      pwrite ~stdin:(`FD_move pin) pout);

  test "can read from subproc stdout"
    (fun () ->
      let pin, pout = Lwt_unix.pipe_in ~cloexec:true () in
      pread ~stdout:(`FD_move pout) pin);

  test "can read from subproc stderr"
    (fun () ->
      let pin, perr = Lwt_unix.pipe_in ~cloexec:true () in
      pread ~stderr:(`FD_move perr) pin);
]