popen.test 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ;;;; popen.test --- exercise ice-9/popen.scm -*- scheme -*-
  2. ;;;;
  3. ;;;; Copyright 2003, 2006 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This library is free software; you can redistribute it and/or
  6. ;;;; modify it under the terms of the GNU Lesser General Public
  7. ;;;; License as published by the Free Software Foundation; either
  8. ;;;; version 2.1 of the License, or (at your option) any later version.
  9. ;;;;
  10. ;;;; This library is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ;;;; Lesser General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU Lesser General Public
  16. ;;;; License along with this library; if not, write to the Free Software
  17. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. (define-module (test-suite test-ice-9-popen)
  19. #:use-module (test-suite lib)
  20. #:use-module (ice-9 popen))
  21. ;; read from PORT until eof is reached, return what's read as a string
  22. (define (read-string-to-eof port)
  23. (do ((lst '() (cons c lst))
  24. (c (read-char port) (read-char port)))
  25. ((eof-object? c)
  26. (list->string (reverse! lst)))))
  27. ;; call (THUNK), with SIGPIPE set to SIG_IGN so that an EPIPE error is
  28. ;; generated rather than a SIGPIPE signal
  29. (define (with-epipe thunk)
  30. (dynamic-wind
  31. (lambda ()
  32. (sigaction SIGPIPE SIG_IGN))
  33. thunk
  34. restore-signals))
  35. ;;
  36. ;; open-input-pipe
  37. ;;
  38. (with-test-prefix "open-input-pipe"
  39. (pass-if-exception "no args" exception:wrong-num-args
  40. (open-input-pipe))
  41. (pass-if "port?"
  42. (port? (open-input-pipe "echo hello")))
  43. (pass-if "echo hello"
  44. (string=? "hello\n" (read-string-to-eof (open-input-pipe "echo hello"))))
  45. ;; exercise file descriptor setups when stdin is the same as stderr
  46. (pass-if "stdin==stderr"
  47. (let ((port (open-file "/dev/null" "r+")))
  48. (with-input-from-port port
  49. (lambda ()
  50. (with-error-to-port port
  51. (lambda ()
  52. (open-input-pipe "echo hello"))))))
  53. #t)
  54. ;; exercise file descriptor setups when stdout is the same as stderr
  55. (pass-if "stdout==stderr"
  56. (let ((port (open-file "/dev/null" "r+")))
  57. (with-output-to-port port
  58. (lambda ()
  59. (with-error-to-port port
  60. (lambda ()
  61. (open-input-pipe "echo hello"))))))
  62. #t)
  63. ;; After the child closes stdout (which it indicates here by writing
  64. ;; "closed" to stderr), the parent should see eof. In Guile 1.6.4 and
  65. ;; earlier a duplicate of stdout existed in the child, meaning eof was not
  66. ;; seen.
  67. (pass-if "no duplicate"
  68. (let* ((pair (pipe))
  69. (port (with-error-to-port (cdr pair)
  70. (lambda ()
  71. (open-input-pipe
  72. "exec 1>/dev/null; echo closed 1>&2; exec 2>/dev/null; sleep 999")))))
  73. (close-port (cdr pair)) ;; write side
  74. (and (char? (read-char (car pair))) ;; wait for child to do its thing
  75. (char-ready? port)
  76. (eof-object? (read-char port))))))
  77. ;;
  78. ;; open-output-pipe
  79. ;;
  80. (with-test-prefix "open-output-pipe"
  81. (pass-if-exception "no args" exception:wrong-num-args
  82. (open-output-pipe))
  83. (pass-if "port?"
  84. (port? (open-output-pipe "exit 0")))
  85. ;; exercise file descriptor setups when stdin is the same as stderr
  86. (pass-if "stdin==stderr"
  87. (let ((port (open-file "/dev/null" "r+")))
  88. (with-input-from-port port
  89. (lambda ()
  90. (with-error-to-port port
  91. (lambda ()
  92. (open-output-pipe "exit 0"))))))
  93. #t)
  94. ;; exercise file descriptor setups when stdout is the same as stderr
  95. (pass-if "stdout==stderr"
  96. (let ((port (open-file "/dev/null" "r+")))
  97. (with-output-to-port port
  98. (lambda ()
  99. (with-error-to-port port
  100. (lambda ()
  101. (open-output-pipe "exit 0"))))))
  102. #t)
  103. ;; After the child closes stdin (which it indicates here by writing
  104. ;; "closed" to stderr), the parent should see a broken pipe. We setup to
  105. ;; see this as EPIPE (rather than SIGPIPE). In Guile 1.6.4 and earlier a
  106. ;; duplicate of stdin existed in the child, preventing the broken pipe
  107. ;; occurring.
  108. (pass-if "no duplicate"
  109. (with-epipe
  110. (lambda ()
  111. (let* ((pair (pipe))
  112. (port (with-error-to-port (cdr pair)
  113. (lambda ()
  114. (open-output-pipe
  115. "exec 0</dev/null; echo closed 1>&2; exec 2>/dev/null; sleep 999")))))
  116. (close-port (cdr pair)) ;; write side
  117. (and (char? (read-char (car pair))) ;; wait for child to do its thing
  118. (catch 'system-error
  119. (lambda ()
  120. (write-char #\x port)
  121. (force-output port)
  122. #f)
  123. (lambda (key name fmt args errno-list)
  124. (= (car errno-list) EPIPE)))))))))
  125. ;;
  126. ;; close-pipe
  127. ;;
  128. (with-test-prefix "close-pipe"
  129. (pass-if-exception "no args" exception:wrong-num-args
  130. (close-pipe))
  131. (pass-if "exit 0"
  132. (let ((st (close-pipe (open-output-pipe "exit 0"))))
  133. (and (status:exit-val st)
  134. (= 0 (status:exit-val st)))))
  135. (pass-if "exit 1"
  136. (let ((st (close-pipe (open-output-pipe "exit 1"))))
  137. (and (status:exit-val st)
  138. (= 1 (status:exit-val st))))))