e24ccb5a8d149bc7675e1c25a73df65d2df1b723
[notmuch] / test / notmuch-test
1 #!/bin/bash
2 set -e
3
4 find_notmuch_binary ()
5 {
6     dir=$1
7
8     while [ -n "$dir" ]; do
9         bin=$dir/notmuch
10         if [ -x $bin ]; then
11             echo $bin
12             return
13         fi
14         dir=$(dirname $dir)
15         if [ "$dir" = "/" ]; then
16             break
17         fi
18     done
19
20     echo notmuch
21 }
22
23 increment_mtime_amount=0
24 increment_mtime ()
25 {
26     dir=$1
27
28     increment_mtime_amount=$((increment_mtime_amount + 1))
29     touch -d "+${increment_mtime_amount} seconds" $dir
30 }
31
32 # Generate a new message in the mail directory, with
33 # a unique message ID and subject.
34 #
35 # After this function returns, the filename of the generated message
36 # is available as $gen_msg_filename and the message ID is available as
37 # $gen_msg_id .
38 #
39 # This function supports named parameters with the bash syntax for
40 # assigning a value to an associative array ([name]=value). The
41 # supported parameters are:
42 #
43 #  [dir]=directory/of/choice
44 #
45 #       Generate the message in directory 'directory/of/choice' within
46 #       the mail store. The directory will be created if necessary.
47 #
48 #  [body]=text
49 #
50 #       Text to use as the body of the email message
51 #
52 #  '[from]="Some User <user@example.com>"'
53 #  '[to]="Some User <user@example.com>"'
54 #  '[subject]="Subject of email message"'
55 #  '[date]="RFC 822 Date"'
56 #
57 #       Values for email headers. If not provided, default values will
58 #       be generated instead.
59 #
60 #  '[cc]="Some User <user@example.com>"'
61 #  [reply-to]=some-address
62 #  [in-reply-to]=<message-id>
63 #
64 #       Additional values for email headers. If these are not provided
65 #       then the relevant headers will simply not appear in the
66 #       message.
67 gen_msg_cnt=0
68 gen_msg_filename=""
69 gen_msg_id=""
70 generate_message ()
71 {
72     # This is our (bash-specific) magic for doing named parameters
73     local -A template="($@)"
74     local additional_headers
75
76     gen_msg_cnt=$((gen_msg_cnt + 1))
77     gen_msg_name=msg-$(printf "%03d" $gen_msg_cnt)
78     gen_msg_id="${gen_msg_name}@notmuch-test-suite"
79
80     if [ -z "${template[dir]}" ]; then
81         gen_msg_filename="${MAIL_DIR}/$gen_msg_name"
82     else
83         gen_msg_filename="${MAIL_DIR}/${template[dir]}/$gen_msg_name"
84         mkdir -p $(dirname $gen_msg_filename)
85     fi
86
87     if [ -z "${template[body]}" ]; then
88         template[body]="This is just a test message at ${gen_msg_filename}"
89     fi
90
91     if [ -z "${template[from]}" ]; then
92         template[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"
93     fi
94
95     if [ -z "${template[to]}" ]; then
96         template[to]="Notmuch Test Suite <test_suite@notmuchmail.org>"
97     fi
98
99     if [ -z "${template[subject]}" ]; then
100         template[subject]="Test message ${gen_msg_filename}"
101     fi
102
103     if [ -z "${template[date]}" ]; then
104         template[date]="Tue, 05 Jan 2010 15:43:57 -0800"
105     fi
106
107     additional_headers=""
108     if [ ! -z "${template[reply-to]}" ]; then
109         additional_headers="Reply-To: ${template[reply-to]}
110 ${additional_headers}"
111     fi
112
113     if [ ! -z "${template[in-reply-to]}" ]; then
114         additional_headers="In-Reply-To: ${template[in-reply-to]}
115 ${additional_headers}"
116     fi
117
118     if [ ! -z "${template[cc]}" ]; then
119         additional_headers="Cc: ${template[cc]}
120 ${additional_headers}"
121     fi
122
123 cat <<EOF >$gen_msg_filename
124 From: ${template[from]}
125 To: ${template[to]}
126 Message-Id: <${gen_msg_id}>
127 Subject: ${template[subject]}
128 Date: ${template[date]}
129 ${additional_headers}
130 ${template[body]}
131 EOF
132
133     # Ensure that the mtime of the containing directory is updated
134     increment_mtime $(dirname ${gen_msg_filename})
135 }
136
137 NOTMUCH_IGNORED_OUTPUT_REGEXP='^Processed [0-9]*( total)? file|Found [0-9]* total file'
138
139 execute_expecting ()
140 {
141     args=$1
142     expected=$2
143
144     output=$($NOTMUCH $args | grep -v -E -e "$NOTMUCH_IGNORED_OUTPUT_REGEXP")
145     if [ "$output" = "$expected" ]; then
146         echo "  PASS"
147     else
148         echo "  FAIL"
149         echo "  Expected output: $expected"
150         echo "  Actual output:   $output"
151     fi
152 }
153
154 TEST_DIR=$(pwd)/test.$$
155 MAIL_DIR=${TEST_DIR}/mail
156 export NOTMUCH_CONFIG=${TEST_DIR}/notmuch-config
157 NOTMUCH=$(find_notmuch_binary $(pwd))
158
159 rm -rf ${TEST_DIR}
160 mkdir ${TEST_DIR}
161 cd ${TEST_DIR}
162
163 mkdir ${MAIL_DIR}
164
165 cat <<EOF > ${NOTMUCH_CONFIG}
166 [database]
167 path=${MAIL_DIR}
168
169 [user]
170 name=Notmuch Test Suite
171 primary_email=test_suite@notmuchmail.org
172 other_email=test_suite_other@notmuchmail.org
173 EOF
174
175 printf "Testing \"notmuch new\" in several variations:\n"
176 printf " No new messages...\t\t"
177 execute_expecting new "No new mail."
178
179 printf " Single new message...\t\t"
180 generate_message
181 execute_expecting new "Added 1 new message to the database."
182
183 printf " Multiple new messages...\t"
184 generate_message
185 generate_message
186 execute_expecting new "Added 2 new messages to the database."
187
188 printf " No new messages (non-empty DB)... "
189 execute_expecting new "No new mail."
190
191 printf " New directories...\t\t"
192 rm -rf ${MAIL_DIR}/* ${MAIL_DIR}/.notmuch
193 mkdir ${MAIL_DIR}/def
194 mkdir ${MAIL_DIR}/ghi
195 generate_message [dir]=def
196
197 execute_expecting new "Added 1 new message to the database."
198
199 printf " Alternate inode order...\t"
200
201 rm -rf ${MAIL_DIR}/.notmuch
202 mv ${MAIL_DIR}/ghi ${MAIL_DIR}/abc
203 rm ${MAIL_DIR}/def/*
204 generate_message [dir]=abc
205
206 execute_expecting new "Added 1 new message to the database."
207
208 printf " Message moved in...\t\t"
209 rm -rf ${MAIL_DIR}/* ${MAIL_DIR}/.notmuch
210 generate_message
211 tmp_msg_filename=tmp/$gen_msg_filename
212 mkdir -p $(dirname $tmp_msg_filename)
213 mv $gen_msg_filename $tmp_msg_filename
214 increment_mtime ${MAIL_DIR}
215 $NOTMUCH new > /dev/null
216 mv $tmp_msg_filename $gen_msg_filename
217 increment_mtime ${MAIL_DIR}
218 execute_expecting new "Added 1 new message to the database."
219
220 printf " Renamed message...\t\t"
221
222 generate_message
223 $NOTMUCH new > /dev/null
224 mv $gen_msg_filename ${gen_msg_filename}-renamed
225 increment_mtime ${MAIL_DIR}
226 execute_expecting new "No new mail. Detected 1 file rename."
227
228 printf " Deleted message...\t\t"
229
230 rm ${gen_msg_filename}-renamed
231 increment_mtime ${MAIL_DIR}
232 execute_expecting new "No new mail. Removed 1 message."
233
234 printf " Renamed directory...\t\t"
235
236 generate_message [dir]=dir
237 generate_message [dir]=dir
238 generate_message [dir]=dir
239
240 $NOTMUCH new > /dev/null
241
242 mv ${MAIL_DIR}/dir ${MAIL_DIR}/dir-renamed
243 increment_mtime ${MAIL_DIR}
244
245 execute_expecting new "No new mail. Detected 3 file renames."
246
247 printf " Deleted directory...\t\t"
248
249 rm -rf ${MAIL_DIR}/dir-renamed
250 increment_mtime ${MAIL_DIR}
251
252 execute_expecting new "No new mail. Removed 3 messages."
253
254 printf " New directory (at end of list)... "
255
256 generate_message [dir]=zzz
257 generate_message [dir]=zzz
258 generate_message [dir]=zzz
259
260 execute_expecting new "Added 3 new messages to the database."
261
262 printf " Deleted directory (end of list)... "
263
264 rm -rf ${MAIL_DIR}/zzz
265 increment_mtime ${MAIL_DIR}
266
267 execute_expecting new "No new mail. Removed 3 messages."
268
269 printf " New symlink to directory...\t"
270
271 rm -rf ${MAIL_DIR}/.notmuch
272 mv ${MAIL_DIR} ${TEST_DIR}/actual_maildir
273
274 mkdir ${MAIL_DIR}
275 ln -s ${TEST_DIR}/actual_maildir ${MAIL_DIR}/symlink
276
277 execute_expecting new "Added 1 new message to the database."
278
279 printf " New symlink to a file...\t"
280 generate_message
281 external_msg_filename=${TEST_DIR}/external/$(basename $gen_msg_filename)
282 mkdir -p $(dirname $external_msg_filename)
283 mv $gen_msg_filename $external_msg_filename
284 ln -s $external_msg_filename $gen_msg_filename
285 increment_mtime ${MAIL_DIR}
286 execute_expecting new "Added 1 new message to the database."
287
288 printf " New two-level directory...\t"
289
290 generate_message [dir]=two/levels
291 generate_message [dir]=two/levels
292 generate_message [dir]=two/levels
293
294 execute_expecting new "Added 3 new messages to the database."
295
296 printf " Deleted two-level directory... "
297
298 rm -rf ${MAIL_DIR}/two
299 increment_mtime ${MAIL_DIR}
300
301 execute_expecting new "No new mail. Removed 3 messages."
302
303 printf "\nTesting \"notmuch reply\" in several variations:\n"
304
305 printf " Basic reply...\t\t\t"
306 generate_message '[from]="Sender <sender@example.com>"' \
307                  [to]=test_suite@notmuchmail.org \
308                  [subject]=notmuch-reply-test \
309                  '[date]="Tue, 05 Jan 2010 15:43:56 -0800"' \
310                  '[body]="basic reply test"'
311
312 $NOTMUCH new > /dev/null
313 execute_expecting "reply id:${gen_msg_id}" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
314 Subject: Re: notmuch-reply-test
315 To: Sender <sender@example.com>
316 Bcc: test_suite@notmuchmail.org
317 In-Reply-To: <${gen_msg_id}>
318 References:  <${gen_msg_id}>
319
320 On Tue, 05 Jan 2010 15:43:56 -0800, Sender <sender@example.com> wrote:
321 > basic reply test"
322
323 printf " Reply with CC...\t\t"
324 generate_message '[from]="Sender <sender@example.com>"' \
325                  [to]=test_suite@notmuchmail.org \
326                  '[cc]="Other Parties <cc@example.com>"' \
327                  [subject]=notmuch-reply-test \
328                  '[date]="Tue, 05 Jan 2010 15:43:56 -0800"' \
329                  '[body]="reply with CC"'
330
331 $NOTMUCH new > /dev/null
332 execute_expecting "reply id:${gen_msg_id}" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
333 Subject: Re: notmuch-reply-test
334 To: Sender <sender@example.com>
335 Cc: Other Parties <cc@example.com>
336 Bcc: test_suite@notmuchmail.org
337 In-Reply-To: <${gen_msg_id}>
338 References:  <${gen_msg_id}>
339
340 On Tue, 05 Jan 2010 15:43:56 -0800, Sender <sender@example.com> wrote:
341 > reply with CC"
342
343 printf " Reply from alternate address..."
344 generate_message '[from]="Sender <sender@example.com>"' \
345                  [to]=test_suite_other@notmuchmail.org \
346                  [subject]=notmuch-reply-test \
347                  '[date]="Tue, 05 Jan 2010 15:43:56 -0800"' \
348                  '[body]="reply from alternate address"'
349
350 $NOTMUCH new > /dev/null
351 execute_expecting "reply id:${gen_msg_id}" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
352 Subject: Re: notmuch-reply-test
353 To: Sender <sender@example.com>
354 Bcc: test_suite@notmuchmail.org
355 In-Reply-To: <${gen_msg_id}>
356 References:  <${gen_msg_id}>
357
358 On Tue, 05 Jan 2010 15:43:56 -0800, Sender <sender@example.com> wrote:
359 > reply from alternate address"
360
361 printf " Support for Reply-To...\t"
362 generate_message '[from]="Sender <sender@example.com>"' \
363                  [to]=test_suite@notmuchmail.org \
364                  [subject]=notmuch-reply-test \
365                  '[date]="Tue, 05 Jan 2010 15:43:56 -0800"' \
366                  '[body]="support for reply-to"' \
367                  '[reply-to]="Sender <elsewhere@example.com>"'
368
369 $NOTMUCH new > /dev/null
370 execute_expecting "reply id:${gen_msg_id}" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
371 Subject: Re: notmuch-reply-test
372 To: Sender <elsewhere@example.com>
373 Bcc: test_suite@notmuchmail.org
374 In-Reply-To: <${gen_msg_id}>
375 References:  <${gen_msg_id}>
376
377 On Tue, 05 Jan 2010 15:43:56 -0800, Sender <sender@example.com> wrote:
378 > support for reply-to"
379
380 cat <<EOF
381 Notmuch test suite complete.
382
383 Intermediate state can be examined in:
384         ${TEST_DIR}
385 EOF