In test-post-common.sh and test-mhmail, wait for fakesmtp to start
[mmh] / test / mhmail / test-mhmail
1 #!/bin/sh
2 ######################################################
3 #
4 # Test mhmail
5 #
6 ######################################################
7
8 set -e
9
10 if test -z "${MH_OBJ_DIR}"; then
11     srcdir=`dirname $0`/../..
12     MH_OBJ_DIR=`cd $srcdir && pwd`; export MH_OBJ_DIR
13 fi
14
15 . "${srcdir}/test/post/test-post-common.sh"
16
17 # Customize test_post () for use with mhmail.
18 # $1 is expected output file, provided by caller
19 # $2 is mhmail switches, except for -body
20 # $3 of -b signifies use -body switch, | signifies provide body on stdin
21 # $4 contains the message body.
22 test_mhmail ()
23 {
24     "${MH_OBJ_DIR}/test/fakesmtp" "$actual" $localport &
25     pid="$!"
26
27     # The server doesn't always come up fast enough, so sleep and
28     # retry a few times if it fails...
29     status=1
30     for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
31         if [ $3 = '|' ]; then
32           if printf '%s' "$4" | mhmail recipient@example.com $2 \
33              -server 127.0.0.1 -port $localport; then
34               status=0
35               break
36           fi
37         else
38           if mhmail recipient@example.com $2 -body "$4" \
39              -server 127.0.0.1 -port $localport; then
40               status=0
41               break
42           fi
43         fi
44         sleep 2
45     done
46     if [ $status -ne 0 ]; then
47       printf '%s: mhmail failed, was fakesmtp given enough time to start?\n' \
48              "$0" >&2
49       exit 1
50     fi
51
52     wait ${pid}
53
54     #
55     # It's hard to calculate the exact Date: header post is going to
56     # use, so we'll just use sed to remove the actual date so we can easily
57     # compare it against our "correct" output.  And same for
58     # Message-ID.
59     #
60
61     sed -e 's/^Date:.*/Date:/' \
62         -e 's/^Resent-Date:.*/Resent-Date:/' \
63         -e 's/^Message-ID:.*/Message-ID:/' "$actual" > "$actual".nodate
64     rm -f "$actual"
65
66     check "$actual".nodate "$1"
67 }
68
69 expected=$MH_TEST_DIR/test-mhmail$$.expected
70 expected_err=$MH_TEST_DIR/test-mhmail$$.expected_err
71 actual=$MH_TEST_DIR/test-mhmail$$.actual
72 actual_err=$MH_TEST_DIR/test-mhmail$$.actual_err
73
74
75 # check -help
76 # Verified behavior consistent with compiled sendmail.
77 cat >$expected <<EOF
78 Usage: mhmail [-t(o)] addrs ... [switches]
79   switches are:
80   -at(tach) file [-at(tach) file] ...
81   -b(ody) text
82   -c(c) addrs ...
83   -f(rom) addr
84   -hea(derfield) name:value [-hea(derfield) name:value] ...
85   -su(bject) text
86   -r(esent)
87   -pr(ofile)
88   -se(nd)
89   -nose(nd)
90   -v(ersion)
91   -hel(p)
92   and all post(8)/send(1) switches
93   mhmail with no arguments is equivalent to inc
94 EOF
95
96 mhmail -help >$actual 2>&1
97 check $expected $actual
98
99
100 # check -version
101 # Verified same behavior as compiled mhmail.
102 case `mhmail -v` in
103   mhmail\ --*) ;;
104   *          ) printf '%s: mhmail -v generated unexpected output\n' "$0" >&2
105                failed=`expr ${failed:-0} + 1`;;
106 esac
107
108 # check for missing argument to switches that require them
109 for switch in attach body cc from headerfield subject to; do
110   run_test "mhmail recipient -$switch" \
111            "mhmail: missing argument to -$switch"
112 done
113 for switch in attach body cc from headerfield subject to; do
114   run_test "mhmail recipient -$switch -nosend" \
115            "mhmail: missing argument to -$switch"
116 done
117 for switch in attach body cc from headerfield subject to; do
118   run_test "mhmail recipient -$switch -server 127.0.0.1" \
119            "mhmail: missing argument to -$switch"
120 done
121
122
123 # check with no switches
124 # That will just run inc, which we don't want to do anything,
125 # so tell inc to just display its version.
126 # Verified same behavior as compiled mhmail.
127 printf 'inc: -version\n' >> $MH
128 case `mhmail` in
129   inc\ --*) ;;
130   *           ) echo "$0: mhmail generated unexpected output" >&2
131                 failed=`expr ${failed:-0} + 1`;;
132 esac
133
134
135 # check -nosend
136 # Not supported by compiled mhmail.
137 mhmail -nosend recipient@example.com -from sender@localhost \
138   -server 127.0.0.1 -port $localport -body '' >"$actual" 2>"$actual_err"
139
140 tmpfil=`head -1 $actual | sed -e 's/://'`
141
142 cat > "$expected" <<EOF
143 To: recipient@example.com
144 From: sender@localhost
145
146
147 EOF
148
149 cat > "$expected_err" <<EOF
150 EOF
151
152 check "$expected" "$actual"
153 check "$expected_err" "$actual_err"
154 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
155
156
157 # check -send
158 # Not supported by compiled mhmail.
159 cat > "$expected" <<EOF
160 EHLO nosuchhost.example.com
161 MAIL FROM:<sender@localhost>
162 RCPT TO:<recipient@example.com>
163 DATA
164 To: recipient@example.com
165 From: sender@localhost
166 Date:
167
168 message
169 .
170 QUIT
171 EOF
172
173 test_mhmail "$expected" "-from sender@localhost -nosend -send" '|' message
174 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
175
176
177 # check -from
178 # Verified same behavior as compiled mhmail.
179 cat > "$expected" <<EOF
180 EHLO nosuchhost.example.com
181 MAIL FROM:<sender@localhost>
182 RCPT TO:<recipient@example.com>
183 DATA
184 To: recipient@example.com
185 From: sender@localhost
186 Date:
187
188 message
189 .
190 QUIT
191 EOF
192
193 test_mhmail "$expected" "-from sender@localhost" '|' message
194 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
195
196
197 # check -from and -body
198 # Verified same behavior as compiled mhmail.
199 cat > "$expected" <<EOF
200 EHLO nosuchhost.example.com
201 MAIL FROM:<sender@localhost>
202 RCPT TO:<recipient@example.com>
203 DATA
204 To: recipient@example.com
205 From: sender@localhost
206 Date:
207
208 body
209 .
210 QUIT
211 EOF
212
213 test_mhmail "$expected" "-from sender@localhost" -b body
214 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
215
216
217 # check -from and -cc
218 # Verified same behavior as compiled mhmail.
219 cat > "$expected" <<EOF
220 EHLO nosuchhost.example.com
221 MAIL FROM:<sender@localhost>
222 RCPT TO:<recipient@example.com>
223 RCPT TO:<recipient2@example.com>
224 DATA
225 To: recipient@example.com
226 Cc: recipient2@example.com
227 From: sender@localhost
228 Date:
229
230 message
231 .
232 QUIT
233 EOF
234
235 test_mhmail "$expected" \
236     "-from sender@localhost -cc recipient2@example.com" '|' message
237 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
238
239
240 # check -from and multiple -cc addresses
241 # Verified same behavior as compiled mhmail.
242 cat > "$expected" <<EOF
243 EHLO nosuchhost.example.com
244 MAIL FROM:<sender@localhost>
245 RCPT TO:<recipient@example.com>
246 RCPT TO:<recipient2@example.com>
247 RCPT TO:<recipient3@example.com>
248 RCPT TO:<recipient4@example.com>
249 DATA
250 To: recipient@example.com
251 Cc: recipient2@example.com, recipient3@example.com,
252     recipient4@example.com
253 From: sender@localhost
254 Date:
255
256 message
257 .
258 QUIT
259 EOF
260
261 test_mhmail "$expected" \
262     '-from sender@localhost -cc recipient2@example.com recipient3@example.com '\
263 'recipient4@example.com' '|' message
264 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
265
266
267 # check -from and -subject
268 # Verified same behavior as compiled mhmail.
269 cat > "$expected" <<EOF
270 EHLO nosuchhost.example.com
271 MAIL FROM:<sender@localhost>
272 RCPT TO:<recipient@example.com>
273 DATA
274 To: recipient@example.com
275 Subject: Test
276 From: sender@localhost
277 Date:
278
279 message
280 .
281 QUIT
282 EOF
283
284 test_mhmail "$expected" '-from sender@localhost -subject Test' '|' message
285 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
286
287
288 # check -from and -profile
289 # Show that -profile causes mhmail to 1) read the profile and
290 # 2) use send(1) by added a send switch to the profile and
291 # verifying that it gets used.
292 # Not supported by compiled mhmail.
293 printf 'send: -msgid\n' >> $MH
294
295 cat > "$expected" <<EOF
296 EHLO nosuchhost.example.com
297 MAIL FROM:<sender@localhost>
298 RCPT TO:<recipient@example.com>
299 DATA
300 To: recipient@example.com
301 From: sender@localhost
302 Date:
303 Message-ID:
304
305 message
306 .
307 QUIT
308 EOF
309
310 test_mhmail "$expected" '-from sender@localhost -profile' '|' message
311 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
312
313
314 # check repeated -from and -subject switches
315 # Verified same behavior as compiled mhmail.
316 cat > "$expected" <<EOF
317 EHLO nosuchhost.example.com
318 MAIL FROM:<sender2@localhost>
319 RCPT TO:<recipient@example.com>
320 DATA
321 To: recipient@example.com
322 Subject: Subject2
323 From: sender2@localhost
324 Date:
325
326 message
327 .
328 QUIT
329 EOF
330
331 test_mhmail "$expected" '-from sender@localhost -from sender2@localhost '\
332 '-subject Subject1 -subject Subject2' -b message
333 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
334
335 # check repeated -body switches
336 # Verified same behavior as compiled mhmail.
337 cat > "$expected" <<EOF
338 EHLO nosuchhost.example.com
339 MAIL FROM:<sender@localhost>
340 RCPT TO:<recipient@example.com>
341 DATA
342 To: recipient@example.com
343 From: sender@localhost
344 Date:
345
346 body2
347 .
348 QUIT
349 EOF
350
351 test_mhmail "$expected" "-from sender@localhost -body body1" -b body2
352 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
353
354
355 # check multiple -cc switches
356 # Verified same behavior as compiled mhmail.
357 cat > "$expected" <<EOF
358 EHLO nosuchhost.example.com
359 MAIL FROM:<sender@localhost>
360 RCPT TO:<recipient@example.com>
361 RCPT TO:<cc1@example.com>
362 RCPT TO:<cc2@example.com>
363 DATA
364 To: recipient@example.com
365 Cc: cc1@example.com, cc2@example.com
366 From: sender@localhost
367 Date:
368
369 message
370 .
371 QUIT
372 EOF
373
374 test_mhmail "$expected" \
375   '-from sender@localhost -cc cc1@example.com -cc cc2@example.com' -b message
376 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
377
378
379 # check separated -cc arguments
380 # Verified same behavior as compiled mhmail.
381 cat > "$expected" <<EOF
382 EHLO nosuchhost.example.com
383 MAIL FROM:<sender@localhost>
384 RCPT TO:<recipient@example.com>
385 RCPT TO:<cc1@example.com>
386 RCPT TO:<cc2@example.com>
387 DATA
388 To: recipient@example.com
389 Cc: cc1@example.com, cc2@example.com
390 Subject: Test
391 From: sender@localhost
392 Date:
393
394 message
395 .
396 QUIT
397 EOF
398
399 test_mhmail "$expected" \
400   '-from sender@localhost -cc cc1@example.com -subject Test cc2@example.com' \
401   -b message
402 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
403
404
405 # check -cc switch followed by -to switch
406 # Verified same behavior as compiled mhmail.
407 cat > "$expected" <<EOF
408 EHLO nosuchhost.example.com
409 MAIL FROM:<sender@localhost>
410 RCPT TO:<recipient@example.com>
411 RCPT TO:<recipient2@example.com>
412 RCPT TO:<cc1@example.com>
413 DATA
414 To: recipient@example.com, recipient2@example.com
415 Cc: cc1@example.com
416 Subject: Test
417 From: sender@localhost
418 Date:
419
420 message
421 .
422 QUIT
423 EOF
424
425 test_mhmail "$expected" \
426   "-from sender@localhost -cc cc1@example.com -subject Test \
427    -to recipient2@example.com" \
428   -b message
429 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
430
431
432 # check with no newline on stdin
433 # Shows different behavior than compiled mhmail, which was silent in this case.
434 cat > "$expected" <<EOF
435 EOF
436
437 cat > "$expected_err" <<EOF
438 mhmail: empty message not sent, use -body '' to force.
439 EOF
440
441 set +e
442 printf '' | mhmail recipient@example.com -server 127.0.0.1 -port $localport \
443   >"$actual" 2>"$actual_err"
444 set -e
445
446 check "$expected" "$actual"
447 check "$expected_err" "$actual_err"
448 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
449
450
451 # check with one newline on stdin
452 # Verified same behavior as compiled mhmail.
453 cat > "$expected" <<EOF
454 EHLO nosuchhost.example.com
455 MAIL FROM:<sender@localhost>
456 RCPT TO:<recipient@example.com>
457 DATA
458 To: recipient@example.com
459 From: sender@localhost
460 Date:
461
462
463 .
464 QUIT
465 EOF
466
467 test_mhmail "$expected" '-from sender@localhost' '|' '
468 '
469 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
470
471
472 # check with multiple newlines on stdin
473 # Verified same behavior as compiled mhmail.
474 cat > "$expected" <<EOF
475 EHLO nosuchhost.example.com
476 MAIL FROM:<sender@localhost>
477 RCPT TO:<recipient@example.com>
478 DATA
479 To: recipient@example.com
480 From: sender@localhost
481 Date:
482
483
484
485
486 .
487 QUIT
488 EOF
489
490 test_mhmail "$expected" '-from sender@localhost' '|' '
491
492
493 '
494 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
495
496
497 # check with text and no trailing newline on stdin
498 # Verified same behavior as compiled mhmail.
499 cat > "$expected" <<EOF
500 EHLO nosuchhost.example.com
501 MAIL FROM:<sender@localhost>
502 RCPT TO:<recipient@example.com>
503 DATA
504 To: recipient@example.com
505 From: sender@localhost
506 Date:
507
508 no newline in input
509 .
510 QUIT
511 EOF
512
513 test_mhmail "$expected" '-from sender@localhost' '|' 'no newline in input'
514 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
515
516
517 # check with text and multiple trailing blank lines on stdin
518 # Verified same behavior as compiled mhmail.
519 cat > "$expected" <<EOF
520 EHLO nosuchhost.example.com
521 MAIL FROM:<sender@localhost>
522 RCPT TO:<recipient@example.com>
523 DATA
524 To: recipient@example.com
525 From: sender@localhost
526 Date:
527
528 here's some text
529
530
531 .
532 QUIT
533 EOF
534
535 test_mhmail "$expected" '-from sender@localhost' '|' "here's some text
536
537
538 "
539 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
540
541
542 # check with no newline to -body
543 # Verified same behavior as compiled mhmail.
544 cat > "$expected" <<EOF
545 EHLO nosuchhost.example.com
546 MAIL FROM:<sender@localhost>
547 RCPT TO:<recipient@example.com>
548 DATA
549 To: recipient@example.com
550 From: sender@localhost
551 Date:
552
553
554 .
555 QUIT
556 EOF
557
558 test_mhmail "$expected" '-from sender@localhost' -b ''
559 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
560
561
562 # check with one newline to -body
563 # Shows different behavior than compiled mhmail, which suppressed the newline.
564 cat > "$expected" <<EOF
565 EHLO nosuchhost.example.com
566 MAIL FROM:<sender@localhost>
567 RCPT TO:<recipient@example.com>
568 DATA
569 To: recipient@example.com
570 From: sender@localhost
571 Date:
572
573
574
575 .
576 QUIT
577 EOF
578
579 test_mhmail "$expected" '-from sender@localhost' -b '
580 '
581 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
582
583
584 # check with multiple newlines to -body
585 # Shows different behavior than compiled mhmail, which suppressed one
586 #   of the newlines.
587 cat > "$expected" <<EOF
588 EHLO nosuchhost.example.com
589 MAIL FROM:<sender@localhost>
590 RCPT TO:<recipient@example.com>
591 DATA
592 To: recipient@example.com
593 From: sender@localhost
594 Date:
595
596
597
598
599
600 .
601 QUIT
602 EOF
603
604 test_mhmail "$expected" '-from sender@localhost' -b '
605
606
607 '
608 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
609
610
611 # check with text and no trailing newline to -body
612 # Verified same behavior as compiled mhmail.
613 cat > "$expected" <<EOF
614 EHLO nosuchhost.example.com
615 MAIL FROM:<sender@localhost>
616 RCPT TO:<recipient@example.com>
617 DATA
618 To: recipient@example.com
619 From: sender@localhost
620 Date:
621
622 no newline in input
623 .
624 QUIT
625 EOF
626
627 test_mhmail "$expected" '-from sender@localhost' -b 'no newline in input'
628 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
629
630
631 # check with text and multiple trailing blank lines to -body
632 # Shows different behavior than compiled mhmail, which suppressed one
633 #   of the newlines.
634 cat > "$expected" <<EOF
635 EHLO nosuchhost.example.com
636 MAIL FROM:<sender@localhost>
637 RCPT TO:<recipient@example.com>
638 DATA
639 To: recipient@example.com
640 From: sender@localhost
641 Date:
642
643 here's some text
644
645
646 .
647 QUIT
648 EOF
649
650 test_mhmail "$expected" '-from sender@localhost' -b "here's some text
651
652 "
653 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
654
655
656 # check -resent
657 # Verified same behavior as compiled mhmail.
658 cat > "$expected" <<EOF
659 EHLO nosuchhost.example.com
660 MAIL FROM:<orig_recipient@example.com>
661 RCPT TO:<recipient@example.com>
662 DATA
663 Resent-To: recipient@example.com
664 Resent-From: orig_recipient@example.com
665 To: recipient@example.com
666 From: sender@localhost
667 Date:
668 Resent-Date:
669
670 please resend this message, 1
671 .
672 QUIT
673 EOF
674
675 test_mhmail "$expected" '-from orig_recipient@example.com -resent' \
676   -b 'To: recipient@example.com
677 From: sender@localhost
678 Date: Sat Jun 16 18:35:15 -0500
679
680 please resend this message, 1'
681
682 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
683
684 # check -resent -profile, using stdin
685 # Not supported by compiled mhmail.
686 cat > "$expected" <<EOF
687 EHLO nosuchhost.example.com
688 MAIL FROM:<orig_recipient@example.com>
689 RCPT TO:<recipient@example.com>
690 DATA
691 To: recipient@example.com
692 From: sender@localhost
693 Date:
694 Resent-To: recipient@example.com
695 Resent-From: orig_recipient@example.com
696 Resent-Date:
697
698 please resend this message, 2
699 .
700 QUIT
701 EOF
702
703 test_mhmail "$expected" \
704   '-from orig_recipient@example.com -resent -profile -nomsgid' \
705   '|' 'To: recipient@example.com
706 From: sender@localhost
707 Date: Sat Jun 16 18:35:15 -0500
708
709 please resend this message, 2'
710
711 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
712
713
714 # check -resent -profile, using -b
715 # Not supported by compiled mhmail.
716 cat > "$expected" <<EOF
717 EHLO nosuchhost.example.com
718 MAIL FROM:<orig_recipient@example.com>
719 RCPT TO:<recipient@example.com>
720 DATA
721 To: recipient@example.com
722 From: sender@localhost
723 Date:
724 Resent-To: recipient@example.com
725 Resent-From: orig_recipient@example.com
726 Resent-Date:
727
728 please resend this message, 3
729 .
730 QUIT
731 EOF
732
733 test_mhmail "$expected" \
734   '-from orig_recipient@example.com -resent -profile -nomsgid' \
735   -b 'To: recipient@example.com
736 From: sender@localhost
737 Date: Sat Jun 16 18:35:15 -0500
738
739 please resend this message, 3'
740
741 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
742
743
744 # check -headerfield.
745 # Not supported by compiled mhmail.
746 cat > "$expected" <<EOF
747 EHLO nosuchhost.example.com
748 MAIL FROM:<sender@example.com>
749 RCPT TO:<recipient@example.com>
750 DATA
751 To: recipient@example.com
752 From: sender@example.com
753 User-Agent: nmh
754 Date:
755
756 with added header field
757 .
758 QUIT
759 EOF
760
761 test_mhmail "$expected" \
762   '-from sender@example.com -headerfield User-Agent:nmh' \
763   -b 'with added header field'
764
765 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
766
767
768 # check multiple -headerfields.
769 # Not supported by compiled mhmail.
770 cat > "$expected" <<EOF
771 EHLO nosuchhost.example.com
772 MAIL FROM:<sender@example.com>
773 RCPT TO:<recipient@example.com>
774 DATA
775 To: recipient@example.com
776 From: sender@example.com
777 MIME-Version: 1.0
778 Content-Type: text/plain;charset=utf-8
779 Content-Transfer-Encoding: 8bit
780 Date:
781
782 with added header fields
783 .
784 QUIT
785 EOF
786
787 test_mhmail "$expected" \
788   "-from sender@example.com -headerfield MIME-Version:1.0 \
789 -headerfield Content-Type:text/plain;charset=utf-8 \
790 -headerfield Content-Transfer-Encoding:8bit" \
791   -b 'with added header fields'
792
793 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
794
795
796 # check -attach
797 # Not supported by compiled mhmail.
798 cat > "$expected" <<EOF
799 EHLO nosuchhost.example.com
800 MAIL FROM:<sender@example.com>
801 RCPT TO:<recipient@example.com>
802 DATA
803 To: recipient@example.com
804 From: sender@example.com
805 MIME-Version: 1.0
806 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0"
807 Date:
808 Message-ID:
809
810 ------- =_aaaaaaaaaa0
811 Content-Type: text/plain; charset="us-ascii"
812
813 See how easy it is to add an attachment!
814
815 ------- =_aaaaaaaaaa0
816 Content-Type: text/plain; name="attachment.txt"; charset="us-ascii"
817 Content-Description: attachment.txt
818 Content-Disposition: attachment; filename="attachment.txt"
819
820 The future disappears into memory, With only a moment between,
821 Forever dwells in that moment, hope is what remains to be seen
822 Forever dwells in that moment, hope is what remains to be seen.
823
824 ------- =_aaaaaaaaaa0--
825 .
826 QUIT
827 EOF
828
829 test_mhmail "$expected" \
830   "-from sender@example.com -attach ${srcdir}/test/mhmail/attachment.txt" \
831   -b 'See how easy it is to add an attachment!'
832
833 [ ${failed:-0} -eq 0 ] || exit ${failed:-0}
834
835
836 exit ${failed:-0}