2 # test for basic tee functionality.
4 # Copyright (C) 2005-2024 Free Software Foundation, Inc.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <https://www.gnu.org/licenses/>.
19 .
"${srcdir=.}/tests/init.sh"; path_prepend_ .
/src
22 echo line
>sample || framework_failure_
24 # POSIX says: "Processing of at least 13 file operands shall be supported."
25 for n
in 0 1 2 12 13; do
28 tee $files <sample
>out || fail
=1
29 for f
in out
$files; do
30 compare sample
$f || fail
=1
34 # Ensure tee treats '-' as the name of a file, as mandated by POSIX.
35 # Between v5.3.0 and v8.23, a '-' argument caused tee to send another
36 # copy of input to standard output.
37 tee - <sample
>out
2>err || fail
=1
38 compare sample .
/- || fail
=1
39 compare sample out || fail
=1
40 compare
/dev
/null err || fail
=1
42 # Ensure tee exits early if no more writable outputs
43 if test -w /dev
/full
&& test -c /dev
/full
; then
44 yes | returns_
1 timeout
10 tee /dev
/full
2>err
>/dev
/full || fail
=1
45 # Ensure an error for each of the 2 outputs
46 # (and no redundant errors for stdout).
47 test $
(wc -l < err
) = 2 ||
{ cat err
; fail
=1; }
50 # Ensure we continue with outputs that are OK
51 seq 10000 > multi_read || framework_failure_
53 returns_
1 tee /dev
/full out2
2>err
>out1
<multi_read || fail
=1
54 cmp multi_read out1 || fail
=1
55 cmp multi_read out2 || fail
=1
56 # Ensure an error for failing output
57 test $
(wc -l < err
) = 1 ||
{ cat err
; fail
=1; }
59 returns_
1 tee out1 out2
2>err
>/dev
/full
<multi_read || fail
=1
60 cmp multi_read out1 || fail
=1
61 cmp multi_read out2 || fail
=1
62 # Ensure an error for failing output
63 test $
(wc -l < err
) = 1 ||
{ cat err
; fail
=1; }
67 *aix
*) echo 'avoiding due to no way to detect closed outputs on AIX' ;;
69 # Test iopoll-powered early exit for closed pipes
70 tee_exited
() { sleep $1; test -f tee.exited
; }
71 # Currently this functionality is most useful with
72 # intermittent input from a terminal, but here we
73 # use an input pipe that doesn't write anything
74 # but will exit as soon as tee does, or it times out
75 retry_delay_ tee_exited
.1 7 |
# 12.7s (Must be > following timeout)
76 { timeout
10 tee -p 2>err
&& touch tee.exited
; } |
:
77 test $
(wc -l < err
) = 0 ||
{ cat err
; fail
=1; }
78 test -f tee.exited || fail
=1 ;;
81 # Test with unwritable files
82 if ! uid_is_privileged_
; then # root does not get EPERM.
83 touch file.ro || framework_failure_
84 chmod a-w
file.ro || framework_failure_
85 returns_
1 tee -p </dev
/null
file.ro || fail
=1
90 # Ensure tee handles nonblocking output correctly
91 # Terminate any background processes
92 cleanup_
() { kill $pid 2>/dev
/null
&& wait $pid; }
94 { sleep .1; timeout
10 dd of
=/dev
/null status
=none
; } <fifo
96 read_fifo_delayed
& pid
=$
!
97 dd count
=20 bs
=100K
if=/dev
/zero status
=none |
99 dd count
=0 oflag
=nonblock status
=none
100 tee ||
{ cleanup_
; touch tee.fail
; }
102 test -f tee.fail
&& fail
=1 || cleanup_
104 # Ensure tee honors --output-error modes
105 read_fifo
() { timeout
10 dd count
=1 if=fifo of
=/dev
/null status
=none
& }
107 # Determine platform sigpipe exit status
112 # Default operation is to continue on output errors but exit silently on SIGPIPE
114 yes | returns_
$pipe_status timeout
10 tee .
/e
/noent
2>err
>fifo || fail
=1
115 test $
(wc -l < err
) = 1 ||
{ cat err
; fail
=1; }
117 # With -p, SIGPIPE is suppressed, exit 0 for EPIPE when all outputs finished
119 yes | timeout
10 tee -p 2>err
>fifo || fail
=1
120 test $
(wc -l < err
) = 0 ||
{ cat err
; fail
=1; }
122 # With --output-error=warn, exit 1 for EPIPE when all outputs finished
124 yes | returns_
1 timeout
10 tee --output-error=warn
2>err
>fifo || fail
=1
125 test $
(wc -l < err
) = 1 ||
{ cat err
; fail
=1; }
127 # With --output-error=exit, exit 1 immediately for EPIPE
129 yes | returns_
1 timeout
10 tee --output-error=exit /dev
/null
2>err
>fifo \
131 test $
(wc -l < err
) = 1 ||
{ cat err
; fail
=1; }
133 # With --output-error=exit, exit 1 immediately on output error
135 yes | returns_
1 timeout
10 tee --output-error=exit .
/e
/noent
2>err
>fifo \
137 test $
(wc -l < err
) = 1 ||
{ cat err
; fail
=1; }
139 # With --output-error=exit-nopipe, exit 0 for EPIPE
141 yes | timeout
10 tee --output-error=exit-nopipe
2>err
>fifo || fail
=1
142 test $
(wc -l < err
) = 0 ||
{ cat err
; fail
=1; }