| 1 | #!/usr/bin/env bash |
| 2 | # |
| 3 | # Test set flags, sh flags. |
| 4 | |
| 5 | #### $- with -c |
| 6 | # dash's behavior seems most sensible here? |
| 7 | $SH -o nounset -c 'echo $-' |
| 8 | ## stdout: u |
| 9 | ## OK bash stdout: huBc |
| 10 | ## OK mksh stdout: uhc |
| 11 | ## status: 0 |
| 12 | |
| 13 | #### $- with pipefail |
| 14 | set -o pipefail -o nounset |
| 15 | echo $- |
| 16 | ## stdout: u |
| 17 | ## status: 0 |
| 18 | ## OK bash stdout: huBs |
| 19 | ## OK mksh stdout: ush |
| 20 | ## N-I dash stdout-json: "" |
| 21 | ## N-I dash status: 2 |
| 22 | |
| 23 | #### $- with interactive shell |
| 24 | $SH -c 'echo $-' | grep i || echo FALSE |
| 25 | $SH -i -c 'echo $-' | grep -q i && echo TRUE |
| 26 | ## STDOUT: |
| 27 | FALSE |
| 28 | TRUE |
| 29 | ## END |
| 30 | |
| 31 | #### sh -c |
| 32 | $SH -c 'echo hi' |
| 33 | ## stdout: hi |
| 34 | ## status: 0 |
| 35 | |
| 36 | #### empty -c input |
| 37 | # had a bug here |
| 38 | $SH -c '' |
| 39 | ## stdout-json: "" |
| 40 | ## status: 0 |
| 41 | |
| 42 | #### empty stdin |
| 43 | # had a bug here |
| 44 | echo -n '' | $SH |
| 45 | ## stdout-json: "" |
| 46 | ## status: 0 |
| 47 | |
| 48 | #### args are passed |
| 49 | $SH -c 'argv.py "$@"' dummy a b |
| 50 | ## stdout: ['a', 'b'] |
| 51 | |
| 52 | #### args that look like flags are passed after script |
| 53 | script=$TMP/sh1.sh |
| 54 | echo 'argv.py "$@"' > $script |
| 55 | chmod +x $script |
| 56 | $SH $script --help --help -h |
| 57 | ## stdout: ['--help', '--help', '-h'] |
| 58 | |
| 59 | #### args that look like flags are passed after -c |
| 60 | $SH -c 'argv.py "$@"' --help --help -h |
| 61 | ## stdout: ['--help', '-h'] |
| 62 | |
| 63 | #### pass short options on command line |
| 64 | $SH -e -c 'false; echo status=$?' |
| 65 | ## stdout-json: "" |
| 66 | ## status: 1 |
| 67 | |
| 68 | #### pass long options on command line |
| 69 | $SH -o errexit -c 'false; echo status=$?' |
| 70 | ## stdout-json: "" |
| 71 | ## status: 1 |
| 72 | |
| 73 | #### can continue after unknown option |
| 74 | # dash and mksh make this a fatal error no matter what. |
| 75 | set -o errexit |
| 76 | set -o STRICT || true # unknown option |
| 77 | echo hello |
| 78 | ## stdout: hello |
| 79 | ## status: 0 |
| 80 | ## BUG dash/mksh stdout-json: "" |
| 81 | ## BUG dash status: 2 |
| 82 | ## BUG mksh status: 1 |
| 83 | |
| 84 | #### set with both options and argv |
| 85 | set -o errexit a b c |
| 86 | echo "$@" |
| 87 | false |
| 88 | echo done |
| 89 | ## stdout: a b c |
| 90 | ## status: 1 |
| 91 | |
| 92 | #### set -o vi/emacs |
| 93 | set -o vi |
| 94 | echo $? |
| 95 | set -o emacs |
| 96 | echo $? |
| 97 | ## STDOUT: |
| 98 | 0 |
| 99 | 0 |
| 100 | ## END |
| 101 | |
| 102 | #### nounset |
| 103 | echo "[$unset]" |
| 104 | set -o nounset |
| 105 | echo "[$unset]" |
| 106 | echo end # never reached |
| 107 | ## stdout: [] |
| 108 | ## status: 1 |
| 109 | ## OK dash status: 2 |
| 110 | |
| 111 | #### -u is nounset |
| 112 | echo "[$unset]" |
| 113 | set -u |
| 114 | echo "[$unset]" |
| 115 | echo end # never reached |
| 116 | ## stdout: [] |
| 117 | ## status: 1 |
| 118 | ## OK dash status: 2 |
| 119 | |
| 120 | #### nounset with "$@" |
| 121 | set a b c |
| 122 | set -u # shouldn't touch argv |
| 123 | echo "$@" |
| 124 | ## stdout: a b c |
| 125 | |
| 126 | #### set -u -- clears argv |
| 127 | set a b c |
| 128 | set -u -- # shouldn't touch argv |
| 129 | echo "$@" |
| 130 | ## stdout: |
| 131 | |
| 132 | #### set -u -- x y z |
| 133 | set a b c |
| 134 | set -u -- x y z |
| 135 | echo "$@" |
| 136 | ## stdout: x y z |
| 137 | |
| 138 | #### reset option with long flag |
| 139 | set -o errexit |
| 140 | set +o errexit |
| 141 | echo "[$unset]" |
| 142 | ## stdout: [] |
| 143 | ## status: 0 |
| 144 | |
| 145 | #### reset option with short flag |
| 146 | set -u |
| 147 | set +u |
| 148 | echo "[$unset]" |
| 149 | ## stdout: [] |
| 150 | ## status: 0 |
| 151 | |
| 152 | #### set -eu (flag parsing) |
| 153 | set -eu |
| 154 | echo "[$unset]" |
| 155 | echo status=$? |
| 156 | ## stdout-json: "" |
| 157 | ## status: 1 |
| 158 | ## OK dash status: 2 |
| 159 | |
| 160 | #### -n for no execution (useful with --ast-output) |
| 161 | # NOTE: set +n doesn't work because nothing is executed! |
| 162 | echo 1 |
| 163 | set -n |
| 164 | echo 2 |
| 165 | set +n |
| 166 | echo 3 |
| 167 | ## stdout-json: "1\n" |
| 168 | ## status: 0 |
| 169 | |
| 170 | #### pipefail |
| 171 | # NOTE: the sleeps are because osh can fail non-deterministically because of a |
| 172 | # bug. Same problem as PIPESTATUS. |
| 173 | { sleep 0.01; exit 9; } | { sleep 0.02; exit 2; } | { sleep 0.03; exit 0; } |
| 174 | echo $? |
| 175 | set -o pipefail |
| 176 | { sleep 0.01; exit 9; } | { sleep 0.02; exit 2; } | { sleep 0.03; exit 0; } |
| 177 | echo $? |
| 178 | ## stdout-json: "0\n2\n" |
| 179 | ## status: 0 |
| 180 | ## N-I dash stdout-json: "0\n" |
| 181 | ## N-I dash status: 2 |
| 182 | |
| 183 | #### shopt -p -o |
| 184 | shopt -po nounset |
| 185 | set -u |
| 186 | shopt -po nounset |
| 187 | ## stdout-json: "set +o nounset\nset -o nounset\n" |
| 188 | ## N-I dash/mksh stdout-json: "" |
| 189 | ## N-I dash/mksh status: 127 |
| 190 | |
| 191 | #### shopt -p |
| 192 | shopt -p nullglob |
| 193 | shopt -s nullglob |
| 194 | shopt -p nullglob |
| 195 | ## stdout-json: "shopt -u nullglob\nshopt -s nullglob\n" |
| 196 | ## N-I dash/mksh stdout-json: "" |
| 197 | ## N-I dash/mksh status: 127 |
| 198 | |
| 199 | #### noclobber off |
| 200 | set -o errexit |
| 201 | echo foo > $TMP/can-clobber |
| 202 | set +C |
| 203 | echo foo > $TMP/can-clobber |
| 204 | set +o noclobber |
| 205 | echo foo > $TMP/can-clobber |
| 206 | cat $TMP/can-clobber |
| 207 | ## stdout: foo |
| 208 | |
| 209 | #### noclobber on |
| 210 | # Not implemented yet. |
| 211 | rm $TMP/no-clobber |
| 212 | set -C |
| 213 | echo foo > $TMP/no-clobber |
| 214 | echo $? |
| 215 | echo foo > $TMP/no-clobber |
| 216 | echo $? |
| 217 | ## stdout-json: "0\n1\n" |
| 218 | ## OK dash stdout-json: "0\n2\n" |
| 219 | |
| 220 | #### SHELLOPTS is updated when options are changed |
| 221 | echo $SHELLOPTS | grep -q xtrace |
| 222 | echo $? |
| 223 | set -x |
| 224 | echo $SHELLOPTS | grep -q xtrace |
| 225 | echo $? |
| 226 | set +x |
| 227 | echo $SHELLOPTS | grep -q xtrace |
| 228 | echo $? |
| 229 | ## stdout-json: "1\n0\n1\n" |
| 230 | ## N-I dash/mksh stdout-json: "1\n1\n1\n" |
| 231 | |
| 232 | #### SHELLOPTS is readonly |
| 233 | SHELLOPTS=x |
| 234 | echo status=$? |
| 235 | ## stdout: status=1 |
| 236 | ## N-I dash/mksh stdout: status=0 |
| 237 | |
| 238 | #### set -o lists options |
| 239 | set -o | grep set |
| 240 | ## status: 0 |
| 241 | |
| 242 | #### set without args lists variables |
| 243 | set | grep PWD |
| 244 | ## status: 0 |
| 245 | |
| 246 | #### shopt -q |
| 247 | shopt -q nullglob |
| 248 | echo nullglob=$? |
| 249 | |
| 250 | # set it |
| 251 | shopt -s nullglob |
| 252 | |
| 253 | shopt -q nullglob |
| 254 | echo nullglob=$? |
| 255 | |
| 256 | shopt -q nullglob failglob |
| 257 | echo nullglob,failglob=$? |
| 258 | |
| 259 | # set it |
| 260 | shopt -s failglob |
| 261 | shopt -q nullglob failglob |
| 262 | echo nullglob,failglob=$? |
| 263 | |
| 264 | ## STDOUT: |
| 265 | nullglob=1 |
| 266 | nullglob=0 |
| 267 | nullglob,failglob=1 |
| 268 | nullglob,failglob=0 |
| 269 | ## END |
| 270 | ## N-I dash/mksh STDOUT: |
| 271 | nullglob=127 |
| 272 | nullglob=127 |
| 273 | nullglob,failglob=127 |
| 274 | nullglob,failglob=127 |
| 275 | ## END |
| 276 | |
| 277 | #### shopt -q invalid |
| 278 | shopt -q invalidZZ |
| 279 | echo invalidZZ=$? |
| 280 | ## STDOUT: |
| 281 | invalidZZ=2 |
| 282 | ## END |
| 283 | ## OK bash STDOUT: |
| 284 | invalidZZ=1 |
| 285 | ## END |
| 286 | ## N-I dash/mksh STDOUT: |
| 287 | invalidZZ=127 |
| 288 | ## END |
| 289 | |
| 290 | #### sh -i loads rcfile (when combined with -c) |
| 291 | $SH -c 'echo 1' |
| 292 | cat >$TMP/rcfile <<EOF |
| 293 | echo RCFILE |
| 294 | EOF |
| 295 | $SH --rcfile $TMP/rcfile -i -c 'echo 2' |
| 296 | ## STDOUT: |
| 297 | 1 |
| 298 | RCFILE |
| 299 | 2 |
| 300 | ## END |
| 301 | ## N-I dash/mksh STDOUT: |
| 302 | 1 |
| 303 | ## END |
| 304 | ## N-I dash status: 2 |
| 305 | ## N-I mksh status: 1 |