[PATCH 9/9] add has: query prefix to search for specific properties
[notmuch-archives.git] / 3e / 7f57b3a1ef79205bd40fc72b01b125b9acfcbe
1 Return-Path: <amdragon@mit.edu>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 038AA431FBD\r
6         for <notmuch@notmuchmail.org>; Tue, 24 Jul 2012 19:35:13 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id IRCnqhrjevHr for <notmuch@notmuchmail.org>;\r
16         Tue, 24 Jul 2012 19:35:07 -0700 (PDT)\r
17 Received: from dmz-mailsec-scanner-3.mit.edu (DMZ-MAILSEC-SCANNER-3.MIT.EDU\r
18         [18.9.25.14])\r
19         by olra.theworths.org (Postfix) with ESMTP id 2AC2F431FC7\r
20         for <notmuch@notmuchmail.org>; Tue, 24 Jul 2012 19:35:06 -0700 (PDT)\r
21 X-AuditID: 1209190e-b7fb56d0000008b2-fd-500f5b594212\r
22 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
23         by dmz-mailsec-scanner-3.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id 43.7F.02226.95B5F005; Tue, 24 Jul 2012 22:35:05 -0400 (EDT)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id q6P2Z4tT002599; \r
27         Tue, 24 Jul 2012 22:35:04 -0400\r
28 Received: from drake.dyndns.org\r
29         (209-6-116-242.c3-0.arl-ubr1.sbo-arl.ma.cable.rcn.com\r
30         [209.6.116.242]) (authenticated bits=0)\r
31         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
32         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id q6P2Z2S0025115\r
33         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
34         Tue, 24 Jul 2012 22:35:03 -0400 (EDT)\r
35 Received: from amthrax by drake.dyndns.org with local (Exim 4.77)\r
36         (envelope-from <amdragon@mit.edu>)\r
37         id 1StrRF-0004Yj-8C; Tue, 24 Jul 2012 22:35:01 -0400\r
38 From: Austin Clements <amdragon@MIT.EDU>\r
39 To: notmuch@notmuchmail.org\r
40 Subject: [PATCH 01/13] test: Uniformly canonicalize actual and expected JSON\r
41 Date: Tue, 24 Jul 2012 22:34:41 -0400\r
42 Message-Id: <1343183693-17134-2-git-send-email-amdragon@mit.edu>\r
43 X-Mailer: git-send-email 1.7.10\r
44 In-Reply-To: <1343183693-17134-1-git-send-email-amdragon@mit.edu>\r
45 References: <1343183693-17134-1-git-send-email-amdragon@mit.edu>\r
46 MIME-Version: 1.0\r
47 Content-Type: text/plain; charset=UTF-8\r
48 Content-Transfer-Encoding: 8bit\r
49 X-Brightmail-Tracker:\r
50  H4sIAAAAAAAAA+NgFprIKsWRmVeSWpSXmKPExsUixCmqrRsZzR9gMP2umsXehnZGi+s3ZzI7\r
51         MHks3rSfzePZqlvMAUxRXDYpqTmZZalF+nYJXBl/L7gULNrDWPFgzSzGBsaeRYxdjJwcEgIm\r
52         Et83/GOGsMUkLtxbz9bFyMUhJLCPUaJ1wTtGCGcDo8SMqe1QmUdMEj+alrNCOHMZJaatmcAC\r
53         0s8moCGxbf9ysLkiAtISO+/OZgWxmQXMJOb+nMgGYgsL5ElMXr+cCcRmEVCV6HmwCmw3r4CD\r
54         xNGGiUwQd8hLPL3fB1bPKeAocX7JQrCZQkA1PYuvsUPUC0qcnPkEaC8H0Hx1ifXzhCBWyUs0\r
55         b53NPIFRaBaSqlkIVbOQVC1gZF7FKJuSW6Wbm5iZU5yarFucnJiXl1qka6yXm1mil5pSuokR\r
56         HNqSfDsYvx5UOsQowMGoxMP7+wlfgBBrYllxZe4hRkkOJiVR3opg/gAhvqT8lMqMxOKM+KLS\r
57         nNTiQ4wSHMxKIrxFYUA53pTEyqrUonyYlDQHi5I475WUm/5CAumJJanZqakFqUUwWRkODiUJ\r
58         3tYooEbBotT01Iq0zJwShDQTByfIcB6g4btBaniLCxJzizPTIfKnGHU5zuy/d4tRiCUvPy9V\r
59         Spx3LkiRAEhRRmke3BxYSnrFKA70ljBvM0gVDzCdwU16BbSECWjJ8zA+kCUliQgpqQbG6WFm\r
60         X27/Y1917Jvd8ROBbq539n6+pX3GgG+1ddAHebbbuiWL845+EJCuyTebzDz93tMzxdJNDWrK\r
61         8171bco0bf1rx1s92WzDHUlDGZVrGw9oiNRzGSXbiaQZhC4wbq/aV1zFx/vgfrqjWt/2zj1m\r
62         R7P7qsWPiDw/lVbpdsX05DHLU1V+93WVWIozEg21mIuKEwFgEv56JAMAAA==\r
63 X-BeenThere: notmuch@notmuchmail.org\r
64 X-Mailman-Version: 2.1.13\r
65 Precedence: list\r
66 List-Id: "Use and development of the notmuch mail system."\r
67         <notmuch.notmuchmail.org>\r
68 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
69         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
70 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
71 List-Post: <mailto:notmuch@notmuchmail.org>\r
72 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
73 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
74         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
75 X-List-Received-Date: Wed, 25 Jul 2012 02:35:13 -0000\r
76 \r
77 Previously, we used a variety of ad-hoc canonicalizations for JSON\r
78 output in the test suite, but were ultimately very sensitive to JSON\r
79 irrelevancies such as whitespace.  This introduces a new test\r
80 comparison function, test_expect_equal_json, that first pretty-prints\r
81 *both* the actual and expected JSON and the compares the result.\r
82 \r
83 The current implementation of this simply uses Python's json.tool to\r
84 perform pretty-printing (with a fallback to the identity function if\r
85 parsing fails).  However, since the interface it introduces is\r
86 semantically high-level, we could swap in other mechanisms in the\r
87 future, such as another pretty-printer or something that does not\r
88 re-order object keys (if we decide that we care about that).\r
89 \r
90 In general, this patch does not remove the existing ad-hoc\r
91 canonicalization because it does no harm.  We do have to remove the\r
92 newline-after-comma rule from notmuch_json_show_sanitize and\r
93 filter_show_json because it results in invalid JSON that cannot be\r
94 pretty-printed.\r
95 \r
96 Most of this patch simply replaces test_expect_equal and\r
97 test_expect_equal_file with test_expect_equal_json.  It changes the\r
98 expected JSON in a few places where sanitizers had placed newlines\r
99 after commas inside strings.\r
100 ---\r
101  test/crypto        |   37 +++++++++++++++----------------------\r
102  test/json          |   14 +++++++-------\r
103  test/maildir-sync  |   11 ++++-------\r
104  test/multipart     |   34 +++++++++++++++-------------------\r
105  test/search-output |    2 +-\r
106  test/test-lib.sh   |   17 +++++++++++++----\r
107  6 files changed, 55 insertions(+), 60 deletions(-)\r
108 \r
109 diff --git a/test/crypto b/test/crypto\r
110 index be752b1..5dd14c4 100755\r
111 --- a/test/crypto\r
112 +++ b/test/crypto\r
113 @@ -51,8 +51,7 @@ expected='[[[{"id": "XXXXX",\r
114   "headers": {"Subject": "test signed message 001",\r
115   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
116   "To": "test_suite@notmuchmail.org",\r
117 - "Date": "Sat,\r
118 - 01 Jan 2000 12:00:00 +0000"},\r
119 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
120   "body": [{"id": 1,\r
121   "sigstatus": [{"status": "good",\r
122   "fingerprint": "'$FINGERPRINT'",\r
123 @@ -64,7 +63,7 @@ expected='[[[{"id": "XXXXX",\r
124   {"id": 3,\r
125   "content-type": "application/pgp-signature"}]}]},\r
126   []]]]'\r
127 -test_expect_equal \\r
128 +test_expect_equal_json \\r
129      "$output" \\r
130      "$expected"\r
131  \r
132 @@ -85,8 +84,7 @@ expected='[[[{"id": "XXXXX",\r
133   "headers": {"Subject": "test signed message 001",\r
134   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
135   "To": "test_suite@notmuchmail.org",\r
136 - "Date": "Sat,\r
137 - 01 Jan 2000 12:00:00 +0000"},\r
138 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
139   "body": [{"id": 1,\r
140   "sigstatus": [{"status": "good",\r
141   "fingerprint": "'$FINGERPRINT'",\r
142 @@ -99,7 +97,7 @@ expected='[[[{"id": "XXXXX",\r
143   {"id": 3,\r
144   "content-type": "application/pgp-signature"}]}]},\r
145   []]]]'\r
146 -test_expect_equal \\r
147 +test_expect_equal_json \\r
148      "$output" \\r
149      "$expected"\r
150  \r
151 @@ -119,8 +117,7 @@ expected='[[[{"id": "XXXXX",\r
152   "headers": {"Subject": "test signed message 001",\r
153   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
154   "To": "test_suite@notmuchmail.org",\r
155 - "Date": "Sat,\r
156 - 01 Jan 2000 12:00:00 +0000"},\r
157 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
158   "body": [{"id": 1,\r
159   "sigstatus": [{"status": "error",\r
160   "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",\r
161 @@ -132,7 +129,7 @@ expected='[[[{"id": "XXXXX",\r
162   {"id": 3,\r
163   "content-type": "application/pgp-signature"}]}]},\r
164   []]]]'\r
165 -test_expect_equal \\r
166 +test_expect_equal_json \\r
167      "$output" \\r
168      "$expected"\r
169  mv "${GNUPGHOME}"{.bak,}\r
170 @@ -193,8 +190,7 @@ expected='[[[{"id": "XXXXX",\r
171   "headers": {"Subject": "test encrypted message 001",\r
172   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
173   "To": "test_suite@notmuchmail.org",\r
174 - "Date": "Sat,\r
175 - 01 Jan 2000 12:00:00 +0000"},\r
176 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
177   "body": [{"id": 1,\r
178   "encstatus": [{"status": "good"}],\r
179   "sigstatus": [],\r
180 @@ -210,7 +206,7 @@ expected='[[[{"id": "XXXXX",\r
181   "content-type": "application/octet-stream",\r
182   "filename": "TESTATTACHMENT"}]}]}]},\r
183   []]]]'\r
184 -test_expect_equal \\r
185 +test_expect_equal_json \\r
186      "$output" \\r
187      "$expected"\r
188  \r
189 @@ -221,7 +217,7 @@ output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted m\r
190  expected='{"id": 4,\r
191   "content-type": "text/plain",\r
192   "content": "This is a test encrypted message.\n"}'\r
193 -test_expect_equal \\r
194 +test_expect_equal_json \\r
195      "$output" \\r
196      "$expected"\r
197  \r
198 @@ -248,8 +244,7 @@ expected='[[[{"id": "XXXXX",\r
199   "headers": {"Subject": "test encrypted message 001",\r
200   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
201   "To": "test_suite@notmuchmail.org",\r
202 - "Date": "Sat,\r
203 - 01 Jan 2000 12:00:00 +0000"},\r
204 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
205   "body": [{"id": 1,\r
206   "encstatus": [{"status": "bad"}],\r
207   "content-type": "multipart/encrypted",\r
208 @@ -258,7 +253,7 @@ expected='[[[{"id": "XXXXX",\r
209   {"id": 3,\r
210   "content-type": "application/octet-stream"}]}]},\r
211   []]]]'\r
212 -test_expect_equal \\r
213 +test_expect_equal_json \\r
214      "$output" \\r
215      "$expected"\r
216  mv "${GNUPGHOME}"{.bak,}\r
217 @@ -283,8 +278,7 @@ expected='[[[{"id": "XXXXX",\r
218   "headers": {"Subject": "test encrypted message 002",\r
219   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
220   "To": "test_suite@notmuchmail.org",\r
221 - "Date": "Sat,\r
222 - 01 Jan 2000 12:00:00 +0000"},\r
223 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
224   "body": [{"id": 1,\r
225   "encstatus": [{"status": "good"}],\r
226   "sigstatus": [{"status": "good",\r
227 @@ -298,7 +292,7 @@ expected='[[[{"id": "XXXXX",\r
228   "content-type": "text/plain",\r
229   "content": "This is another test encrypted message.\n"}]}]},\r
230   []]]]'\r
231 -test_expect_equal \\r
232 +test_expect_equal_json \\r
233      "$output" \\r
234      "$expected"\r
235  \r
236 @@ -338,8 +332,7 @@ expected='[[[{"id": "XXXXX",\r
237   "headers": {"Subject": "test signed message 001",\r
238   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
239   "To": "test_suite@notmuchmail.org",\r
240 - "Date": "Sat,\r
241 - 01 Jan 2000 12:00:00 +0000"},\r
242 + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},\r
243   "body": [{"id": 1,\r
244   "sigstatus": [{"status": "error",\r
245   "keyid": "6D92612D94E46381",\r
246 @@ -351,7 +344,7 @@ expected='[[[{"id": "XXXXX",\r
247   {"id": 3,\r
248   "content-type": "application/pgp-signature"}]}]},\r
249   []]]]'\r
250 -test_expect_equal \\r
251 +test_expect_equal_json \\r
252      "$output" \\r
253      "$expected"\r
254  \r
255 diff --git a/test/json b/test/json\r
256 index 831e105..d86ee46 100755\r
257 --- a/test/json\r
258 +++ b/test/json\r
259 @@ -5,21 +5,21 @@ test_description="--format=json output"\r
260  test_begin_subtest "Show message: json"\r
261  add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\""\r
262  output=$(notmuch show --format=json "json-show-message")\r
263 -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"\r
264 +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"\r
265  \r
266  # This should be the same output as above.\r
267  test_begin_subtest "Show message: json --body=true"\r
268  output=$(notmuch show --format=json --body=true "json-show-message")\r
269 -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"\r
270 +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"\r
271  \r
272  test_begin_subtest "Show message: json --body=false"\r
273  output=$(notmuch show --format=json --body=false "json-show-message")\r
274 -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]"\r
275 +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]"\r
276  \r
277  test_begin_subtest "Search message: json"\r
278  add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""\r
279  output=$(notmuch search --format=json "json-search-message" | notmuch_json_show_sanitize | notmuch_search_sanitize)\r
280 -test_expect_equal "$output" "[{\"thread\": \"XXX\",\r
281 +test_expect_equal_json "$output" "[{\"thread\": \"XXX\",\r
282   \"timestamp\": 946728000,\r
283   \"date_relative\": \"2000-01-01\",\r
284   \"matched\": 1,\r
285 @@ -32,7 +32,7 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\",\r
286  test_begin_subtest "Show message: json, utf-8"\r
287  add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""\r
288  output=$(notmuch show --format=json "jsön-show-méssage")\r
289 -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"\r
290 +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"\r
291  \r
292  test_begin_subtest "Show message: json, inline attachment filename"\r
293  subject='json-show-inline-attachment-filename'\r
294 @@ -45,12 +45,12 @@ emacs_deliver_message \\r
295       (insert \"Message-ID: <$id>\n\")"\r
296  output=$(notmuch show --format=json "id:$id")\r
297  filename=$(notmuch search --output=files "id:$id")\r
298 -test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\": false, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"filename\": \"README\"}]}]}, []]]]"\r
299 +test_expect_equal_json "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\": false, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"filename\": \"README\"}]}]}, []]]]"\r
300  \r
301  test_begin_subtest "Search message: json, utf-8"\r
302  add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""\r
303  output=$(notmuch search --format=json "jsön-search-méssage" | notmuch_json_show_sanitize | notmuch_search_sanitize)\r
304 -test_expect_equal "$output" "[{\"thread\": \"XXX\",\r
305 +test_expect_equal_json "$output" "[{\"thread\": \"XXX\",\r
306   \"timestamp\": 946728000,\r
307   \"date_relative\": \"2000-01-01\",\r
308   \"matched\": 1,\r
309 diff --git a/test/maildir-sync b/test/maildir-sync\r
310 index 01348d3..b748d04 100755\r
311 --- a/test/maildir-sync\r
312 +++ b/test/maildir-sync\r
313 @@ -4,11 +4,9 @@ test_description="maildir synchronization"\r
314  \r
315  . ./test-lib.sh\r
316  \r
317 -# Much easier to examine differences if the "notmuch show\r
318 -# --format=json" output includes some newlines. Also, need to avoid\r
319 -# including the local value of MAIL_DIR in the result.\r
320 +# Avoid including the local value of MAIL_DIR in the result.\r
321  filter_show_json() {\r
322 -    sed -e 's/, /,\n/g'  | sed -e "s|${MAIL_DIR}/|MAIL_DIR/|"\r
323 +    sed -e "s|${MAIL_DIR}/|MAIL_DIR/|"\r
324      echo\r
325  }\r
326  \r
327 @@ -44,7 +42,7 @@ test_expect_equal "$output" "adding-replied-tag:2,RS"\r
328  \r
329  test_begin_subtest "notmuch show works with renamed file (without notmuch new)"\r
330  output=$(notmuch show --format=json id:${gen_msg_id} | filter_show_json)\r
331 -test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite",\r
332 +test_expect_equal_json "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite",\r
333  "match": true,\r
334  "excluded": false,\r
335  "filename": "MAIL_DIR/cur/adding-replied-tag:2,RS",\r
336 @@ -54,8 +52,7 @@ test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite",\r
337  "headers": {"Subject": "Adding replied tag",\r
338  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
339  "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
340 -"Date": "Fri,\r
341 -05 Jan 2001 15:43:57 +0000"},\r
342 +"Date": "Fri, 05 Jan 2001 15:43:57 +0000"},\r
343  "body": [{"id": 1,\r
344  "content-type": "text/plain",\r
345  "content": "This is just a test message (#3)\n"}]},\r
346 diff --git a/test/multipart b/test/multipart\r
347 index 72d3927..3ccf27f 100755\r
348 --- a/test/multipart\r
349 +++ b/test/multipart\r
350 @@ -334,7 +334,7 @@ cat <<EOF >EXPECTED\r
351  {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, \r
352  {"id": 9, "content-type": "application/pgp-signature"}]}]}\r
353  EOF\r
354 -test_expect_equal_file OUTPUT EXPECTED\r
355 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
356  \r
357  test_begin_subtest "--format=json --part=1, message body"\r
358  notmuch show --format=json --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
359 @@ -351,7 +351,7 @@ cat <<EOF >EXPECTED\r
360  {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, \r
361  {"id": 9, "content-type": "application/pgp-signature"}]}\r
362  EOF\r
363 -test_expect_equal_file OUTPUT EXPECTED\r
364 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
365  \r
366  test_begin_subtest "--format=json --part=2, multipart/mixed"\r
367  notmuch show --format=json --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
368 @@ -366,7 +366,7 @@ cat <<EOF >EXPECTED\r
369  {"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}, \r
370  {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}\r
371  EOF\r
372 -test_expect_equal_file OUTPUT EXPECTED\r
373 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
374  \r
375  test_begin_subtest "--format=json --part=3, rfc822 part"\r
376  notmuch show --format=json --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
377 @@ -378,7 +378,7 @@ cat <<EOF >EXPECTED\r
378  {"id": 5, "content-type": "text/html"}, \r
379  {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}\r
380  EOF\r
381 -test_expect_equal_file OUTPUT EXPECTED\r
382 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
383  \r
384  test_begin_subtest "--format=json --part=4, rfc822's multipart/alternative"\r
385  notmuch show --format=json --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
386 @@ -389,7 +389,7 @@ cat <<EOF >EXPECTED\r
387  {"id": 5, "content-type": "text/html"}, \r
388  {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}\r
389  EOF\r
390 -test_expect_equal_file OUTPUT EXPECTED\r
391 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
392  \r
393  test_begin_subtest "--format=json --part=5, rfc822's html part"\r
394  notmuch show --format=json --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
395 @@ -398,7 +398,7 @@ cat <<EOF >EXPECTED\r
396  \r
397  {"id": 5, "content-type": "text/html"}\r
398  EOF\r
399 -test_expect_equal_file OUTPUT EXPECTED\r
400 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
401  \r
402  test_begin_subtest "--format=json --part=6, rfc822's text part"\r
403  notmuch show --format=json --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
404 @@ -407,7 +407,7 @@ cat <<EOF >EXPECTED\r
405  \r
406  {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}\r
407  EOF\r
408 -test_expect_equal_file OUTPUT EXPECTED\r
409 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
410  \r
411  test_begin_subtest "--format=json --part=7, inline attachment"\r
412  notmuch show --format=json --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
413 @@ -416,7 +416,7 @@ cat <<EOF >EXPECTED\r
414  \r
415  {"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}\r
416  EOF\r
417 -test_expect_equal_file OUTPUT EXPECTED\r
418 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
419  \r
420  test_begin_subtest "--format=json --part=8, plain text part"\r
421  notmuch show --format=json --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
422 @@ -425,7 +425,7 @@ cat <<EOF >EXPECTED\r
423  \r
424  {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}\r
425  EOF\r
426 -test_expect_equal_file OUTPUT EXPECTED\r
427 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
428  \r
429  test_begin_subtest "--format=json --part=9, pgp signature (unverified)"\r
430  notmuch show --format=json --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT\r
431 @@ -434,7 +434,7 @@ cat <<EOF >EXPECTED\r
432  \r
433  {"id": 9, "content-type": "application/pgp-signature"}\r
434  EOF\r
435 -test_expect_equal_file OUTPUT EXPECTED\r
436 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
437  \r
438  test_expect_success \\r
439      "--format=json --part=10, no part, expect error" \\r
440 @@ -617,8 +617,7 @@ notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_j\r
441  cat <<EOF >EXPECTED\r
442  {"reply-headers": {"Subject": "Re: Multipart message",\r
443   "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",\r
444 - "To": "Carl Worth <cworth@cworth.org>,\r
445 - cworth@cworth.org",\r
446 + "To": "Carl Worth <cworth@cworth.org>, cworth@cworth.org",\r
447   "In-reply-to": "<87liy5ap00.fsf@yoom.home.cworth.org>",\r
448   "References": " <87liy5ap00.fsf@yoom.home.cworth.org>"},\r
449   "original": {"id": "XXXXX",\r
450 @@ -631,8 +630,7 @@ cat <<EOF >EXPECTED\r
451   "headers": {"Subject": "Multipart message",\r
452   "From": "Carl Worth <cworth@cworth.org>",\r
453   "To": "cworth@cworth.org",\r
454 - "Date": "Fri,\r
455 - 05 Jan 2001 15:43:57 +0000"},\r
456 + "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},\r
457   "body": [{"id": 1,\r
458   "content-type": "multipart/signed",\r
459   "content": [{"id": 2,\r
460 @@ -642,16 +640,14 @@ cat <<EOF >EXPECTED\r
461   "content": [{"headers": {"Subject": "html message",\r
462   "From": "Carl Worth <cworth@cworth.org>",\r
463   "To": "cworth@cworth.org",\r
464 - "Date": "Fri,\r
465 - 05 Jan 2001 15:42:57 +0000"},\r
466 + "Date": "Fri, 05 Jan 2001 15:42:57 +0000"},\r
467   "body": [{"id": 4,\r
468   "content-type": "multipart/alternative",\r
469   "content": [{"id": 5,\r
470   "content-type": "text/html"},\r
471   {"id": 6,\r
472   "content-type": "text/plain",\r
473 - "content": "This is an embedded message,\r
474 - with a multipart/alternative part.\n"}]}]}]},\r
475 + "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},\r
476   {"id": 7,\r
477   "content-type": "text/plain",\r
478   "filename": "YYYYY",\r
479 @@ -662,7 +658,7 @@ cat <<EOF >EXPECTED\r
480   {"id": 9,\r
481   "content-type": "application/pgp-signature"}]}]}}\r
482  EOF\r
483 -test_expect_equal_file OUTPUT EXPECTED\r
484 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
485  \r
486  test_begin_subtest "'notmuch show --part' does not corrupt a part with CRLF pair"\r
487  notmuch show --format=raw --part=3 id:base64-part-with-crlf > crlf.out\r
488 diff --git a/test/search-output b/test/search-output\r
489 index 8b57a43..c2a87eb 100755\r
490 --- a/test/search-output\r
491 +++ b/test/search-output\r
492 @@ -62,7 +62,7 @@ cat <<EOF >EXPECTED\r
493  "THREADID",\r
494  "THREADID"]\r
495  EOF\r
496 -test_expect_equal_file OUTPUT EXPECTED\r
497 +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"\r
498  \r
499  test_begin_subtest "--output=messages"\r
500  notmuch search --output=messages '*' >OUTPUT\r
501 diff --git a/test/test-lib.sh b/test/test-lib.sh\r
502 index 06aaea2..791d2dc 100644\r
503 --- a/test/test-lib.sh\r
504 +++ b/test/test-lib.sh\r
505 @@ -512,6 +512,16 @@ test_expect_equal_file ()\r
506      fi\r
507  }\r
508  \r
509 +# Like test_expect_equal, but arguments are JSON expressions to be\r
510 +# canonicalized before diff'ing.  If an argument cannot be parsed, it\r
511 +# is used unchanged so that there's something to diff against.\r
512 +test_expect_equal_json () {\r
513 +    output=$(echo "$1" | python -mjson.tool || echo "$1")\r
514 +    expected=$(echo "$2" | python -mjson.tool || echo "$2")\r
515 +    shift 2\r
516 +    test_expect_equal "$output" "$expected" "$@"\r
517 +}\r
518 +\r
519  test_emacs_expect_t () {\r
520         test "$#" = 2 && { prereq=$1; shift; } || prereq=\r
521         test "$#" = 1 ||\r
522 @@ -565,10 +575,9 @@ notmuch_show_sanitize_all ()\r
523  \r
524  notmuch_json_show_sanitize ()\r
525  {\r
526 -    sed -e 's|, |,\n |g' | \\r
527 -       sed \\r
528 -       -e 's|"id": "[^"]*",|"id": "XXXXX",|' \\r
529 -       -e 's|"filename": "[^"]*",|"filename": "YYYYY",|'\r
530 +    sed \\r
531 +       -e 's|"id": "[^"]*",|"id": "XXXXX",|g' \\r
532 +       -e 's|"filename": "[^"]*",|"filename": "YYYYY",|g'\r
533  }\r
534  \r
535  # End of notmuch helper functions\r
536 -- \r
537 1.7.10\r
538 \r