Allow $USER to be an empty string, don't abort(3)..
[s-mailx.git] / cc-test.sh
blob8181fc6559ce3261744d3082568422e6dcc47cb4
1 #!/bin/sh -
2 #@ Usage: ./cc-test.sh [--check-only [s-nail-binary]]
4 SNAIL=./s-nail
5 CONF=./make.rc
6 BODY=./.cc-body.txt
7 MBOX=./.cc-test.mbox
9 MAKE="${MAKE:-`command -v make`}"
10 awk=${awk:-`command -v awk`}
11 cat=${cat:-`command -v cat`}
12 # TODO cksum not fixated via mk-conf.sh, mk.mk should export variables!!
13 cksum=${cksum:-`command -v cksum`}
14 rm=${rm:-`command -v rm`}
15 sed=${sed:-`command -v sed`}
16 grep=${grep:-`command -v grep`}
18 ## -- >8 -- 8< -- ##
20 export SNAIL CONF BODY MBOX MAKE awk cat cksum rm sed grep
22 # NOTE! UnixWare 7.1.4 gives ISO-10646-Minimum-European-Subset for
23 # nl_langinfo(CODESET), then, so also overwrite ttycharset.
24 # (In addition this setup allows us to succeed on TinyCore 4.4 that has no
25 # other locales than C/POSIX installed by default!)
26 LC=en_US.UTF-8
27 LC_ALL=${LC} LANG=${LC}
28 ttycharset=UTF-8
29 export LC_ALL LANG ttycharset
31 ESTAT=0
33 usage() {
34 echo >&2 "Usage: ./cc-test.sh [--check-only [s-nail-binary]]"
35 exit 1
38 CHECK_ONLY=
39 [ ${#} -gt 0 ] && {
40 [ "${1}" = --check-only ] || usage
41 [ ${#} -gt 2 ] && usage
42 [ ${#} -eq 2 ] && SNAIL="${2}"
43 [ -x "${SNAIL}" ] || usage
44 CHECK_ONLY=1
47 # cc_all_configs()
48 # Test all configs TODO doesn't cover all *combinations*, stupid!
49 cc_all_configs() {
50 < ${CONF} ${awk} '
51 BEGIN {i = 0}
52 /^[[:space:]]*WANT_/ {
53 sub(/^[[:space:]]*/, "")
54 # This bails for UnixWare 7.1.4 awk(1), but preceeding = with \
55 # does not seem to be a compliant escape for =
56 #sub(/=.*$/, "")
57 $1 = substr($1, 1, index($1, "=") - 1)
58 if ($1 == "WANT_AUTOCC")
59 next
60 data[i++] = $1
62 END {
63 for (j = 0; j < i; ++j) {
64 for (k = 0; k < j; ++k)
65 printf data[k] "=1 "
66 for (k = j; k < i; ++k)
67 printf data[k] "=0 "
68 printf "WANT_AUTOCC=1\n"
70 for (k = 0; k < j; ++k)
71 printf data[k] "=0 "
72 for (k = j; k < i; ++k)
73 printf data[k] "=1 "
74 printf "WANT_AUTOCC=1\n"
77 ' | while read c; do
78 printf "\n\n##########\n$c\n"
79 printf "\n\n##########\n$c\n" >&2
80 sh -c "${MAKE} ${c}"
81 t_all
82 ${MAKE} distclean
83 done
86 # cksum_test()
87 # Read mailbox $2, strip non-constant headers and MIME boundaries, query the
88 # cksum(1) of the resulting data and compare against the checksum $3
89 cksum_test() {
90 tid=${1} f=${2} s=${3}
91 printf "${tid}: "
92 csum="`${sed} -e '/^From /d' -e '/^Date: /d' \
93 -e '/^ boundary=/d' -e '/^--=_/d' < \"${f}\" \
94 -e '/^\[-- Message/d' | ${cksum}`";
95 if [ "${csum}" = "${s}" ]; then
96 printf 'ok\n'
97 else
98 ESTAT=1
99 printf 'error: checksum mismatch (got %s)\n' "${csum}"
103 have_feat() {
105 echo 'feat' |
106 MAILRC=/dev/null "${SNAIL}" -n -# |
107 ${grep} ${1}
108 ) >/dev/null 2>&1
111 # t_behave()
112 # Basic (easily testable) behaviour tests
113 t_behave() {
114 # Test for [d1f1a19]
115 ${rm} -f "${MBOX}"
116 printf 'echo +nix\nset folder=/\necho +nix\nset nofolder\necho +nix\nx' |
117 MAILRC=/dev/null "${SNAIL}" -n -# -SPAGER="${cat}" > "${MBOX}"
118 cksum_test behave:001 "${MBOX}" '4214021069 15'
120 # POSIX: setting *noprompt*/prompt='' shall prevent prompting TODO
121 # TODO for this to be testable we need a way to echo a variable
122 # TODO or to force echo of the prompt
124 __behave_ifelse
126 have_feat SSL/TLS && have_feat S/MIME && __behave_smime
129 __behave_ifelse() {
130 # Nestable conditions test
131 ${rm} -f "${MBOX}"
132 ${cat} <<- '__EOT' | MAILRC=/dev/null "${SNAIL}" -n -# > "${MBOX}"
133 if 0
134 echo 1.err
135 else
136 echo 1.ok
137 endif
138 if 1
139 echo 2.ok
140 else
141 echo 2.err
142 endif
143 if $dietcurd
144 echo 3.err
145 else
146 echo 3.ok
147 endif
148 set dietcurd=yoho
149 if $dietcurd
150 echo 4.ok
151 else
152 echo 4.err
153 endif
154 if $dietcurd == 'yoho'
155 echo 5.ok
156 else
157 echo 5.err
158 endif
159 if $dietcurd != 'yoho'
160 echo 6.err
161 else
162 echo 6.ok
163 endif
164 # Nesting
165 if 0
166 echo 7.err1
167 if 1
168 echo 7.err2
169 if 1
170 echo 7.err3
171 else
172 echo 7.err4
173 endif
174 echo 7.err5
175 endif
176 echo 7.err6
177 else
178 echo 7.ok7
179 if 1
180 echo 7.ok8
181 if 0
182 echo 7.err9
183 else
184 echo 7.ok9
185 endif
186 echo 7.ok10
187 else
188 echo 7.err11
189 if 1
190 echo 7.err12
191 else
192 echo 7.err13
193 endif
194 endif
195 echo 7.ok14
196 endif
197 if r
198 echo 8.ok1
199 if R
200 echo 8.ok2
201 else
202 echo 8.err2
203 endif
204 echo 8.ok3
205 else
206 echo 8.err1
207 endif
208 if s
209 echo 9.err1
210 else
211 echo 9.ok1
212 if S
213 echo 9.err2
214 else
215 echo 9.ok2
216 endif
217 echo 9.ok3
218 endif
219 # `elif'
220 if $dietcurd == 'yohu'
221 echo 10.err1
222 elif $dietcurd == 'yoha'
223 echo 10.err2
224 elif $dietcurd == 'yohe'
225 echo 10.err3
226 elif $dietcurd == 'yoho'
227 echo 10.ok1
228 if $dietcurd == 'yohu'
229 echo 10.err4
230 elif $dietcurd == 'yoha'
231 echo 10.err5
232 elif $dietcurd == 'yohe'
233 echo 10.err6
234 elif $dietcurd == 'yoho'
235 echo 10.ok2
236 if $dietcurd == 'yohu'
237 echo 10.err7
238 elif $dietcurd == 'yoha'
239 echo 10.err8
240 elif $dietcurd == 'yohe'
241 echo 10.err9
242 elif $dietcurd == 'yoho'
243 echo 10.ok3
244 else
245 echo 10.err10
246 endif
247 else
248 echo 10.err11
249 endif
250 else
251 echo 10.err12
252 endif
253 __EOT
254 cksum_test behave:if-normal "${MBOX}" '2760114576 119'
256 if have_feat REGEX; then
257 ${rm} -f "${MBOX}"
258 ${cat} <<- '__EOT' | MAILRC=/dev/null "${SNAIL}" -n -# > "${MBOX}"
259 set dietcurd=yoho
260 if $dietcurd =~ '^yo.*'
261 echo 1.ok
262 else
263 echo 1.err
264 endif
265 if $dietcurd =~ '^yoho.+'
266 echo 2.err
267 else
268 echo 2.ok
269 endif
270 if $dietcurd !~ '.*ho$'
271 echo 3.err
272 else
273 echo 3.ok
274 endif
275 if $dietcurd !~ '.+yoho$'
276 echo 4.ok
277 else
278 echo 4.err
279 endif
280 __EOT
281 cksum_test behave:if-regex "${MBOX}" '3930005258 20'
285 __behave_smime() { # FIXME add test/ dir, unroll tests therein, regular enable!
286 printf 'behave:s/mime: .. generating test key and certificate ..\n'
287 ${cat} <<-_EOT > ./t.conf
288 [ req ]
289 default_bits = 1024
290 default_keyfile = keyfile.pem
291 distinguished_name = req_distinguished_name
292 attributes = req_attributes
293 prompt = no
294 output_password =
296 [ req_distinguished_name ]
297 C = GB
298 ST = Over the
299 L = rainbow
300 O = S-nail
301 OU = S-nail.smime
302 CN = S-nail.test
303 emailAddress = test@localhost
305 [ req_attributes ]
306 challengePassword =
307 _EOT
308 openssl req -x509 -nodes -days 3650 -config ./t.conf \
309 -newkey rsa:1024 -keyout ./tkey.pem -out ./tcert.pem >/dev/null 2>&1
310 ${rm} -f ./t.conf
311 ${cat} ./tkey.pem ./tcert.pem > ./tpair.pem
313 printf "behave:s/mime:sign/verify: "
314 echo bla |
315 MAILRC=/dev/null ./s-nail -n# \
316 -Ssmime-ca-file=./tcert.pem -Ssmime-sign-cert=./tpair.pem \
317 -Ssmime-sign -Sfrom=test@localhost \
318 -s 'S/MIME test' ./VERIFY
319 # TODO CHECK
320 printf 'verify\nx\n' |
321 MAILRC=/dev/null ./s-nail -n# \
322 -Ssmime-ca-file=./tcert.pem -Ssmime-sign-cert=./tpair.pem \
323 -Ssmime-sign -Sfrom=test@localhost \
324 -Sbatch-exit-on-error -R \
325 -f ./VERIFY >/dev/null 2>&1
326 if [ $? -eq 0 ]; then
327 printf 'ok\n'
328 else
329 ESTAT=1
330 printf 'error: verification failed\n'
331 ${rm} -f ./VERIFY ./tkey.pem ./tcert.pem ./tpair.pem
332 return
334 ${rm} -rf ./VERIFY
336 printf "behave:s/mime:encrypt/decrypt: "
337 ${cat} <<-_EOT > ./tsendmail.sh
338 #!/bin/sh -
339 (echo 'From S-Postman Thu May 10 20:40:54 2012' && ${cat}) > ./ENCRYPT
340 _EOT
341 chmod 0755 ./tsendmail.sh
343 echo bla |
344 MAILRC=/dev/null ./s-nail -n# \
345 -Ssmime-force-encryption \
346 -Ssmime-encrypt-recei@ver.com=./tpair.pem \
347 -Ssendmail=./tsendmail.sh \
348 -Ssmime-ca-file=./tcert.pem -Ssmime-sign-cert=./tpair.pem \
349 -Ssmime-sign -Sfrom=test@localhost \
350 -s 'S/MIME test' recei@ver.com
351 # TODO CHECK
352 printf 'decrypt ./DECRYPT\nfi ./DECRYPT\nverify\nx\n' |
353 MAILRC=/dev/null ./s-nail -n# \
354 -Ssmime-force-encryption \
355 -Ssmime-encrypt-recei@ver.com=./tpair.pem \
356 -Ssendmail=./tsendmail.sh \
357 -Ssmime-ca-file=./tcert.pem -Ssmime-sign-cert=./tpair.pem \
358 -Ssmime-sign -Sfrom=test@localhost \
359 -Sbatch-exit-on-error -R \
360 -f ./ENCRYPT >/dev/null 2>&1
361 if [ $? -eq 0 ]; then
362 printf 'ok\n'
363 else
364 ESTAT=1
365 printf 'error: decryption+verification failed\n'
367 ${rm} -f ./tsendmail.sh ./ENCRYPT ./DECRYPT \
368 ./tkey.pem ./tcert.pem ./tpair.pem
371 # t_content()
372 # Some basic tests regarding correct sending of mails, via STDIN / -t / -q,
373 # including basic MIME Content-Transfer-Encoding correctness (quoted-printable)
374 # Note we unfortunately need to place some statements without proper
375 # indentation because of continuation problems
376 t_content() {
377 ${rm} -f "${BODY}" "${MBOX}"
379 # MIME CTE (QP) stress message body
380 printf \
381 'Ich bin eine DÖS-Datäi mit sehr langen Zeilen und auch '\
382 'sonst bin ich ganz schön am Schleudern, da kannste denke '\
383 "wasde willst, gelle, gelle, gelle, gelle, gelle.\r\n"\
384 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst \r\n"\
385 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 1\r\n"\
386 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 12\r\n"\
387 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 123\r\n"\
388 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 1234\r\n"\
389 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 12345\r\n"\
390 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 123456\r\n"\
391 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 1234567\r\n"\
392 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 12345678\r\n"\
393 "Ich bin eine DÖS-Datäi mit langen Zeilen und auch sonst 123456789\r\n"\
394 "Unn ausserdem habe ich trailing SP/HT/SP/HT whitespace \r\n"\
395 "Unn ausserdem habe ich trailing HT/SP/HT/SP whitespace \r\n"\
396 "auf den zeilen vorher.\r\n"\
397 "From am Zeilenbeginn und From der Mitte gibt es auch.\r\n"\
398 ".\r\n"\
399 "Die letzte Zeile war nur ein Punkt.\r\n"\
400 "..\r\n"\
401 "Das waren deren zwei.\r\n"\
402 " \r\n"\
403 "Die letzte Zeile war ein Leerschritt.\n"\
404 "=VIER = EQUAL SIGNS=ON A LINE=\r\n"\
405 "Prösterchen.\r\n"\
406 ".\n"\
407 "Die letzte Zeile war nur ein Punkt, mit Unix Zeilenende.\n"\
408 "..\n"\
409 "Das waren deren zwei. ditto.\n"\
410 "Prösterchen.\n"\
411 "Unn ausseerdem habe ich trailing SP/HT/SP/HT whitespace \n"\
412 "Unn ausseerdem habe ich trailing HT/SP/HT/SP whitespace \n"\
413 "auf den zeilen vorher.\n"\
414 "ditto.\n"\
415 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.\n"\
416 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.1"\
417 "\n"\
418 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.12"\
419 "\n"\
420 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.12"\
421 "3\n"\
422 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.12"\
423 "34\n"\
424 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.12"\
425 "345\n"\
426 "Ich bin eine ziemlich lange, steile, scharfe Zeile mit Unix Zeilenende.12"\
427 "3456\n"\
428 "=VIER = EQUAL SIGNS=ON A LINE=\n"\
429 " \n"\
430 "Die letzte Zeile war ein Leerschritt.\n"\
431 ' '\
432 > "${BODY}"
434 # MIME CTE (QP) stress message subject
435 SUB="Äbrä Kä?dä=brö Fü?di=bus? \
436 adadaddsssssssddddddddddddddddddddd\
437 ddddddddddddddddddddddddddddddddddd\
438 ddddddddddddddddddddddddddddddddddd\
439 dddddddddddddddddddd Hallelulja? Od\
440 er?? eeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
441 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
442 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee f\
443 fffffffffffffffffffffffffffffffffff\
444 fffffffffffffffffffff ggggggggggggg\
445 ggggggggggggggggggggggggggggggggggg\
446 ggggggggggggggggggggggggggggggggggg\
447 ggggggggggggggggggggggggggggggggggg\
448 gggggggggggggggg"
450 # Three tests for MIME-CTE and (a bit) content classification.
451 # At the same time testing -q FILE, < FILE and -t FILE
452 ${rm} -f "${MBOX}"
453 < "${BODY}" MAILRC=/dev/null \
454 "${SNAIL}" -nSstealthmua -a "${BODY}" -s "${SUB}" "${MBOX}"
455 cksum_test content:001 "${MBOX}" '2289641826 5632'
457 ${rm} -f "${MBOX}"
458 < /dev/null MAILRC=/dev/null \
459 "${SNAIL}" -n#Sstealthmua -a "${BODY}" -s "${SUB}" \
460 -q "${BODY}" "${MBOX}"
461 cksum_test content:002 "${MBOX}" '2289641826 5632'
463 ${rm} -f "${MBOX}"
464 ( echo "To: ${MBOX}" && echo "Subject: ${SUB}" && echo &&
465 ${cat} "${BODY}"
466 ) | MAILRC=/dev/null "${SNAIL}" -nSstealthmua -a "${BODY}" -t
467 cksum_test content:003 "${MBOX}" '2898659780 5631'
469 # Test for [260e19d] (Juergen Daubert)
470 ${rm} -f "${MBOX}"
471 echo body | MAILRC=/dev/null "${SNAIL}" -n#Sstealthmua "${MBOX}"
472 cksum_test content:004 "${MBOX}" '506144051 104'
474 # Sending of multiple mails in a single invocation
475 ${rm} -f "${MBOX}"
476 ( printf "m ${MBOX}\n~s subject1\nE-Mail Körper 1\n.\n" &&
477 printf "m ${MBOX}\n~s subject2\nEmail body 2\n.\n" &&
478 echo x
479 ) | MAILRC=/dev/null "${SNAIL}" -n#Sstealthmua
480 cksum_test content:005 "${MBOX}" '2028749685 277'
482 ## $BODY CHANGED
484 # "Test for" [d6f316a] (Gavin Troy)
485 ${rm} -f "${MBOX}"
486 printf "m ${MBOX}\n~s subject1\nEmail body\n.\nfi ${MBOX}\np\nx\n" |
487 MAILRC=/dev/null "${SNAIL}" -n#Sstealthmua \
488 -SPAGER="${cat}" -Spipe-text/plain="${cat}" > "${BODY}"
489 ${sed} -e 1d < "${BODY}" > "${MBOX}"
490 cksum_test content:006 "${MBOX}" '1520300594 138'
492 # "Test for" [c299c45] (Peter Hofmann) TODO shouldn't end up QP-encoded?
493 ${rm} -f "${MBOX}"
494 LC_ALL=C ${awk} 'BEGIN{
495 for(i = 0; i < 10000; ++i)
496 printf "\xC3\xBC"
497 #printf "\xF0\x90\x87\x90"
498 }' |
499 MAILRC=/dev/null "${SNAIL}" -nSstealthmua -s TestSubject "${MBOX}"
500 cksum_test content:007 "${MBOX}" '2747333583 61729'
502 ## Test some more corner cases for header bodies (as good as we can today) ##
505 ${rm} -f "${MBOX}"
506 echo |
507 MAILRC=/dev/null "${SNAIL}" -nSstealthmua \
508 -s 'a̲b̲c̲d̲e̲f̲h̲i̲k̲l̲m̲n̲o̲r̲s̲t̲u̲v̲w̲x̲z̲a̲b̲c̲d̲e̲f̲h̲i̲k̲l̲m̲n̲o̲r̲s̲t̲u̲v̲w̲x̲z̲' \
509 "${MBOX}"
510 cksum_test content:008 "${MBOX}" '1428748699 320'
512 # Single word (overlong line split -- bad standard! Requires injection of
513 # artificial data!! Bad can be prevented by using RFC 2047 encoding)
514 ${rm} -f "${MBOX}"
515 i=`LC_ALL=C ${awk} 'BEGIN{for(i=0; i<92; ++i) printf "0123456789_"}'`
516 echo | MAILRC=/dev/null "${SNAIL}" -nSstealthmua -s "${i}" "${MBOX}"
517 cksum_test content:009 "${MBOX}" '141403131 1663'
519 # Combination of encoded words, space and tabs of varying sort
520 ${rm} -f "${MBOX}"
521 echo | MAILRC=/dev/null "${SNAIL}" -nSstealthmua \
522 -s "1Abrä Kaspas1 2Abra Katä b_kaspas2 \
523 3Abrä Kaspas3 4Abrä Kaspas4 5Abrä Kaspas5 \
524 6Abra Kaspas6 7Abrä Kaspas7 8Abra Kaspas8 \
525 9Abra Kaspastäb4-3 10Abra Kaspas1 _ 11Abra Katäb1 \
526 12Abra Kadabrä1 After Tab after Täb this is NUTS" \
527 "${MBOX}"
528 cksum_test content:010 "${MBOX}" '2324198710 536'
530 # Overlong multibyte sequence that must be forcefully split
531 # todo This works even before v15.0, but only by accident
532 ${rm} -f "${MBOX}"
533 echo | MAILRC=/dev/null "${SNAIL}" -nSstealthmua \
534 -s "✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄\
535 ✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄\
536 ✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄✄" \
537 "${MBOX}"
538 cksum_test content:011 "${MBOX}" '3085014590 604'
540 # Trailing WS
541 ${rm} -f "${MBOX}"
542 echo |
543 MAILRC=/dev/null "${SNAIL}" -nSstealthmua \
544 -s "1-1 B2 B3 B4 B5 B6 B\
545 1-2 B2 B3 B4 B5 B6 B\
546 1-3 B2 B3 B4 B5 B6 B\
547 1-4 B2 B3 B4 B5 B6 B\
548 1-5 B2 B3 B4 B5 B6 B\
549 1-6 B2 B3 B4 B5 B6 " \
550 "${MBOX}"
551 cksum_test content:012 "${MBOX}" '2868799725 303'
553 # Leading and trailing WS
554 ${rm} -f "${MBOX}"
555 echo |
556 MAILRC=/dev/null "${SNAIL}" -nSstealthmua \
557 -s " 2-1 B2 B3 B4 B5 B6 B\
558 1-2 B2 B3 B4 B5 B6 B\
559 1-3 B2 B3 B4 B5 B6 B\
560 1-4 B2 B3 B4 B5 B6 " \
561 "${MBOX}"
562 cksum_test content:013 "${MBOX}" '3962521045 243'
564 ${rm} -f "${BODY}" "${MBOX}"
567 t_all() {
568 t_behave
569 t_content
572 if [ -z "${CHECK_ONLY}" ]; then
573 cc_all_configs
574 else
575 t_all
578 [ ${ESTAT} -eq 0 ] && echo Ok || echo >&2 'Errors occurred'
580 exit ${ESTAT}
581 # s-sh-mode