1#
2# Copyright (c) 2010-2020 Notmuch Developers
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program.  If not, see https://www.gnu.org/licenses/ .
16
17test_require_emacs () {
18    local ret=0
19    test_require_external_prereq "$TEST_EMACS" || ret=1
20    test_require_external_prereq "$TEST_EMACSCLIENT" || ret=1
21    test_require_external_prereq dtach || ret=1
22    return $ret
23}
24
25# Deliver a message with emacs and add it to the database
26#
27# Uses emacs to generate and deliver a message to the mail store.
28# Accepts arbitrary extra emacs/elisp functions to modify the message
29# before sending, which is useful to doing things like attaching files
30# to the message and encrypting/signing.
31emacs_deliver_message () {
32    local subject body smtp_dummy_pid smtp_dummy_port
33    subject="$1"
34    body="$2"
35    shift 2
36    # before we can send a message, we have to prepare the FCC maildir
37    mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp}
38    # eval'ing smtp-dummy --background will set smtp_dummy_pid and -_port
39    smtp_dummy_pid= smtp_dummy_port=
40    eval `$TEST_DIRECTORY/smtp-dummy --background sent_message`
41    test -n "$smtp_dummy_pid" || return 1
42    test -n "$smtp_dummy_port" || return 1
43
44    test_emacs \
45	"(let ((message-send-mail-function 'message-smtpmail-send-it)
46	       (mail-host-address \"example.com\")
47	       (smtpmail-smtp-server \"localhost\")
48	       (smtpmail-smtp-service \"${smtp_dummy_port}\"))
49	   (notmuch-mua-mail)
50	   (message-goto-to)
51	   (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\")
52	   (message-goto-subject)
53	   (insert \"${subject}\")
54	   (message-goto-body)
55	   (insert \"${body}\")
56	   $*
57	   (notmuch-mua-send-and-exit))"
58
59    # In case message was sent properly, client waits for confirmation
60    # before exiting and resuming control here; therefore making sure
61    # that server exits by sending (KILL) signal to it is safe.
62    kill -9 $smtp_dummy_pid
63    notmuch new >/dev/null
64}
65
66# Pretend to deliver a message with emacs. Really save it to a file
67# and add it to the database
68#
69# Uses emacs to generate and deliver a message to the mail store.
70# Accepts arbitrary extra emacs/elisp functions to modify the message
71# before sending, which is useful to doing things like attaching files
72# to the message and encrypting/signing.
73#
74# If any GNU-style long-arguments (like --quiet or --decrypt=true) are
75# at the head of the argument list, they are sent directly to "notmuch
76# new" after message delivery
77emacs_fcc_message () {
78    local nmn_args subject body
79    nmn_args=''
80    while [[ "$1" =~ ^-- ]]; do
81	nmn_args="$nmn_args $1"
82	shift
83    done
84    subject="$1"
85    body="$2"
86    shift 2
87    # before we can send a message, we have to prepare the FCC maildir
88    mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp}
89
90    test_emacs \
91	"(let ((message-send-mail-function (lambda () t))
92	       (mail-host-address \"example.com\"))
93	   (notmuch-mua-mail)
94	   (message-goto-to)
95	   (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\")
96	   (message-goto-subject)
97	   (insert \"${subject}\")
98	   (message-goto-body)
99	   (insert \"${body}\")
100	   $*
101	   (let ((mml-secure-smime-sign-with-sender t)
102		 (mml-secure-openpgp-sign-with-sender t))
103	     (notmuch-mua-send-and-exit)))" || return 1
104    notmuch new $nmn_args >/dev/null
105}
106
107test_emacs_expect_t () {
108	local result
109	test "$#" = 1 ||
110	error "bug in the test script: not 1 parameter to test_emacs_expect_t"
111	if [ -z "$inside_subtest" ]; then
112		error "bug in the test script: test_emacs_expect_t without test_begin_subtest"
113	fi
114
115	# Run the test.
116	if ! test_skip "$test_subtest_name"
117	then
118		test_emacs "(notmuch-test-run $1)" >/dev/null
119
120		# Restore state after the test.
121		exec 1>&6 2>&7		# Restore stdout and stderr
122		inside_subtest=
123
124		# test_emacs may update missing external prerequisites
125		test_check_missing_external_prereqs_ "$test_subtest_name" && return
126
127		# Report success/failure.
128		result=$(cat OUTPUT)
129		if [ "$result" = t ]
130		then
131			test_ok_
132		else
133			test_failure_ "${result}"
134		fi
135	else
136		# Restore state after the (non) test.
137		exec 1>&6 2>&7		# Restore stdout and stderr
138		inside_subtest=
139	fi
140}
141
142emacs_generate_script () {
143	# Construct a little test script here for the benefit of the user,
144	# (who can easily run "run_emacs" to get the same emacs environment
145	# for investigating any failures).
146	cat <<EOF >"$TMP_DIRECTORY/run_emacs"
147#!/bin/sh
148export PATH=$PATH
149export NOTMUCH_CONFIG=$NOTMUCH_CONFIG
150
151# Here's what we are using here:
152#
153# --quick		Use minimal customization. This implies --no-init-file,
154#			--no-site-file and (emacs 24) --no-site-lisp
155#
156# --directory		Ensure that the local elisp sources are found
157#
158# --load		Force loading of notmuch.el and test-lib.el
159
160exec ${TEST_EMACS} --quick \
161	--directory "$NOTMUCH_BUILDDIR/emacs" --load notmuch.el \
162	--directory "$NOTMUCH_SRCDIR/test" --load test-lib.el \
163	"\$@"
164EOF
165	chmod a+x "$TMP_DIRECTORY/run_emacs"
166}
167
168test_emacs () {
169	# test dependencies beforehand to avoid the waiting loop below
170	test_require_emacs || return
171
172	if [ -z "$EMACS_SERVER" ]; then
173		emacs_tests="$NOTMUCH_SRCDIR/test/${this_test_bare}.el"
174		if [ -f "$emacs_tests" ]; then
175			load_emacs_tests="--eval '(load \"$emacs_tests\")'"
176		else
177			load_emacs_tests=
178		fi
179		server_name="notmuch-test-suite-$$"
180		# start a detached session with an emacs server
181		# user's TERM (or 'vt100' in case user's TERM is known dumb
182		# or unknown) is given to dtach which assumes a minimally
183		# VT100-compatible terminal -- and emacs inherits that
184		TERM=$SMART_TERM dtach -n "$TEST_TMPDIR/emacs-dtach-socket.$$" \
185			sh -c "stty rows 24 cols 80; exec '$TMP_DIRECTORY/run_emacs' \
186				--no-window-system \
187				$load_emacs_tests \
188				--eval '(setq server-name \"$server_name\")' \
189				--eval '(server-start)' \
190				--eval '(orphan-watchdog $$)'" || return
191		EMACS_SERVER="$server_name"
192		# wait until the emacs server is up
193		until test_emacs '()' >/dev/null 2>/dev/null; do
194			sleep 1
195		done
196	fi
197
198	# Clear test-output output file.  Most Emacs tests end with a
199	# call to (test-output).  If the test code fails with an
200	# exception before this call, the output file won't get
201	# updated.  Since we don't want to compare against an output
202	# file from another test, so start out with an empty file.
203	rm -f OUTPUT
204	touch OUTPUT
205
206	${TEST_EMACSCLIENT} --socket-name="$EMACS_SERVER" --eval "(notmuch-test-progn $*)"
207}
208
209emacs_generate_script
210