]> git.cworth.org Git - notmuch/blob - test/T081-sexpr-search.sh
4231dd386d9b17671e0d818bbccf936edb609f6f
[notmuch] / test / T081-sexpr-search.sh
1 #!/usr/bin/env bash
2 test_description='"notmuch search" in several variations'
3 . $(dirname "$0")/test-lib.sh || exit 1
4
5 if [ $NOTMUCH_HAVE_SFSEXP -ne 1 ]; then
6     printf "Skipping due to missing sfsexp library\n"
7     test_done
8 fi
9
10 add_email_corpus
11
12 for query in '()' '(not)' '(and)' '(or ())' '(or (not))' '(or (and))' \
13             '(or (and) (or) (not (and)))'; do
14     test_begin_subtest "all messages: $query"
15     notmuch search '*' > EXPECTED
16     notmuch search --query=sexp "$query" > OUTPUT
17     test_expect_equal_file EXPECTED OUTPUT
18 done
19
20 for query in '(or)' '(not ())' '(not (not))' '(not (and))' \
21                    '(not (or (and) (or) (not (and))))'; do
22     test_begin_subtest "no messages: $query"
23     notmuch search --query=sexp "$query" > OUTPUT
24     test_expect_equal_file /dev/null OUTPUT
25 done
26
27 test_begin_subtest "and of exact terms"
28 notmuch search --query=sexp '(and "wonderful" "wizard")' | notmuch_search_sanitize > OUTPUT
29 cat <<EOF > EXPECTED
30 thread:XXX   2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
31 EOF
32 test_expect_equal_file EXPECTED OUTPUT
33
34 test_begin_subtest "or of exact terms"
35 notmuch search --query=sexp '(or "php" "wizard")' | notmuch_search_sanitize > OUTPUT
36 cat <<EOF > EXPECTED
37 thread:XXX   2010-12-29 [1/1] François Boulogne; [aur-general] Guidelines: cp, mkdir vs install (inbox unread)
38 thread:XXX   2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
39 EOF
40 test_expect_equal_file EXPECTED OUTPUT
41
42 test_begin_subtest "single term in body"
43 notmuch search --query=sexp 'wizard' | notmuch_search_sanitize>OUTPUT
44 cat <<EOF > EXPECTED
45 thread:XXX   2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
46 EOF
47 test_expect_equal_file EXPECTED OUTPUT
48
49 test_begin_subtest "single term in body (case insensitive)"
50 notmuch search --query=sexp 'Wizard' | notmuch_search_sanitize>OUTPUT
51 cat <<EOF > EXPECTED
52 thread:XXX   2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
53 EOF
54 test_expect_equal_file EXPECTED OUTPUT
55
56 test_begin_subtest "single term in body, stemmed version"
57 notmuch search arriv > EXPECTED
58 notmuch search --query=sexp arriv > OUTPUT
59 test_expect_equal_file EXPECTED OUTPUT
60
61 test_begin_subtest "single term in body, unstemmed version"
62 notmuch search --query=sexp '"arriv"' > OUTPUT
63 test_expect_equal_file /dev/null OUTPUT
64
65 test_begin_subtest "Search by 'subject'"
66 add_message [subject]=subjectsearchtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
67 output=$(notmuch search --query=sexp '(subject subjectsearchtest)' | notmuch_search_sanitize)
68 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)"
69
70 test_begin_subtest "Search by 'subject' (case insensitive)"
71 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
72 notmuch search --query=sexp '(subject "Maildir")' | notmuch_search_sanitize > OUTPUT
73 test_expect_equal_file EXPECTED OUTPUT
74
75 test_begin_subtest "Search by 'subject' (utf-8):"
76 add_message [subject]=utf8-sübjéct '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
77 output=$(notmuch search --query=sexp '(subject utf8 sübjéct)' | notmuch_search_sanitize)
78 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
79
80 test_begin_subtest "Search by 'subject' (utf-8, and):"
81 output=$(notmuch search --query=sexp '(subject (and utf8 sübjéct))' | notmuch_search_sanitize)
82 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
83
84 test_begin_subtest "Search by 'subject' (utf-8, and outside):"
85 output=$(notmuch search --query=sexp '(and (subject utf8) (subject sübjéct))' | notmuch_search_sanitize)
86 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
87
88 test_begin_subtest "Search by 'subject' (utf-8, or):"
89 notmuch search --query=sexp '(subject (or utf8 subjectsearchtest))' | notmuch_search_sanitize > OUTPUT
90 cat <<EOF > EXPECTED
91 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)
92 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)
93 EOF
94 test_expect_equal_file EXPECTED OUTPUT
95
96 test_begin_subtest "Search by 'subject' (utf-8, or outside):"
97 notmuch search --query=sexp '(or (subject utf8) (subject subjectsearchtest))' | notmuch_search_sanitize > OUTPUT
98 cat <<EOF > EXPECTED
99 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)
100 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)
101 EOF
102 test_expect_equal_file EXPECTED OUTPUT
103
104 test_begin_subtest "Search by 'attachment'"
105 notmuch search attachment:notmuch-help.patch > EXPECTED
106 notmuch search --query=sexp '(attachment notmuch-help.patch)' > OUTPUT
107 test_expect_equal_file EXPECTED OUTPUT
108
109 test_begin_subtest "Search by 'body'"
110 add_message '[subject]="body search"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [body]=bodysearchtest
111 output=$(notmuch search --query=sexp '(body bodysearchtest)' | notmuch_search_sanitize)
112 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; body search (inbox unread)"
113
114 test_begin_subtest "Search by 'body' (phrase)"
115 add_message '[subject]="body search (phrase)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="body search (phrase)"'
116 add_message '[subject]="negative result"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="This phrase should not match the body search"'
117 output=$(notmuch search --query=sexp '(body "body search phrase")' | notmuch_search_sanitize)
118 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; body search (phrase) (inbox unread)"
119
120 test_begin_subtest "Search by 'body' (utf-8):"
121 add_message '[subject]="utf8-message-body-subject"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="message body utf8: bödý"'
122 output=$(notmuch search --query=sexp '(body bödý)' | notmuch_search_sanitize)
123 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)"
124
125 add_message "[body]=thebody-1" "[subject]=kryptonite-1"
126 add_message "[body]=nothing-to-see-here-1" "[subject]=thebody-1"
127
128 test_begin_subtest 'search without body: prefix'
129 notmuch search thebody > EXPECTED
130 notmuch search --query=sexp '(and thebody)' > OUTPUT
131 test_expect_equal_file EXPECTED OUTPUT
132
133 test_begin_subtest 'negated body: prefix'
134 notmuch search thebody and not body:thebody > EXPECTED
135 notmuch search --query=sexp '(and (not (body thebody)) thebody)' > OUTPUT
136 test_expect_equal_file EXPECTED OUTPUT
137
138 test_begin_subtest 'search unprefixed for prefixed term'
139 notmuch search kryptonite > EXPECTED
140 notmuch search --query=sexp '(and kryptonite)' > OUTPUT
141 test_expect_equal_file EXPECTED OUTPUT
142
143 test_begin_subtest 'search with body: prefix for term only in subject'
144 notmuch search body:kryptonite > EXPECTED
145 notmuch search --query=sexp '(body kryptonite)' > OUTPUT
146 test_expect_equal_file EXPECTED OUTPUT
147
148 test_begin_subtest "Search by 'from'"
149 add_message '[subject]="search by from"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom
150 output=$(notmuch search --query=sexp '(from searchbyfrom)' | notmuch_search_sanitize)
151 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] searchbyfrom; search by from (inbox unread)"
152
153 test_begin_subtest "Search by 'from' (address)"
154 add_message '[subject]="search by from (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom@example.com
155 output=$(notmuch search --query=sexp '(from searchbyfrom@example.com)' | notmuch_search_sanitize)
156 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] searchbyfrom@example.com; search by from (address) (inbox unread)"
157
158 test_begin_subtest "Search by 'from' (name)"
159 add_message '[subject]="search by from (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[from]="Search By From Name <test@example.com>"'
160 output=$(notmuch search --query=sexp '(from "Search By From Name")' | notmuch_search_sanitize)
161 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Search By From Name; search by from (name) (inbox unread)"
162
163 test_begin_subtest "Search by 'from' (name and address)"
164 output=$(notmuch search --query=sexp '(from "Search By From Name <test@example.com>")' | notmuch_search_sanitize)
165 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Search By From Name; search by from (name) (inbox unread)"
166
167 add_message '[dir]=bad' '[subject]="To the bone"'
168 add_message '[dir]=.' '[subject]="Top level"'
169 add_message '[dir]=bad/news' '[subject]="Bears"'
170 mkdir -p "${MAIL_DIR}/duplicate/bad/news"
171 cp "$gen_msg_filename" "${MAIL_DIR}/duplicate/bad/news"
172
173 add_message '[dir]=things' '[subject]="These are a few"'
174 add_message '[dir]=things/favorite' '[subject]="Raindrops, whiskers, kettles"'
175 add_message '[dir]=things/bad' '[subject]="Bites, stings, sad feelings"'
176
177 test_begin_subtest "Search by 'folder' (multiple)"
178 output=$(notmuch search --query=sexp '(folder bad bad/news things/bad)' | notmuch_search_sanitize)
179 test_expect_equal "$output" "thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
180 thread:XXX   2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
181 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
182
183 test_begin_subtest "Search by 'folder': top level."
184 notmuch search folder:'""' > EXPECTED
185 notmuch search --query=sexp '(folder "")'  > OUTPUT
186 test_expect_equal_file EXPECTED OUTPUT
187
188 test_begin_subtest "Search by 'id'"
189 add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
190 output=$(notmuch search --query=sexp "(id ${gen_msg_id})" | notmuch_search_sanitize)
191 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)"
192
193 test_begin_subtest "Search by 'id' (or)"
194 add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
195 output=$(notmuch search --query=sexp "(id non-existent-mid ${gen_msg_id})" | notmuch_search_sanitize)
196 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)"
197
198 test_begin_subtest "Search by 'is' (multiple)"
199 notmuch tag -inbox tag:searchbytag
200 notmuch search is:inbox AND is:unread | notmuch_search_sanitize > EXPECTED
201 notmuch search --query=sexp '(is inbox unread)' | notmuch_search_sanitize > OUTPUT
202 notmuch tag +inbox tag:searchbytag
203 test_expect_equal_file EXPECTED OUTPUT
204
205 test_begin_subtest "Search by 'mid'"
206 add_message '[subject]="search by mid"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
207 output=$(notmuch search --query=sexp "(mid ${gen_msg_id})" | notmuch_search_sanitize)
208 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by mid (inbox unread)"
209
210 test_begin_subtest "Search by 'mid' (or)"
211 add_message '[subject]="search by mid"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
212 output=$(notmuch search --query=sexp "(mid non-existent-mid ${gen_msg_id})" | notmuch_search_sanitize)
213 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by mid (inbox unread)"
214
215 test_begin_subtest "Search by 'mimetype'"
216 notmuch search mimetype:text/html > EXPECTED
217 notmuch search --query=sexp '(mimetype text html)'  > OUTPUT
218 test_expect_equal_file EXPECTED OUTPUT
219
220 QUERYSTR="date:2009-11-18..2009-11-18 and tag:unread"
221 QUERYSTR2="query:test and subject:Maildir"
222 notmuch config set --database query.test "$QUERYSTR"
223 notmuch config set query.test2 "$QUERYSTR2"
224
225 test_begin_subtest "ill-formed named query search"
226 notmuch search --query=sexp '(query)' > OUTPUT 2>&1
227 cat <<EOF > EXPECTED
228 notmuch search: Syntax error in query
229 'query' expects single atom as argument
230 EOF
231 test_expect_equal_file EXPECTED OUTPUT
232
233 test_begin_subtest "ill-formed named query search 2"
234 notmuch search --query=sexp '(to (query))' > OUTPUT 2>&1
235 cat <<EOF > EXPECTED
236 notmuch search: Syntax error in query
237 'query' not supported inside 'to'
238 EOF
239 test_expect_equal_file EXPECTED OUTPUT
240
241 test_begin_subtest "search named query"
242 notmuch search --query=sexp '(query test)' > OUTPUT
243 notmuch search $QUERYSTR > EXPECTED
244 test_expect_equal_file EXPECTED OUTPUT
245
246 test_begin_subtest "Search by 'subject' (utf-8, phrase-token):"
247 output=$(notmuch search --query=sexp '(subject utf8-sübjéct)' | notmuch_search_sanitize)
248 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
249
250 test_begin_subtest "search named query with other terms"
251 notmuch search --query=sexp '(and (query test) (subject Maildir))' > OUTPUT
252 notmuch search $QUERYSTR and subject:Maildir > EXPECTED
253 test_expect_equal_file EXPECTED OUTPUT
254
255 test_begin_subtest "search nested named query"
256 notmuch search --query=sexp '(query test2)' > OUTPUT
257 notmuch search $QUERYSTR2 > EXPECTED
258 test_expect_equal_file EXPECTED OUTPUT
259
260 test_begin_subtest "Search by 'subject' (utf-8, quoted string):"
261 output=$(notmuch search --query=sexp '(subject "utf8 sübjéct")' | notmuch_search_sanitize)
262 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
263
264 test_begin_subtest "Search by 'subject' (combine phrase, term):"
265 output=$(notmuch search --query=sexp '(subject Mac "compatibility issues")' | notmuch_search_sanitize)
266 test_expect_equal "$output" "thread:XXX   2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
267
268 test_begin_subtest "Search by 'subject' (combine phrase, term 2):"
269 notmuch search --query=sexp '(subject (or utf8 "compatibility issues"))' | notmuch_search_sanitize > OUTPUT
270 cat <<EOF > EXPECTED
271 thread:XXX   2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
272 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)
273 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)
274 EOF
275 test_expect_equal_file EXPECTED OUTPUT
276
277 test_begin_subtest "Search by 'subject' (combine phrase, term 3):"
278 notmuch search --query=sexp '(subject issues X/Darwin)' | notmuch_search_sanitize > OUTPUT
279 cat <<EOF > EXPECTED
280 thread:XXX   2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
281 EOF
282 test_expect_equal_file EXPECTED OUTPUT
283
284 test_begin_subtest "Search by 'tag'"
285 add_message '[subject]="search by tag"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
286 notmuch tag +searchbytag id:${gen_msg_id}
287 output=$(notmuch search --query=sexp '(tag searchbytag)' | notmuch_search_sanitize)
288 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)"
289
290 test_begin_subtest "Search by 'tag' (multiple)"
291 notmuch tag -inbox tag:searchbytag
292 notmuch search tag:inbox AND tag:unread | notmuch_search_sanitize > EXPECTED
293 notmuch search --query=sexp '(tag inbox unread)' | notmuch_search_sanitize > OUTPUT
294 notmuch tag +inbox tag:searchbytag
295 test_expect_equal_file EXPECTED OUTPUT
296
297 test_begin_subtest "Search by 'tag' and 'subject'"
298 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
299 notmuch search --query=sexp '(and (tag inbox) (subject maildir))' | notmuch_search_sanitize > OUTPUT
300 test_expect_equal_file EXPECTED OUTPUT
301
302 test_begin_subtest "Search by 'thread'"
303 add_message '[subject]="search by thread"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
304 thread_id=$(notmuch search id:${gen_msg_id} | sed -e "s/thread:\([a-f0-9]*\).*/\1/")
305 output=$(notmuch search --query=sexp "(thread ${thread_id})" | notmuch_search_sanitize)
306 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by thread (inbox unread)"
307
308 test_begin_subtest "Search by 'to'"
309 add_message '[subject]="search by to"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto
310 output=$(notmuch search --query=sexp '(to searchbyto)' | notmuch_search_sanitize)
311 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)"
312
313 test_begin_subtest "Search by 'to' (address)"
314 add_message '[subject]="search by to (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto@example.com
315 output=$(notmuch search --query=sexp '(to searchbyto@example.com)' | notmuch_search_sanitize)
316 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)"
317
318 test_begin_subtest "Search by 'to' (name)"
319 add_message '[subject]="search by to (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[to]="Search By To Name <test@example.com>"'
320 output=$(notmuch search --query=sexp '(to "Search By To Name")' | notmuch_search_sanitize)
321 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
322
323 test_begin_subtest "Search by 'to' (name and address)"
324 output=$(notmuch search --query=sexp '(to "Search By To Name <test@example.com>")' | notmuch_search_sanitize)
325 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
326
327 test_begin_subtest "starts-with, no prefix"
328 output=$(notmuch search --query=sexp '(starts-with prelim)' | notmuch_search_sanitize)
329 test_expect_equal "$output" "thread:XXX   2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)"
330
331 test_begin_subtest "starts-with, case-insensitive"
332 notmuch search --query=sexp '(starts-with FreeB)' | notmuch_search_sanitize > OUTPUT
333 cat <<EOF > EXPECTED
334 thread:XXX   2009-11-18 [3/4] Alexander Botero-Lowry, Jjgod Jiang; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
335 thread:XXX   2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
336 EOF
337 test_expect_equal_file EXPECTED OUTPUT
338
339 test_begin_subtest "starts-with, no prefix, all messages"
340 notmuch search --query=sexp '(starts-with "")' | notmuch_search_sanitize > OUTPUT
341 notmuch search '*' | notmuch_search_sanitize > EXPECTED
342 test_expect_equal_file EXPECTED OUTPUT
343
344 test_begin_subtest "starts-with, attachment"
345 output=$(notmuch search --query=sexp '(attachment (starts-with not))' | notmuch_search_sanitize)
346 test_expect_equal "$output" 'thread:XXX   2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)'
347
348 test_begin_subtest "starts-with, folder"
349 notmuch search --output=files --query=sexp '(folder (starts-with bad))' | notmuch_dir_sanitize | sed 's/[0-9]*$/XXX/' > OUTPUT
350 cat <<EOF > EXPECTED
351 MAIL_DIR/bad/msg-XXX
352 MAIL_DIR/bad/news/msg-XXX
353 MAIL_DIR/duplicate/bad/news/msg-XXX
354 EOF
355 test_expect_equal_file EXPECTED OUTPUT
356
357 test_begin_subtest "starts-with, from"
358 notmuch search --query=sexp '(from (starts-with Mik))' | notmuch_search_sanitize > OUTPUT
359 cat <<EOF > EXPECTED
360 thread:XXX   2009-11-17 [1/1] Mikhail Gusarov; [notmuch] [PATCH] Handle rename of message file (inbox unread)
361 thread:XXX   2009-11-17 [2/7] Mikhail Gusarov| Lars Kellogg-Stedman, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
362 thread:XXX   2009-11-17 [2/5] Mikhail Gusarov| Carl Worth, Keith Packard; [notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox unread)
363 EOF
364 test_expect_equal_file EXPECTED OUTPUT
365
366 test_begin_subtest "starts-with, id"
367 notmuch search --query=sexp --output=messages '(id (starts-with 877))' > OUTPUT
368 cat <<EOF > EXPECTED
369 id:877h1wv7mg.fsf@inf-8657.int-evry.fr
370 id:877htoqdbo.fsf@yoom.home.cworth.org
371 EOF
372 test_expect_equal_file EXPECTED OUTPUT
373
374 test_begin_subtest "starts-with, is"
375 output=$(notmuch search --query=sexp '(is (starts-with searchby))' | notmuch_search_sanitize)
376 test_expect_equal "$output" 'thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)'
377
378 test_begin_subtest "starts-with, mid"
379 notmuch search --query=sexp --output=messages '(mid (starts-with 877))' > OUTPUT
380 cat <<EOF > EXPECTED
381 id:877h1wv7mg.fsf@inf-8657.int-evry.fr
382 id:877htoqdbo.fsf@yoom.home.cworth.org
383 EOF
384 test_expect_equal_file EXPECTED OUTPUT
385
386 test_begin_subtest "starts-with, mimetype"
387 notmuch search --query=sexp '(mimetype (starts-with sig))' | notmuch_search_sanitize > OUTPUT
388 cat <<EOF > EXPECTED
389 thread:XXX   2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
390 thread:XXX   2009-11-18 [4/7] Lars Kellogg-Stedman, Mikhail Gusarov| Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
391 thread:XXX   2009-11-17 [1/3] Adrian Perez de Castro| Keith Packard, Carl Worth; [notmuch] Introducing myself (inbox signed unread)
392 EOF
393 test_expect_equal_file EXPECTED OUTPUT
394
395 add_message '[subject]="message with properties"'
396 notmuch restore <<EOF
397 #= ${gen_msg_id} foo=bar
398 EOF
399
400 test_begin_subtest "starts-with, property"
401 notmuch search --query=sexp '(property (starts-with foo=))' | notmuch_search_sanitize > OUTPUT
402 cat <<EOF > EXPECTED
403 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; message with properties (inbox unread)
404 EOF
405 test_expect_equal_file EXPECTED OUTPUT
406
407 test_begin_subtest "starts-with, subject"
408 notmuch search --query=sexp '(subject (starts-with FreeB))' | notmuch_search_sanitize > OUTPUT
409 cat <<EOF > EXPECTED
410 thread:XXX   2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
411 EOF
412 test_expect_equal_file EXPECTED OUTPUT
413
414 test_begin_subtest "starts-with, tag"
415 output=$(notmuch search --query=sexp '(tag (starts-with searchby))' | notmuch_search_sanitize)
416 test_expect_equal "$output" 'thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)'
417
418 add_message '[subject]="no tags"'
419 notag_mid=${gen_msg_id}
420 notmuch tag -unread -inbox id:${notag_mid}
421
422 test_begin_subtest "negated starts-with, tag"
423 output=$(notmuch search --query=sexp '(tag (not (starts-with in)))' | notmuch_search_sanitize)
424 test_expect_equal "$output" 'thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; no tags ()'
425
426 test_begin_subtest "negated starts-with, tag 2"
427 output=$(notmuch search --query=sexp '(not (tag (starts-with in)))' | notmuch_search_sanitize)
428 test_expect_equal "$output" 'thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; no tags ()'
429
430 test_begin_subtest "negated starts-with, tag 3"
431 output=$(notmuch search --query=sexp '(not (tag (starts-with "")))' | notmuch_search_sanitize)
432 test_expect_equal "$output" 'thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; no tags ()'
433
434 test_begin_subtest "starts-with, thread"
435 notmuch search --query=sexp '(thread (starts-with "00"))' > OUTPUT
436 notmuch search '*' > EXPECTED
437 test_expect_equal_file EXPECTED OUTPUT
438
439 test_begin_subtest "starts-with, to"
440 notmuch search --query=sexp '(to (starts-with "search"))' | notmuch_search_sanitize > OUTPUT
441 cat <<EOF > EXPECTED
442 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)
443 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)
444 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)
445 EOF
446 test_expect_equal_file EXPECTED OUTPUT
447
448 test_begin_subtest "wildcard search for 'is'"
449 notmuch search not id:${notag_mid} > EXPECTED
450 notmuch search --query=sexp '(is *)' > OUTPUT
451 test_expect_equal_file EXPECTED OUTPUT
452
453 test_begin_subtest "negated wildcard search for 'is'"
454 notmuch search id:${notag_mid} > EXPECTED
455 notmuch search --query=sexp '(not (is *))' > OUTPUT
456 test_expect_equal_file EXPECTED OUTPUT
457
458 test_begin_subtest "wildcard search for 'property'"
459 notmuch search property:foo=bar > EXPECTED
460 notmuch search --query=sexp '(property *)' > OUTPUT
461 test_expect_equal_file EXPECTED OUTPUT
462
463 test_begin_subtest "wildcard search for 'tag'"
464 notmuch search not id:${notag_mid} > EXPECTED
465 notmuch search --query=sexp '(tag *)' > OUTPUT
466 test_expect_equal_file EXPECTED OUTPUT
467
468 test_begin_subtest "negated wildcard search for 'tag'"
469 notmuch search id:${notag_mid} > EXPECTED
470 notmuch search --query=sexp '(not (tag *))' > OUTPUT
471 test_expect_equal_file EXPECTED OUTPUT
472
473 add_message '[subject]="message with tag \"*\""'
474 notmuch tag '+*' id:${gen_msg_id}
475
476 test_begin_subtest "search for 'tag' \"*\""
477 output=$(notmuch search --query=sexp --output=messages '(tag "*")')
478 test_expect_equal "$output" "id:$gen_msg_id"
479
480 test_begin_subtest "search for missing / empty to"
481 add_message [to]="undisclosed-recipients:"
482 notmuch search --query=sexp '(not (to *))' | notmuch_search_sanitize > OUTPUT
483 cat <<EOF > EXPECTED
484 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; search for missing / empty to (inbox unread)
485 EOF
486 test_expect_equal_file EXPECTED OUTPUT
487
488 test_begin_subtest "Unbalanced parens"
489 # A code 1 indicates the error was handled (a crash will return e.g. 139).
490 test_expect_code 1 "notmuch search --query=sexp '('"
491
492 test_begin_subtest "Unbalanced parens, error message"
493 notmuch search --query=sexp '(' >OUTPUT 2>&1
494 cat <<EOF > EXPECTED
495 notmuch search: Syntax error in query
496 invalid s-expression: '('
497 EOF
498 test_expect_equal_file EXPECTED OUTPUT
499
500 test_begin_subtest "unknown prefix"
501 notmuch search --query=sexp '(foo)' >OUTPUT 2>&1
502 cat <<EOF > EXPECTED
503 notmuch search: Syntax error in query
504 unknown prefix 'foo'
505 EOF
506 test_expect_equal_file EXPECTED OUTPUT
507
508 test_begin_subtest "list as prefix"
509 notmuch search --query=sexp '((foo))' >OUTPUT 2>&1
510 cat <<EOF > EXPECTED
511 notmuch search: Syntax error in query
512 unexpected list in field/operation position
513 EOF
514 test_expect_equal_file EXPECTED OUTPUT
515
516 test_begin_subtest "illegal nesting"
517 notmuch search --query=sexp '(subject (subject foo))' >OUTPUT 2>&1
518 cat <<EOF > EXPECTED
519 notmuch search: Syntax error in query
520 nested field: 'subject' inside 'subject'
521 EOF
522 test_expect_equal_file EXPECTED OUTPUT
523
524 test_begin_subtest "starts-with, no argument"
525 notmuch search --query=sexp '(starts-with)' >OUTPUT 2>&1
526 cat <<EOF > EXPECTED
527 notmuch search: Syntax error in query
528 'starts-with' expects single atom as argument
529 EOF
530 test_expect_equal_file EXPECTED OUTPUT
531
532 test_begin_subtest "starts-with, list argument"
533 notmuch search --query=sexp '(starts-with (stuff))' >OUTPUT 2>&1
534 cat <<EOF > EXPECTED
535 notmuch search: Syntax error in query
536 'starts-with' expects single atom as argument
537 EOF
538 test_expect_equal_file EXPECTED OUTPUT
539
540 test_begin_subtest "starts-with, too many arguments"
541 notmuch search --query=sexp '(starts-with a b c)' >OUTPUT 2>&1
542 cat <<EOF > EXPECTED
543 notmuch search: Syntax error in query
544 'starts-with' expects single atom as argument
545 EOF
546 test_expect_equal_file EXPECTED OUTPUT
547
548 test_begin_subtest "starts-with, illegal field"
549 notmuch search --query=sexp '(body (starts-with foo))' >OUTPUT 2>&1
550 cat <<EOF > EXPECTED
551 notmuch search: Syntax error in query
552 'body' does not support wildcard queries
553 EOF
554 test_expect_equal_file EXPECTED OUTPUT
555
556 test_begin_subtest "wildcard, illegal field"
557 notmuch search --query=sexp '(body *)' >OUTPUT 2>&1
558 cat <<EOF > EXPECTED
559 notmuch search: Syntax error in query
560 'body' does not support wildcard queries
561 EOF
562 test_expect_equal_file EXPECTED OUTPUT
563
564 test_begin_subtest "Search, exclude \"deleted\" messages from search"
565 notmuch config set search.exclude_tags deleted
566 generate_message '[subject]="Not deleted"'
567 not_deleted_id=$gen_msg_id
568 generate_message '[subject]="Deleted"'
569 notmuch new > /dev/null
570 notmuch tag +deleted id:$gen_msg_id
571 deleted_id=$gen_msg_id
572 output=$(notmuch search --query=sexp '(subject deleted)' | notmuch_search_sanitize)
573 test_expect_equal "$output" "thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)"
574
575 test_begin_subtest "Search, exclude \"deleted\" messages from message search --exclude=false"
576 output=$(notmuch search --query=sexp --exclude=false --output=messages '(subject deleted)' | notmuch_search_sanitize)
577 test_expect_equal "$output" "id:$not_deleted_id
578 id:$deleted_id"
579
580 test_begin_subtest "Search, exclude \"deleted\" messages from search, overridden"
581 notmuch search --query=sexp '(and (subject deleted) (tag deleted))' | notmuch_search_sanitize > OUTPUT
582 cat <<EOF > EXPECTED
583 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Deleted (deleted inbox unread)
584 EOF
585 test_expect_equal_file EXPECTED OUTPUT
586
587 test_begin_subtest "Search, exclude \"deleted\" messages from threads"
588 add_message '[subject]="Not deleted reply"' '[in-reply-to]="<$gen_msg_id>"'
589 output=$(notmuch search --query=sexp '(subject deleted)' | notmuch_search_sanitize)
590 test_expect_equal "$output" "thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
591 thread:XXX   2001-01-05 [1/2] Notmuch Test Suite; Not deleted reply (deleted inbox unread)"
592
593 test_begin_subtest "Search, don't exclude \"deleted\" messages when --exclude=flag specified"
594 output=$(notmuch search --query=sexp --exclude=flag '(subject deleted)' | notmuch_search_sanitize)
595 test_expect_equal "$output" "thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
596 thread:XXX   2001-01-05 [1/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
597
598 test_begin_subtest "Search, don't exclude \"deleted\" messages from search if not configured"
599 notmuch config set search.exclude_tags
600 output=$(notmuch search --query=sexp '(subject deleted)' | notmuch_search_sanitize)
601 test_expect_equal "$output" "thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
602 thread:XXX   2001-01-05 [2/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
603
604 test_begin_subtest "regex at top level"
605 notmuch search --query=sexp '(rx foo)' >& OUTPUT
606 cat <<EOF > EXPECTED
607 notmuch search: Syntax error in query
608 illegal 'rx' outside field
609 EOF
610 test_expect_equal_file EXPECTED OUTPUT
611
612 test_begin_subtest "regex in illegal field"
613 notmuch search --query=sexp '(body (regex foo))' >& OUTPUT
614 cat <<EOF > EXPECTED
615 notmuch search: Syntax error in query
616 'regex' not supported in field 'body'
617 EOF
618 test_expect_equal_file EXPECTED OUTPUT
619
620 notmuch search --output=messages from:cworth > cworth.msg-ids
621
622 test_begin_subtest "regexp 'from' search"
623 notmuch search --output=messages --query=sexp '(from (rx cworth))' > OUTPUT
624 test_expect_equal_file cworth.msg-ids OUTPUT
625
626 test_begin_subtest "regexp search for 'from' 2"
627 notmuch search from:/cworth@cworth.org/ and subject:patch | notmuch_search_sanitize > EXPECTED
628 notmuch search --query=sexp '(and (from (rx cworth@cworth.org)) (subject patch))' \
629     | notmuch_search_sanitize > OUTPUT
630 test_expect_equal_file EXPECTED OUTPUT
631
632 test_begin_subtest "regexp 'folder' search"
633 notmuch search 'folder:/^bar$/' | notmuch_search_sanitize > EXPECTED
634 notmuch search --query=sexp '(folder (rx ^bar$))' | notmuch_search_sanitize > OUTPUT
635 test_expect_equal_file EXPECTED OUTPUT
636
637 test_begin_subtest "regexp 'id' search"
638 notmuch search --output=messages --query=sexp '(id (rx yoom))' > OUTPUT
639 test_expect_equal_file cworth.msg-ids OUTPUT
640
641 test_begin_subtest "unanchored 'is' search"
642 notmuch search tag:signed or tag:inbox > EXPECTED
643 notmuch search --query=sexp '(is (rx i))' > OUTPUT
644 test_expect_equal_file EXPECTED OUTPUT
645
646 test_begin_subtest "anchored 'is' search"
647 notmuch search tag:signed > EXPECTED
648 notmuch search --query=sexp '(is (rx ^si))' > OUTPUT
649 test_expect_equal_file EXPECTED OUTPUT
650
651 test_begin_subtest "combine regexp mid and subject"
652 notmuch search subject:/-C/ and mid:/y..m/ | notmuch_search_sanitize > EXPECTED
653 notmuch search --query=sexp '(and (subject (rx -C)) (mid (rx y..m)))' | notmuch_search_sanitize > OUTPUT
654 test_expect_equal_file EXPECTED OUTPUT
655
656 test_begin_subtest "regexp 'path' search"
657 notmuch search 'path:/^bar$/' | notmuch_search_sanitize > EXPECTED
658 notmuch search --query=sexp '(path (rx ^bar$))' | notmuch_search_sanitize > OUTPUT
659 test_expect_equal_file EXPECTED OUTPUT
660
661 test_begin_subtest "regexp 'property' search"
662 notmuch search property:foo=bar > EXPECTED
663 notmuch search --query=sexp '(property (rx foo=.*))' > OUTPUT
664 test_expect_equal_file EXPECTED OUTPUT
665
666 test_begin_subtest "anchored 'tag' search"
667 notmuch search tag:signed > EXPECTED
668 notmuch search --query=sexp '(tag (rx ^si))' > OUTPUT
669 test_expect_equal_file EXPECTED OUTPUT
670
671 test_begin_subtest "regexp 'thread' search"
672 notmuch search --output=threads '*' | grep '7$' > EXPECTED
673 notmuch search --output=threads --query=sexp '(thread (rx 7$))' > OUTPUT
674 test_expect_equal_file EXPECTED OUTPUT
675
676 test_begin_subtest "Basic query that matches no messages"
677 count=$(notmuch count from:keithp and to:keithp)
678 test_expect_equal 0 "$count"
679
680 test_begin_subtest "Same query against threads"
681 notmuch search --query=sexp '(and (thread (of (from keithp))) (thread (matching (to keithp))))' \
682     | notmuch_search_sanitize > OUTPUT
683 cat<<EOF > EXPECTED
684 thread:XXX   2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
685 EOF
686 test_expect_equal_file EXPECTED OUTPUT
687
688 test_begin_subtest "Mix thread and non-threads query"
689 notmuch search --query=sexp '(and (thread (matching keithp)) (to keithp))' | notmuch_search_sanitize > OUTPUT
690 cat<<EOF > EXPECTED
691 thread:XXX   2009-11-18 [1/7] Lars Kellogg-Stedman| Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
692 EOF
693 test_expect_equal_file EXPECTED OUTPUT
694
695 test_begin_subtest "Compound subquery"
696 notmuch search --query=sexp '(thread (of (from keithp) (subject Maildir)))' | notmuch_search_sanitize > OUTPUT
697 cat<<EOF > EXPECTED
698 thread:XXX   2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
699 EOF
700 test_expect_equal_file EXPECTED OUTPUT
701
702 test_begin_subtest "empty subquery"
703 notmuch search --query=sexp '(thread (of))' 1>OUTPUT 2>&1
704 notmuch search '*' > EXPECTED
705 test_expect_equal_file EXPECTED OUTPUT
706
707 test_begin_subtest "illegal expansion"
708 notmuch search --query=sexp '(id (of ego))' 1>OUTPUT 2>&1
709 cat<<EOF > EXPECTED
710 notmuch search: Syntax error in query
711 'of' unsupported inside 'id'
712 EOF
713 test_expect_equal_file EXPECTED OUTPUT
714
715 test_begin_subtest "(folder (of subquery))"
716 notmuch search --query=sexp --output=messages '(folder (of (id yun3a4cegoa.fsf@aiko.keithp.com)))' > OUTPUT
717 cat <<EOF > EXPECTED
718 id:yun1vjwegii.fsf@aiko.keithp.com
719 id:yun3a4cegoa.fsf@aiko.keithp.com
720 id:1258509400-32511-1-git-send-email-stewart@flamingspork.com
721 id:1258506353-20352-1-git-send-email-stewart@flamingspork.com
722 id:20091118010116.GC25380@dottiness.seas.harvard.edu
723 id:20091118005829.GB25380@dottiness.seas.harvard.edu
724 id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com
725 EOF
726 test_expect_equal_file EXPECTED OUTPUT
727
728 test_begin_subtest "infix query"
729 notmuch search to:searchbyto | notmuch_search_sanitize > EXPECTED
730 notmuch search --query=sexp '(infix "to:searchbyto")' |  notmuch_search_sanitize > OUTPUT
731 test_expect_equal_file EXPECTED OUTPUT
732
733 test_begin_subtest "bad infix query 1"
734 notmuch search --query=sexp '(infix "from:/unbalanced")' 2>&1|  notmuch_search_sanitize > OUTPUT
735 cat <<EOF > EXPECTED
736 notmuch search: Syntax error in query
737 Syntax error in infix query: from:/unbalanced
738 EOF
739 test_expect_equal_file EXPECTED OUTPUT
740
741 test_begin_subtest "bad infix query 2"
742 notmuch search --query=sexp '(infix "thread:{unbalanced")' 2>&1|  notmuch_search_sanitize > OUTPUT
743 cat <<EOF > EXPECTED
744 notmuch search: Syntax error in query
745 Syntax error in infix query: thread:{unbalanced
746 EOF
747 test_expect_equal_file EXPECTED OUTPUT
748
749 test_begin_subtest "bad infix query 3: bad nesting"
750 notmuch search --query=sexp '(subject (infix "tag:inbox"))' 2>&1|  notmuch_search_sanitize > OUTPUT
751 cat <<EOF > EXPECTED
752 notmuch search: Syntax error in query
753 'infix' not supported inside 'subject'
754 EOF
755 test_expect_equal_file EXPECTED OUTPUT
756
757 test_begin_subtest "infix query that matches no messages"
758 notmuch search --query=sexp '(and (infix "from:keithp") (infix "to:keithp"))' > OUTPUT
759 test_expect_equal_file /dev/null OUTPUT
760
761 test_begin_subtest "compound infix query"
762 notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
763 notmuch search --query=sexp  '(infix "date:2009-11-18..2009-11-18 and tag:unread")' > OUTPUT
764 test_expect_equal_file EXPECTED OUTPUT
765
766 test_begin_subtest "compound infix query 2"
767 notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
768 notmuch search --query=sexp  '(and (infix "date:2009-11-18..2009-11-18") (infix "tag:unread"))' > OUTPUT
769 test_expect_equal_file EXPECTED OUTPUT
770
771 test_begin_subtest "date query, empty"
772 notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
773 notmuch search --query=sexp  '(and (date) (from keithp))'| notmuch_search_sanitize > OUTPUT
774 test_expect_equal_file EXPECTED OUTPUT
775
776 test_begin_subtest "date query, one argument"
777 notmuch search date:2009-11-18 and from:keithp | notmuch_search_sanitize > EXPECTED
778 notmuch search --query=sexp  '(and (date 2009-11-18) (from keithp))' | notmuch_search_sanitize > OUTPUT
779 test_expect_equal_file EXPECTED OUTPUT
780
781 test_begin_subtest "date query, two arguments"
782 notmuch search date:2009-11-17..2009-11-18 and from:keithp | notmuch_search_sanitize > EXPECTED
783 notmuch search --query=sexp  '(and (date 2009-11-17 2009-11-18) (from keithp))' | notmuch_search_sanitize > OUTPUT
784 test_expect_equal_file EXPECTED OUTPUT
785
786 test_begin_subtest "date query, illegal nesting 1"
787 notmuch search --query=sexp '(to (date))' > OUTPUT 2>&1
788 cat <<EOF > EXPECTED
789 notmuch search: Syntax error in query
790 nested field: 'date' inside 'to'
791 EOF
792 test_expect_equal_file EXPECTED OUTPUT
793
794 test_begin_subtest "date query, illegal nesting 2"
795 notmuch search --query=sexp '(to (date 2021-11-18))' > OUTPUT 2>&1
796 cat <<EOF > EXPECTED
797 notmuch search: Syntax error in query
798 nested field: 'date' inside 'to'
799 EOF
800 test_expect_equal_file EXPECTED OUTPUT
801
802 test_begin_subtest "date query, illegal nesting 3"
803 notmuch search --query=sexp '(date (to))' > OUTPUT 2>&1
804 cat <<EOF > EXPECTED
805 notmuch search: Syntax error in query
806 expected atom as first argument of 'date'
807 EOF
808 test_expect_equal_file EXPECTED OUTPUT
809
810 test_begin_subtest "date query, illegal nesting 4"
811 notmuch search --query=sexp '(date today (to))' > OUTPUT 2>&1
812 cat <<EOF > EXPECTED
813 notmuch search: Syntax error in query
814 expected atom as second argument of 'date'
815 EOF
816 test_expect_equal_file EXPECTED OUTPUT
817
818 test_begin_subtest "date query, too many arguments"
819 notmuch search --query=sexp '(date yesterday and tommorow)' > OUTPUT 2>&1
820 cat <<EOF > EXPECTED
821 notmuch search: Syntax error in query
822 'date' expects maximum of two arguments
823 EOF
824 test_expect_equal_file EXPECTED OUTPUT
825
826 test_begin_subtest "date query, bad date"
827 notmuch search --query=sexp '(date "hawaiian-pizza-day")' > OUTPUT 2>&1
828 cat <<EOF > EXPECTED
829 notmuch search: Syntax error in query
830 Didn't understand date specification 'hawaiian-pizza-day'
831 EOF
832 test_expect_equal_file EXPECTED OUTPUT
833
834 test_begin_subtest "lastmod query, empty"
835 test_subtest_known_broken
836 notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
837 notmuch search --query=sexp  '(and (lastmod) (from keithp))'| notmuch_search_sanitize > OUTPUT
838 test_expect_equal_file EXPECTED OUTPUT
839
840 test_begin_subtest "lastmod query, one argument"
841 test_subtest_known_broken
842 notmuch tag +4EFC743A.3060609@april.org id:4EFC743A.3060609@april.org
843 revision=$(notmuch count --lastmod '*' | cut -f3)
844 notmuch search lastmod:$revision..$revision | notmuch_search_sanitize > EXPECTED
845 notmuch search --query=sexp  "(and (lastmod $revision))" | notmuch_search_sanitize > OUTPUT
846 test_expect_equal_file EXPECTED OUTPUT
847
848 test_begin_subtest "lastmod query, two arguments"
849 test_subtest_known_broken
850 notmuch tag +keithp from:keithp
851 revision2=$(notmuch count --lastmod '*' | cut -f3)
852 notmuch search lastmod:$revision..$revision2 | notmuch_search_sanitize > EXPECTED
853 notmuch search --query=sexp  "(and (lastmod $revision $revision2))" | notmuch_search_sanitize > OUTPUT
854 test_expect_equal_file EXPECTED OUTPUT
855
856 test_begin_subtest "lastmod query, illegal nesting 1"
857 test_subtest_known_broken
858 notmuch search --query=sexp '(to (lastmod))' > OUTPUT 2>&1
859 cat <<EOF > EXPECTED
860 notmuch search: Syntax error in query
861 nested field: 'lastmod' inside 'to'
862 EOF
863 test_expect_equal_file EXPECTED OUTPUT
864
865 test_begin_subtest "lastmod query, bad from revision"
866 test_subtest_known_broken
867 notmuch search --query=sexp '(lastmod apples)' > OUTPUT 2>&1
868 cat <<EOF > EXPECTED
869 notmuch search: Syntax error in query
870 bad 'from' revision: 'apples'
871 EOF
872 test_expect_equal_file EXPECTED OUTPUT
873
874 test_begin_subtest "lastmod query, bad to revision"
875 test_subtest_known_broken
876 notmuch search --query=sexp '(lastmod 0 apples)' > OUTPUT 2>&1
877 cat <<EOF > EXPECTED
878 notmuch search: Syntax error in query
879 bad 'to' revision: 'apples'
880 EOF
881 test_expect_equal_file EXPECTED OUTPUT
882
883 test_begin_subtest "lastmod query, illegal nesting 2"
884 test_subtest_known_broken
885 notmuch search --query=sexp '(to (lastmod 2021-11-18))' > OUTPUT 2>&1
886 cat <<EOF > EXPECTED
887 notmuch search: Syntax error in query
888 nested field: 'lastmod' inside 'to'
889 EOF
890 test_expect_equal_file EXPECTED OUTPUT
891
892 test_begin_subtest "lastmod query, illegal nesting 3"
893 test_subtest_known_broken
894 notmuch search --query=sexp '(lastmod (to))' > OUTPUT 2>&1
895 cat <<EOF > EXPECTED
896 notmuch search: Syntax error in query
897 expected atom as first argument of 'lastmod'
898 EOF
899 test_expect_equal_file EXPECTED OUTPUT
900
901 test_begin_subtest "lastmod query, illegal nesting 4"
902 test_subtest_known_broken
903 notmuch search --query=sexp '(lastmod today (to))' > OUTPUT 2>&1
904 cat <<EOF > EXPECTED
905 notmuch search: Syntax error in query
906 expected atom as second argument of 'lastmod'
907 EOF
908 test_expect_equal_file EXPECTED OUTPUT
909
910 test_begin_subtest "lastmod query, too many arguments"
911 test_subtest_known_broken
912 notmuch search --query=sexp '(lastmod yesterday and tommorow)' > OUTPUT 2>&1
913 cat <<EOF > EXPECTED
914 notmuch search: Syntax error in query
915 'lastmod' expects maximum of two arguments
916 EOF
917 test_expect_equal_file EXPECTED OUTPUT
918
919 test_begin_subtest "user header (unknown header)"
920 notmuch search --query=sexp '(FooBar)' >& OUTPUT
921 cat <<EOF > EXPECTED
922 notmuch search: Syntax error in query
923 unknown prefix 'FooBar'
924 EOF
925 test_expect_equal_file EXPECTED OUTPUT
926
927 test_begin_subtest "adding user header"
928 test_expect_code 0 "notmuch config set index.header.List \"List-Id\""
929
930 test_begin_subtest "reindexing"
931 test_expect_code 0 'notmuch reindex "*"'
932
933 test_begin_subtest "wildcard search for user header"
934 grep -Ril List-Id ${MAIL_DIR} | sort | notmuch_dir_sanitize > EXPECTED
935 notmuch search --output=files --query=sexp '(List *)' | sort | notmuch_dir_sanitize > OUTPUT
936 test_expect_equal_file EXPECTED OUTPUT
937
938 test_begin_subtest "wildcard search for user header 2"
939 grep -Ril List-Id ${MAIL_DIR} | sort | notmuch_dir_sanitize > EXPECTED
940 notmuch search --output=files --query=sexp '(List (starts-with not))' | sort | notmuch_dir_sanitize > OUTPUT
941 test_expect_equal_file EXPECTED OUTPUT
942
943 test_begin_subtest "search for user header"
944 notmuch search List:notmuch | notmuch_search_sanitize > EXPECTED
945 notmuch search --query=sexp '(List notmuch)' | notmuch_search_sanitize > OUTPUT
946 test_expect_equal_file EXPECTED OUTPUT
947
948 test_begin_subtest "search for user header (list token)"
949 notmuch search List:notmuch | notmuch_search_sanitize > EXPECTED
950 notmuch search --query=sexp '(List notmuch.notmuchmail.org)' | notmuch_search_sanitize > OUTPUT
951 test_expect_equal_file EXPECTED OUTPUT
952
953 test_begin_subtest "search for user header (quoted string)"
954 notmuch search 'List:"notmuch notmuchmail org"' | notmuch_search_sanitize > EXPECTED
955 notmuch search --query=sexp '(List "notmuch notmuchmail org")' | notmuch_search_sanitize > OUTPUT
956 test_expect_equal_file EXPECTED OUTPUT
957
958 test_begin_subtest "search for user header (atoms)"
959 notmuch search 'List:"notmuch notmuchmail org"' | notmuch_search_sanitize > EXPECTED
960 notmuch search --query=sexp '(List notmuch notmuchmail org)' | notmuch_search_sanitize > OUTPUT
961 test_expect_equal_file EXPECTED OUTPUT
962
963 test_begin_subtest "check saved query name"
964 test_expect_code 1 "notmuch config set squery.test '(subject utf8-sübjéct)'"
965
966 test_begin_subtest "roundtrip saved query (database)"
967 notmuch config set --database squery.Test '(subject utf8-sübjéct)'
968 output=$(notmuch config get squery.Test)
969 test_expect_equal "$output" '(subject utf8-sübjéct)'
970
971 test_begin_subtest "roundtrip saved query"
972 notmuch config set squery.Test '(subject override subject)'
973 output=$(notmuch config get squery.Test)
974 test_expect_equal "$output" '(subject override subject)'
975
976 test_begin_subtest "unknown saved query"
977 notmuch search --query=sexp '(Unknown foo bar)' >OUTPUT 2>&1
978 cat <<EOF > EXPECTED
979 notmuch search: Syntax error in query
980 unknown prefix 'Unknown'
981 EOF
982 test_expect_equal_file EXPECTED OUTPUT
983
984 test_begin_subtest "syntax error in saved query"
985 notmuch config set squery.Bad '(Bad'
986 notmuch search --query=sexp '(Bad foo bar)' >OUTPUT 2>&1
987 cat <<EOF > EXPECTED
988 notmuch search: Syntax error in query
989 invalid saved s-expression query: '(Bad'
990 EOF
991 test_expect_equal_file EXPECTED OUTPUT
992
993 test_begin_subtest "Saved Search by 'tag' and 'subject'"
994 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
995 notmuch config set squery.TagSubject  '(and (tag inbox) (subject maildir))'
996 notmuch search --query=sexp '(TagSubject)' | notmuch_search_sanitize > OUTPUT
997 test_expect_equal_file EXPECTED OUTPUT
998
999 test_begin_subtest "Saved Search: illegal nesting"
1000 notmuch config set squery.TagSubject  '(and (tag inbox) (subject maildir))'
1001 notmuch search --query=sexp '(subject (TagSubject))' >OUTPUT 2>&1
1002 cat <<EOF > EXPECTED
1003 notmuch search: Syntax error in query
1004 nested field: 'tag' inside 'subject'
1005 EOF
1006 test_expect_equal_file EXPECTED OUTPUT
1007
1008 test_begin_subtest "Saved Search: list as prefix"
1009 notmuch config set squery.Bad2  '((and) (tag inbox) (subject maildir))'
1010 notmuch search --query=sexp '(Bad2)' >OUTPUT 2>&1
1011 cat <<EOF > EXPECTED
1012 notmuch search: Syntax error in query
1013 unexpected list in field/operation position
1014 EOF
1015 test_expect_equal_file EXPECTED OUTPUT
1016
1017 test_begin_subtest "Saved Search: bad parameter syntax"
1018 notmuch config set squery.Bad3  '(macro a b)'
1019 notmuch search --query=sexp '(Bad3)' >OUTPUT 2>&1
1020 cat <<EOF > EXPECTED
1021 notmuch search: Syntax error in query
1022 missing (possibly empty) list of arguments to macro
1023 EOF
1024 test_expect_equal_file EXPECTED OUTPUT
1025
1026 test_begin_subtest "Saved Search: bad parameter syntax 2"
1027 notmuch config set squery.Bad4  '(macro ((a b)) a)'
1028 notmuch search --query=sexp '(Bad4 1)' >OUTPUT 2>&1
1029 cat <<EOF > EXPECTED
1030 notmuch search: Syntax error in query
1031 macro parameters must be unquoted atoms
1032 EOF
1033 test_expect_equal_file EXPECTED OUTPUT
1034
1035 test_begin_subtest "Saved Search: bad parameter syntax 3"
1036 notmuch config set squery.Bad5  '(macro (a b) a)'
1037 notmuch search --query=sexp '(Bad5 1)' >OUTPUT 2>&1
1038 cat <<EOF > EXPECTED
1039 notmuch search: Syntax error in query
1040 too few arguments to macro
1041 EOF
1042 test_expect_equal_file EXPECTED OUTPUT
1043
1044 test_begin_subtest "Saved Search: bad parameter syntax 4"
1045 notmuch search --query=sexp '(Bad5 1 2 3)' >OUTPUT 2>&1
1046 cat <<EOF > EXPECTED
1047 notmuch search: Syntax error in query
1048 too many arguments to macro
1049 EOF
1050 test_expect_equal_file EXPECTED OUTPUT
1051
1052 test_begin_subtest "Saved Search: macro without body"
1053 notmuch config set squery.Bad3  '(macro (a b))'
1054 notmuch search --query=sexp '(Bad3)' >OUTPUT 2>&1
1055 cat <<EOF > EXPECTED
1056 notmuch search: Syntax error in query
1057 missing body of macro
1058 EOF
1059 test_expect_equal_file EXPECTED OUTPUT
1060
1061 test_begin_subtest "macro in query"
1062 notmuch search --query=sexp '(macro (a) (and ,b (subject maildir)))' >OUTPUT 2>&1
1063 cat <<EOF > EXPECTED
1064 notmuch search: Syntax error in query
1065 macro definition not permitted here
1066 EOF
1067 test_expect_equal_file EXPECTED OUTPUT
1068
1069 test_begin_subtest "zero argument macro"
1070 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1071 notmuch config set squery.TagSubject0  '(macro () (and (tag inbox) (subject maildir)))'
1072 notmuch search --query=sexp '(TagSubject0)' | notmuch_search_sanitize > OUTPUT
1073 test_expect_equal_file EXPECTED OUTPUT
1074
1075 test_begin_subtest "undefined argument"
1076 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1077 notmuch config set squery.Bad6  '(macro (a) (and ,b (subject maildir)))'
1078 notmuch search --query=sexp '(Bad6 foo)' >OUTPUT 2>&1
1079 cat <<EOF > EXPECTED
1080 notmuch search: Syntax error in query
1081 undefined parameter b
1082 EOF
1083 test_expect_equal_file EXPECTED OUTPUT
1084
1085 test_begin_subtest "Single argument macro"
1086 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1087 notmuch config set squery.TagSubject1  '(macro (tagname) (and (tag ,tagname) (subject maildir)))'
1088 notmuch search --query=sexp '(TagSubject1 inbox)' | notmuch_search_sanitize > OUTPUT
1089 test_expect_equal_file EXPECTED OUTPUT
1090
1091 test_begin_subtest "Single argument macro, list argument"
1092 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1093 notmuch config set squery.ThingSubject  '(macro (thing) (and ,thing (subject maildir)))'
1094 notmuch search --query=sexp '(ThingSubject (tag inbox))' | notmuch_search_sanitize > OUTPUT
1095 test_expect_equal_file EXPECTED OUTPUT
1096
1097 test_begin_subtest "two argument macro"
1098 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1099 notmuch config set squery.TagSubject2  '(macro (tagname subj) (and (tag ,tagname) (subject ,subj)))'
1100 notmuch search --query=sexp '(TagSubject2 inbox maildir)' | notmuch_search_sanitize > OUTPUT
1101 test_expect_equal_file EXPECTED OUTPUT
1102
1103 test_begin_subtest "nested macros (shadowing)"
1104 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1105 notmuch config set squery.Inner '(macro (x) (subject ,x))'
1106 notmuch config set squery.Outer  '(macro (x y) (and (tag ,x) (Inner ,y)))'
1107 notmuch search --query=sexp '(Outer inbox maildir)' | notmuch_search_sanitize > OUTPUT
1108 test_expect_equal_file EXPECTED OUTPUT
1109
1110 test_begin_subtest "nested macros (no dynamic scope)"
1111 notmuch config set squery.Inner2 '(macro (x) (subject ,y))'
1112 notmuch config set squery.Outer2  '(macro (x y) (and (tag ,x) (Inner2 ,y)))'
1113 notmuch search --query=sexp '(Outer2 inbox maildir)' > OUTPUT 2>&1
1114 cat <<EOF > EXPECTED
1115 notmuch search: Syntax error in query
1116 undefined parameter y
1117 EOF
1118 test_expect_equal_file EXPECTED OUTPUT
1119
1120 test_begin_subtest "combine macro and user defined header"
1121 notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
1122 notmuch search subject:notmuch or List:notmuch | notmuch_search_sanitize > EXPECTED
1123 notmuch search --query=sexp '(About notmuch)' | notmuch_search_sanitize > OUTPUT
1124 test_expect_equal_file EXPECTED OUTPUT
1125
1126
1127 test_begin_subtest "combine macro and user defined header"
1128 notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
1129 notmuch search subject:notmuch or List:notmuch | notmuch_search_sanitize > EXPECTED
1130 notmuch search --query=sexp '(About notmuch)' | notmuch_search_sanitize > OUTPUT
1131 test_expect_equal_file EXPECTED OUTPUT
1132
1133
1134 test_done