2 test_description='"notmuch search" in several variations'
3 . $(dirname "$0")/test-lib.sh || exit 1
5 if [ $NOTMUCH_HAVE_SFSEXP -ne 1 ]; then
6 printf "Skipping due to missing sfsexp library\n"
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
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
27 test_begin_subtest "and of exact terms"
28 notmuch search --query=sexp '(and "wonderful" "wizard")' | notmuch_search_sanitize > OUTPUT
30 thread:XXX 2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
32 test_expect_equal_file EXPECTED OUTPUT
34 test_begin_subtest "or of exact terms"
35 notmuch search --query=sexp '(or "php" "wizard")' | notmuch_search_sanitize > OUTPUT
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)
40 test_expect_equal_file EXPECTED OUTPUT
42 test_begin_subtest "single term in body"
43 notmuch search --query=sexp 'wizard' | notmuch_search_sanitize>OUTPUT
45 thread:XXX 2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
47 test_expect_equal_file EXPECTED OUTPUT
49 test_begin_subtest "single term in body (case insensitive)"
50 notmuch search --query=sexp 'Wizard' | notmuch_search_sanitize>OUTPUT
52 thread:XXX 2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
54 test_expect_equal_file EXPECTED OUTPUT
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
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
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)"
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
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)"
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)"
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)"
88 test_begin_subtest "Search by 'subject' (utf-8, or):"
89 notmuch search --query=sexp '(subject (or utf8 subjectsearchtest))' | notmuch_search_sanitize > OUTPUT
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)
94 test_expect_equal_file EXPECTED OUTPUT
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
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)
102 test_expect_equal_file EXPECTED OUTPUT
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
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)"
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)"
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)"
125 add_message "[body]=thebody-1" "[subject]=kryptonite-1"
126 add_message "[body]=nothing-to-see-here-1" "[subject]=thebody-1"
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
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
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
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
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)"
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)"
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)"
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)"
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"
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"'
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)"
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
188 test_begin_subtest "Search by 'folder' with --output=files"
189 output=$(notmuch search --output=files --query=sexp '(folder bad/news)' | notmuch_search_files_sanitize)
190 test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
191 MAIL_DIR/duplicate/bad/news/msg-XXX"
193 test_begin_subtest "Search by 'folder' with --output=files (trailing /)"
194 output=$(notmuch search --output=files --query=sexp '(folder bad/news/)' | notmuch_search_files_sanitize)
195 test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
196 MAIL_DIR/duplicate/bad/news/msg-XXX"
198 test_begin_subtest "Search by 'folder' (multiple)"
199 output=$(notmuch search --query=sexp '(folder bad bad/news things/bad)' | notmuch_search_sanitize)
200 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
201 thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
202 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
204 test_begin_subtest "Search by 'folder' (multiple, trailing /)"
205 output=$(notmuch search --query=sexp '(folder bad bad/news/ things/bad)' | notmuch_search_sanitize)
206 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
207 thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
208 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
210 test_begin_subtest "Search by 'path' with --output=files"
211 output=$(notmuch search --output=files --query=sexp '(path bad/news)' | notmuch_search_files_sanitize)
212 test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
213 MAIL_DIR/duplicate/bad/news/msg-XXX"
215 test_begin_subtest "Search by 'path' with --output=files (trailing /)"
216 output=$(notmuch search --output=files --query=sexp '(path bad/news/)' | notmuch_search_files_sanitize)
217 test_expect_equal "$output" "MAIL_DIR/bad/news/msg-XXX
218 MAIL_DIR/duplicate/bad/news/msg-XXX"
220 test_begin_subtest "Search by 'path' specification (multiple)"
221 output=$(notmuch search --query=sexp '(path bad bad/news things/bad)' | notmuch_search_sanitize)
222 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
223 thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
224 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
226 test_begin_subtest "Search by 'path' specification (multiple, trailing /)"
227 output=$(notmuch search --query=sexp '(path bad bad/news/ things/bad)' | notmuch_search_sanitize)
228 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
229 thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)
230 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
232 test_begin_subtest "Search by 'id'"
233 add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
234 output=$(notmuch search --query=sexp "(id ${gen_msg_id})" | notmuch_search_sanitize)
235 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)"
237 test_begin_subtest "Search by 'id' (or)"
238 add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
239 output=$(notmuch search --query=sexp "(id non-existent-mid ${gen_msg_id})" | notmuch_search_sanitize)
240 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)"
242 test_begin_subtest "Search by 'is' (multiple)"
243 notmuch tag -inbox tag:searchbytag
244 notmuch search is:inbox AND is:unread | notmuch_search_sanitize > EXPECTED
245 notmuch search --query=sexp '(is inbox unread)' | notmuch_search_sanitize > OUTPUT
246 notmuch tag +inbox tag:searchbytag
247 test_expect_equal_file EXPECTED OUTPUT
249 test_begin_subtest "Search by 'mid'"
250 add_message '[subject]="search by mid"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
251 output=$(notmuch search --query=sexp "(mid ${gen_msg_id})" | notmuch_search_sanitize)
252 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by mid (inbox unread)"
254 test_begin_subtest "Search by 'mid' (or)"
255 add_message '[subject]="search by mid"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
256 output=$(notmuch search --query=sexp "(mid non-existent-mid ${gen_msg_id})" | notmuch_search_sanitize)
257 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by mid (inbox unread)"
259 test_begin_subtest "Search by 'mimetype'"
260 notmuch search mimetype:text/html > EXPECTED
261 notmuch search --query=sexp '(mimetype text html)' > OUTPUT
262 test_expect_equal_file EXPECTED OUTPUT
264 QUERYSTR="date:2009-11-18..2009-11-18 and tag:unread"
265 QUERYSTR2="query:test and subject:Maildir"
266 notmuch config set --database query.test "$QUERYSTR"
267 notmuch config set query.test2 "$QUERYSTR2"
269 test_begin_subtest "ill-formed named query search"
270 notmuch search --query=sexp '(query)' > OUTPUT 2>&1
272 notmuch search: Syntax error in query
273 'query' expects single atom as argument
275 test_expect_equal_file EXPECTED OUTPUT
277 test_begin_subtest "ill-formed named query search 2"
278 notmuch search --query=sexp '(to (query))' > OUTPUT 2>&1
280 notmuch search: Syntax error in query
281 'query' not supported inside 'to'
283 test_expect_equal_file EXPECTED OUTPUT
285 test_begin_subtest "search named query"
286 notmuch search --query=sexp '(query test)' > OUTPUT
287 notmuch search $QUERYSTR > EXPECTED
288 test_expect_equal_file EXPECTED OUTPUT
290 test_begin_subtest "Search by 'subject' (utf-8, phrase-token):"
291 output=$(notmuch search --query=sexp '(subject utf8-sübjéct)' | notmuch_search_sanitize)
292 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
294 test_begin_subtest "search named query with other terms"
295 notmuch search --query=sexp '(and (query test) (subject Maildir))' > OUTPUT
296 notmuch search $QUERYSTR and subject:Maildir > EXPECTED
297 test_expect_equal_file EXPECTED OUTPUT
299 test_begin_subtest "search nested named query"
300 notmuch search --query=sexp '(query test2)' > OUTPUT
301 notmuch search $QUERYSTR2 > EXPECTED
302 test_expect_equal_file EXPECTED OUTPUT
304 test_begin_subtest "Search by 'subject' (utf-8, quoted string):"
305 output=$(notmuch search --query=sexp '(subject "utf8 sübjéct")' | notmuch_search_sanitize)
306 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
308 test_begin_subtest "Search by 'subject' (combine phrase, term):"
309 output=$(notmuch search --query=sexp '(subject Mac "compatibility issues")' | notmuch_search_sanitize)
310 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)"
312 test_begin_subtest "Search by 'subject' (combine phrase, term 2):"
313 notmuch search --query=sexp '(subject (or utf8 "compatibility issues"))' | notmuch_search_sanitize > OUTPUT
315 thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
316 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)
317 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)
319 test_expect_equal_file EXPECTED OUTPUT
321 test_begin_subtest "Search by 'subject' (combine phrase, term 3):"
322 notmuch search --query=sexp '(subject issues X/Darwin)' | notmuch_search_sanitize > OUTPUT
324 thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
326 test_expect_equal_file EXPECTED OUTPUT
328 test_begin_subtest "Search by 'tag'"
329 add_message '[subject]="search by tag"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
330 notmuch tag +searchbytag id:${gen_msg_id}
331 output=$(notmuch search --query=sexp '(tag searchbytag)' | notmuch_search_sanitize)
332 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)"
334 test_begin_subtest "Search by 'tag' (multiple)"
335 notmuch tag -inbox tag:searchbytag
336 notmuch search tag:inbox AND tag:unread | notmuch_search_sanitize > EXPECTED
337 notmuch search --query=sexp '(tag inbox unread)' | notmuch_search_sanitize > OUTPUT
338 notmuch tag +inbox tag:searchbytag
339 test_expect_equal_file EXPECTED OUTPUT
341 test_begin_subtest "Search by 'tag' and 'subject'"
342 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
343 notmuch search --query=sexp '(and (tag inbox) (subject maildir))' | notmuch_search_sanitize > OUTPUT
344 test_expect_equal_file EXPECTED OUTPUT
346 test_begin_subtest "Search by 'thread'"
347 add_message '[subject]="search by thread"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
348 thread_id=$(notmuch search id:${gen_msg_id} | sed -e "s/thread:\([a-f0-9]*\).*/\1/")
349 output=$(notmuch search --query=sexp "(thread ${thread_id})" | notmuch_search_sanitize)
350 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by thread (inbox unread)"
352 test_begin_subtest "Search by 'to'"
353 add_message '[subject]="search by to"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto
354 output=$(notmuch search --query=sexp '(to searchbyto)' | notmuch_search_sanitize)
355 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)"
357 test_begin_subtest "Search by 'to' (address)"
358 add_message '[subject]="search by to (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto@example.com
359 output=$(notmuch search --query=sexp '(to searchbyto@example.com)' | notmuch_search_sanitize)
360 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)"
362 test_begin_subtest "Search by 'to' (name)"
363 add_message '[subject]="search by to (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[to]="Search By To Name <test@example.com>"'
364 output=$(notmuch search --query=sexp '(to "Search By To Name")' | notmuch_search_sanitize)
365 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
367 test_begin_subtest "Search by 'to' (name and address)"
368 output=$(notmuch search --query=sexp '(to "Search By To Name <test@example.com>")' | notmuch_search_sanitize)
369 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
371 test_begin_subtest "starts-with, no prefix"
372 output=$(notmuch search --query=sexp '(starts-with prelim)' | notmuch_search_sanitize)
373 test_expect_equal "$output" "thread:XXX 2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)"
375 test_begin_subtest "starts-with, case-insensitive"
376 notmuch search --query=sexp '(starts-with FreeB)' | notmuch_search_sanitize > OUTPUT
378 thread:XXX 2009-11-18 [3/4] Alexander Botero-Lowry, Jjgod Jiang; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
379 thread:XXX 2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
381 test_expect_equal_file EXPECTED OUTPUT
383 test_begin_subtest "starts-with, no prefix, all messages"
384 notmuch search --query=sexp '(starts-with "")' | notmuch_search_sanitize > OUTPUT
385 notmuch search '*' | notmuch_search_sanitize > EXPECTED
386 test_expect_equal_file EXPECTED OUTPUT
388 test_begin_subtest "starts-with, attachment"
389 output=$(notmuch search --query=sexp '(attachment (starts-with not))' | notmuch_search_sanitize)
390 test_expect_equal "$output" 'thread:XXX 2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)'
392 test_begin_subtest "starts-with, folder"
393 notmuch search --output=files --query=sexp '(folder (starts-with bad))' | notmuch_search_files_sanitize > OUTPUT
396 MAIL_DIR/bad/news/msg-XXX
397 MAIL_DIR/duplicate/bad/news/msg-XXX
399 test_expect_equal_file EXPECTED OUTPUT
401 test_begin_subtest "starts-with, from"
402 notmuch search --query=sexp '(from (starts-with Mik))' | notmuch_search_sanitize > OUTPUT
404 thread:XXX 2009-11-17 [1/1] Mikhail Gusarov; [notmuch] [PATCH] Handle rename of message file (inbox unread)
405 thread:XXX 2009-11-17 [2/7] Mikhail Gusarov| Lars Kellogg-Stedman, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
406 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)
408 test_expect_equal_file EXPECTED OUTPUT
410 test_begin_subtest "starts-with, id"
411 notmuch search --query=sexp --output=messages '(id (starts-with 877))' > OUTPUT
413 id:877h1wv7mg.fsf@inf-8657.int-evry.fr
414 id:877htoqdbo.fsf@yoom.home.cworth.org
416 test_expect_equal_file EXPECTED OUTPUT
418 test_begin_subtest "starts-with, is"
419 output=$(notmuch search --query=sexp '(is (starts-with searchby))' | notmuch_search_sanitize)
420 test_expect_equal "$output" 'thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)'
422 test_begin_subtest "starts-with, mid"
423 notmuch search --query=sexp --output=messages '(mid (starts-with 877))' > OUTPUT
425 id:877h1wv7mg.fsf@inf-8657.int-evry.fr
426 id:877htoqdbo.fsf@yoom.home.cworth.org
428 test_expect_equal_file EXPECTED OUTPUT
430 test_begin_subtest "starts-with, mimetype"
431 notmuch search --query=sexp '(mimetype (starts-with sig))' | notmuch_search_sanitize > OUTPUT
433 thread:XXX 2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
434 thread:XXX 2009-11-18 [4/7] Lars Kellogg-Stedman, Mikhail Gusarov| Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
435 thread:XXX 2009-11-17 [1/3] Adrian Perez de Castro| Keith Packard, Carl Worth; [notmuch] Introducing myself (inbox signed unread)
437 test_expect_equal_file EXPECTED OUTPUT
439 add_message '[subject]="message with properties"'
440 notmuch restore <<EOF
441 #= ${gen_msg_id} foo=bar
444 test_begin_subtest "starts-with, property"
445 notmuch search --query=sexp '(property (starts-with foo=))' | notmuch_search_sanitize > OUTPUT
447 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; message with properties (inbox unread)
449 test_expect_equal_file EXPECTED OUTPUT
451 test_begin_subtest "starts-with, subject"
452 notmuch search --query=sexp '(subject (starts-with FreeB))' | notmuch_search_sanitize > OUTPUT
454 thread:XXX 2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
456 test_expect_equal_file EXPECTED OUTPUT
458 test_begin_subtest "starts-with, tag"
459 output=$(notmuch search --query=sexp '(tag (starts-with searchby))' | notmuch_search_sanitize)
460 test_expect_equal "$output" 'thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)'
462 add_message '[subject]="no tags"'
463 notag_mid=${gen_msg_id}
464 notmuch tag -unread -inbox id:${notag_mid}
466 test_begin_subtest "negated starts-with, tag"
467 output=$(notmuch search --query=sexp '(tag (not (starts-with in)))' | notmuch_search_sanitize)
468 test_expect_equal "$output" 'thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; no tags ()'
470 test_begin_subtest "negated starts-with, tag 2"
471 output=$(notmuch search --query=sexp '(not (tag (starts-with in)))' | notmuch_search_sanitize)
472 test_expect_equal "$output" 'thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; no tags ()'
474 test_begin_subtest "negated starts-with, tag 3"
475 output=$(notmuch search --query=sexp '(not (tag (starts-with "")))' | notmuch_search_sanitize)
476 test_expect_equal "$output" 'thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; no tags ()'
478 test_begin_subtest "starts-with, thread"
479 notmuch search --query=sexp '(thread (starts-with "00"))' > OUTPUT
480 notmuch search '*' > EXPECTED
481 test_expect_equal_file EXPECTED OUTPUT
483 test_begin_subtest "starts-with, to"
484 notmuch search --query=sexp '(to (starts-with "search"))' | notmuch_search_sanitize > OUTPUT
486 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)
487 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)
488 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)
490 test_expect_equal_file EXPECTED OUTPUT
492 test_begin_subtest "wildcard search for 'is'"
493 notmuch search not id:${notag_mid} > EXPECTED
494 notmuch search --query=sexp '(is *)' > OUTPUT
495 test_expect_equal_file EXPECTED OUTPUT
497 test_begin_subtest "negated wildcard search for 'is'"
498 notmuch search id:${notag_mid} > EXPECTED
499 notmuch search --query=sexp '(not (is *))' > OUTPUT
500 test_expect_equal_file EXPECTED OUTPUT
502 test_begin_subtest "wildcard search for 'property'"
503 notmuch search property:foo=bar > EXPECTED
504 notmuch search --query=sexp '(property *)' > OUTPUT
505 test_expect_equal_file EXPECTED OUTPUT
507 test_begin_subtest "wildcard search for 'tag'"
508 notmuch search not id:${notag_mid} > EXPECTED
509 notmuch search --query=sexp '(tag *)' > OUTPUT
510 test_expect_equal_file EXPECTED OUTPUT
512 test_begin_subtest "negated wildcard search for 'tag'"
513 notmuch search id:${notag_mid} > EXPECTED
514 notmuch search --query=sexp '(not (tag *))' > OUTPUT
515 test_expect_equal_file EXPECTED OUTPUT
517 add_message '[subject]="message with tag \"*\""'
518 notmuch tag '+*' id:${gen_msg_id}
520 test_begin_subtest "search for 'tag' \"*\""
521 output=$(notmuch search --query=sexp --output=messages '(tag "*")')
522 test_expect_equal "$output" "id:$gen_msg_id"
524 test_begin_subtest "search for missing / empty to"
525 add_message [to]="undisclosed-recipients:"
526 notmuch search --query=sexp '(not (to *))' | notmuch_search_sanitize > OUTPUT
528 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; search for missing / empty to (inbox unread)
530 test_expect_equal_file EXPECTED OUTPUT
532 test_begin_subtest "Unbalanced parens"
533 # A code 1 indicates the error was handled (a crash will return e.g. 139).
534 test_expect_code 1 "notmuch search --query=sexp '('"
536 test_begin_subtest "Unbalanced parens, error message"
537 notmuch search --query=sexp '(' >OUTPUT 2>&1
539 notmuch search: Syntax error in query
540 invalid s-expression: '('
542 test_expect_equal_file EXPECTED OUTPUT
544 test_begin_subtest "unknown prefix"
545 notmuch search --query=sexp '(foo)' >OUTPUT 2>&1
547 notmuch search: Syntax error in query
550 test_expect_equal_file EXPECTED OUTPUT
552 test_begin_subtest "list as prefix"
553 notmuch search --query=sexp '((foo))' >OUTPUT 2>&1
555 notmuch search: Syntax error in query
556 unexpected list in field/operation position
558 test_expect_equal_file EXPECTED OUTPUT
560 test_begin_subtest "illegal nesting"
561 notmuch search --query=sexp '(subject (subject foo))' >OUTPUT 2>&1
563 notmuch search: Syntax error in query
564 nested field: 'subject' inside 'subject'
566 test_expect_equal_file EXPECTED OUTPUT
568 test_begin_subtest "starts-with, no argument"
569 notmuch search --query=sexp '(starts-with)' >OUTPUT 2>&1
571 notmuch search: Syntax error in query
572 'starts-with' expects single atom as argument
574 test_expect_equal_file EXPECTED OUTPUT
576 test_begin_subtest "starts-with, list argument"
577 notmuch search --query=sexp '(starts-with (stuff))' >OUTPUT 2>&1
579 notmuch search: Syntax error in query
580 'starts-with' expects single atom as argument
582 test_expect_equal_file EXPECTED OUTPUT
584 test_begin_subtest "starts-with, too many arguments"
585 notmuch search --query=sexp '(starts-with a b c)' >OUTPUT 2>&1
587 notmuch search: Syntax error in query
588 'starts-with' expects single atom as argument
590 test_expect_equal_file EXPECTED OUTPUT
592 test_begin_subtest "starts-with, illegal field"
593 notmuch search --query=sexp '(body (starts-with foo))' >OUTPUT 2>&1
595 notmuch search: Syntax error in query
596 'body' does not support wildcard queries
598 test_expect_equal_file EXPECTED OUTPUT
600 test_begin_subtest "wildcard, illegal field"
601 notmuch search --query=sexp '(body *)' >OUTPUT 2>&1
603 notmuch search: Syntax error in query
604 'body' does not support wildcard queries
606 test_expect_equal_file EXPECTED OUTPUT
608 test_begin_subtest "Search, exclude \"deleted\" messages from search"
609 notmuch config set search.exclude_tags deleted
610 generate_message '[subject]="Not deleted"'
611 not_deleted_id=$gen_msg_id
612 generate_message '[subject]="Deleted"'
613 notmuch new > /dev/null
614 notmuch tag +deleted id:$gen_msg_id
615 deleted_id=$gen_msg_id
616 output=$(notmuch search --query=sexp '(subject deleted)' | notmuch_search_sanitize)
617 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)"
619 test_begin_subtest "Search, exclude \"deleted\" messages from message search --exclude=false"
620 output=$(notmuch search --query=sexp --exclude=false --output=messages '(subject deleted)' | notmuch_search_sanitize)
621 test_expect_equal "$output" "id:$not_deleted_id
624 test_begin_subtest "Search, exclude \"deleted\" messages from search, overridden"
625 notmuch search --query=sexp '(and (subject deleted) (tag deleted))' | notmuch_search_sanitize > OUTPUT
627 thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Deleted (deleted inbox unread)
629 test_expect_equal_file EXPECTED OUTPUT
631 test_begin_subtest "Search, exclude \"deleted\" messages from threads"
632 add_message '[subject]="Not deleted reply"' '[in-reply-to]="<$gen_msg_id>"'
633 output=$(notmuch search --query=sexp '(subject deleted)' | notmuch_search_sanitize)
634 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
635 thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Not deleted reply (deleted inbox unread)"
637 test_begin_subtest "Search, don't exclude \"deleted\" messages when --exclude=flag specified"
638 output=$(notmuch search --query=sexp --exclude=flag '(subject deleted)' | notmuch_search_sanitize)
639 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
640 thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
642 test_begin_subtest "Search, don't exclude \"deleted\" messages from search if not configured"
643 notmuch config set search.exclude_tags
644 output=$(notmuch search --query=sexp '(subject deleted)' | notmuch_search_sanitize)
645 test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
646 thread:XXX 2001-01-05 [2/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
648 test_begin_subtest "regex at top level"
649 notmuch search --query=sexp '(rx foo)' >& OUTPUT
651 notmuch search: Syntax error in query
652 illegal 'rx' outside field
654 test_expect_equal_file EXPECTED OUTPUT
656 test_begin_subtest "regex in illegal field"
657 notmuch search --query=sexp '(body (regex foo))' >& OUTPUT
659 notmuch search: Syntax error in query
660 'regex' not supported in field 'body'
662 test_expect_equal_file EXPECTED OUTPUT
664 notmuch search --output=messages from:cworth > cworth.msg-ids
666 test_begin_subtest "regexp 'from' search"
667 notmuch search --output=messages --query=sexp '(from (rx cworth))' > OUTPUT
668 test_expect_equal_file cworth.msg-ids OUTPUT
670 test_begin_subtest "regexp search for 'from' 2"
671 notmuch search from:/cworth@cworth.org/ and subject:patch | notmuch_search_sanitize > EXPECTED
672 notmuch search --query=sexp '(and (from (rx cworth@cworth.org)) (subject patch))' \
673 | notmuch_search_sanitize > OUTPUT
674 test_expect_equal_file EXPECTED OUTPUT
676 test_begin_subtest "regexp 'folder' search"
677 notmuch search 'folder:/^bar$/' | notmuch_search_sanitize > EXPECTED
678 notmuch search --query=sexp '(folder (rx ^bar$))' | notmuch_search_sanitize > OUTPUT
679 test_expect_equal_file EXPECTED OUTPUT
681 test_begin_subtest "regexp 'id' search"
682 notmuch search --output=messages --query=sexp '(id (rx yoom))' > OUTPUT
683 test_expect_equal_file cworth.msg-ids OUTPUT
685 test_begin_subtest "unanchored 'is' search"
686 notmuch search tag:signed or tag:inbox > EXPECTED
687 notmuch search --query=sexp '(is (rx i))' > OUTPUT
688 test_expect_equal_file EXPECTED OUTPUT
690 test_begin_subtest "anchored 'is' search"
691 notmuch search tag:signed > EXPECTED
692 notmuch search --query=sexp '(is (rx ^si))' > OUTPUT
693 test_expect_equal_file EXPECTED OUTPUT
695 test_begin_subtest "combine regexp mid and subject"
696 notmuch search subject:/-C/ and mid:/y..m/ | notmuch_search_sanitize > EXPECTED
697 notmuch search --query=sexp '(and (subject (rx -C)) (mid (rx y..m)))' | notmuch_search_sanitize > OUTPUT
698 test_expect_equal_file EXPECTED OUTPUT
700 test_begin_subtest "regexp 'path' search"
701 notmuch search 'path:/^bar$/' | notmuch_search_sanitize > EXPECTED
702 notmuch search --query=sexp '(path (rx ^bar$))' | notmuch_search_sanitize > OUTPUT
703 test_expect_equal_file EXPECTED OUTPUT
705 test_begin_subtest "regexp 'property' search"
706 notmuch search property:foo=bar > EXPECTED
707 notmuch search --query=sexp '(property (rx foo=.*))' > OUTPUT
708 test_expect_equal_file EXPECTED OUTPUT
710 test_begin_subtest "anchored 'tag' search"
711 notmuch search tag:signed > EXPECTED
712 notmuch search --query=sexp '(tag (rx ^si))' > OUTPUT
713 test_expect_equal_file EXPECTED OUTPUT
715 test_begin_subtest "regexp 'thread' search"
716 notmuch search --output=threads '*' | grep '7$' > EXPECTED
717 notmuch search --output=threads --query=sexp '(thread (rx 7$))' > OUTPUT
718 test_expect_equal_file EXPECTED OUTPUT
720 test_begin_subtest "Basic query that matches no messages"
721 count=$(notmuch count from:keithp and to:keithp)
722 test_expect_equal 0 "$count"
724 test_begin_subtest "Same query against threads"
725 notmuch search --query=sexp '(and (thread (of (from keithp))) (thread (matching (to keithp))))' \
726 | notmuch_search_sanitize > OUTPUT
728 thread:XXX 2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
730 test_expect_equal_file EXPECTED OUTPUT
732 test_begin_subtest "Mix thread and non-threads query"
733 notmuch search --query=sexp '(and (thread (matching keithp)) (to keithp))' | notmuch_search_sanitize > OUTPUT
735 thread:XXX 2009-11-18 [1/7] Lars Kellogg-Stedman| Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
737 test_expect_equal_file EXPECTED OUTPUT
739 test_begin_subtest "Compound subquery"
740 notmuch search --query=sexp '(thread (of (from keithp) (subject Maildir)))' | notmuch_search_sanitize > OUTPUT
742 thread:XXX 2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
744 test_expect_equal_file EXPECTED OUTPUT
746 test_begin_subtest "empty subquery"
747 notmuch search --query=sexp '(thread (of))' 1>OUTPUT 2>&1
748 notmuch search '*' > EXPECTED
749 test_expect_equal_file EXPECTED OUTPUT
751 test_begin_subtest "illegal expansion"
752 notmuch search --query=sexp '(id (of ego))' 1>OUTPUT 2>&1
754 notmuch search: Syntax error in query
755 'of' unsupported inside 'id'
757 test_expect_equal_file EXPECTED OUTPUT
759 test_begin_subtest "(folder (of subquery))"
760 notmuch search --query=sexp --output=messages '(folder (of (id yun3a4cegoa.fsf@aiko.keithp.com)))' > OUTPUT
762 id:yun1vjwegii.fsf@aiko.keithp.com
763 id:yun3a4cegoa.fsf@aiko.keithp.com
764 id:1258509400-32511-1-git-send-email-stewart@flamingspork.com
765 id:1258506353-20352-1-git-send-email-stewart@flamingspork.com
766 id:20091118010116.GC25380@dottiness.seas.harvard.edu
767 id:20091118005829.GB25380@dottiness.seas.harvard.edu
768 id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com
770 test_expect_equal_file EXPECTED OUTPUT
772 test_begin_subtest "infix query"
773 notmuch search to:searchbyto | notmuch_search_sanitize > EXPECTED
774 notmuch search --query=sexp '(infix "to:searchbyto")' | notmuch_search_sanitize > OUTPUT
775 test_expect_equal_file EXPECTED OUTPUT
777 test_begin_subtest "bad infix query 1"
778 notmuch search --query=sexp '(infix "from:/unbalanced")' 2>&1| notmuch_search_sanitize > OUTPUT
780 notmuch search: Syntax error in query
781 Syntax error in infix query: from:/unbalanced
783 test_expect_equal_file EXPECTED OUTPUT
785 test_begin_subtest "bad infix query 2"
786 notmuch search --query=sexp '(infix "thread:{unbalanced")' 2>&1| notmuch_search_sanitize > OUTPUT
788 notmuch search: Syntax error in query
789 Syntax error in infix query: thread:{unbalanced
791 test_expect_equal_file EXPECTED OUTPUT
793 test_begin_subtest "bad infix query 3: bad nesting"
794 notmuch search --query=sexp '(subject (infix "tag:inbox"))' 2>&1| notmuch_search_sanitize > OUTPUT
796 notmuch search: Syntax error in query
797 'infix' not supported inside 'subject'
799 test_expect_equal_file EXPECTED OUTPUT
801 test_begin_subtest "infix query that matches no messages"
802 notmuch search --query=sexp '(and (infix "from:keithp") (infix "to:keithp"))' > OUTPUT
803 test_expect_equal_file /dev/null OUTPUT
805 test_begin_subtest "compound infix query"
806 notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
807 notmuch search --query=sexp '(infix "date:2009-11-18..2009-11-18 and tag:unread")' > OUTPUT
808 test_expect_equal_file EXPECTED OUTPUT
810 test_begin_subtest "compound infix query 2"
811 notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
812 notmuch search --query=sexp '(and (infix "date:2009-11-18..2009-11-18") (infix "tag:unread"))' > OUTPUT
813 test_expect_equal_file EXPECTED OUTPUT
815 test_begin_subtest "date query, empty"
816 notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
817 notmuch search --query=sexp '(and (date) (from keithp))'| notmuch_search_sanitize > OUTPUT
818 test_expect_equal_file EXPECTED OUTPUT
820 test_begin_subtest "date query, one argument"
821 notmuch search date:2009-11-18 and from:keithp | notmuch_search_sanitize > EXPECTED
822 notmuch search --query=sexp '(and (date 2009-11-18) (from keithp))' | notmuch_search_sanitize > OUTPUT
823 test_expect_equal_file EXPECTED OUTPUT
825 test_begin_subtest "date query, two arguments"
826 notmuch search date:2009-11-17..2009-11-18 and from:keithp | notmuch_search_sanitize > EXPECTED
827 notmuch search --query=sexp '(and (date 2009-11-17 2009-11-18) (from keithp))' | notmuch_search_sanitize > OUTPUT
828 test_expect_equal_file EXPECTED OUTPUT
830 test_begin_subtest "date query, illegal nesting 1"
831 notmuch search --query=sexp '(to (date))' > OUTPUT 2>&1
833 notmuch search: Syntax error in query
834 nested field: 'date' inside 'to'
836 test_expect_equal_file EXPECTED OUTPUT
838 test_begin_subtest "date query, illegal nesting 2"
839 notmuch search --query=sexp '(to (date 2021-11-18))' > OUTPUT 2>&1
841 notmuch search: Syntax error in query
842 nested field: 'date' inside 'to'
844 test_expect_equal_file EXPECTED OUTPUT
846 test_begin_subtest "date query, illegal nesting 3"
847 notmuch search --query=sexp '(date (to))' > OUTPUT 2>&1
849 notmuch search: Syntax error in query
850 expected atom as first argument of 'date'
852 test_expect_equal_file EXPECTED OUTPUT
854 test_begin_subtest "date query, illegal nesting 4"
855 notmuch search --query=sexp '(date today (to))' > OUTPUT 2>&1
857 notmuch search: Syntax error in query
858 expected atom as second argument of 'date'
860 test_expect_equal_file EXPECTED OUTPUT
862 test_begin_subtest "date query, too many arguments"
863 notmuch search --query=sexp '(date yesterday and tommorow)' > OUTPUT 2>&1
865 notmuch search: Syntax error in query
866 'date' expects maximum of two arguments
868 test_expect_equal_file EXPECTED OUTPUT
870 test_begin_subtest "date query, bad date"
871 notmuch search --query=sexp '(date "hawaiian-pizza-day")' > OUTPUT 2>&1
873 notmuch search: Syntax error in query
874 Didn't understand date specification 'hawaiian-pizza-day'
876 test_expect_equal_file EXPECTED OUTPUT
878 test_begin_subtest "lastmod query, empty"
879 notmuch search from:keithp | notmuch_search_sanitize > EXPECTED
880 notmuch search --query=sexp '(and (lastmod) (from keithp))'| notmuch_search_sanitize > OUTPUT
881 test_expect_equal_file EXPECTED OUTPUT
883 test_begin_subtest "lastmod query, one argument"
884 notmuch tag +4EFC743A.3060609@april.org id:4EFC743A.3060609@april.org
885 revision=$(notmuch count --lastmod '*' | cut -f3)
886 notmuch search lastmod:$revision..$revision | notmuch_search_sanitize > EXPECTED
887 notmuch search --query=sexp "(and (lastmod $revision))" | notmuch_search_sanitize > OUTPUT
888 test_expect_equal_file EXPECTED OUTPUT
890 test_begin_subtest "lastmod query, two arguments"
891 notmuch tag +keithp from:keithp
892 revision2=$(notmuch count --lastmod '*' | cut -f3)
893 notmuch search lastmod:$revision..$revision2 | notmuch_search_sanitize > EXPECTED
894 notmuch search --query=sexp "(and (lastmod $revision $revision2))" | notmuch_search_sanitize > OUTPUT
895 test_expect_equal_file EXPECTED OUTPUT
897 test_begin_subtest "lastmod query, illegal nesting 1"
898 notmuch search --query=sexp '(to (lastmod))' > OUTPUT 2>&1
900 notmuch search: Syntax error in query
901 nested field: 'lastmod' inside 'to'
903 test_expect_equal_file EXPECTED OUTPUT
905 test_begin_subtest "lastmod query, bad from revision"
906 notmuch search --query=sexp '(lastmod apples)' > OUTPUT 2>&1
908 notmuch search: Syntax error in query
909 bad 'from' revision: 'apples'
911 test_expect_equal_file EXPECTED OUTPUT
913 test_begin_subtest "lastmod query, bad to revision"
914 notmuch search --query=sexp '(lastmod 0 apples)' > OUTPUT 2>&1
916 notmuch search: Syntax error in query
917 bad 'to' revision: 'apples'
919 test_expect_equal_file EXPECTED OUTPUT
921 test_begin_subtest "lastmod query, illegal nesting 2"
922 notmuch search --query=sexp '(to (lastmod 2021-11-18))' > OUTPUT 2>&1
924 notmuch search: Syntax error in query
925 nested field: 'lastmod' inside 'to'
927 test_expect_equal_file EXPECTED OUTPUT
929 test_begin_subtest "lastmod query, illegal nesting 3"
930 notmuch search --query=sexp '(lastmod (to))' > OUTPUT 2>&1
932 notmuch search: Syntax error in query
933 expected atom as first argument of 'lastmod'
935 test_expect_equal_file EXPECTED OUTPUT
937 test_begin_subtest "lastmod query, illegal nesting 4"
938 notmuch search --query=sexp '(lastmod today (to))' > OUTPUT 2>&1
940 notmuch search: Syntax error in query
941 expected atom as second argument of 'lastmod'
943 test_expect_equal_file EXPECTED OUTPUT
945 test_begin_subtest "lastmod query, too many arguments"
946 notmuch search --query=sexp '(lastmod yesterday and tommorow)' > OUTPUT 2>&1
948 notmuch search: Syntax error in query
949 'lastmod' expects maximum of two arguments
951 test_expect_equal_file EXPECTED OUTPUT
953 test_begin_subtest "user header (unknown header)"
954 notmuch search --query=sexp '(FooBar)' >& OUTPUT
956 notmuch search: Syntax error in query
957 unknown prefix 'FooBar'
959 test_expect_equal_file EXPECTED OUTPUT
961 test_begin_subtest "adding user header"
962 test_expect_code 0 "notmuch config set index.header.List \"List-Id\""
964 test_begin_subtest "reindexing"
965 test_expect_code 0 'notmuch reindex "*"'
967 test_begin_subtest "wildcard search for user header"
968 grep -Ril List-Id ${MAIL_DIR} | sort | notmuch_dir_sanitize > EXPECTED
969 notmuch search --output=files --query=sexp '(List *)' | sort | notmuch_dir_sanitize > OUTPUT
970 test_expect_equal_file EXPECTED OUTPUT
972 test_begin_subtest "wildcard search for user header 2"
973 grep -Ril List-Id ${MAIL_DIR} | sort | notmuch_dir_sanitize > EXPECTED
974 notmuch search --output=files --query=sexp '(List (starts-with not))' | sort | notmuch_dir_sanitize > OUTPUT
975 test_expect_equal_file EXPECTED OUTPUT
977 test_begin_subtest "search for user header"
978 notmuch search List:notmuch | notmuch_search_sanitize > EXPECTED
979 notmuch search --query=sexp '(List notmuch)' | notmuch_search_sanitize > OUTPUT
980 test_expect_equal_file EXPECTED OUTPUT
982 test_begin_subtest "search for user header (list token)"
983 notmuch search List:notmuch | notmuch_search_sanitize > EXPECTED
984 notmuch search --query=sexp '(List notmuch.notmuchmail.org)' | notmuch_search_sanitize > OUTPUT
985 test_expect_equal_file EXPECTED OUTPUT
987 test_begin_subtest "search for user header (quoted string)"
988 notmuch search 'List:"notmuch notmuchmail org"' | notmuch_search_sanitize > EXPECTED
989 notmuch search --query=sexp '(List "notmuch notmuchmail org")' | notmuch_search_sanitize > OUTPUT
990 test_expect_equal_file EXPECTED OUTPUT
992 test_begin_subtest "search for user header (atoms)"
993 notmuch search 'List:"notmuch notmuchmail org"' | notmuch_search_sanitize > EXPECTED
994 notmuch search --query=sexp '(List notmuch notmuchmail org)' | notmuch_search_sanitize > OUTPUT
995 test_expect_equal_file EXPECTED OUTPUT
997 test_begin_subtest "check saved query name"
998 test_expect_code 1 "notmuch config set squery.test '(subject utf8-sübjéct)'"
1000 test_begin_subtest "roundtrip saved query (database)"
1001 notmuch config set --database squery.Test '(subject utf8-sübjéct)'
1002 output=$(notmuch config get squery.Test)
1003 test_expect_equal "$output" '(subject utf8-sübjéct)'
1005 test_begin_subtest "roundtrip saved query"
1006 notmuch config set squery.Test '(subject override subject)'
1007 output=$(notmuch config get squery.Test)
1008 test_expect_equal "$output" '(subject override subject)'
1010 test_begin_subtest "unknown saved query"
1011 notmuch search --query=sexp '(Unknown foo bar)' >OUTPUT 2>&1
1012 cat <<EOF > EXPECTED
1013 notmuch search: Syntax error in query
1014 unknown prefix 'Unknown'
1016 test_expect_equal_file EXPECTED OUTPUT
1018 test_begin_subtest "syntax error in saved query"
1019 notmuch config set squery.Bad '(Bad'
1020 notmuch search --query=sexp '(Bad foo bar)' >OUTPUT 2>&1
1021 cat <<EOF > EXPECTED
1022 notmuch search: Syntax error in query
1023 invalid saved s-expression query: '(Bad'
1025 test_expect_equal_file EXPECTED OUTPUT
1027 test_begin_subtest "Saved Search by 'tag' and 'subject'"
1028 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1029 notmuch config set squery.TagSubject '(and (tag inbox) (subject maildir))'
1030 notmuch search --query=sexp '(TagSubject)' | notmuch_search_sanitize > OUTPUT
1031 test_expect_equal_file EXPECTED OUTPUT
1033 test_begin_subtest "Saved Search: illegal nesting"
1034 notmuch config set squery.TagSubject '(and (tag inbox) (subject maildir))'
1035 notmuch search --query=sexp '(subject (TagSubject))' >OUTPUT 2>&1
1036 cat <<EOF > EXPECTED
1037 notmuch search: Syntax error in query
1038 nested field: 'tag' inside 'subject'
1040 test_expect_equal_file EXPECTED OUTPUT
1042 test_begin_subtest "Saved Search: list as prefix"
1043 notmuch config set squery.Bad2 '((and) (tag inbox) (subject maildir))'
1044 notmuch search --query=sexp '(Bad2)' >OUTPUT 2>&1
1045 cat <<EOF > EXPECTED
1046 notmuch search: Syntax error in query
1047 unexpected list in field/operation position
1049 test_expect_equal_file EXPECTED OUTPUT
1051 test_begin_subtest "Saved Search: bad parameter syntax"
1052 notmuch config set squery.Bad3 '(macro a b)'
1053 notmuch search --query=sexp '(Bad3)' >OUTPUT 2>&1
1054 cat <<EOF > EXPECTED
1055 notmuch search: Syntax error in query
1056 missing (possibly empty) list of arguments to macro
1058 test_expect_equal_file EXPECTED OUTPUT
1060 test_begin_subtest "Saved Search: bad parameter syntax 2"
1061 notmuch config set squery.Bad4 '(macro ((a b)) a)'
1062 notmuch search --query=sexp '(Bad4 1)' >OUTPUT 2>&1
1063 cat <<EOF > EXPECTED
1064 notmuch search: Syntax error in query
1065 macro parameters must be unquoted atoms
1067 test_expect_equal_file EXPECTED OUTPUT
1069 test_begin_subtest "Saved Search: bad parameter syntax 3"
1070 notmuch config set squery.Bad5 '(macro (a b) a)'
1071 notmuch search --query=sexp '(Bad5 1)' >OUTPUT 2>&1
1072 cat <<EOF > EXPECTED
1073 notmuch search: Syntax error in query
1074 too few arguments to macro
1076 test_expect_equal_file EXPECTED OUTPUT
1078 test_begin_subtest "Saved Search: bad parameter syntax 4"
1079 notmuch search --query=sexp '(Bad5 1 2 3)' >OUTPUT 2>&1
1080 cat <<EOF > EXPECTED
1081 notmuch search: Syntax error in query
1082 too many arguments to macro
1084 test_expect_equal_file EXPECTED OUTPUT
1086 test_begin_subtest "Saved Search: macro without body"
1087 notmuch config set squery.Bad3 '(macro (a b))'
1088 notmuch search --query=sexp '(Bad3)' >OUTPUT 2>&1
1089 cat <<EOF > EXPECTED
1090 notmuch search: Syntax error in query
1091 missing body of macro
1093 test_expect_equal_file EXPECTED OUTPUT
1095 test_begin_subtest "macro in query"
1096 notmuch search --query=sexp '(macro (a) (and ,b (subject maildir)))' >OUTPUT 2>&1
1097 cat <<EOF > EXPECTED
1098 notmuch search: Syntax error in query
1099 macro definition not permitted here
1101 test_expect_equal_file EXPECTED OUTPUT
1103 test_begin_subtest "zero argument macro"
1104 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1105 notmuch config set squery.TagSubject0 '(macro () (and (tag inbox) (subject maildir)))'
1106 notmuch search --query=sexp '(TagSubject0)' | notmuch_search_sanitize > OUTPUT
1107 test_expect_equal_file EXPECTED OUTPUT
1109 test_begin_subtest "undefined argument"
1110 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1111 notmuch config set squery.Bad6 '(macro (a) (and ,b (subject maildir)))'
1112 notmuch search --query=sexp '(Bad6 foo)' >OUTPUT 2>&1
1113 cat <<EOF > EXPECTED
1114 notmuch search: Syntax error in query
1115 undefined parameter b
1117 test_expect_equal_file EXPECTED OUTPUT
1119 test_begin_subtest "Single argument macro"
1120 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1121 notmuch config set squery.TagSubject1 '(macro (tagname) (and (tag ,tagname) (subject maildir)))'
1122 notmuch search --query=sexp '(TagSubject1 inbox)' | notmuch_search_sanitize > OUTPUT
1123 test_expect_equal_file EXPECTED OUTPUT
1125 test_begin_subtest "Single argument macro, list argument"
1126 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1127 notmuch config set squery.ThingSubject '(macro (thing) (and ,thing (subject maildir)))'
1128 notmuch search --query=sexp '(ThingSubject (tag inbox))' | notmuch_search_sanitize > OUTPUT
1129 test_expect_equal_file EXPECTED OUTPUT
1131 test_begin_subtest "two argument macro"
1132 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1133 notmuch config set squery.TagSubject2 '(macro (tagname subj) (and (tag ,tagname) (subject ,subj)))'
1134 notmuch search --query=sexp '(TagSubject2 inbox maildir)' | notmuch_search_sanitize > OUTPUT
1135 test_expect_equal_file EXPECTED OUTPUT
1137 test_begin_subtest "nested macros (shadowing)"
1138 notmuch search tag:inbox and subject:maildir | notmuch_search_sanitize > EXPECTED
1139 notmuch config set squery.Inner '(macro (x) (subject ,x))'
1140 notmuch config set squery.Outer '(macro (x y) (and (tag ,x) (Inner ,y)))'
1141 notmuch search --query=sexp '(Outer inbox maildir)' | notmuch_search_sanitize > OUTPUT
1142 test_expect_equal_file EXPECTED OUTPUT
1144 test_begin_subtest "nested macros (no dynamic scope)"
1145 notmuch config set squery.Inner2 '(macro (x) (subject ,y))'
1146 notmuch config set squery.Outer2 '(macro (x y) (and (tag ,x) (Inner2 ,y)))'
1147 notmuch search --query=sexp '(Outer2 inbox maildir)' > OUTPUT 2>&1
1148 cat <<EOF > EXPECTED
1149 notmuch search: Syntax error in query
1150 undefined parameter y
1152 test_expect_equal_file EXPECTED OUTPUT
1154 test_begin_subtest "combine macro and user defined header"
1155 notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
1156 notmuch search subject:notmuch or List:notmuch | notmuch_search_sanitize > EXPECTED
1157 notmuch search --query=sexp '(About notmuch)' | notmuch_search_sanitize > OUTPUT
1158 test_expect_equal_file EXPECTED OUTPUT
1161 test_begin_subtest "combine macro and user defined header"
1162 notmuch config set squery.About '(macro (name) (or (subject ,name) (List ,name)))'
1163 notmuch search subject:notmuch or List:notmuch | notmuch_search_sanitize > EXPECTED
1164 notmuch search --query=sexp '(About notmuch)' | notmuch_search_sanitize > OUTPUT
1165 test_expect_equal_file EXPECTED OUTPUT