]> git.notmuchmail.org Git - notmuch/blob - test/T081-sexpr-search.sh
lib/parse-sexp: handle lastmod queries.
[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 notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
836 notmuch search --query=sexp  '(and (lastmod) (from keithp))'| notmuch_search_sanitize > OUTPUT
837 test_expect_equal_file EXPECTED OUTPUT
838
839 test_begin_subtest "lastmod query, one argument"
840 notmuch tag +4EFC743A.3060609@april.org id:4EFC743A.3060609@april.org
841 revision=$(notmuch count --lastmod '*' | cut -f3)
842 notmuch search lastmod:$revision..$revision | notmuch_search_sanitize > EXPECTED
843 notmuch search --query=sexp  "(and (lastmod $revision))" | notmuch_search_sanitize > OUTPUT
844 test_expect_equal_file EXPECTED OUTPUT
845
846 test_begin_subtest "lastmod query, two arguments"
847 notmuch tag +keithp from:keithp
848 revision2=$(notmuch count --lastmod '*' | cut -f3)
849 notmuch search lastmod:$revision..$revision2 | notmuch_search_sanitize > EXPECTED
850 notmuch search --query=sexp  "(and (lastmod $revision $revision2))" | notmuch_search_sanitize > OUTPUT
851 test_expect_equal_file EXPECTED OUTPUT
852
853 test_begin_subtest "lastmod query, illegal nesting 1"
854 notmuch search --query=sexp '(to (lastmod))' > OUTPUT 2>&1
855 cat <<EOF > EXPECTED
856 notmuch search: Syntax error in query
857 nested field: 'lastmod' inside 'to'
858 EOF
859 test_expect_equal_file EXPECTED OUTPUT
860
861 test_begin_subtest "lastmod query, bad from revision"
862 notmuch search --query=sexp '(lastmod apples)' > OUTPUT 2>&1
863 cat <<EOF > EXPECTED
864 notmuch search: Syntax error in query
865 bad 'from' revision: 'apples'
866 EOF
867 test_expect_equal_file EXPECTED OUTPUT
868
869 test_begin_subtest "lastmod query, bad to revision"
870 notmuch search --query=sexp '(lastmod 0 apples)' > OUTPUT 2>&1
871 cat <<EOF > EXPECTED
872 notmuch search: Syntax error in query
873 bad 'to' revision: 'apples'
874 EOF
875 test_expect_equal_file EXPECTED OUTPUT
876
877 test_begin_subtest "lastmod query, illegal nesting 2"
878 notmuch search --query=sexp '(to (lastmod 2021-11-18))' > OUTPUT 2>&1
879 cat <<EOF > EXPECTED
880 notmuch search: Syntax error in query
881 nested field: 'lastmod' inside 'to'
882 EOF
883 test_expect_equal_file EXPECTED OUTPUT
884
885 test_begin_subtest "lastmod query, illegal nesting 3"
886 notmuch search --query=sexp '(lastmod (to))' > OUTPUT 2>&1
887 cat <<EOF > EXPECTED
888 notmuch search: Syntax error in query
889 expected atom as first argument of 'lastmod'
890 EOF
891 test_expect_equal_file EXPECTED OUTPUT
892
893 test_begin_subtest "lastmod query, illegal nesting 4"
894 notmuch search --query=sexp '(lastmod today (to))' > OUTPUT 2>&1
895 cat <<EOF > EXPECTED
896 notmuch search: Syntax error in query
897 expected atom as second argument of 'lastmod'
898 EOF
899 test_expect_equal_file EXPECTED OUTPUT
900
901 test_begin_subtest "lastmod query, too many arguments"
902 notmuch search --query=sexp '(lastmod yesterday and tommorow)' > OUTPUT 2>&1
903 cat <<EOF > EXPECTED
904 notmuch search: Syntax error in query
905 'lastmod' expects maximum of two arguments
906 EOF
907 test_expect_equal_file EXPECTED OUTPUT
908
909 test_begin_subtest "user header (unknown header)"
910 notmuch search --query=sexp '(FooBar)' >& OUTPUT
911 cat <<EOF > EXPECTED
912 notmuch search: Syntax error in query
913 unknown prefix 'FooBar'
914 EOF
915 test_expect_equal_file EXPECTED OUTPUT
916
917 test_begin_subtest "adding user header"
918 test_expect_code 0 "notmuch config set index.header.List \"List-Id\""
919
920 test_begin_subtest "reindexing"
921 test_expect_code 0 'notmuch reindex "*"'
922
923 test_begin_subtest "wildcard search for user header"
924 grep -Ril List-Id ${MAIL_DIR} | sort | notmuch_dir_sanitize > EXPECTED
925 notmuch search --output=files --query=sexp '(List *)' | sort | notmuch_dir_sanitize > OUTPUT
926 test_expect_equal_file EXPECTED OUTPUT
927
928 test_begin_subtest "wildcard search for user header 2"
929 grep -Ril List-Id ${MAIL_DIR} | sort | notmuch_dir_sanitize > EXPECTED
930 notmuch search --output=files --query=sexp '(List (starts-with not))' | sort | notmuch_dir_sanitize > OUTPUT
931 test_expect_equal_file EXPECTED OUTPUT
932
933 test_begin_subtest "search for user header"
934 notmuch search List:notmuch | notmuch_search_sanitize > EXPECTED
935 notmuch search --query=sexp '(List notmuch)' | notmuch_search_sanitize > OUTPUT
936 test_expect_equal_file EXPECTED OUTPUT
937
938 test_begin_subtest "search for user header (list token)"
939 notmuch search List:notmuch | notmuch_search_sanitize > EXPECTED
940 notmuch search --query=sexp '(List notmuch.notmuchmail.org)' | notmuch_search_sanitize > OUTPUT
941 test_expect_equal_file EXPECTED OUTPUT
942
943 test_begin_subtest "search for user header (quoted string)"
944 notmuch search 'List:"notmuch notmuchmail org"' | notmuch_search_sanitize > EXPECTED
945 notmuch search --query=sexp '(List "notmuch notmuchmail org")' | notmuch_search_sanitize > OUTPUT
946 test_expect_equal_file EXPECTED OUTPUT
947
948 test_begin_subtest "search for user header (atoms)"
949 notmuch search 'List:"notmuch notmuchmail org"' | 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 "check saved query name"
954 test_expect_code 1 "notmuch config set squery.test '(subject utf8-sübjéct)'"
955
956 test_begin_subtest "roundtrip saved query (database)"
957 notmuch config set --database squery.Test '(subject utf8-sübjéct)'
958 output=$(notmuch config get squery.Test)
959 test_expect_equal "$output" '(subject utf8-sübjéct)'
960
961 test_begin_subtest "roundtrip saved query"
962 notmuch config set squery.Test '(subject override subject)'
963 output=$(notmuch config get squery.Test)
964 test_expect_equal "$output" '(subject override subject)'
965
966 test_begin_subtest "unknown saved query"
967 notmuch search --query=sexp '(Unknown foo bar)' >OUTPUT 2>&1
968 cat <<EOF > EXPECTED
969 notmuch search: Syntax error in query
970 unknown prefix 'Unknown'
971 EOF
972 test_expect_equal_file EXPECTED OUTPUT
973
974 test_begin_subtest "syntax error in saved query"
975 notmuch config set squery.Bad '(Bad'
976 notmuch search --query=sexp '(Bad foo bar)' >OUTPUT 2>&1
977 cat <<EOF > EXPECTED
978 notmuch search: Syntax error in query
979 invalid saved s-expression query: '(Bad'
980 EOF
981 test_expect_equal_file EXPECTED OUTPUT
982
983 test_begin_subtest "Saved Search by 'tag' and 'subject'"
984 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
985 notmuch config set squery.TagSubject  '(and (tag inbox) (subject maildir))'
986 notmuch search --query=sexp '(TagSubject)' | notmuch_search_sanitize > OUTPUT
987 test_expect_equal_file EXPECTED OUTPUT
988
989 test_begin_subtest "Saved Search: illegal nesting"
990 notmuch config set squery.TagSubject  '(and (tag inbox) (subject maildir))'
991 notmuch search --query=sexp '(subject (TagSubject))' >OUTPUT 2>&1
992 cat <<EOF > EXPECTED
993 notmuch search: Syntax error in query
994 nested field: 'tag' inside 'subject'
995 EOF
996 test_expect_equal_file EXPECTED OUTPUT
997
998 test_begin_subtest "Saved Search: list as prefix"
999 notmuch config set squery.Bad2  '((and) (tag inbox) (subject maildir))'
1000 notmuch search --query=sexp '(Bad2)' >OUTPUT 2>&1
1001 cat <<EOF > EXPECTED
1002 notmuch search: Syntax error in query
1003 unexpected list in field/operation position
1004 EOF
1005 test_expect_equal_file EXPECTED OUTPUT
1006
1007 test_begin_subtest "Saved Search: bad parameter syntax"
1008 notmuch config set squery.Bad3  '(macro a b)'
1009 notmuch search --query=sexp '(Bad3)' >OUTPUT 2>&1
1010 cat <<EOF > EXPECTED
1011 notmuch search: Syntax error in query
1012 missing (possibly empty) list of arguments to macro
1013 EOF
1014 test_expect_equal_file EXPECTED OUTPUT
1015
1016 test_begin_subtest "Saved Search: bad parameter syntax 2"
1017 notmuch config set squery.Bad4  '(macro ((a b)) a)'
1018 notmuch search --query=sexp '(Bad4 1)' >OUTPUT 2>&1
1019 cat <<EOF > EXPECTED
1020 notmuch search: Syntax error in query
1021 macro parameters must be unquoted atoms
1022 EOF
1023 test_expect_equal_file EXPECTED OUTPUT
1024
1025 test_begin_subtest "Saved Search: bad parameter syntax 3"
1026 notmuch config set squery.Bad5  '(macro (a b) a)'
1027 notmuch search --query=sexp '(Bad5 1)' >OUTPUT 2>&1
1028 cat <<EOF > EXPECTED
1029 notmuch search: Syntax error in query
1030 too few arguments to macro
1031 EOF
1032 test_expect_equal_file EXPECTED OUTPUT
1033
1034 test_begin_subtest "Saved Search: bad parameter syntax 4"
1035 notmuch search --query=sexp '(Bad5 1 2 3)' >OUTPUT 2>&1
1036 cat <<EOF > EXPECTED
1037 notmuch search: Syntax error in query
1038 too many arguments to macro
1039 EOF
1040 test_expect_equal_file EXPECTED OUTPUT
1041
1042 test_begin_subtest "Saved Search: macro without body"
1043 notmuch config set squery.Bad3  '(macro (a b))'
1044 notmuch search --query=sexp '(Bad3)' >OUTPUT 2>&1
1045 cat <<EOF > EXPECTED
1046 notmuch search: Syntax error in query
1047 missing body of macro
1048 EOF
1049 test_expect_equal_file EXPECTED OUTPUT
1050
1051 test_begin_subtest "macro in query"
1052 notmuch search --query=sexp '(macro (a) (and ,b (subject maildir)))' >OUTPUT 2>&1
1053 cat <<EOF > EXPECTED
1054 notmuch search: Syntax error in query
1055 macro definition not permitted here
1056 EOF
1057 test_expect_equal_file EXPECTED OUTPUT
1058
1059 test_begin_subtest "zero argument macro"
1060 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1061 notmuch config set squery.TagSubject0  '(macro () (and (tag inbox) (subject maildir)))'
1062 notmuch search --query=sexp '(TagSubject0)' | notmuch_search_sanitize > OUTPUT
1063 test_expect_equal_file EXPECTED OUTPUT
1064
1065 test_begin_subtest "undefined argument"
1066 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1067 notmuch config set squery.Bad6  '(macro (a) (and ,b (subject maildir)))'
1068 notmuch search --query=sexp '(Bad6 foo)' >OUTPUT 2>&1
1069 cat <<EOF > EXPECTED
1070 notmuch search: Syntax error in query
1071 undefined parameter b
1072 EOF
1073 test_expect_equal_file EXPECTED OUTPUT
1074
1075 test_begin_subtest "Single argument macro"
1076 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1077 notmuch config set squery.TagSubject1  '(macro (tagname) (and (tag ,tagname) (subject maildir)))'
1078 notmuch search --query=sexp '(TagSubject1 inbox)' | notmuch_search_sanitize > OUTPUT
1079 test_expect_equal_file EXPECTED OUTPUT
1080
1081 test_begin_subtest "Single argument macro, list argument"
1082 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1083 notmuch config set squery.ThingSubject  '(macro (thing) (and ,thing (subject maildir)))'
1084 notmuch search --query=sexp '(ThingSubject (tag inbox))' | notmuch_search_sanitize > OUTPUT
1085 test_expect_equal_file EXPECTED OUTPUT
1086
1087 test_begin_subtest "two argument macro"
1088 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1089 notmuch config set squery.TagSubject2  '(macro (tagname subj) (and (tag ,tagname) (subject ,subj)))'
1090 notmuch search --query=sexp '(TagSubject2 inbox maildir)' | notmuch_search_sanitize > OUTPUT
1091 test_expect_equal_file EXPECTED OUTPUT
1092
1093 test_begin_subtest "nested macros (shadowing)"
1094 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1095 notmuch config set squery.Inner '(macro (x) (subject ,x))'
1096 notmuch config set squery.Outer  '(macro (x y) (and (tag ,x) (Inner ,y)))'
1097 notmuch search --query=sexp '(Outer inbox maildir)' | notmuch_search_sanitize > OUTPUT
1098 test_expect_equal_file EXPECTED OUTPUT
1099
1100 test_begin_subtest "nested macros (no dynamic scope)"
1101 notmuch config set squery.Inner2 '(macro (x) (subject ,y))'
1102 notmuch config set squery.Outer2  '(macro (x y) (and (tag ,x) (Inner2 ,y)))'
1103 notmuch search --query=sexp '(Outer2 inbox maildir)' > OUTPUT 2>&1
1104 cat <<EOF > EXPECTED
1105 notmuch search: Syntax error in query
1106 undefined parameter y
1107 EOF
1108 test_expect_equal_file EXPECTED OUTPUT
1109
1110 test_begin_subtest "combine macro and user defined header"
1111 notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
1112 notmuch search subject:notmuch or List:notmuch | notmuch_search_sanitize > EXPECTED
1113 notmuch search --query=sexp '(About notmuch)' | notmuch_search_sanitize > OUTPUT
1114 test_expect_equal_file EXPECTED OUTPUT
1115
1116
1117 test_begin_subtest "combine macro and user defined header"
1118 notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
1119 notmuch search subject:notmuch or List:notmuch | notmuch_search_sanitize > EXPECTED
1120 notmuch search --query=sexp '(About notmuch)' | notmuch_search_sanitize > OUTPUT
1121 test_expect_equal_file EXPECTED OUTPUT
1122
1123
1124 test_done