summaryrefslogtreecommitdiff
path: root/tests/xargs/conflicting_opts.sh
blob: 95ea75af498adca29743917c588fbb63bd800a5f (plain)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/bin/sh
# Test mutually exclusive options --max-args, --max-lines, --replace, and
# their short-option aliases (-L, -l -I -i -n).

# Copyright (C) 2021-2022 Free Software Foundation, Inc.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

. "${srcdir=.}/tests/init.sh"
print_ver_ xargs

# The idea behind: when using the mutually exclusive options, the last one
# specified overrides the values of the previous ones.  Or to put it in
# other words: the resulting output (and exit code btw.) is the same as if
# the earlier, conflicting options had not been passed - apart from the
# error diagnostic for every overridden option.

# Create some input file.
cat <<\EOF > in || framework_failure_
a b c
d e f
g h i
EOF

WARNFMT='xargs: warning: options %s and %s are mutually exclusive, ignoring previous %s value'

str4opt() {
  case "$1" in
  -n*|--max-args*) echo '--max-args/-n';;
  -l*|--max-lines*) echo '--max-lines/-l';;
  -i|-I*|--replace*) echo '--replace/-I/-i';;
  esac
}
lopt4opt() {
  case "$1" in
  -n*|--max-args*) echo '--max-args';;
  -l*|--max-lines*) echo '--max-lines';;
  -i|-I*|--replace*) echo '--replace';;
  esac
}

gen_err() {  # see warn_mutually_exclusive in xargs.c.
  s="$(str4opt "$1")" || framework_failure_
  l="$(lopt4opt "$2")" || framework_failure_

  printf "$WARNFMT\n" "$l" "$s" "$l"
}

# test_xargs a test case, using $1 as the last option which should finally override
# any other of the mutually exclusive options.
# Example: test_xargs -n2 OTHER_OPTION
# This will invoke 'xargs' with that option as the last one:
#   xargs OTHER_OPTION -n2
test_xargs() {
  rm -f out err err2 expout experr || framework_failure_

  # Generate the expected output file for the option in "$1".
  # test_xargs xargs with that option only; stderr should be empty
  # and stdout of this test_xargs is the reference for the actual test.
  last_opt="$1" \
    && shift 1 \
    && xargs "$last_opt" < in > expout 2>err \
    && compare /dev/null err \
    || framework_failure_

  # Generate the expected error diagnostic for the mutually exclusive option
  # passed earlier.  No diagnostic if the previous mutually-exclusive option
  # is the same as the current one.
  prev_excl_option=  # variable for previous mutually-exclusive option.
  for o in "$@" "$last_opt"; do
    lopt="$(lopt4opt "$o")" || framework_failure_
    case $o in -n*|--max-args*|-l*|--max-lines*|-i|-I*|--replace*)
      test "$prev_excl_option" != '' \
        && test "$prev_excl_option" != "$lopt" \
        && gen_err "$o" "$prev_excl_option"
      prev_excl_option="$lopt"
      ;;
    esac
  done > experr

  # test_xargs the test.
  xargs "$@" "$last_opt" < in > out 2>err || fail=1
  sed 's/^.*\(xargs:\)/&/' err > err2 || framework_failure_
  compare expout out || fail=1
  compare experr err2 || fail=1
}

# test_xargs the tests for --max-args as last option.
for last_opt in -n2 --max-args=2; do
  for other_opt in --max-lines=2 -l2 --replace='REPL' -I'REPL' -i; do
    test_xargs $last_opt $other_opt
  done
done

# test_xargs the tests for --max-line as last option.
for last_opt in -l2 --max-lines=2; do
  for other_opt in --max-args=2 -n2 --replace='REPL' -I'REPL' -i; do
    test_xargs $last_opt $other_opt
  done
done

# test_xargs the tests for --replace as last option.
for last_opt in --replace='REPL' -I'REPL' -i; do
  for other_opt in --max-args=2 -n2 -l2 --max-lines=2; do
    test_xargs $last_opt $other_opt
  done
done

# Finally do some multi-option tests.
# Test 'xargs -l2 -l3 -l4 -i -n2':
# diagnostic for -l once, then for -i being overridden.
test_xargs -n2   -l2 -l3 -l4 -i

# Test 'xargs -n2 -i -l4 -l5': diagnostic for -n, then once for -i.
test_xargs -l5   -n2 -i -l4

# Test 'xargs -l2 --max-lines=3 --replace=4 -I5 --max-args=6 -n7 -n1':
# Diagnostic for the change from MAX-LINES to REPLACE,
# then from REPLACE to MAX-ARGS.
test_xargs -n1 -l2 --max-lines=3 --replace=4 -I5 --max-args=6 -n7

# Test 'xargs --replace=REPL -n1': verify that it doesn't emit the warning.
# See discussion at: https://sv.gnu.org/patch/?1500
xargs -I_ echo 'a._.b' < in > expout 2>err \
  && compare /dev/null err \
  || framework_failure_

xargs -I_ -n1 echo 'a._.b' < in > out 2>err || fail=1
compare expout out || fail=1
compare /dev/null err || fail=1

Exit $fail