Bump S-nail v14.9.21 ("Tit escapes with a peanut"), 2021-01-21
[s-nail.git] / mx-test.sh
1 #!/bin/sh -
2 #@ Synopsis: [OBJDIR=XY] ./mx-test.sh --check mailx-binary [:SKIPTESTNAME:]
3 #@           [OBJDIR=XY] ./mx-test.sh --run-test mailx-binary [:TESTNAME:]
4 #@           [./mx-test.sh # Note: performs hundreds of compilations!]
5 #@ --no-jobs can be used to prevent spawning concurrent tests.
6 #@ --no-colour or $MAILX_CC_TEST_NO_COLOUR for not trying to use colour
7 #@             (then grep for ^ERROR, for example).
8 #@ The last mode also reacts on $MAILX_CC_ALL_TESTS_DUMPERR, for even easier
9 #@ grep ^ERROR handling.
10 #@ And setting $MAILX_CC_TEST_NO_CLEANUP keeps all test data around, fwiw:
11 #@ this works with --run-test only.
12 #@ $JOBWAIT, $JOBMON and $SKIPTEST are taken from environment when found.
13 #
14 # Public Domain
15
16 : ${OBJDIR:=.obj}
17
18 # Instead of figuring out the environment in here, require a configured build
19 # system and include that!  Our makefile and configure ensure that this test
20 # does not run in the configured, but the user environment nonetheless!
21 i=
22 while :; do
23    if [ -f ./mk-config.env ]; then
24       break
25    elif [ -f snailmail.jpg ] && [ -f "${OBJDIR}"/mk-config.env ]; then
26       i=`pwd`/ # not from environment, sic
27       cd "${OBJDIR}"
28       break
29    else
30       echo >&2 'S-nail/S-mailx is not configured.'
31       echo >&2 'This test script requires the shell environment that only the'
32       echo >&2 'configuration script can figure out, even if used to test'
33       echo >&2 'a different binary than the one that would be produced!'
34       echo >&2 '(The information will be in ${OBJDIR:=.obj}/mk-config.env.)'
35       echo >&2 'Hit RETURN to run "make config"'
36       read l
37       make config
38    fi
39 done
40 . ./mk-config.env
41 if [ -z "${MAILX__CC_TEST_RUNNING}" ]; then
42    MAILX__CC_TEST_RUNNING=1
43    export MAILX__CC_TEST_RUNNING
44    exec "${SHELL}" "${i}${0}" "${@}"
45 fi
46
47 # We need *stealthmua* regardless of $SOURCE_DATE_EPOCH, the program name as
48 # such is a compile-time variable
49 ARGS='-Sv15-compat -:/ -Sdotlock-disable -Smta=test -Smta-bcc-ok'
50    ARGS="${ARGS}"' -Smemdebug -Sstealthmua'
51    ARGS="${ARGS}"' -Smime-encoding=quoted-printable -Snosave'
52    ARGS="${ARGS}"' -Smailcap-disable -Smimetypes-load-control='
53 NOBATCH_ARGS="${ARGS}"' -Sexpandaddr'
54    ARGS="${ARGS}"' -Sexpandaddr=restrict -#'
55 ADDARG_UNI=-Sttycharset=UTF-8
56 CONF=../make.rc
57 BODY=./.cc-body.txt
58 MBOX=./.cc-test.mbox
59 ERR=./.cc-test.err # Covers some which cannot be checksummed; not quoted!
60 MAIL=/dev/null
61 #UTF8_LOCALE= HONOURS_READONLY= autodetected unless set
62 TMPDIR=`${pwd}`
63
64 # When testing mass mail/loops, maximum number of receivers/loops.
65 # TODO note we do not gracefully handle ARG_MAX excess yet!
66 # Those which use this have checksums for 2001 and 201.
67 # Some use the smaller automatically if +debug
68 LOOPS_BIG=2001 LOOPS_SMALL=201
69 LOOPS_MAX=$LOOPS_SMALL
70
71 # How long unless started tests get reaped (avoid endless looping)
72 : ${JOBWAIT:=42}
73 : ${JOBMON:=y}
74 : ${SKIPTEST:=}
75
76 # Note valgrind has problems with FDs in forked childs, which causes some tests
77 # to fail (the FD is rewound and thus will be dumped twice)
78 MEMTESTER=
79 #MEMTESTER='valgrind --leak-check=full --log-file=.vl-%p '
80
81 ##  --  >8  --  8<  --  ##
82
83 t_all() {
84    # Absolute Basics
85    jspawn X_Y_opt_input_go_stack
86    jspawn X_errexit
87    jspawn Y_errexit
88    jspawn S_freeze
89    jspawn f_batch_order
90    jspawn input_inject_semicolon_seq
91    jspawn wysh
92    jspawn commandalias # test now, save space later on!
93    jspawn posix_abbrev
94    jsync
95
96    # Basics
97    jspawn shcodec
98    jspawn ifelse
99    jspawn localopts
100    jspawn local
101    jspawn environ
102    jspawn macro_param_shift
103    jspawn addrcodec
104    jspawn csop
105    jspawn vexpr
106    jspawn call_ret
107    jspawn xcall
108    jspawn vpospar
109    jspawn atxplode
110    jspawn read
111    jspawn readsh
112    jspawn headerpick # so we have a notion that it works a bit
113    jsync
114
115    # Send/RFC absolute basics
116    jspawn can_send_rfc
117    jspawn reply
118    jspawn forward
119    jspawn resend
120    jsync
121
122    # VFS
123    jspawn copy
124    jspawn save
125    jspawn move
126    jspawn mbox
127    jspawn maildir
128    jsync
129
130    # MIME and RFC basics
131    jspawn mime_if_not_ascii
132    jspawn mime_encoding
133    jspawn xxxheads_rfc2047
134    jspawn iconv_mbyte_base64
135    jspawn iconv_mainbody
136    jspawn mime_force_sendout
137    jspawn binary_mainbody
138    jspawn C_opt_customhdr
139    jsync
140
141    # Operational basics with trivial tests
142    jspawn alias
143    jspawn charsetalias
144    jspawn shortcut
145    jspawn netrc
146    jsync
147
148    # Operational basics with easy tests
149    jspawn expandaddr # (after t_alias)
150    jspawn mta_aliases # (after t_expandaddr)
151    jspawn filetype
152    jspawn e_H_L_opts
153    jspawn q_t_etc_opts
154    jspawn message_injections
155    jspawn attachments
156    jspawn rfc2231 # (after attachments)
157    jspawn mime_types_load_control
158    jsync
159
160    # Around state machine, after basics
161    jspawn alternates
162    jspawn cmd_escapes
163    jspawn compose_edits
164    jspawn digmsg
165    jspawn on_main_loop_tick
166    jspawn on_program_exit
167    jsync
168
169    # Heavy use of/rely on state machine (behaviour) and basics
170    jspawn compose_hooks
171    jspawn mass_recipients
172    jspawn lreply_futh_rth_etc
173    jspawn pipe_handlers
174    jspawn mailcap
175    jsync
176
177    # Unclassified rest
178    jspawn top
179    jspawn s_mime
180    jspawn z
181    jsync
182
183    jsync 1
184 }
185
186 ## Now it is getting really weird. You have been warned.
187 # Setup and support {{{
188 export ARGS ADDARG_UNI CONF BODY MBOX MAIL TMPDIR  \
189    MAKE awk cat cksum rm sed grep
190
191 LC_ALL=C LANG=C
192 TZ=UTC
193 # Wed Oct  2 01:50:07 UTC 1996
194 SOURCE_DATE_EPOCH=844221007
195
196 export LC_ALL LANG TZ SOURCE_DATE_EPOCH
197 unset POSIXLY_CORRECT LOGNAME USER
198
199 # usage {{{
200 usage() {
201    ${cat} >&2 <<'_EOT'
202 Synopsis: [OBJDIR=x] mx-test.sh [--no-jobs] --check mailx-binary [:SKIPTEST:]
203 Synopsis: [OBJDIR=x] mx-test.sh [--no-jobs] --run-test mailx-binary [:TEST:]
204 Synopsis: [OBJDIR=x] mx-test.sh [--no-jobs]
205
206  --check EXE [:SKIPTEST:] run test series, exit success or error.
207                           [:SKIPTEST:]s (and $SKIPTEST=) will be excluded.
208  --run-test EXE [:TEST:]  run all or only the given TESTs, and create
209                           test output data files; if run in a git(1)
210                           checkout with the [test-out] branch available,
211                           it will also create file diff(1)erences
212  --no-jobs                do not spawn multiple jobs simultaneously
213                           (dependent on make(1) and sh(1), pass JOBMON=n, too)
214  --no-colour              or $MAILX_CC_TEST_NO_COLOUR: no colour
215                           (for example to: grep ^ERROR)
216                           $MAILX_CC_ALL_TESTS_DUMPER in addition for even
217                           easier grep ^ERROR handling
218
219 The last invocation style will compile and test as many different
220 configurations as possible.
221 EXE should be absolute or relative to $OBJDIR, which can be may be set to the
222 location of the built objects etc.
223 $MAILX_CC_TEST_NO_CLEANUP skips deletion of test data (works only with
224 one test, aka --run-test).
225 $JOBWAIT could denote a timeout, $JOBMON controls usage of "set -m".
226 _EOT
227    exit 1
228 }
229
230 CHECK= RUN_TEST= MAILX=
231 DEVELDIFF= DUMPERR= GIT_REPO=
232 MAXJOBS=1 NOCOLOUR= NOJOBS=
233 while [ ${#} -gt 0 ]; do
234    if [ "${1}" = --no-jobs ]; then
235       NOJOBS=y
236       shift
237    elif [ "${1}" = --no-colour ]; then
238       NOCOLOUR=y
239       shift
240    elif [ "${1}" = -h ] || [ "${1}" = --help ]; then
241       usage
242       exit 0
243    else
244       break
245    fi
246 done
247
248 if [ "${1}" = --check ]; then
249    CHECK=1 MAILX=${2}
250    [ -x "${MAILX}" ] || usage
251    shift 2
252    SKIPTEST="${@} ${SKIPTEST}"
253    [ -d ../.git ] && [ -z "${MAILX__CC_TEST_NO_DATA_FILES}" ] && GIT_REPO=1
254    echo 'Mode: --check, binary: '"${MAILX}"
255 elif [ "${1}" = --run-test ]; then
256    [ ${#} -ge 2 ] || usage
257    RUN_TEST=1 MAILX=${2}
258    [ -x "${MAILX}" ] || usage
259    shift 2
260    [ -d ../.git ] && GIT_REPO=1
261    echo 'Mode: --run-test, binary: '"${MAILX}"
262 else
263    [ ${#} -eq 0 ] || usage
264    echo 'Mode: full compile test, this will take a long time...'
265    MAILX__CC_TEST_NO_DATA_FILES=1
266    export MAILX__CC_TEST_NO_DATA_FILES
267 fi
268 # }}}
269
270 # Since we invoke $MAILX from within several directories we need a fully
271 # qualified path.  Or at least something similar.
272 { echo ${MAILX} | ${grep} -q ^/; } || MAILX="${TMPDIR}"/${MAILX}
273 RAWMAILX=${MAILX}
274 MAILX="${MEMTESTER}${MAILX}"
275 export RAWMAILX MAILX
276
277 # We want an UTF-8 locale, and HONOURS_READONLY {{{
278 if [ -n "${CHECK}${RUN_TEST}" ]; then
279    if [ -z "${UTF8_LOCALE}" ]; then
280       # Try ourselfs via nl_langinfo(CODESET) first (requires a new version)
281       if command -v "${RAWMAILX}" >/dev/null 2>&1 &&
282             ("${RAWMAILX}" -:/ -Xxit) >/dev/null 2>&1; then
283          echo 'Trying to detect UTF-8 locale via '"${RAWMAILX}"
284          i=`</dev/null LC_ALL=C.utf8 "${RAWMAILX}" ${ARGS} -X '
285             \set errexit
286             \define cset_test {
287                \if "${ttycharset}" =%?case utf
288                   \echo $LC_ALL
289                   \xit 0
290                \end
291                \if "${#}" -gt 0
292                   \set LC_ALL=${1}
293                   \shift
294                   \xcall cset_test "${@}"
295                \end
296                \xit 1
297             }
298             \call cset_test C.UTF-8 POSIX.utf8 POSIX.UTF-8 \
299                en_EN.utf8 en_EN.UTF-8 en_US.utf8 en_US.UTF-8
300          '`
301          [ $? -eq 0 ] && UTF8_LOCALE=$i
302       fi
303
304       if [ -z "${UTF8_LOCALE}" ] && (locale yesexpr) >/dev/null 2>&1; then
305          echo 'Trying to detect UTF-8 locale via locale -a'
306          UTF8_LOCALE=`locale -a | { m=
307             while read n; do
308                if { echo ${n} |
309                      ${grep} -i -e utf8 -e utf-8; } >/dev/null 2>&1; then
310                   m=${n}
311                   if { echo ${n} |
312                         ${grep} -e POSIX -e en_EN -e en_US; } \
313                            >/dev/null 2>&1; then
314                      break
315                   fi
316                fi
317             done
318             echo ${m}
319          }`
320       fi
321    fi
322
323    if [ -n "${UTF8_LOCALE}" ]; then
324       echo 'Using Unicode locale '"${UTF8_LOCALE}"
325    else
326       echo 'No Unicode locale found, disabling Unicode tests'
327    fi
328
329    if [ -z "${HONOURS_READONLY}" ]; then
330       trap "${rm} -f ./.tisrdonly" EXIT
331       trap "exit 1" HUP INT TERM
332       printf '' > ./.tisrdonly
333       ${chmod} 0444 ./.tisrdonly
334       if (printf 'no\n' > ./.tisrdonly) >/dev/null 2>&1 &&
335             test -s ./.tisrdonly; then
336          HONOURS_READONLY=
337       else
338          HONOURS_READONLY=yes
339       fi
340       ${rm} -f ./.tisrdonly
341       trap '' EXIT HUP INT TERM
342    fi
343 fi
344
345 export UTF8_LOCALE HONOURS_READONLY
346 # }}}
347
348 TESTS_PERFORMED=0 TESTS_OK=0 TESTS_FAILED=0 TESTS_SKIPPED=0
349 JOBS=0 JOBLIST= JOBREAPER= JOBSYNC=
350 SUBSECOND_SLEEP=
351    ( sleep .1 ) >/dev/null 2>&1 && SUBSECOND_SLEEP=y
352
353 COLOR_ERR_ON= COLOR_ERR_OFF=
354 COLOR_WARN_ON= COLOR_WARN_OFF=
355 COLOR_OK_ON= COLOR_OK_OFF=
356 ESTAT=0
357 TEST_NAME=
358
359 trap "
360    jobreaper_stop
361    [ -z "${MAILX_CC_TEST_NO_CLEANUP}" ] &&
362       ${rm} -rf ./t.*.d ./t.*.io ./t.*.result ./t.time.out
363 " EXIT
364 trap "exit 1" HUP INT QUIT TERM
365
366 # JOBS {{{
367 if [ -n "${NOJOBS}" ]; then
368    jobs_max() { :; }
369 else
370    jobs_max() {
371       # The user desired variant
372       if ( echo "${MAKEFLAGS}" | ${grep} -- -j ) >/dev/null 2>&1; then
373          i=`echo "${MAKEFLAGS}" |
374                ${sed} -e 's/^.*-j[      ]*\([0-9]\{1,\}\).*$/\1/'`
375          if ( echo "${i}" | grep -q -e '^[0-9]\{1,\}$' ); then
376             printf 'Job number derived from MAKEFLAGS: %s\n' ${i}
377             MAXJOBS=${i}
378             [ "${MAXJOBS}" -eq 0 ] && MAXJOBS=1
379             return
380          fi
381       fi
382
383       # The actual hardware
384       printf 'all:\n' > t.mk.io
385       if ( ${MAKE} -j 10 -f t.mk.io ) >/dev/null 2>&1; then
386          if command -v nproc >/dev/null 2>&1; then
387             i=`nproc 2>/dev/null`
388             [ ${?} -eq 0 ] && MAXJOBS=${i}
389          else
390             i=`getconf _NPROCESSORS_ONLN 2>/dev/null`
391             j=${?}
392             if [ ${j} -ne 0 ]; then
393                i=`getconf NPROCESSORS_ONLN 2>/dev/null`
394                j=${?}
395             fi
396             if [ ${j} -ne 0 ]; then
397                # SunOS 5.9 ++
398                if command -v kstat >/dev/null 2>&1; then
399                   i=`PERL5OPT= kstat -p cpu | ${awk} '
400                      BEGIN{no=0; FS=":"}
401                      {if($2 > no) max = $2; next}
402                      END{print ++max}
403                      ' 2>/dev/null`
404                   j=${?}
405                fi
406             fi
407             if [ ${j} -eq 0 ] && [ -n "${i}" ]; then
408                printf 'Job number derived from CPU number: %s\n' ${i}
409                MAXJOBS=${i}
410             fi
411          fi
412          [ "${MAXJOBS}" -eq 0 ] && MAXJOBS=1
413       fi
414    }
415 fi
416
417 jobreaper_start() {
418    case "${JOBMON}" in
419    [yY]*)
420       # There were problems when using monitor mode with mksh
421       i=`env -i ${SHELL} -c 'echo $KSH_VERSION'`
422       if [ -n "${i}" ]; then
423          if [ "${i}" != "${i#*MIRBSD}" ]; then
424             JOBMON=
425          fi
426       fi
427
428       if [ -n "${JOBMON}" ]; then
429          ( set -m ) </dev/null >/dev/null 2>&1 || JOBMON=
430       else
431          printf >&2 '%s! $JOBMON: $SHELL %s incapable, disabled!%s\n' \
432             "${COLOR_ERR_ON}" "${SHELL}" "${COLOR_ERR_OFF}"
433          printf >&2 '%s!  No process groups available, killed tests may '\
434 'leave process "zombies"!%s\n' \
435             "${COLOR_ERR_ON}" "${COLOR_ERR_OFF}"
436       fi
437       ;;
438    *)
439       JOBMON=
440       ;;
441    esac
442 }
443
444 jobreaper_stop() {
445    if [ ${JOBS} -gt 0 ]; then
446       echo 'Cleaning up running jobs'
447       [ -n "${JOBREAPER}" ] && kill -KILL ${JOBREAPER} >/dev/null 2>&1
448       jtimeout
449       wait ${JOBLIST}
450       JOBLIST=
451    fi
452 }
453
454 jspawn() {
455    if [ -n "${CHECK}" ] && [ -n "${SKIPTEST}" ]; then
456       i="${@}"
457       j="${1}"
458       k=
459       set -- ${SKIPTEST}
460       SKIPTEST=
461       while [ ${#} -gt 0 ]; do
462          if [ "${1}" != "${j}" ]; then
463             SKIPTEST="${SKIPTEST} ${1}"
464          elif [ -z "${k}" ]; then
465             k=y
466             t_echoskip ${1}
467          fi
468          shift
469       done
470       [ -n "${k}" ] && return
471       set -- "${i}"
472    fi
473
474    if [ ${MAXJOBS} -gt 1 ]; then
475       # We are spawning multiple jobs..
476       [ ${JOBS} -eq 0 ] && printf '...'
477       JOBS=`add ${JOBS} 1`
478       printf ' [%s=%s]' ${JOBS} "${1}"
479    else
480       JOBS=1
481       # Assume problems exist, do not let user keep hanging on terminal
482       if [ -n "${RUN_TEST}" ]; then
483          printf '... [%s]\n' "${1}"
484       fi
485    fi
486
487    [ -n "${JOBMON}" ] && set -m >/dev/null 2>&1
488    (  # Place the job in its own directory to ease file management
489       trap '' EXIT HUP INT QUIT TERM USR1 USR2
490       ${mkdir} t.${JOBS}.d && cd t.${JOBS}.d &&
491          eval t_${1} ${JOBS} ${1} &&
492          ${rm} -f ../t.${JOBS}.id
493    ) > t.${JOBS}.io </dev/null & # 2>&1 </dev/null &
494    i=${!}
495    [ -n "${JOBMON}" ] && set +m >/dev/null 2>&1
496    JOBLIST="${JOBLIST} ${i}"
497    printf '%s\n%s\n' ${i} ${1} > t.${JOBS}.id
498
499    # ..until we should sync or reach the maximum concurrent number
500    [ ${JOBS} -lt ${MAXJOBS} ] && return
501
502    jsync 1
503 }
504
505 jsync() {
506    if [ ${JOBS} -eq 0 ]; then
507       [ -n "${TEST_ANY}" ] && printf '\n'
508       TEST_ANY=
509       return
510    fi
511    [ -z "${JOBSYNC}" ] && [ ${#} -eq 0 ] && return
512
513    [ ${MAXJOBS} -ne 1 ] && printf ' .. waiting\n'
514
515    # Start an asynchronous notify process
516    ${rm} -f ./t.time.out
517    (
518       sleep ${JOBWAIT} &
519       sleeper=${!}
520       trap "kill -TERM ${sleeper}; exit 1" HUP INT TERM
521       wait ${sleeper}
522       trap '' HUP INT TERM
523       printf '' > ./t.time.out
524    ) </dev/null >/dev/null 2>&1 &
525    JOBREAPER=${!}
526
527    # Then loop a while, looking out for collecting tests
528    loops=0
529    while :; do
530       [ -f ./t.time.out ] && break
531       alldone=1
532       i=0
533       while [ ${i} -lt ${JOBS} ]; do
534          i=`add ${i} 1`
535          [ -f t.${i}.id ] || continue
536          alldone=
537          break
538       done
539       [ -n "${alldone}" ] && break
540
541       if [ -z "${SUBSECOND_SLEEP}" ]; then
542          loops=`add ${loops} 1`
543          [ ${loops} -lt 111 ] && continue
544          sleep 1 &
545       else
546          sleep .25 &
547       fi
548       wait ${!}
549    done
550
551    if [ -f ./t.time.out ]; then
552       ${rm} -f ./t.time.out
553       jtimeout
554    else
555       kill -TERM ${JOBREAPER} >/dev/null 2>&1
556    fi
557    wait ${JOBREAPER}
558    JOBREAPER=
559
560    # Now collect the zombies
561    wait ${JOBLIST}
562    JOBLIST=
563
564    # Update global counters
565    i=0
566    while [ ${i} -lt ${JOBS} ]; do
567       i=`add ${i} 1`
568
569       [ -s t.${i}.io ] && ${cat} t.${i}.io
570       if [ -n "${DUMPERR}" ] && [ -s ./t.${i}.d/${ERR} ]; then
571          printf '%s   [Debug/Devel: nullified errors]\n' "${COLOR_ERR_ON}"
572          while read l; do
573             printf '   %s\n' "${l}"
574          done < t.${i}.d/${ERR}
575          printf '%s' "${COLOR_ERR_OFF}"
576       fi
577
578       if [ -f t.${i}.id ]; then
579          { read pid; read desc; } < t.${i}.id
580          desc=${desc#${desc%%[! ]*}}
581          desc=${desc%${desc##*[! ]}}
582          [ -s t.${i}.io ] && printf >&2 '\n'
583          printf >&2 '%s!! Timeout: reaped job %s [%s]%s\n' \
584             "${COLOR_ERR_ON}" ${i} "${desc}" "${COLOR_ERR_OFF}"
585          TESTS_FAILED=`add ${TESTS_FAILED} 1`
586       elif [ -s t.${i}.result ]; then
587          read es tp to tf ts < t.${i}.result
588          TESTS_PERFORMED=`add ${TESTS_PERFORMED} ${tp}`
589          TESTS_OK=`add ${TESTS_OK} ${to}`
590          TESTS_FAILED=`add ${TESTS_FAILED} ${tf}`
591          TESTS_SKIPPED=`add ${TESTS_SKIPPED} ${ts}`
592          [ "${es}" != 0 ] && ESTAT=${es}
593       else
594          TESTS_FAILED=`add ${TESTS_FAILED} 1`
595          ESTAT=1
596       fi
597    done
598
599    [ -z "${MAILX_CC_TEST_NO_CLEANUP}" ] &&
600       ${rm} -rf ./t.*.d ./t.*.id ./t.*.io t.*.result ./t.time.out
601
602    JOBS=0
603 }
604
605 jtimeout() {
606    i=0
607    while [ ${i} -lt ${JOBS} ]; do
608       i=`add ${i} 1`
609       if [ -f t.${i}.id ] &&
610             read pid < t.${i}.id >/dev/null 2>&1 &&
611             kill -0 ${pid} >/dev/null 2>&1; then
612          j=${pid}
613          [ -n "${JOBMON}" ] && j=-${j}
614          kill -KILL ${j} >/dev/null 2>&1
615       else
616          ${rm} -f t.${i}.id
617       fi
618    done
619 }
620 # }}}
621
622 # echoes, checks, etc. {{{
623 t_prolog() {
624    shift
625
626    ESTAT=0 TESTS_PERFORMED=0 TESTS_OK=0 TESTS_FAILED=0 TESTS_SKIPPED=0 \
627       TEST_NAME=${1} TEST_ANY=
628
629    printf '%s[%s]%s\n' "" "${TEST_NAME}" ""
630 }
631
632 t_epilog() {
633    [ -n "${TEST_ANY}" ] && printf '\n'
634
635    printf '%s %s %s %s %s\n' \
636       ${ESTAT} \
637          ${TESTS_PERFORMED} ${TESTS_OK} ${TESTS_FAILED} ${TESTS_SKIPPED} \
638       > ../t.${1}.result
639 }
640
641 t_echo() {
642    [ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
643    printf "${__i__}"'%s' "${*}"
644    TEST_ANY=1
645 }
646
647 t_echook() {
648    [ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
649    printf "${__i__}"'%s%s:ok%s' "${COLOR_OK_ON}" "${*}" "${COLOR_OK_OFF}"
650    TEST_ANY=1
651 }
652
653 t_echoerr() {
654    ESTAT=1
655    t_echo0err "${@}"
656 }
657
658 t_echo0err() {
659    [ -n "${TEST_ANY}" ] && __i__="\n" || __i__=
660    printf "${__i__}"'%sERROR: %s%s\n' \
661       "${COLOR_ERR_ON}" "${*}" "${COLOR_ERR_OFF}"
662    TEST_ANY=
663 }
664
665 t_echowarn() {
666    [ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
667    printf "${__i__}"'%s%s%s' "${COLOR_WARN_ON}" "${*}" "${COLOR_WARN_OFF}"
668    TEST_ANY=1
669 }
670
671 t_echoskip() {
672    [ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
673    printf "${__i__}"'%s%s[skip]%s' \
674       "${COLOR_WARN_ON}" "${*}" "${COLOR_WARN_OFF}"
675    TEST_ANY=1
676    TESTS_SKIPPED=`add ${TESTS_SKIPPED} 1`
677 }
678
679 check() {
680    restat=${?} tid=${1} eestat=${2} f=${3} s=${4} optmode=${5}
681
682    TESTS_PERFORMED=`add ${TESTS_PERFORMED} 1`
683
684    case "${optmode}" in
685    '') ;;
686    async)
687       [ "$eestat" = - ] || exit 200
688       while :; do
689          [ -f "${f}" ] && break
690          t_echowarn "[${tid}:async=wait]"
691          sleep 1 &
692          wait ${!}
693       done
694       ;;
695    *) exit 222;;
696    esac
697
698    check__bad= check__runx=
699
700    if [ "${eestat}" != - ] && [ "${restat}" != "${eestat}" ]; then
701       ESTAT=1
702       t_echoerr "${tid}: bad-status: ${restat} != ${eestat}"
703       check__bad=1
704    fi
705
706    csum="`${cksum} < "${f}" | ${sed} -e 's/[    ]\{1,\}/ /g'`"
707    if [ "${csum}" = "${s}" ]; then
708       t_echook "${tid}"
709       check__runx=${DEVELDIFF}
710    else
711       ESTAT=1
712       t_echoerr "${tid}: checksum mismatch (got ${csum})"
713       check__bad=1 check__runx=1
714    fi
715
716    if [ -z "${check__bad}" ]; then
717       TESTS_OK=`add ${TESTS_OK} 1`
718    else
719       TESTS_FAILED=`add ${TESTS_FAILED} 1`
720    fi
721
722    if [ -n "${CHECK}${RUN_TEST}" ]; then
723       x="t.${TEST_NAME}-${tid}"
724       if [ -n "${RUN_TEST}" ] ||
725             [ -n "${check__runx}" -a -n "${GIT_REPO}" ]; then
726          ${cp} -f "${f}" ../"${x}"
727       fi
728
729       if [ -n "${check__runx}" ] && [ -n "${GIT_REPO}" ] &&
730             command -v diff >/dev/null 2>&1; then
731          y=test-out
732          if (git rev-parse --verify $y) >/dev/null 2>&1; then :; else
733             y=refs/remotes/origin/test-out
734             (git rev-parse --verify $y) >/dev/null 2>&1 || y=
735          fi
736          if [ -n "${y}" ]; then
737             if GIT_CONFIG=/dev/null git show "${y}":"${x}" > \
738                   ../"${x}".old 2>/dev/null; then
739                diff -ru ../"${x}".old ../"${x}" > ../"${x}".diff
740                if [ ${?} -eq 0 ]; then
741                   [ -z "${MAILX_CC_TEST_NO_CLEANUP}" ] &&
742                      ${rm} -f ../"${x}" ../"${x}".old ../"${x}".diff
743                elif [ -n "${MAILX_CC_ALL_TESTS_DUMPERR}" ]; then
744                   while read l; do
745                      printf 'ERROR-DIFF  %s\n' "${l}"
746                   done < ../"${x}".diff
747                fi
748             else
749                t_echo0err "${tid}: misses [test-out] template"
750             fi
751          fi
752       fi
753    fi
754 }
755
756 check_ex0() {
757    # $1=test name [$2=status]
758    __qm__=${?}
759    [ ${#} -gt 1 ] && __qm__=${2}
760
761    TESTS_PERFORMED=`add ${TESTS_PERFORMED} 1`
762
763    if [ ${__qm__} -ne 0 ]; then
764       ESTAT=1
765       t_echoerr "${1}: unexpected non-0 exit status: ${__qm__}"
766       TESTS_FAILED=`add ${TESTS_FAILED} 1`
767    else
768       t_echook "${1}"
769       TESTS_OK=`add ${TESTS_OK} 1`
770    fi
771 }
772
773 check_exn0() {
774    # $1=test name [$2=status]
775    __qm__=${?}
776    [ ${#} -gt 1 ] && __qm__=${2}
777    [ ${#} -gt 2 ] && __expect__=${3} || __expect__=
778
779    TESTS_PERFORMED=`add ${TESTS_PERFORMED} 1`
780
781    if [ ${__qm__} -eq 0 ]; then
782       ESTAT=1
783       t_echoerr "${1}: unexpected 0 exit status: ${__qm__}"
784       TESTS_FAILED=`add ${TESTS_FAILED} 1`
785    elif [ -n "${__expect__}" ] && [ ${__expect__} -ne ${__qm__} ]; then
786       ESTAT=1
787       t_echoerr "${1}: unexpected exit status: ${__qm__} != ${__expected__}"
788       TESTS_FAILED=`add ${TESTS_FAILED} 1`
789    else
790       t_echook "${1}"
791       TESTS_OK=`add ${TESTS_OK} 1`
792    fi
793 }
794 # }}}
795
796 color_init() {
797    [ -n "${NOCOLOUR}" ] && return
798    [ -n "${MAILX_CC_TEST_NO_COLOUR}" ] && return
799    # We do not want color for "make test > .LOG"!
800    if command -v stty >/dev/null 2>&1 && command -v tput >/dev/null 2>&1 &&
801          (<&1 >/dev/null stty -a) 2>/dev/null; then
802       { sgr0=`tput sgr0`; } 2>/dev/null
803       [ $? -eq 0 ] || return
804       { saf1=`tput setaf 1`; } 2>/dev/null
805       [ $? -eq 0 ] || return
806       { saf2=`tput setaf 2`; } 2>/dev/null
807       [ $? -eq 0 ] || return
808       { saf3=`tput setaf 3`; } 2>/dev/null
809       [ $? -eq 0 ] || return
810       { b=`tput bold`; } 2>/dev/null
811       [ $? -eq 0 ] || return
812
813       COLOR_ERR_ON=${saf1}${b} COLOR_ERR_OFF=${sgr0}
814       COLOR_WARN_ON=${saf3}${b} COLOR_WARN_OFF=${sgr0}
815       COLOR_OK_ON=${saf2} COLOR_OK_OFF=${sgr0}
816       unset saf1 saf2 saf3 b
817    fi
818 }
819
820 if ( [ "$((1 + 1))" = 2 ] ) >/dev/null 2>&1; then
821    add() {
822       echo "$((${1} + ${2}))"
823    }
824 else
825    add() {
826       ${awk} 'BEGIN{print '${1}' + '${2}'}'
827    }
828 fi
829
830 if ( [ "$((2 % 3))" = 2 ] ) >/dev/null 2>&1; then
831    modulo() {
832       echo "$((${1} % ${2}))"
833    }
834 else
835    modulo() {
836       ${awk} 'BEGIN{print '${1}' % '${2}'}'
837    }
838 fi
839
840 have_feat() {
841    ( "${RAWMAILX}" ${ARGS} -X'echo $features' -Xx |
842       ${grep} ,+${1}, ) >/dev/null 2>&1
843 }
844 # }}}
845
846 # Absolute Basics {{{
847 t_X_Y_opt_input_go_stack() {
848    t_prolog "${@}"
849
850    ${cat} <<- '__EOT' > "${BODY}"
851         echo 1
852         define mac0 {
853            echo mac0-1 via1 $0
854         }
855         call mac0
856         echo 2
857         source '\
858            echo "define mac1 {";\
859            echo "  echo mac1-1 via1 \$0";\
860            echo "  call mac0";\
861            echo "  echo mac1-2";\
862            echo "  call mac2";\
863            echo "  echo mac1-3";\
864            echo "}";\
865            echo "echo 1-1";\
866            echo "define mac2 {";\
867            echo "  echo mac2-1 via1 \$0";\
868            echo "  call mac0";\
869            echo "  echo mac2-2";\
870            echo "}";\
871            echo "echo 1-2";\
872            echo "call mac1";\
873            echo "echo 1-3";\
874            echo "source \"\
875               echo echo 1-1-1 via1 \$0;\
876               echo call mac0;\
877               echo echo 1-1-2;\
878            | \"";\
879            echo "echo 1-4";\
880         |  '
881         echo 3
882         call mac2
883         echo 4
884         undefine *
885         __EOT
886
887    # The -X option supports multiline arguments, and those can internally use
888    # reverse solidus newline escaping.  And all -X options are joined...
889    APO=\'
890    < "${BODY}" ${MAILX} ${ARGS} \
891       -X 'e\' \
892       -X ' c\' \
893       -X '  h\' \
894       -X '   o \' \
895       -X 1 \
896       -X'
897    define mac0 {
898       echo mac0-1 via2 $0
899    }
900    call mac0
901    echo 2
902    ' \
903       -X'
904    source '${APO}'\
905       echo "define mac1 {";\
906       echo "  echo mac1-1 via2 \$0";\
907       echo "  call mac0";\
908       echo "  echo mac1-2";\
909       echo "  call mac2";\
910       echo "  echo mac1-3";\
911       echo "}";\
912       echo "echo 1-1";\
913       echo "define mac2 {";\
914       echo "  echo mac2-1 via2 \$0";\
915       echo "  call mac0";\
916       echo "  echo mac2-2";\
917       echo "}";\
918       echo "echo 1-2";\
919       echo "call mac1";\
920       echo "echo 1-3";\
921       echo "source \"\
922          echo echo 1-1-1 via2 \$0;\
923          echo call mac0;\
924          echo echo 1-1-2;\
925       | \"";\
926       echo "echo 1-4";\
927    |  '${APO}'
928    echo 3
929    ' \
930       -X'
931    call mac2
932    echo 4
933    undefine *
934    ' > "${MBOX}"
935
936    check 1 0 "${MBOX}" '1786542668 416'
937
938    # The -Y option supports multiline arguments, and those can internally use
939    # reverse solidus newline escaping.
940    APO=\'
941    < "${BODY}" ${MAILX} ${ARGS} \
942       -X 'echo FIRST_X' \
943       -X 'echo SECOND_X' \
944       -Y 'e\' \
945       -Y ' c\' \
946       -Y '  h\' \
947       -Y '   o \' \
948       -Y 1 \
949       -Y'
950    define mac0 {
951       echo mac0-1 via2 $0
952    }
953    call mac0
954    echo 2
955    ' \
956       -Y'
957    source '${APO}'\
958       echo "define mac1 {";\
959       echo "  echo mac1-1 via2 \$0";\
960       echo "  call mac0";\
961       echo "  echo mac1-2";\
962       echo "  call mac2";\
963       echo "  echo mac1-3";\
964       echo "}";\
965       echo "echo 1-1";\
966       echo "define mac2 {";\
967       echo "  echo mac2-1 via2 \$0";\
968       echo "  call mac0";\
969       echo "  echo mac2-2";\
970       echo "}";\
971       echo "echo 1-2";\
972       echo "call mac1";\
973       echo "echo 1-3";\
974       echo "source \"\
975          echo echo 1-1-1 via2 \$0;\
976          echo call mac0;\
977          echo echo 1-1-2;\
978       | \"";\
979       echo "echo 1-4";\
980    |  '${APO}'
981    echo 3
982    ' \
983       -Y'
984    call mac2
985    echo 4
986    undefine *
987    ' \
988       -Y 'echo LAST_Y' > "${MBOX}"
989
990    check 2 0 "${MBOX}" '1845176711 440'
991
992    # Compose mode, too!
993    </dev/null ${MAILX} ${ARGS} \
994       -X 'echo X before compose mode' \
995       -Y '~s Subject via -Y' \
996       -Y 'Body via -Y' -. ./.tybox > "${MBOX}" 2>&1
997    check 3 0 ./.tybox '264636255 125'
998    check 4 - "${MBOX}" '467429373 22'
999
1000    ${cat} <<-_EOT | ${MAILX} ${ARGS} -t \
1001       -X 'echo X before compose mode' \
1002       -Y '~s Subject via -Y' \
1003       -Y 'Additional body via -Y' -. ./.tybox > "${MBOX}" 2>&1
1004         from: heya@exam.ple
1005         subject:diet not to be seen!
1006
1007         this body via -t.
1008         _EOT
1009    check 5 0 ./.tybox '3313167452 299'
1010    check 6 - "${MBOX}" '467429373 22'
1011
1012    #
1013    printf 'this body via stdin pipe.\n' | ${MAILX} ${NOBATCH_ARGS} \
1014       -X 'echo X before compose mode' \
1015       -Y '~s Subject via -Y (not!)' \
1016       -Y 'Additional body via -Y, nobatch mode' -. ./.tybox > "${MBOX}" 2>&1
1017    check 7 0 ./.tybox '1561798488 476'
1018    check 8 - "${MBOX}" '467429373 22'
1019
1020    printf 'this body via stdin pipe.\n' | ${MAILX} ${ARGS} \
1021       -X 'echo X before compose mode' \
1022       -Y '~s Subject via -Y' \
1023       -Y 'Additional body via -Y, batch mode' -. ./.tybox > "${MBOX}" 2>&1
1024    check 9 0 ./.tybox '3245082485 650'
1025    check 10 - "${MBOX}" '467429373 22'
1026
1027    # Test for [8412796a] (n_cmd_arg_parse(): FIX token error -> crash, e.g.
1028    # "-RX 'bind;echo $?' -Xx".., 2018-08-02)
1029    ${MAILX} ${ARGS} -RX'call;echo $?' -Xx > ./.tall 2>&1
1030    ${MAILX} ${ARGS} -RX'call ;echo $?' -Xx >> ./.tall 2>&1
1031    ${MAILX} ${ARGS} -RX'call    ;echo $?' -Xx >> ./.tall 2>&1
1032    ${MAILX} ${ARGS} -RX'call      ;echo $?' -Xx >> ./.tall 2>&1
1033    check cmdline 0 ./.tall '1867586969 8'
1034
1035    t_epilog "${@}"
1036 }
1037
1038 t_X_errexit() {
1039    t_prolog "${@}"
1040
1041    if have_feat uistrings; then :; else
1042       t_echoskip '[!UISTRINGS]'
1043       t_epilog "${@}"
1044       return
1045    fi
1046
1047    ${cat} <<- '__EOT' > "${BODY}"
1048         echo one
1049         echos nono
1050         echo two
1051         __EOT
1052
1053    </dev/null ${MAILX} ${ARGS} -Snomemdebug \
1054          -X'echo one' -X' echos nono ' -X'echo two' \
1055       > "${MBOX}" 2>&1
1056    check 1 0 "${MBOX}" '2700500141 51'
1057
1058    </dev/null ${MAILX} ${ARGS} -X'source '"${BODY}" -Snomemdebug \
1059       > "${MBOX}" 2>&1
1060    check 2 0 "${MBOX}" '2700500141 51'
1061
1062    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u -Snomemdebug \
1063       > "${MBOX}" 2>&1
1064    check 3 0 "${MBOX}" '2700500141 51'
1065
1066    ##
1067
1068    </dev/null ${MAILX} ${ARGS} -Serrexit -Snomemdebug \
1069          -X'echo one' -X' echos nono ' -X'echo two' \
1070       > "${MBOX}" 2>&1
1071    check 4 1 "${MBOX}" '4096689457 47'
1072
1073    </dev/null ${MAILX} ${ARGS} -X'source '"${BODY}" -Serrexit -Snomemdebug \
1074       > "${MBOX}" 2>&1
1075    check 5 1 "${MBOX}" '4096689457 47'
1076
1077    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u -Serrexit -Snomemdebug \
1078       > "${MBOX}" 2>&1
1079    check 6 1 "${MBOX}" '1669262132 170'
1080
1081    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u -Sposix -Snomemdebug \
1082       > "${MBOX}" 2>&1
1083    check 7 1 "${MBOX}" '1669262132 170'
1084
1085    ## Repeat 4-7 with ignerr set
1086
1087    ${sed} -e 's/^echos /ignerr echos /' < "${BODY}" > "${MBOX}"
1088
1089    </dev/null ${MAILX} ${ARGS} -Serrexit -Snomemdebug \
1090          -X'echo one' -X'ignerr echos nono ' -X'echo two' \
1091       > "${BODY}" 2>&1
1092    check 8 0 "${BODY}" '2700500141 51'
1093
1094    </dev/null ${MAILX} ${ARGS} -X'source '"${MBOX}" -Serrexit -Snomemdebug \
1095       > "${BODY}" 2>&1
1096    check 9 0 "${BODY}" '2700500141 51'
1097
1098    </dev/null MAILRC="${MBOX}" ${MAILX} ${ARGS} -:u -Serrexit -Snomemdebug \
1099       > "${BODY}" 2>&1
1100    check 10 0 "${BODY}" '2700500141 51'
1101
1102    </dev/null MAILRC="${MBOX}" ${MAILX} ${ARGS} -:u -Sposix -Snomemdebug \
1103       > "${BODY}" 2>&1
1104    check 11 0 "${BODY}" '2700500141 51'
1105
1106    # Ensure "good-injection" in a deeper indirection does not cause trouble
1107    # This actually only works with MLE and HISTORY, and TODO needs a pseudo TTY
1108    # interaction so that we DO initialize our line editor...
1109    ${cat} <<- '__EOT' > "${BODY}"
1110         define oha {
1111            return 0
1112         }
1113         define x {
1114           eval set $xarg
1115           echoes time
1116           return 0
1117         }
1118         __EOT
1119
1120    printf 'source %s\ncall x\necho au' "${BODY}"  |
1121       ${MAILX} ${ARGS} -Snomemdebug -Sxarg=errexit > "${MBOX}" 2>&1
1122    check 12 1 "${MBOX}" '2908921993 44'
1123
1124    printf 'source %s\nset on-history-addition=oha\ncall x\necho au' "${BODY}" |
1125       ${MAILX} ${ARGS} -Snomemdebug -Sxarg=errexit > "${MBOX}" 2>&1
1126    check 13 1 "${MBOX}" '2908921993 44'
1127
1128    printf 'source %s\ncall x\necho au' "${BODY}" |
1129       ${MAILX} ${ARGS} -Snomemdebug -Sxarg=nowhere > "${MBOX}" 2>&1
1130    check 14 0 "${MBOX}" '2049365617 47'
1131
1132    t_epilog "${@}"
1133 }
1134
1135 t_Y_errexit() {
1136    t_prolog "${@}"
1137
1138    if have_feat uistrings; then :; else
1139       t_echoskip '[!UISTRINGS]'
1140       t_epilog "${@}"
1141       return
1142    fi
1143
1144    ${cat} <<- '__EOT' > "${BODY}"
1145         echo one
1146         echos nono
1147         echo two
1148         __EOT
1149
1150    </dev/null ${MAILX} ${ARGS} -Snomemdebug \
1151          -Y'echo one' -Y' echos nono ' -Y'echo two' \
1152       > "${MBOX}" 2>&1
1153    check 1 0 "${MBOX}" '2700500141 51'
1154
1155    </dev/null ${MAILX} ${ARGS} -Y'source '"${BODY}" -Snomemdebug \
1156       > "${MBOX}" 2>&1
1157    check 2 0 "${MBOX}" '2700500141 51'
1158
1159    ##
1160
1161    </dev/null ${MAILX} ${ARGS} -Serrexit -Snomemdebug \
1162          -Y'echo one' -Y' echos nono ' -Y'echo two' \
1163       > "${MBOX}" 2>&1
1164    check 3 1 "${MBOX}" '4096689457 47'
1165
1166    </dev/null ${MAILX} ${ARGS} -Y'source '"${BODY}" -Serrexit -Snomemdebug \
1167       > "${MBOX}" 2>&1
1168    check 4 1 "${MBOX}" '4096689457 47'
1169
1170    ## Repeat 3-4 with ignerr set
1171
1172    ${sed} -e 's/^echos /ignerr echos /' < "${BODY}" > "${MBOX}"
1173
1174    </dev/null ${MAILX} ${ARGS} -Serrexit -Snomemdebug \
1175          -Y'echo one' -Y'ignerr echos nono ' -Y'echo two' \
1176       > "${BODY}" 2>&1
1177    check 5 0 "${BODY}" '2700500141 51'
1178
1179    </dev/null ${MAILX} ${ARGS} -Y'source '"${MBOX}" -Serrexit -Snomemdebug \
1180       > "${BODY}" 2>&1
1181    check 6 0 "${BODY}" '2700500141 51'
1182
1183    t_epilog "${@}"
1184 }
1185
1186 t_S_freeze() {
1187    t_prolog "${@}"
1188    oterm=$TERM
1189    unset TERM
1190
1191    # Test basic assumption
1192    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} \
1193       -X'echo asksub<$asksub> dietcurd<$dietcurd>' \
1194       -Xx > "${MBOX}" 2>&1
1195    check 1 0 "${MBOX}" '270686329 21'
1196
1197    #
1198    ${cat} <<- '__EOT' > "${BODY}"
1199         echo asksub<$asksub>
1200         set asksub
1201         echo asksub<$asksub>
1202         __EOT
1203    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u \
1204       -Snoasksub -Sasksub -Snoasksub \
1205       -X'echo asksub<$asksub>' -X'set asksub' -X'echo asksub<$asksub>' \
1206       -Xx > "${MBOX}" 2>&1
1207    check 2 0 "${MBOX}" '3182942628 37'
1208
1209    ${cat} <<- '__EOT' > "${BODY}"
1210         echo asksub<$asksub>
1211         unset asksub
1212         echo asksub<$asksub>
1213         __EOT
1214    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u \
1215       -Snoasksub -Sasksub \
1216       -X'echo asksub<$asksub>' -X'unset asksub' -X'echo asksub<$asksub>' \
1217       -Xx > "${MBOX}" 2>&1
1218    check 3 0 "${MBOX}" '2006554293 39'
1219
1220    #
1221    ${cat} <<- '__EOT' > "${BODY}"
1222         echo dietcurd<$dietcurd>
1223         set dietcurd=cherry
1224         echo dietcurd<$dietcurd>
1225         __EOT
1226    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u \
1227       -Sdietcurd=strawberry -Snodietcurd -Sdietcurd=vanilla \
1228       -X'echo dietcurd<$dietcurd>' -X'unset dietcurd' \
1229          -X'echo dietcurd<$dietcurd>' \
1230       -Xx > "${MBOX}" 2>&1
1231    check 4 0 "${MBOX}" '1985768109 65'
1232
1233    ${cat} <<- '__EOT' > "${BODY}"
1234         echo dietcurd<$dietcurd>
1235         unset dietcurd
1236         echo dietcurd<$dietcurd>
1237         __EOT
1238    </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u \
1239       -Sdietcurd=strawberry -Snodietcurd \
1240       -X'echo dietcurd<$dietcurd>' -X'set dietcurd=vanilla' \
1241          -X'echo dietcurd<$dietcurd>' \
1242       -Xx > "${MBOX}" 2>&1
1243    check 5 0 "${MBOX}" '151574279 51'
1244
1245    # TODO once we have a detached one with env=1..
1246    if [ -n "`</dev/null ${MAILX} ${ARGS} -X'!echo \$TERM' -Xx`" ]; then
1247       t_echoskip 's_freeze-{6,7}:[shell sets $TERM]'
1248    else
1249       ${cat} <<- '__EOT' > "${BODY}"
1250                 !echo "shell says TERM<$TERM>"
1251         echo TERM<$TERM>
1252                 !echo "shell says TERM<$TERM>"
1253         set TERM=cherry
1254                 !echo "shell says TERM<$TERM>"
1255         echo TERM<$TERM>
1256                 !echo "shell says TERM<$TERM>"
1257                 __EOT
1258       </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u \
1259          -STERM=strawberry -SnoTERM -STERM=vanilla \
1260          -X'echo mail<$TERM>' -X'unset TERM' \
1261          -X'!echo "shell says TERM<$TERM>"' -X'echo TERM<$TERM>' \
1262          -Xx > "${MBOX}" 2>&1
1263    check 6 0 "${MBOX}" '1211476036 167'
1264
1265       ${cat} <<- '__EOT' > "${BODY}"
1266                 !echo "shell says TERM<$TERM>"
1267         echo TERM<$TERM>
1268                 !echo "shell says TERM<$TERM>"
1269         set TERM=cherry
1270                 !echo "shell says TERM<$TERM>"
1271         echo TERM<$TERM>
1272                 !echo "shell says TERM<$TERM>"
1273         __EOT
1274       </dev/null MAILRC="${BODY}" ${MAILX} ${ARGS} -:u \
1275          -STERM=strawberry -SnoTERM \
1276          -X'echo TERM<$TERM>' -X'set TERM=vanilla' \
1277          -X'!echo "shell says TERM<$TERM>"' -X'echo TERM<$TERM>' \
1278          -Xx > "${MBOX}" 2>&1
1279       check 7 0 "${MBOX}" '3365080441 132'
1280    fi
1281
1282    TERM=$oterm
1283    t_epilog "${@}"
1284 }
1285
1286 t_f_batch_order() {
1287    t_prolog "${@}"
1288
1289    t__gen_msg subject f-batch-order > "${MBOX}"
1290
1291    # This would exit 64 (EX_USAGE) from ? to [fbddb3b3] (FIX: -f: add
1292    # n_PO_f_FLAG to avoid that command line order matters)
1293    </dev/null ${MAILX} ${NOBATCH_ARGS} -R -f -# \
1294       -Y 'echo du;h;echo da;x' "${MBOX}" >./.tall 2>&1
1295    check 1 0 ./.tall '1690247457 86'
1296
1297    # And this ever worked (hopefully)
1298    </dev/null ${MAILX} ${NOBATCH_ARGS} -R -# -f \
1299       -Y 'echo du;h;echo da;x' "${MBOX}" >./.tall 2>&1
1300    check 2 0 ./.tall '1690247457 86'
1301
1302    t_epilog "${@}"
1303 }
1304
1305 t_input_inject_semicolon_seq() {
1306    t_prolog "${@}"
1307
1308    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}"
1309         define mydeepmac {
1310                 echon '(mydeepmac)';
1311         }
1312         define mymac {
1313                 echon this_is_mymac;call mydeepmac;echon ';';
1314         }
1315         echon one';';call mymac;echon two";";call mymac;echo three$';';
1316         define mymac {
1317                 echon this_is_mymac;call mydeepmac;echon ,TOO'!;';
1318         }
1319         echon one';';call mymac;echon two";";call mymac;echo three$';';
1320         __EOT
1321
1322    check 1 0 "${MBOX}" '512117110 140'
1323
1324    t_epilog "${@}"
1325 }
1326
1327 t_wysh() {
1328    t_prolog "${@}"
1329
1330    ${cat} <<- '__EOT' > "${BODY}"
1331         #
1332         echo abcd
1333         echo a'b'c'd'
1334         echo a"b"c"d"
1335         echo a$'b'c$'d'
1336         echo 'abcd'
1337         echo "abcd"
1338         echo $'abcd'
1339         echo a\ b\ c\ d
1340         echo a 'b c' d
1341         echo a "b c" d
1342         echo a $'b c' d
1343         #
1344         echo 'a$`"\'
1345         echo "a\$\`'\"\\"
1346         echo $'a\$`\'\"\\'
1347         echo $'a\$`\'"\\'
1348         # DIET=CURD TIED=
1349         echo 'a${DIET}b${TIED}c\${DIET}d\${TIED}e' # COMMENT
1350         echo "a${DIET}b${TIED}c\${DIET}d\${TIED}e"
1351         echo $'a${DIET}b${TIED}c\${DIET}d\${TIED}e'
1352         #
1353         echo a$'\101\0101\x41\u0041\u41\U00000041\U41'c
1354         echo a$'\u0041\u41\u0C1\U00000041\U41'c
1355         echo a$'\377'c
1356         echo a$'\0377'c
1357         echo a$'\400'c
1358         echo a$'\0400'c
1359         echo a$'\U1100001'c
1360         #
1361         echo a$'b\0c'd
1362         echo a$'b\00c'de
1363         echo a$'b\000c'df
1364         echo a$'b\0000c'dg
1365         echo a$'b\x0c'dh
1366         echo a$'b\x00c'di
1367         echo a$'b\u0'dj
1368         echo a$'b\u00'dk
1369         echo a$'b\u000'dl
1370         echo a$'b\u0000'dm
1371         echo a$'b\U0'dn
1372         echo a$'b\U00'do
1373         echo a$'b\U000'dp
1374         echo a$'b\U0000'dq
1375         echo a$'b\U00000'dr
1376         echo a$'b\U000000'ds
1377         echo a$'b\U0000000'dt
1378         echo a$'b\U00000000'du
1379         #
1380         echo a$'\cI'b
1381         echo a$'\011'b
1382         echo a$'\x9'b
1383         echo a$'\u9'b
1384         echo a$'\U9'b
1385         echo a$'\c@'b c d
1386         __EOT
1387
1388    if [ -z "${UTF8_LOCALE}" ]; then
1389       t_echoskip 'wysh-unicode:[no UTF-8 locale]'
1390    else
1391       < "${BODY}" DIET=CURD TIED= \
1392       LC_ALL=${UTF8_LOCALE} ${MAILX} ${ARGS} > "${MBOX}" 2>>${ERR}
1393       check unicode 0 "${MBOX}" '475805847 317'
1394    fi
1395
1396    < "${BODY}" DIET=CURD TIED= ${MAILX} ${ARGS} > "${MBOX}" 2>>${ERR}
1397    check c 0 "${MBOX}" '1473887148 321'
1398
1399    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}"
1400    wysh set mager='\hey\'
1401    varshow mager
1402    wysh set mager="\hey\\"
1403    varshow mager
1404    wysh set mager=$'\hey\\'
1405    varshow mager
1406         __EOT
1407    check 3 0 "${MBOX}" '1289698238 69'
1408
1409    t_epilog "${@}"
1410 }
1411
1412 t_commandalias() {
1413    t_prolog "${@}"
1414
1415    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}"
1416         commandalias echo echo hoho
1417         echo stop.
1418         commandalias X Xx
1419         commandalias Xx XxX
1420         commandalias XxX XxXx
1421         commandalias XxXx XxXxX
1422         commandalias XxXxX XxXxXx
1423         commandalias XxXxXx echo huhu
1424         commandalias XxXxXxX echo huhu
1425         X
1426         commandalias XxXxXx XxXxXxX
1427         X
1428         uncommandalias echo
1429         commandalias XxXxXx echo huhu
1430         X
1431         __EOT
1432
1433    check 1 0 "${MBOX}" '1638809585 36'
1434
1435    t_epilog "${@}"
1436 }
1437
1438 t_posix_abbrev() {
1439    t_prolog "${@}"
1440
1441    # In POSIX C181 standard order
1442    </dev/null ${MAILX} ${ARGS} \
1443       -Y 'echon alias/a\ ; ? a; echon group/g\ ; ?g' \
1444       -Y 'echon alternates/alt\ ; ? alt' \
1445       -Y 'echon chdir/ch\ ; ? ch' \
1446       -Y 'echon copy/c\ ; ? c; echon Copy/C\ ; ?C' \
1447       -Y 'echon delete/d\ ; ? d' \
1448       -Y 'echon discard/di\ ; ? di; echon ignore/ig\ ; ?ig' \
1449       -Y 'echon echo/ec\ ; ? ec' \
1450       -Y 'echon edit/e\ ; ? e' \
1451       -Y 'echon exit/ex\ ; ? ex; echon xit/x\ ; ?x' \
1452       -Y 'echon file/fi\ ; ? fi; echon folder/fold\ ; ?  fold' \
1453       -Y 'echon followup/fo\ ; ? fo; echon Followup/F\ ; ?F' \
1454       -Y 'echon from/f\ ; ? f' \
1455       -Y 'echon headers/h\ ; ? h' \
1456       -Y 'echon help/hel\ ; ? hel' \
1457       -Y 'echon hold/ho\ ; ? ho; echon preserve/pre\ ; ? pre' \
1458       -Y 'echon if/i\ ; ? i; echon else/el\ ; ? el; echon endif/en\ ; ? en' \
1459       -Y 'echon list/l\ ; ? l' \
1460       -Y 'echon mail/m\ ; ? m' \
1461       -Y 'echon mbox/mb\ ; ? mb' \
1462       -Y 'echon next/n\ ; ? n' \
1463       -Y 'echon pipe/pi\ ; ? pi' \
1464       -Y 'echon Print/P\ ; ? P; echon Type/T\ ; ? T' \
1465       -Y 'echon print/p\ ; ? p; echon type/t\ ; ? t' \
1466       -Y 'echon quit/q\ ; ? q' \
1467       -Y 'echon Reply/R\ ; ? R' \
1468       -Y 'echon reply/r\ ; ? r' \
1469       -Y 'echon retain/ret\ ; ? ret' \
1470       -Y 'echon save/s\ ; ? s; echon Save/S\ ; ? S' \
1471       -Y 'echon set/se\ ; ? se' \
1472       -Y 'echon shell/sh\ ; ? sh' \
1473       -Y 'echon size/si\ ; ? si' \
1474       -Y 'echon source/so\ ; ? so' \
1475       -Y 'echon touch/tou\ ; ? tou' \
1476       -Y 'echon unalias/una\ ; ? una' \
1477       -Y 'echon undelete/u\ ; ? u' \
1478       -Y 'echon unset/uns\ ; ? uns' \
1479       -Y 'echon visual/v\ ; ? v' \
1480       -Y 'echon write/w\ ; ? w' \
1481       | ${sed} -e 's/:.*$//' > "${MBOX}"
1482    check 1 0 "${MBOX}" '1012680481 968'
1483
1484    t_epilog "${@}"
1485 }
1486 # }}}
1487
1488 # Basics {{{
1489 t_shcodec() {
1490    t_prolog "${@}"
1491
1492    # XXX the first needs to be checked, it is quite dumb as such
1493    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>&1
1494         commandalias x echo '$?/$^ERRNAME'
1495         shcodec e abcd
1496         x
1497         shcodec d abcd
1498         x
1499         shcodec e a'b'c'd'
1500         x
1501         shcodec d a'b'c'd'
1502         x
1503         shcodec e a"b"c"d"
1504         x
1505         shcodec d a"b"c"d"
1506         x
1507         shcodec e a$'b'c$'d'
1508         x
1509         shcodec d a$'b'c$'d'
1510         x
1511         shcodec e 'abcd'
1512         x
1513         shcodec d 'abcd'
1514         x
1515         shcodec e "abcd"
1516         x
1517         shcodec d "abcd"
1518         x
1519         shcodec e $'abcd'
1520         x
1521         shcodec d $'abcd'
1522         x
1523         # same but with vput
1524         commandalias y echo '$?/$^ERRNAME $res'
1525         vput shcodec res e abcd
1526         y
1527         eval shcodec d $res
1528         x
1529         vput shcodec res d abcd
1530         y
1531         eval shcodec d $res
1532         x
1533         vput shcodec res e a'b'c'd'
1534         y
1535         eval shcodec d $res
1536         x
1537         vput shcodec res d a'b'c'd'
1538         y
1539         eval shcodec d $res
1540         x
1541         vput shcodec res e a"b"c"d"
1542         y
1543         eval shcodec d $res
1544         x
1545         vput shcodec res d a"b"c"d"
1546         y
1547         eval shcodec d $res
1548         x
1549         vput shcodec res e a$'b'c$'d'
1550         y
1551         eval shcodec d $res
1552         x
1553         vput shcodec res d a$'b'c$'d'
1554         y
1555         eval shcodec d $res
1556         x
1557         vput shcodec res e 'abcd'
1558         y
1559         eval shcodec d $res
1560         x
1561         vput shcodec res d 'abcd'
1562         y
1563         eval shcodec d $res
1564         x
1565         vput shcodec res e "abcd"
1566         y
1567         eval shcodec d $res
1568         x
1569         vput shcodec res d "abcd"
1570         y
1571         eval shcodec d $res
1572         x
1573         vput shcodec res e $'abcd'
1574         y
1575         eval shcodec d $res
1576         x
1577         vput shcodec res d $'abcd'
1578         y
1579         eval shcodec d $res
1580         x
1581         #
1582         vput shcodec res e a b\ c d
1583         y
1584         eval shcodec d $res
1585         x
1586         vput shcodec res d a b\ c d
1587         y
1588         vput shcodec res e ab cd
1589         y
1590         eval shcodec d $res
1591         x
1592         vput shcodec res d 'ab cd'
1593         y
1594         vput shcodec res e a 'b c' d
1595         y
1596         eval shcodec d $res
1597         x
1598         vput shcodec res d a 'b c' d
1599         y
1600         vput shcodec res e a "b c" d
1601         y
1602         eval shcodec d $res
1603         x
1604         vput shcodec res d a "b c" d
1605         y
1606         vput shcodec res e a $'b c' d
1607         y
1608         eval shcodec d $res
1609         x
1610         vput shcodec res d a $'b c' d
1611         y
1612         #
1613         vput shcodec res e 'a$`"\'
1614         y
1615         eval shcodec d $res
1616         x
1617         vput shcodec res d 'a$`"\'
1618         y
1619         vput shcodec res e "a\$\`'\"\\"
1620         y
1621         eval shcodec d $res
1622         x
1623         vput shcodec res d "a\$\`'\"\\"
1624         y
1625         vput shcodec res e $'a\$`\'\"\\'
1626         y
1627         eval shcodec d $res
1628         x
1629         vput shcodec res d $'a\$`\'\"\\'
1630         y
1631         vput shcodec res e $'a\$`\'"\\'
1632         y
1633         eval shcodec d $res
1634         x
1635         vput shcodec res d $'a\$`\'"\\'
1636         y
1637         #
1638         set diet=curd
1639         vput shcodec res e a${diet}c
1640         y
1641         eval shcodec d $res
1642         x
1643         eval vput shcodec res e a${diet}c
1644         y
1645         eval shcodec d $res
1646         x
1647         vput shcodec res e "a${diet}c"
1648         y
1649         eval shcodec d $res
1650         x
1651         eval vput shcodec res e "a${diet}c"
1652         y
1653         eval shcodec d $res
1654         x
1655         __EOT
1656    check 1 0 "${MBOX}" '3316745312 1241'
1657
1658    if [ -z "${UTF8_LOCALE}" ]; then
1659       t_echoskip 'unicode:[no UTF-8 locale]'
1660    elif have_feat multibyte-charsets; then
1661       ${cat} <<- '__EOT' | LC_ALL=${UTF8_LOCALE} \
1662          ${MAILX} ${ARGS} > "${MBOX}" 2>>${ERR}
1663                 #
1664                 shcodec e täst
1665                 shcodec +e täst
1666                 shcodec d $'t\u00E4st'
1667                 shcodec e aՍc
1668                 shcodec +e aՍc
1669                 shcodec d $'a\u054Dc'
1670                 shcodec e a𝕂c
1671                 shcodec +e a𝕂c
1672                 shcodec d $'a\U0001D542c'
1673                 __EOT
1674       check unicode 0 "${MBOX}" '1175985867 77'
1675    else
1676       t_echoskip 'unicode:[!MULTIBYTE-CHARSETS]'
1677    fi
1678
1679    t_epilog "${@}"
1680 }
1681
1682 t_ifelse() {
1683    t_prolog "${@}"
1684
1685    # v15compat: old and new tests share the same result files!
1686    # v15compat: i.e., just throw away -old tests one day
1687
1688    # Nestable conditions test
1689    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}"
1690                 if 0
1691                    echo 1.err
1692                 else
1693                    echo 1.ok
1694                 endif
1695                 if 1
1696                    echo 2.ok
1697                 else
1698                    echo 2.err
1699                 endif
1700                 if $dietcurd
1701                    echo 3.err
1702                 else
1703                    echo 3.ok
1704                 endif
1705                 set dietcurd=yoho
1706                 if $dietcurd
1707                    echo 4.ok
1708                 else
1709                    echo 4.err
1710                 endif
1711                 if $dietcurd == 'yoho'
1712                    echo 5.ok
1713                 else
1714                    echo 5.err
1715                 endif
1716                 if $dietcurd ==? 'Yoho'
1717                         echo 5-1.ok
1718                 else
1719                         echo 5-1.err
1720                 endif
1721                 if $dietcurd == 'Yoho'
1722                         echo 5-2.err
1723                 else
1724                         echo 5-2.ok
1725                 endif
1726                 if $dietcurd != 'yoho'
1727                    echo 6.err
1728                 else
1729                    echo 6.ok
1730                 endif
1731                 if $dietcurd !=?case 'Yoho'
1732                         echo 6-1.err
1733                 else
1734                         echo 6-1.ok
1735                 endif
1736                 if $dietcurd != 'Yoho'
1737                         echo 6-2.ok
1738                 else
1739                         echo 6-2.err
1740                 endif
1741                 # Nesting
1742                 if faLse
1743                    echo 7.err1
1744                    if tRue
1745                       echo 7.err2
1746                       if yEs
1747                          echo 7.err3
1748                       else
1749                          echo 7.err4
1750                       endif
1751                       echo 7.err5
1752                    endif
1753                    echo 7.err6
1754                 else
1755                    echo 7.ok7
1756                    if YeS
1757                       echo 7.ok8
1758                       if No
1759                          echo 7.err9
1760                       else
1761                          echo 7.ok9
1762                       endif
1763                       echo 7.ok10
1764                    else
1765                       echo 7.err11
1766                       if yeS
1767                          echo 7.err12
1768                       else
1769                          echo 7.err13
1770                       endif
1771                    endif
1772                    echo 7.ok14
1773                 endif
1774                 if r
1775                    echo 8.ok1
1776                    if R
1777                       echo 8.ok2
1778                    else
1779                       echo 8.err2
1780                    endif
1781                    echo 8.ok3
1782                 else
1783                    echo 8.err1
1784                 endif
1785                 if s
1786                    echo 9.err1
1787                 else
1788                    echo 9.ok1
1789                    if S
1790                       echo 9.err2
1791                    else
1792                       echo 9.ok2
1793                    endif
1794                    echo 9.ok3
1795                 endif
1796                 # `elif'
1797                 if $dietcurd == 'yohu'
1798                    echo 10.err1
1799                 elif $dietcurd == 'yoha'
1800                    echo 10.err2
1801                 elif $dietcurd == 'yohe'
1802                    echo 10.err3
1803                 elif $dietcurd == 'yoho'
1804                    echo 10.ok1
1805                    if $dietcurd == 'yohu'
1806                       echo 10.err4
1807                    elif $dietcurd == 'yoha'
1808                       echo 10.err5
1809                    elif $dietcurd == 'yohe'
1810                       echo 10.err6
1811                    elif $dietcurd == 'yoho'
1812                       echo 10.ok2
1813                       if $dietcurd == 'yohu'
1814                          echo 10.err7
1815                       elif $dietcurd == 'yoha'
1816                          echo 10.err8
1817                       elif $dietcurd == 'yohe'
1818                          echo 10.err9
1819                       elif $dietcurd == 'yoho'
1820                          echo 10.ok3
1821                       else
1822                          echo 10.err10
1823                       endif
1824                    else
1825                       echo 10.err11
1826                    endif
1827                 else
1828                    echo 10.err12
1829                 endif
1830                 # integer
1831                 set dietcurd=10
1832                 if $dietcurd -lt 11
1833                    echo 11.ok1
1834                    if $dietcurd -gt 9
1835                       echo 11.ok2
1836                    else
1837                       echo 11.err2
1838                    endif
1839                    if $dietcurd -eq 10
1840                       echo 11.ok3
1841                    else
1842                       echo 11.err3
1843                    endif
1844                    if $dietcurd -ge 10
1845                       echo 11.ok4
1846                    else
1847                       echo 11.err4
1848                    endif
1849                    if $dietcurd -le 10
1850                       echo 11.ok5
1851                    else
1852                       echo 11.err5
1853                    endif
1854                    if $dietcurd -ge 11
1855                       echo 11.err6
1856                    else
1857                       echo 11.ok6
1858                    endif
1859                    if $dietcurd -le 9
1860                       echo 11.err7
1861                    else
1862                       echo 11.ok7
1863                    endif
1864                 else
1865                    echo 11.err1
1866                 endif
1867                 set dietcurd=Abc
1868                 if $dietcurd < aBd
1869                    echo 12.ok1
1870                    if $dietcurd >? abB
1871                       echo 12.ok2
1872                    else
1873                       echo 12.err2
1874                    endif
1875                    if $dietcurd ==?case aBC
1876                       echo 12.ok3
1877                    else
1878                       echo 12.err3
1879                    endif
1880                    if $dietcurd >=?ca AbC
1881                       echo 12.ok4
1882                    else
1883                       echo 12.err4
1884                    endif
1885                    if $dietcurd <=? ABc
1886                       echo 12.ok5
1887                    else
1888                       echo 12.err5
1889                    endif
1890                    if $dietcurd >=?case abd
1891                       echo 12.err6
1892                    else
1893                       echo 12.ok6
1894                    endif
1895                    if $dietcurd <=? abb
1896                       echo 12.err7
1897                    else
1898                       echo 12.ok7
1899                    endif
1900                 else
1901                    echo 12.err1
1902                 endif
1903                 if $dietcurd < aBc
1904                    echo 12-1.ok
1905                 else
1906                    echo 12-1.err
1907                 endif
1908                 if $dietcurd <? aBc
1909                    echo 12-2.err
1910                 else
1911                    echo 12-2.ok
1912                 endif
1913                 if $dietcurd > ABc
1914                    echo 12-3.ok
1915                 else
1916                    echo 12-3.err
1917                 endif
1918                 if $dietcurd >? ABc
1919                    echo 12-3.err
1920                 else
1921                    echo 12-3.ok
1922                 endif
1923                 if $dietcurd =%?case aB
1924                    echo 13.ok
1925                 else
1926                    echo 13.err
1927                 endif
1928                 if $dietcurd =% aB
1929                    echo 13-1.err
1930                 else
1931                    echo 13-1.ok
1932                 endif
1933                 if $dietcurd =%? bC
1934                    echo 14.ok
1935                 else
1936                    echo 14.err
1937                 endif
1938                 if $dietcurd !% aB
1939                    echo 15-1.ok
1940                 else
1941                    echo 15-1.err
1942                 endif
1943                 if $dietcurd !%? aB
1944                    echo 15-2.err
1945                 else
1946                    echo 15-2.ok
1947                 endif
1948                 if $dietcurd !% bC
1949                    echo 15-3.ok
1950                 else
1951                    echo 15-3.err
1952                 endif
1953                 if $dietcurd !%? bC
1954                    echo 15-4.err
1955                 else
1956                    echo 15-4.ok
1957                 endif
1958                 if $dietcurd =% Cd
1959                    echo 16.err
1960                 else
1961                    echo 16.ok
1962                 endif
1963                 if $dietcurd !% Cd
1964                    echo 17.ok
1965                 else
1966                    echo 17.err
1967                 endif
1968                 set diet=abc curd=abc
1969                 if $diet == $curd
1970                    echo 18.ok
1971                 else
1972                    echo 18.err
1973                 endif
1974                 set diet=abc curd=abcd
1975                 if $diet != $curd
1976                    echo 19.ok
1977                 else
1978                    echo 19.err
1979                 endif
1980                 # 1. Shitty grouping capabilities as of today
1981                 unset diet curd ndefined
1982                 if [ [ false ] || [ false ] || [ true ] ] && \
1983                       [ [ false ] || [ true ] ] && \
1984                       [ yes ]
1985                    echo 20.ok
1986                 else
1987                    echo 20.err
1988                 endif
1989                 if [ [ [ [ 0 ] || [ 1 ] ] && [ [ 1 ] || [ 0 ] ] ] && [ 1 ] ] && [ yes ]
1990                    echo 21.ok
1991                 else
1992                    echo 21.err
1993                 endif
1994                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] ]
1995                    echo 22.ok
1996                 else
1997                    echo 22.err
1998                 endif
1999                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] || [ [ 1 ] ] ]
2000                    echo 23.ok
2001                 else
2002                    echo 23.err
2003                 endif
2004                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] || [ [ 1 ] ] || [ 1 ] ] && [ no ]
2005                    echo 24.err
2006                 else
2007                    echo 24.ok
2008                 endif
2009                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] || [ [ 1 ] ] || [ 1 ] ] \
2010                       && [ no ] || [ yes ]
2011                    echo 25.ok
2012                 else
2013                    echo 25.err
2014                 endif
2015                 if [ [ [ [ [ [ [ 1 ] ] && [ 1 ] ] && [ 1 ] ] && [ 1 ] ] ] && [ 1 ] ]
2016                    echo 26.ok
2017                 else
2018                    echo 26.err
2019                 endif
2020                 if [ [ [ [ [ [ [ 1 ] ] && [ 1 ] ] && [ 1 ] ] && [ 1 ] ] ] && [ 0 ] ]
2021                    echo 27.err
2022                 else
2023                    echo 27.ok
2024                 endif
2025                 if [ [ [ [ [ [ [ 1 ] ] && [ 1 ] ] && [ 0 ] ] && [ 1 ] ] ] && [ 1 ] ]
2026                    echo 28.err
2027                 else
2028                    echo 28.ok
2029                 endif
2030                 if [ [ [ [ [ [ [ 0 ] ] && [ 1 ] ] && [ 1 ] ] && [ 1 ] ] ] && [ 1 ] ]
2031                    echo 29.err
2032                 else
2033                    echo 29.ok
2034                 endif
2035                 if [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] && [ 0 ]
2036                    echo 30.err
2037                 else
2038                    echo 30.ok
2039                 endif
2040                 if [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] && [ 1 ]
2041                    echo 31.ok
2042                 else
2043                    echo 31.err
2044                 endif
2045                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 0 ]
2046                    echo 32.err
2047                 else
2048                    echo 32.ok
2049                 endif
2050                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 1 ]
2051                    echo 33.ok
2052                 else
2053                    echo 33.err
2054                 endif
2055                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 0 ] || [ 1 ] && [ 0 ]
2056                    echo 34.err
2057                 else
2058                    echo 34.ok
2059                 endif
2060                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 0 ] || [ 1 ] && [ 1 ]
2061                    echo 35.ok
2062                 else
2063                    echo 35.err
2064                 endif
2065                 set diet=yo curd=ho
2066                 if [ [ $diet == 'yo' ] && [ $curd == 'ho' ] ] && [ $ndefined ]
2067                    echo 36.err
2068                 else
2069                    echo 36.ok
2070                 endif
2071                 set ndefined
2072                 if [ [ $diet == 'yo' ] && [ $curd == 'ho' ] ] && [ $ndefined ]
2073                    echo 37.ok
2074                 else
2075                    echo 37.err
2076                 endif
2077                 # 2. Shitty grouping capabilities as of today
2078                 unset diet curd ndefined
2079                 if [ false || false || true ] && [ false || true ] && yes
2080                    echo 40.ok
2081                 else
2082                    echo 40.err
2083                 endif
2084                 if [ [ [ 0 || 1 ] && [ 1 || 0 ] ] && 1 ] && [ yes ]
2085                    echo 41.ok
2086                 else
2087                    echo 41.err
2088                 endif
2089                 if [ 1 || 0 || 0 || 0 ]
2090                    echo 42.ok
2091                 else
2092                    echo 42.err
2093                 endif
2094                 if [ 1 || 0 || 0 || 0 || [ 1 ] ]
2095                    echo 43.ok
2096                 else
2097                    echo 43.err
2098                 endif
2099                 if [ 1 || 0 || 0 || 0 || [ 1 ] || 1 ] && no
2100                    echo 44.err
2101                 else
2102                    echo 44.ok
2103                 endif
2104                 if [ 1 || 0 || 0 || 0 || 1 || [ 1 ] ] && no || [ yes ]
2105                    echo 45.ok
2106                 else
2107                    echo 45.err
2108                 endif
2109                 if [ [ [ [ [ [ 1 ] && 1 ] && 1 ] && 1 ] ] && [ 1 ] ]
2110                    echo 46.ok
2111                 else
2112                    echo 46.err
2113                 endif
2114                 if [ [ [ [ [ [ 1 ] && 1 ] && 1 ] && [ 1 ] ] ] && 0 ]
2115                    echo 47.err
2116                 else
2117                    echo 47.ok
2118                 endif
2119                 if [ [ [ [ [ [ [ 1 ] ] && 1 ] && 0 ] && [ 1 ] ] ] && 1 ]
2120                    echo 48.err
2121                 else
2122                    echo 48.ok
2123                 endif
2124                 if [ [ [ [ [ [ 0 ] && 1 ] && 1 ] && 1 ] ] && 1 ]
2125                    echo 49.err
2126                 else
2127                    echo 49.ok
2128                 endif
2129                 if 1 || 0 || 0 || 0 && 0
2130                    echo 50.err
2131                 else
2132                    echo 50.ok
2133                 endif
2134                 if 1 || 0 || 0 || 0 && 1
2135                    echo 51.ok
2136                 else
2137                    echo 51.err
2138                 endif
2139                 if 0 || 0 || 0 || 1 && 0
2140                    echo 52.err
2141                 else
2142                    echo 52.ok
2143                 endif
2144                 if 0 || 0 || 0 || 1 && 1
2145                    echo 53.ok
2146                 else
2147                    echo 53.err
2148                 endif
2149                 if 0 || 0 || 0 || 1 && 0 || 1 && 0
2150                    echo 54.err
2151                 else
2152                    echo 54.ok
2153                 endif
2154                 if 0 || 0 || 0 || 1 && 0 || 1 && 1
2155                    echo 55.ok
2156                 else
2157                    echo 55.err
2158                 endif
2159                 set diet=yo curd=ho
2160                 if [ $diet == 'yo' && $curd == 'ho' ] && $ndefined
2161                    echo 56.err
2162                 else
2163                    echo 56.ok
2164                 endif
2165                 if $diet == 'yo' && $curd == 'ho' && $ndefined
2166                    echo 57.err
2167                 else
2168                    echo 57.ok
2169                 endif
2170                 set ndefined
2171                 if [ $diet == 'yo' && $curd == 'ho' ] && $ndefined
2172                    echo 57.ok
2173                 else
2174                    echo 57.err
2175                 endif
2176                 if $diet == 'yo' && $curd == 'ho' && $ndefined
2177                    echo 58.ok
2178                 else
2179                    echo 58.err
2180                 endif
2181                 if [ [ [ [ [ [ $diet == 'yo' && $curd == 'ho' && $ndefined ] ] ] ] ] ]
2182                    echo 59.ok
2183                 else
2184                    echo 59.err
2185                 endif
2186                 # Some more en-braced variables
2187                 set diet=yo curd=ho
2188                 if ${diet} == ${curd}
2189                    echo 70.err
2190                 else
2191                    echo 70.ok
2192                 endif
2193                 if ${diet} != ${curd}
2194                    echo 71.ok
2195                 else
2196                    echo 71.err
2197                 endif
2198                 if $diet == ${curd}
2199                    echo 72.err
2200                 else
2201                    echo 72.ok
2202                 endif
2203                 if ${diet} == $curd
2204                    echo 73.err
2205                 else
2206                    echo 73.ok
2207                 endif
2208                 # Unary !
2209                 if ! 0 && ! ! 1 && ! ! ! ! 2 && 3
2210                    echo 80.ok
2211                 else
2212                    echo 80.err
2213                 endif
2214                 if ! 0 && ! [ ! 1 ] && ! [ ! [ ! [ ! 2 ] ] ] && 3
2215                    echo 81.ok
2216                 else
2217                    echo 81.err
2218                 endif
2219                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && 3
2220                    echo 82.ok
2221                 else
2222                    echo 82.err
2223                 endif
2224                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && ! 3
2225                    echo 83.err
2226                 else
2227                    echo 83.ok
2228                 endif
2229                 if [ ! 0 ] && [ ! [ ! 1 ] ] && ! [ [ ! [ ! [ ! [ 2 ] ] ] ] ] && ! 3
2230                    echo 84.err
2231                 else
2232                    echo 84.ok
2233                 endif
2234                 if [ ! 0 ] && ! [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && 3
2235                    echo 85.err
2236                 else
2237                    echo 85.ok
2238                 endif
2239                 if ! [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && 3
2240                    echo 86.err
2241                 else
2242                    echo 86.ok
2243                 endif
2244                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] || 3
2245                    echo 87.ok
2246                 else
2247                    echo 87.err
2248                 endif
2249                 if [ ! 0 ] && [ ! ! [ ! ! 1 ] ] && [ ! ! [ ! ! [ ! ! [ ! ! [ 2 ] ] ] ] ]
2250                    echo 88.ok
2251                 else
2252                    echo 88.err
2253                 endif
2254                 # Unary !, odd
2255                 if ! 0 && ! ! 1 && ! ! ! 0 && 3
2256                    echo 90.ok
2257                 else
2258                    echo 90.err
2259                 endif
2260                 if ! 0 && ! [ ! 1 ] && ! [ ! [ ! [ 0 ] ] ] && 3
2261                    echo 91.ok
2262                 else
2263                    echo 91.err
2264                 endif
2265                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ [ 0 ] ] ] ] ] && 3
2266                    echo 92.ok
2267                 else
2268                    echo 92.err
2269                 endif
2270                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! ! [ ! [ ! 0 ] ] ] ] && ! 3
2271                    echo 93.err
2272                 else
2273                    echo 93.ok
2274                 endif
2275                 if [ ! 0 ] && [ ! [ ! 1 ] ] && ! [ ! [ ! [ ! [ ! 0 ] ] ] ] && 3
2276                    echo 94.ok
2277                 else
2278                    echo 94.err
2279                 endif
2280                 if [ ! 0 ] && ! [ ! [ ! 1 ] ] && [ ! ! [ ! [ ! [ ! [ 0 ] ] ] ] ] && 3
2281                    echo 95.err
2282                 else
2283                    echo 95.ok
2284                 endif
2285                 if ! [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! ! 0 ] ] ] ] && 3
2286                    echo 96.err
2287                 else
2288                    echo 96.ok
2289                 endif
2290                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ ! 0 ] ] ] ] ] || 3
2291                    echo 97.ok
2292                 else
2293                    echo 97.err
2294                 endif
2295                 if [ ! 0 ] && [ ! ! [ ! ! 1 ] ] && [ ! ! [ ! ! [ ! ! [ ! [ 0 ] ] ] ] ]
2296                    echo 98.ok
2297                 else
2298                    echo 98.err
2299                 endif
2300         __EOT
2301
2302    check normal-old 0 "${MBOX}" '1688759742 719' # pre v15compat
2303
2304    if have_feat regex; then
2305       ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}"
2306                         set dietcurd=yoho
2307                         if $dietcurd =~ '^yo.*'
2308                            echo 1.ok
2309                         else
2310                            echo 1.err
2311                         endif
2312                         if $dietcurd =~ '^Yo.*'
2313                            echo 1-1.err
2314                         else
2315                            echo 1-1.ok
2316                         endif
2317                         if $dietcurd =~?case '^Yo.*'
2318                            echo 1-2.ok
2319                         else
2320                            echo 1-2.err
2321                         endif
2322                         if $dietcurd =~ '^yOho.+'
2323                            echo 2.err
2324                         else
2325                            echo 2.ok
2326                         endif
2327                         if $dietcurd !~? '.*Ho$'
2328                            echo 3.err
2329                         else
2330                            echo 3.ok
2331                         endif
2332                         if $dietcurd !~ '.+yohO$'
2333                            echo 4.ok
2334                         else
2335                            echo 4.err
2336                         endif
2337                         if [ $dietcurd !~?cas '.+yoho$' ]
2338                            echo 5.ok
2339                         else
2340                            echo 5.err
2341                         endif
2342                         if ! [ $dietcurd =~?case '.+yoho$' ]
2343                            echo 6.ok
2344                         else
2345                            echo 6.err
2346                         endif
2347                         if ! ! [ $dietcurd !~? '.+yoho$' ]
2348                            echo 7.ok
2349                         else
2350                            echo 7.err
2351                         endif
2352                         if ! [ ! [ $dietcurd !~? '.+yoho$' ] ]
2353                            echo 8.ok
2354                         else
2355                            echo 8.err
2356                         endif
2357                         if [ ! [ ! [ $dietcurd !~? '.+yoho$' ] ] ]
2358                            echo 9.ok
2359                         else
2360                            echo 9.err
2361                         endif
2362                         if ! [ ! [ ! [ $dietcurd !~ '.+yoho$' ] ] ]
2363                            echo 10.err
2364                         else
2365                            echo 10.ok
2366                         endif
2367                         if !  ! ! $dietcurd !~ '.+yoho$'
2368                            echo 11.err
2369                         else
2370                            echo 11.ok
2371                         endif
2372                         if !  ! ! $dietcurd =~ '.+yoho$'
2373                            echo 12.ok
2374                         else
2375                            echo 12.err
2376                         endif
2377                         if ! [ ! ! [ ! [ $dietcurd !~ '.+yoho$' ] ] ]
2378                            echo 13.ok
2379                         else
2380                            echo 13.err
2381                         endif
2382                         set diet=abc curd='^abc$'
2383                         if $diet =~ $curd
2384                            echo 14.ok
2385                         else
2386                            echo 14.err
2387                         endif
2388                         set diet=abc curd='^abcd$'
2389                         if $diet !~ $curd
2390                            echo 15.ok
2391                         else
2392                            echo 15.err
2393                         endif
2394                 __EOT
2395
2396       check regex-old 0 "${MBOX}" '1115671789 95' # pre v15compat
2397    else
2398       t_echoskip 'regex-old:[no regex option]'
2399    fi
2400
2401    ## post v15compat
2402
2403    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} -Sv15-compat=X > "${MBOX}"
2404         \if -N xyz; echo 1.err-1; \
2405                 \elif ! -Z xyz;echo 1.err-2;\
2406                 \elif -n "$xyz"     ;      echo 1.err-3   ;    \
2407                 \elif ! -z "$xyz"     ;      echo 1.err-4   ;    \
2408                 \else;echo 1.ok;\
2409                 \end
2410         \set xyz
2411         \if ! -N xyz; echo 2.err-1; \
2412                 \elif -Z xyz;echo 2.err-2;\
2413                 \elif -n "$xyz"     ;      echo 2.err-3   ;    \
2414                 \elif ! -z "$xyz"     ;      echo 2.err-4   ;    \
2415                 \else;echo 2.ok;\
2416                 \end
2417         \set xyz=notempty
2418         \if ! -N xyz; echo 3.err-1; \
2419                 \elif -Z xyz;echo 3.err-2;\
2420                 \elif ! -n "$xyz";echo 3.err-3;\
2421                 \elif -z "$xyz";echo 3.err-4;\
2422                 \else;echo 3.ok;\
2423                 \end
2424         \if $xyz != notempty;echo 4.err-1;else;echo 4.ok;\end
2425         \if $xyz == notempty;echo 5.ok;else;echo 5.err-1;\end
2426         __EOT
2427
2428    check NnZz_whiteout 0 "${MBOX}" '4280687462 25'
2429
2430    # TODO t_ifelse: individual tests as for NnZz_whiteout
2431    # Nestable conditions test
2432    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} -Sv15-compat=x > "${MBOX}"
2433                 if 0
2434                    echo 1.err
2435                 else
2436                    echo 1.ok
2437                 endif
2438                 if 1
2439                    echo 2.ok
2440                 else
2441                    echo 2.err
2442                 endif
2443                 if [ "$dietcurd" != "" ]
2444                    echo 3.err
2445                 else
2446                    echo 3.ok
2447                 endif
2448                 set dietcurd=yoho
2449                 if $'\$dietcurd' != ""
2450                    echo 4.ok
2451                 else
2452                    echo 4.err
2453                 endif
2454                 if "$dietcurd" == 'yoho'
2455                    echo 5.ok
2456                 else
2457                    echo 5.err
2458                 endif
2459                 if $'\$dietcurd' ==? 'Yoho'
2460                         echo 5-1.ok
2461                 else
2462                         echo 5-1.err
2463                 endif
2464                 if $dietcurd == 'Yoho'
2465                         echo 5-2.err
2466                 else
2467                         echo 5-2.ok
2468                 endif
2469                 if $dietcurd != 'yoho'
2470                    echo 6.err
2471                 else
2472                    echo 6.ok
2473                 endif
2474                 if $dietcurd !=?case 'Yoho'
2475                         echo 6-1.err
2476                 else
2477                         echo 6-1.ok
2478                 endif
2479                 if $dietcurd != 'Yoho'
2480                         echo 6-2.ok
2481                 else
2482                         echo 6-2.err
2483                 endif
2484                 # Nesting
2485                 if faLse
2486                    echo 7.err1
2487                    if tRue
2488                       echo 7.err2
2489                       if yEs
2490                          echo 7.err3
2491                       else
2492                          echo 7.err4
2493                       endif
2494                       echo 7.err5
2495                    endif
2496                    echo 7.err6
2497                 else
2498                    echo 7.ok7
2499                    if YeS
2500                       echo 7.ok8
2501                       if No
2502                          echo 7.err9
2503                       else
2504                          echo 7.ok9
2505                       endif
2506                       echo 7.ok10
2507                    else
2508                       echo 7.err11
2509                       if yeS
2510                          echo 7.err12
2511                       else
2512                          echo 7.err13
2513                       endif
2514                    endif
2515                    echo 7.ok14
2516                 endif
2517                 if r
2518                    echo 8.ok1
2519                    if R
2520                       echo 8.ok2
2521                    else
2522                       echo 8.err2
2523                    endif
2524                    echo 8.ok3
2525                 else
2526                    echo 8.err1
2527                 endif
2528                 if s
2529                    echo 9.err1
2530                 else
2531                    echo 9.ok1
2532                    if S
2533                       echo 9.err2
2534                    else
2535                       echo 9.ok2
2536                    endif
2537                    echo 9.ok3
2538                 endif
2539                 # `elif'
2540                 if $dietcurd == 'yohu'
2541                    echo 10.err1
2542                 elif $dietcurd == 'yoha'
2543                    echo 10.err2
2544                 elif $dietcurd == 'yohe'
2545                    echo 10.err3
2546                 elif $dietcurd == 'yoho'
2547                    echo 10.ok1
2548                    if $dietcurd == 'yohu'
2549                       echo 10.err4
2550                    elif $dietcurd == 'yoha'
2551                       echo 10.err5
2552                    elif $dietcurd == 'yohe'
2553                       echo 10.err6
2554                    elif $dietcurd == 'yoho'
2555                       echo 10.ok2
2556                       if $dietcurd == 'yohu'
2557                          echo 10.err7
2558                       elif $dietcurd == 'yoha'
2559                          echo 10.err8
2560                       elif $dietcurd == 'yohe'
2561                          echo 10.err9
2562                       elif $dietcurd == 'yoho'
2563                          echo 10.ok3
2564                       else
2565                          echo 10.err10
2566                       endif
2567                    else
2568                       echo 10.err11
2569                    endif
2570                 else
2571                    echo 10.err12
2572                 endif
2573                 # integer
2574                 set dietcurd=10
2575                 if $dietcurd -lt 11
2576                    echo 11.ok1
2577                    if $dietcurd -gt 9
2578                       echo 11.ok2
2579                    else
2580                       echo 11.err2
2581                    endif
2582                    if $dietcurd -eq 10
2583                       echo 11.ok3
2584                    else
2585                       echo 11.err3
2586                    endif
2587                    if $dietcurd -ge 10
2588                       echo 11.ok4
2589                    else
2590                       echo 11.err4
2591                    endif
2592                    if $dietcurd -le 10
2593                       echo 11.ok5
2594                    else
2595                       echo 11.err5
2596                    endif
2597                    if $dietcurd -ge 11
2598                       echo 11.err6
2599                    else
2600                       echo 11.ok6
2601                    endif
2602                    if $dietcurd -ge?satu -0xFFFFFFFFFFFFFFFF1
2603                       echo 11.err7
2604                    else
2605                       echo 11.ok7
2606                    endif
2607                 else
2608                    echo 11.err1
2609                 endif
2610                 set dietcurd=Abc
2611                 if $dietcurd < aBd
2612                    echo 12.ok1
2613                    if $dietcurd >? abB
2614                       echo 12.ok2
2615                    else
2616                       echo 12.err2
2617                    endif
2618                    if $dietcurd ==?case aBC
2619                       echo 12.ok3
2620                    else
2621                       echo 12.err3
2622                    endif
2623                    if $dietcurd >=?ca AbC
2624                       echo 12.ok4
2625                    else
2626                       echo 12.err4
2627                    endif
2628                    if $dietcurd <=? ABc
2629                       echo 12.ok5
2630                    else
2631                       echo 12.err5
2632                    endif
2633                    if $dietcurd >=?case abd
2634                       echo 12.err6
2635                    else
2636                       echo 12.ok6
2637                    endif
2638                    if $dietcurd <=? abb
2639                       echo 12.err7
2640                    else
2641                       echo 12.ok7
2642                    endif
2643                 else
2644                    echo 12.err1
2645                 endif
2646                 if $dietcurd < aBc
2647                    echo 12-1.ok
2648                 else
2649                    echo 12-1.err
2650                 endif
2651                 if $dietcurd <? aBc
2652                    echo 12-2.err
2653                 else
2654                    echo 12-2.ok
2655                 endif
2656                 if $dietcurd > ABc
2657                    echo 12-3.ok
2658                 else
2659                    echo 12-3.err
2660                 endif
2661                 if $dietcurd >? ABc
2662                    echo 12-3.err
2663                 else
2664                    echo 12-3.ok
2665                 endif
2666                 if $dietcurd =%?case aB
2667                    echo 13.ok
2668                 else
2669                    echo 13.err
2670                 endif
2671                 if $dietcurd =% aB
2672                    echo 13-1.err
2673                 else
2674                    echo 13-1.ok
2675                 endif
2676                 if $dietcurd =%? bC
2677                    echo 14.ok
2678                 else
2679                    echo 14.err
2680                 endif
2681                 if $dietcurd !% aB
2682                    echo 15-1.ok
2683                 else
2684                    echo 15-1.err
2685                 endif
2686                 if $dietcurd !%? aB
2687                    echo 15-2.err
2688                 else
2689                    echo 15-2.ok
2690                 endif
2691                 if $dietcurd !% bC
2692                    echo 15-3.ok
2693                 else
2694                    echo 15-3.err
2695                 endif
2696                 if $dietcurd !%? bC
2697                    echo 15-4.err
2698                 else
2699                    echo 15-4.ok
2700                 endif
2701                 if $dietcurd =% Cd
2702                    echo 16.err
2703                 else
2704                    echo 16.ok
2705                 endif
2706                 if $dietcurd !% Cd
2707                    echo 17.ok
2708                 else
2709                    echo 17.err
2710                 endif
2711                 set diet='ab c' curd='ab c'
2712                 if "$diet" == "$curd"
2713                    echo 18.ok
2714                 else
2715                    echo 18.err
2716                 endif
2717                 set diet='ab c' curd='ab cd'
2718                 if "$diet" != "$curd"
2719                    echo 19.ok
2720                 else
2721                    echo 19.err
2722                 endif
2723                 # 1. Shitty grouping capabilities as of today
2724                 unset diet curd ndefined
2725                 if [ [ false ] || [ false ] || [ true ] ] && \
2726                       [ [ false ] || [ true ] ] && \
2727                       [ yes ]
2728                    echo 20.ok
2729                 else
2730                    echo 20.err
2731                 endif
2732                 if [ [ [ [ 0 ] || [ 1 ] ] && [ [ 1 ] || [ 0 ] ] ] && [ 1 ] ] && [ yes ]
2733                    echo 21.ok
2734                 else
2735                    echo 21.err
2736                 endif
2737                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] ]
2738                    echo 22.ok
2739                 else
2740                    echo 22.err
2741                 endif
2742                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] || [ [ 1 ] ] ]
2743                    echo 23.ok
2744                 else
2745                    echo 23.err
2746                 endif
2747                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] || [ [ 1 ] ] || [ 1 ] ] && [ no ]
2748                    echo 24.err
2749                 else
2750                    echo 24.ok
2751                 endif
2752                 if [ [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] || [ [ 1 ] ] || [ 1 ] ] \
2753                       && [ no ] || [ yes ]
2754                    echo 25.ok
2755                 else
2756                    echo 25.err
2757                 endif
2758                 if [ [ [ [ [ [ [ 1 ] ] && [ 1 ] ] && [ 1 ] ] && [ 1 ] ] ] && [ 1 ] ]
2759                    echo 26.ok
2760                 else
2761                    echo 26.err
2762                 endif
2763                 if [ [ [ [ [ [ [ 1 ] ] && [ 1 ] ] && [ 1 ] ] && [ 1 ] ] ] && [ 0 ] ]
2764                    echo 27.err
2765                 else
2766                    echo 27.ok
2767                 endif
2768                 if [ [ [ [ [ [ [ 1 ] ] && [ 1 ] ] && [ 0 ] ] && [ 1 ] ] ] && [ 1 ] ]
2769                    echo 28.err
2770                 else
2771                    echo 28.ok
2772                 endif
2773                 if [ [ [ [ [ [ [ 0 ] ] && [ 1 ] ] && [ 1 ] ] && [ 1 ] ] ] && [ 1 ] ]
2774                    echo 29.err
2775                 else
2776                    echo 29.ok
2777                 endif
2778                 if [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] && [ 0 ]
2779                    echo 30.err
2780                 else
2781                    echo 30.ok
2782                 endif
2783                 if [ 1 ] || [ 0 ] || [ 0 ] || [ 0 ] && [ 1 ]
2784                    echo 31.ok
2785                 else
2786                    echo 31.err
2787                 endif
2788                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 0 ]
2789                    echo 32.err
2790                 else
2791                    echo 32.ok
2792                 endif
2793                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 1 ]
2794                    echo 33.ok
2795                 else
2796                    echo 33.err
2797                 endif
2798                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 0 ] || [ 1 ] && [ 0 ]
2799                    echo 34.err
2800                 else
2801                    echo 34.ok
2802                 endif
2803                 if [ 0 ] || [ 0 ] || [ 0 ] || [ 1 ] && [ 0 ] || [ 1 ] && [ 1 ]
2804                    echo 35.ok
2805                 else
2806                    echo 35.err
2807                 endif
2808                 set diet=yo curd=ho
2809                 if [ [ $diet == 'yo' ] && [ $curd == 'ho' ] ] && \
2810                       [ -N ndefined || -n "$ndefined" || \
2811                       ! -Z ndefined || ! -z "$ndefined" ]
2812                    echo 36.err
2813                 else
2814                    echo 36.ok
2815                 endif
2816                 set ndefined
2817                 if [ [ $diet == 'yo' ] && [ $curd == 'ho' ] ] && \
2818                       -N ndefined && ! -n "$ndefined" && \
2819                       ! -Z ndefined && -z "$ndefined"
2820                    echo 37.ok
2821                 else
2822                    echo 37.err
2823                 endif
2824                 # 2. Shitty grouping capabilities as of today
2825                 unset diet curd ndefined
2826                 if [ false || false || true ] && [ false || true ] && yes
2827                    echo 40.ok
2828                 else
2829                    echo 40.err
2830                 endif
2831                 if [ [ [ 0 || 1 ] && [ 1 || 0 ] ] && 1 ] && [ yes ]
2832                    echo 41.ok
2833                 else
2834                    echo 41.err
2835                 endif
2836                 if [ 1 || 0 || 0 || 0 ]
2837                    echo 42.ok
2838                 else
2839                    echo 42.err
2840                 endif
2841                 if [ 1 || 0 || 0 || 0 || [ 1 ] ]
2842                    echo 43.ok
2843                 else
2844                    echo 43.err
2845                 endif
2846                 if [ 1 || 0 || 0 || 0 || [ 1 ] || 1 ] && no
2847                    echo 44.err
2848                 else
2849                    echo 44.ok
2850                 endif
2851                 if [ 1 || 0 || 0 || 0 || 1 || [ 1 ] ] && no || [ yes ]
2852                    echo 45.ok
2853                 else
2854                    echo 45.err
2855                 endif
2856                 if [ [ [ [ [ [ 1 ] && 1 ] && 1 ] && 1 ] ] && [ 1 ] ]
2857                    echo 46.ok
2858                 else
2859                    echo 46.err
2860                 endif
2861                 if [ [ [ [ [ [ 1 ] && 1 ] && 1 ] && [ 1 ] ] ] && 0 ]
2862                    echo 47.err
2863                 else
2864                    echo 47.ok
2865                 endif
2866                 if [ [ [ [ [ [ [ 1 ] ] && 1 ] && 0 ] && [ 1 ] ] ] && 1 ]
2867                    echo 48.err
2868                 else
2869                    echo 48.ok
2870                 endif
2871                 if [ [ [ [ [ [ 0 ] && 1 ] && 1 ] && 1 ] ] && 1 ]
2872                    echo 49.err
2873                 else
2874                    echo 49.ok
2875                 endif
2876                 if 1 || 0 || 0 || 0 && 0
2877                    echo 50.err
2878                 else
2879                    echo 50.ok
2880                 endif
2881                 if 1 || 0 || 0 || 0 && 1
2882                    echo 51.ok
2883                 else
2884                    echo 51.err
2885                 endif
2886                 if 0 || 0 || 0 || 1 && 0
2887                    echo 52.err
2888                 else
2889                    echo 52.ok
2890                 endif
2891                 if 0 || 0 || 0 || 1 && 1
2892                    echo 53.ok
2893                 else
2894                    echo 53.err
2895                 endif
2896                 if 0 || 0 || 0 || 1 && 0 || 1 && 0
2897                    echo 54.err
2898                 else
2899                    echo 54.ok
2900                 endif
2901                 if 0 || 0 || 0 || 1 && 0 || 1 && 1
2902                    echo 55.ok
2903                 else
2904                    echo 55.err
2905                 endif
2906                 set diet=yo curd=ho
2907                 if [ $diet == 'yo' && $curd == 'ho' ] && \
2908                       [ -N ndefined || -n "$ndefined" || \
2909                          ! -Z ndefined || ! -z "$ndefined" ]
2910                    echo 56.err
2911                 else
2912                    echo 56.ok
2913                 endif
2914                 if [ $diet == 'yo' && $curd == 'ho' && \
2915                       [ [ -N ndefined || -n "$ndefined" || \
2916                          ! -Z ndefined || ! -z "$ndefined" ] ] ]
2917                    echo 57.err
2918                 else
2919                    echo 57.ok
2920                 endif
2921                 set ndefined
2922                 if [ $diet == 'yo' && $curd == 'ho' ] && \
2923                       -N ndefined && ! -n "$ndefined" && \
2924                       ! -Z ndefined && -z "$ndefined"
2925                    echo 57.ok
2926                 else
2927                    echo 57.err
2928                 endif
2929                 if $diet == 'yo' && $curd == 'ho' && ! -Z ndefined
2930                    echo 58.ok
2931                 else
2932                    echo 58.err
2933                 endif
2934                 if [ [ [ [ [ [ $diet == 'yo' && $curd == 'ho' && -N ndefined ] ] ] ] ] ]
2935                    echo 59.ok
2936                 else
2937                    echo 59.err
2938                 endif
2939                 # Some more en-braced variables
2940                 set diet=yo curd=ho
2941                 if ${diet} == ${curd}
2942                    echo 70.err
2943                 else
2944                    echo 70.ok
2945                 endif
2946                 if "${diet}" != "${curd}"
2947                    echo 71.ok
2948                 else
2949                    echo 71.err
2950                 endif
2951                 if $diet == ${curd}
2952                    echo 72.err
2953                 else
2954                    echo 72.ok
2955                 endif
2956                 if ${diet} == $curd
2957                    echo 73.err
2958                 else
2959                    echo 73.ok
2960                 endif
2961                 # Unary !
2962                 if ! 0 && ! ! 1 && ! ! ! ! 2 && 3
2963                    echo 80.ok
2964                 else
2965                    echo 80.err
2966                 endif
2967                 if ! 0 && ! [ ! 1 ] && ! [ ! [ ! [ ! 2 ] ] ] && 3
2968                    echo 81.ok
2969                 else
2970                    echo 81.err
2971                 endif
2972                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && 3
2973                    echo 82.ok
2974                 else
2975                    echo 82.err
2976                 endif
2977                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && ! 3
2978                    echo 83.err
2979                 else
2980                    echo 83.ok
2981                 endif
2982                 if [ ! 0 ] && [ ! [ ! 1 ] ] && ! [ [ ! [ ! [ ! [ 2 ] ] ] ] ] && ! 3
2983                    echo 84.err
2984                 else
2985                    echo 84.ok
2986                 endif
2987                 if [ ! 0 ] && ! [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && 3
2988                    echo 85.err
2989                 else
2990                    echo 85.ok
2991                 endif
2992                 if ! [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] && 3
2993                    echo 86.err
2994                 else
2995                    echo 86.ok
2996                 endif
2997                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ 2 ] ] ] ] ] || 3
2998                    echo 87.ok
2999                 else
3000                    echo 87.err
3001                 endif
3002                 if [ ! 0 ] && [ ! ! [ ! ! 1 ] ] && [ ! ! [ ! ! [ ! ! [ ! ! [ 2 ] ] ] ] ]
3003                    echo 88.ok
3004                 else
3005                    echo 88.err
3006                 endif
3007                 # Unary !, odd
3008                 if ! 0 && ! ! 1 && ! ! ! 0 && 3
3009                    echo 90.ok
3010                 else
3011                    echo 90.err
3012                 endif
3013                 if ! 0 && ! [ ! 1 ] && ! [ ! [ ! [ 0 ] ] ] && 3
3014                    echo 91.ok
3015                 else
3016                    echo 91.err
3017                 endif
3018                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ [ 0 ] ] ] ] ] && 3
3019                    echo 92.ok
3020                 else
3021                    echo 92.err
3022                 endif
3023                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! ! [ ! [ ! 0 ] ] ] ] && ! 3
3024                    echo 93.err
3025                 else
3026                    echo 93.ok
3027                 endif
3028                 if [ ! 0 ] && [ ! [ ! 1 ] ] && ! [ ! [ ! [ ! [ ! 0 ] ] ] ] && 3
3029                    echo 94.ok
3030                 else
3031                    echo 94.err
3032                 endif
3033                 if [ ! 0 ] && ! [ ! [ ! 1 ] ] && [ ! ! [ ! [ ! [ ! [ 0 ] ] ] ] ] && 3
3034                    echo 95.err
3035                 else
3036                    echo 95.ok
3037                 endif
3038                 if ! [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! ! 0 ] ] ] ] && 3
3039                    echo 96.err
3040                 else
3041                    echo 96.ok
3042                 endif
3043                 if [ ! 0 ] && [ ! [ ! 1 ] ] && [ ! [ ! [ ! [ ! [ ! 0 ] ] ] ] ] || 3
3044                    echo 97.ok
3045                 else
3046                    echo 97.err
3047                 endif
3048                 if [ ! 0 ] && [ ! ! [ ! ! 1 ] ] && [ ! ! [ ! ! [ ! ! [ ! [ 0 ] ] ] ] ]
3049                    echo 98.ok
3050                 else
3051                    echo 98.err
3052                 endif
3053         __EOT
3054
3055    check normal 0 "${MBOX}" '1688759742 719'
3056
3057    if have_feat regex; then
3058       ${cat} <<- '__EOT' | ${MAILX} ${ARGS} -Sv15-compat=X > "${MBOX}"
3059                         set dietcurd=yoho
3060                         if $dietcurd =~ '^yo.*'
3061                            echo 1.ok
3062                         else
3063                            echo 1.err
3064                         endif
3065                         if "$dietcurd" =~ '^Yo.*'
3066                            echo 1-1.err
3067                         else
3068                            echo 1-1.ok
3069                         endif
3070                         if $dietcurd =~?case '^Yo.*'
3071                            echo 1-2.ok
3072                         else
3073                            echo 1-2.err
3074                         endif
3075                         if $dietcurd =~ '^yOho.+'
3076                            echo 2.err
3077                         else
3078                            echo 2.ok
3079                         endif
3080                         if $dietcurd !~? '.*Ho$'
3081                            echo 3.err
3082                         else
3083                            echo 3.ok
3084                         endif
3085                         if $dietcurd !~ '.+yohO$'
3086                            echo 4.ok
3087                         else
3088                            echo 4.err
3089                         endif
3090                         if [ $dietcurd !~?cas '.+yoho$' ]
3091                            echo 5.ok
3092                         else
3093                            echo 5.err
3094                         endif
3095                         if ! [ "$dietcurd" =~?case '.+yoho$' ]
3096                            echo 6.ok
3097                         else
3098                            echo 6.err
3099                         endif
3100                         if ! ! [ $'\$dietcurd' !~? '.+yoho$' ]
3101                            echo 7.ok
3102                         else
3103                            echo 7.err
3104                         endif
3105                         if ! [ ! [ $dietcurd !~? '.+yoho$' ] ]
3106                            echo 8.ok
3107                         else
3108                            echo 8.err
3109                         endif
3110                         if [ ! [ ! [ $dietcurd !~? '.+yoho$' ] ] ]
3111                            echo 9.ok
3112                         else
3113                            echo 9.err
3114                         endif
3115                         if ! [ ! [ ! [ $dietcurd !~ '.+yoho$' ] ] ]
3116                            echo 10.err
3117                         else
3118                            echo 10.ok
3119                         endif
3120                         if !  ! ! $dietcurd !~ '.+yoho$'
3121                            echo 11.err
3122                         else
3123                            echo 11.ok
3124                         endif
3125                         if !  ! ! $dietcurd =~ '.+yoho$'
3126                            echo 12.ok
3127                         else
3128                            echo 12.err
3129                         endif
3130                         if ! [ ! ! [ ! [ $dietcurd !~ '.+yoho$' ] ] ]
3131                            echo 13.ok
3132                         else
3133                            echo 13.err
3134                         endif
3135                         set diet=abc curd='^abc$'
3136                         if $diet =~ $curd
3137                            echo 14.ok
3138                         else
3139                            echo 14.err
3140                         endif
3141                         set diet=abc curd='^abcd$'
3142                         if "$diet" !~ $'\$curd'
3143                            echo 15.ok
3144                         else
3145                            echo 15.err
3146                         endif
3147                 __EOT
3148
3149       check regex 0 "${MBOX}" '1115671789 95'
3150    else
3151       t_echoskip 'regex:[!REGEX]'
3152    fi
3153
3154    t_epilog "${@}"
3155 }
3156
3157 t_localopts() {
3158    t_prolog "${@}"
3159
3160    # Nestable conditions test
3161    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>&1
3162         define t2 {
3163            echo in: t2
3164            set t2=t2
3165            echo $t2
3166         }
3167         define t1 {
3168            echo in: t1
3169            set gv1=gv1
3170            localopts on
3171            set lv1=lv1 lv2=lv2
3172            set lv3=lv3
3173            call t2
3174            localopts off
3175            set gv2=gv2
3176            echo $gv1 $lv1 ${lv2} ${lv3} ${gv2}, $t2
3177         }
3178         define t0 {
3179            echo in: t0
3180            call t1
3181            echo $gv1 $lv1 ${lv2} ${lv3} ${gv2}, $t2
3182            echo "$gv1 $lv1 ${lv2} ${lv3} ${gv2}, $t2"
3183         }
3184         account trouble {
3185            echo in: trouble
3186            call t0
3187         }
3188         call t0
3189         unset gv1 gv2
3190         account trouble
3191         echo active trouble: $gv1 $lv1 ${lv2} ${lv3} ${gv2}, $t3
3192         account null
3193         echo active null: $gv1 $lv1 ${lv2} ${lv3} ${gv2}, $t3
3194
3195    #
3196    define ll2 {
3197       localopts $1
3198       set x=2
3199       echo ll2=$x
3200    }
3201    define ll1 {
3202       wysh set y=$1; shift; eval localopts $y; localopts $1; shift
3203       set x=1
3204       echo ll1.1=$x
3205       call ll2 $1
3206       echo ll1.2=$x
3207    }
3208    define ll0 {
3209       wysh set y=$1; shift; eval localopts $y; localopts $1; shift
3210       set x=0
3211       echo ll0.1=$x
3212       call ll1 $y "$@"
3213       echo ll0.2=$x
3214    }
3215    define llx {
3216       echo ----- $1: $2 -> $3 -> $4
3217       echo ll-1.1=$x
3218       eval localopts $1
3219       call ll0 "$@"
3220       echo ll-1.2=$x
3221       unset x
3222    }
3223    define lly {
3224       call llx 'call off' on on on
3225       call llx 'call off' off on on
3226       call llx 'call off' on off on
3227       call llx 'call off' on off off
3228       localopts call-fixate on
3229       call llx 'call-fixate on' on on on
3230       call llx 'call-fixate on' off on on
3231       call llx 'call-fixate on' on off on
3232       call llx 'call-fixate on' on off off
3233       unset x;localopts call on
3234       call llx 'call on' on on on
3235       call llx 'call on' off on on
3236       call llx 'call on' on off on
3237       call llx 'call on' on off off
3238    }
3239    call lly
3240         __EOT
3241
3242    check 1 0 "${MBOX}" '4016155249 1246'
3243
3244    t_epilog "${@}"
3245 }
3246
3247 t_local() {
3248    t_prolog "${@}"
3249
3250    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>&1
3251                 define du2 {
3252                    echo du2-1 du=$du
3253                    local set du=$1
3254                    echo du2-2 du=$du
3255                    local unset du
3256                    echo du2-3 du=$du
3257                 }
3258                 define du {
3259                    local set du=dudu
3260                    echo du-1 du=$du
3261                    call du2 du2du2
3262                    echo du-2 du=$du
3263                    local set nodu
3264                    echo du-3 du=$du
3265                 }
3266                 define ich {
3267                    echo ich-1 du=$du
3268                    call du
3269                    echo ich-2 du=$du
3270                 }
3271                 define wir {
3272                    localopts $1
3273                    set du=wirwir
3274                    echo wir-1 du=$du
3275                    call ich
3276                    echo wir-2 du=$du
3277                 }
3278                 echo ------- global-1 du=$du
3279                 call ich
3280                 echo ------- global-2 du=$du
3281                 set du=global
3282                 call ich
3283                 echo ------- global-3 du=$du
3284                 call wir on
3285                 echo ------- global-4 du=$du
3286                 call wir off
3287                 echo ------- global-5 du=$du
3288                 __EOT
3289    check 1 0 "${MBOX}" '2411598140 641'
3290
3291    #
3292    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>&1
3293       define z {
3294          echo z-1: x=$x y=$y z=$z crt=$crt
3295          local set z=1 y=2 crt=10
3296          echo z-2: x=$x y=$y z=$z crt=$crt
3297       }
3298       define y {
3299          echo y-1: x=$x y=$y z=$z crt=$crt
3300          local set x=2 y=1 crt=5
3301          echo y-2: x=$x y=$y z=$z crt=$crt
3302          call z
3303          echo y-3: x=$x y=$y z=$z crt=$crt
3304       }
3305       define x {
3306          echo x-1: x=$x y=$y z=$z crt=$crt
3307          local set x=1 crt=1
3308          echo x-2: x=$x y=$y z=$z crt=$crt
3309          call y
3310          echo x-3: x=$x y=$y z=$z crt=$crt
3311       }
3312       set crt
3313       echo global-1: x=$x y=$y z=$z crt=$crt
3314       call x
3315       echo global-2: x=$x y=$y z=$z crt=$crt
3316                 __EOT
3317    check 2 0 "${MBOX}" '2560788669 216'
3318
3319    t_epilog "${@}"
3320 }
3321
3322 t_environ() {
3323    t_prolog "${@}"
3324
3325    ${cat} <<- '__EOT' | EK1=EV1 EK2=EV2 ${MAILX} ${ARGS} > "${MBOX}" 2>&1
3326         echo "we: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3327         !echo "shell: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3328         varshow EK1 EK2 EK3 EK4 NEK5
3329
3330         echo environ set EK3 EK4, set NEK5
3331         environ set EK3=EV3 EK4=EV4
3332         set NEK5=NEV5
3333         echo "we: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3334         !echo "shell: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3335         varshow EK1 EK2 EK3 EK4 NEK5
3336
3337         echo removing NEK5 EK3
3338         unset NEK5
3339         environ unset EK3
3340         echo "we: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3341         !echo "shell: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3342         varshow EK1 EK2 EK3 EK4 NEK5
3343
3344         echo changing EK1, EK4
3345         set EK1=EV1_CHANGED EK4=EV4_CHANGED
3346         echo "we: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3347         !echo "shell: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3348         varshow EK1 EK2 EK3 EK4 NEK5
3349
3350         echo linking EK4, rechanging EK1, EK4
3351         environ link EK4
3352         set EK1=EV1 EK4=EV4
3353         echo "we: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3354         !echo "shell: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3355         varshow EK1 EK2 EK3 EK4 NEK5
3356
3357         echo unset all
3358         unset EK1 EK2 EK4
3359         echo "we: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3360         !echo "shell: EK1<$EK1> EK2<$EK2> EK3<$EK3> EK4<$EK4> NEK5<$NEK5>"
3361         varshow EK1 EK2 EK3 EK4 NEK5
3362         __EOT
3363
3364    check 1 0 "${MBOX}" '1685686686 1342'
3365
3366 t_epilog "${@}"
3367 return
3368
3369
3370    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>&1
3371         define l4 {
3372            echo '-------> L4 (environ unlink EK1, own localopts)'
3373            localopts yes
3374            environ unlink EK1
3375            set LK1=LK1_L4 EK1=EK1_L4
3376                 echo "we: L4: LK1<$LK1> EK1<$EK1>"
3377                 !echo "shell: L4: LK1<$LK1> EK1<$EK1>"
3378                 varshow LK1 EK1
3379            echo '-------< L4'
3380         }
3381         define l3 {
3382            echo '-------> L3'
3383            set LK1=LK1_L3 EK1=EK1_L3
3384                 echo "we: L3-pre: LK1<$LK1> EK1<$EK1>"
3385                 !echo "shell: L3-pre: LK1<$LK1> EK1<$EK1>"
3386                 varshow LK1 EK1
3387            call l4
3388                 echo "we: L3-post: LK1<$LK1> EK1<$EK1>"
3389                 !echo "shell: L3-post: LK1<$LK1> EK1<$EK1>"
3390                 varshow LK1 EK1
3391            echo '-------< L3'
3392         }
3393         define l2 {
3394            echo '-------> L2'
3395            set LK1=LK1_L2 EK1=EK1_L2
3396                 echo "we: L2-pre: LK1<$LK1> EK1<$EK1>"
3397                 !echo "shell: L2-pre: LK1<$LK1> EK1<$EK1>"
3398                 varshow LK1 EK1
3399            call l3
3400                 echo "we: L2-post: LK1<$LK1> EK1<$EK1>"
3401                 !echo "shell: L2-post: LK1<$LK1> EK1<$EK1>"
3402                 varshow LK1 EK1
3403            echo '-------< L2'
3404         }
3405         define l1 {
3406            echo '-------> L1 (environ link EK1; localopts call-fixate)'
3407            localopts call-fixate yes
3408            set LK1=LK1_L1 EK1=EK1_L1
3409            environ link EK1
3410                 echo "we: L1-pre: LK1<$LK1> EK1<$EK1>"
3411                 !echo "shell: L1-pre: LK1<$LK1> EK1<$EK1>"
3412                 varshow LK1 EK1
3413            call l2
3414                 echo "we: L1-post: LK1<$LK1> EK1<$EK1>"
3415                 !echo "shell: L1-post: LK1<$LK1> EK1<$EK1>"
3416                 varshow LK1 EK1
3417            echo '-------< L1'
3418         }
3419         echo "we: outer-pre: LK1<$LK1> EK1<$EK1>"
3420         !echo "shell: outer-pre: LK1<$LK1> EK1<$EK1>"
3421         varshow LK1 EK1
3422         call l1
3423         echo "we: outer-post: LK1<$LK1> EK1<$EK1>"
3424         !echo "shell: outer-post: LK1<$LK1> EK1<$EK1>"
3425         varshow LK1 EK1
3426         __EOT
3427
3428    check 2 0 "${MBOX}" '1903030743 1131'
3429
3430    t_epilog "${@}"
3431 }
3432
3433 t_macro_param_shift() {
3434    t_prolog "${@}"
3435
3436    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>>${ERR}
3437         define t2 {
3438            echo in: t2
3439            echo t2.0 has $#/${#} parameters: "$1,${2},$3" (${*}) [$@]
3440            localopts on
3441            wysh set ignerr=$1
3442            shift
3443            localopts off
3444            echo t2.1 has $#/${#} parameters: "$1,${2},$3" (${*}) [$@]
3445            if [ $# > 1 ] || [ $ignerr == '' ]
3446               shift 2
3447            else
3448               ignerr shift 2
3449            endif
3450            echo t2.2:$? has $#/${#} parameters: "$1,${2},$3" (${*}) [$@]
3451            shift 0
3452            echo t2.3:$? has $#/${#} parameters: "$1,${2},$3" (${*}) [$@]
3453            if [ $# > 0 ]
3454               shift
3455            endif
3456            echo t2.4:$? has $#/${#} parameters: "$1,${2},$3" (${*}) [$@]
3457         }
3458         define t1 {
3459            set errexit
3460            echo in: t1
3461            call t2 1 you get four args
3462            echo t1.1: $?';' ignerr ($ignerr) should not exist
3463            call t2 1 you get 'three args'
3464            echo t1.2: $?';' ignerr ($ignerr) should not exist
3465            call t2 1 you 'get two args'
3466            echo t1.3: $?';' ignerr ($ignerr) should not exist
3467            call t2 1 'you get one arg'
3468            echo t1.4: $?';' ignerr ($ignerr) should not exist
3469            ignerr call t2 '' 'you get one arg'
3470            echo t1.5: $?';' ignerr ($ignerr) should not exist
3471         }
3472         call t1
3473         __EOT
3474
3475    check 1 0 "${MBOX}" '1402489146 1682'
3476
3477    t_epilog "${@}"
3478 }
3479
3480 t_addrcodec() {
3481    t_prolog "${@}"
3482
3483    ${cat} <<- '__EOT' | ${MAILX} ${ARGS} > "${MBOX}" 2>&1
3484         commandalias x echo '$?/$^ERRNAME $res'
3485         vput addrcodec res e 1 <doog@def>
3486         x
3487         eval vput addrcodec res d $res
3488         x
3489         vput addrcodec res e 2 . <doog@def>
3490         x
3491         eval vput addrcodec res d $res
3492         x
3493         vput addrcodec res e 3 Sauer Dr. <doog@def>
3494         x
3495         eval vput addrcodec res d $res
3496         x
3497         vput addrcodec res e 3.50 Sauer (Ma) Dr. <doog@def>
3498         x
3499         eval vput addrcodec res d $res
3500         x
3501         vput addrcodec res e 3.51 Sauer (Ma) "Dr." <doog@def>
3502         x
3503         eval vput addrcodec res d $res
3504         x
3505         #
3506         vput addrcodec res +e 4 Sauer (Ma) Dr. <doog@def>
3507         x
3508         eval vput addrcodec res d $res
3509         x
3510         vput addrcodec res +e 5 Sauer (Ma) Braten Dr. <doog@def>
3511         x
3512         eval vput addrcodec res d $res
3513         x
3514        &