Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 1872F431FAF for ; Sat, 28 Jul 2012 06:18:19 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -1.098 X-Spam-Level: X-Spam-Status: No, score=-1.098 tagged_above=-999 required=5 tests=[DKIM_ADSP_CUSTOM_MED=0.001, FREEMAIL_FROM=0.001, NML_ADSP_CUSTOM_MED=1.2, RCVD_IN_DNSWL_MED=-2.3] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 88qZYImQnD27 for ; Sat, 28 Jul 2012 06:18:17 -0700 (PDT) Received: from mail2.qmul.ac.uk (mail2.qmul.ac.uk [138.37.6.6]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 9E1D4431FAE for ; Sat, 28 Jul 2012 06:18:16 -0700 (PDT) Received: from smtp.qmul.ac.uk ([138.37.6.40]) by mail2.qmul.ac.uk with esmtp (Exim 4.71) (envelope-from ) id 1Sv6uJ-0000ko-Gi; Sat, 28 Jul 2012 14:18:14 +0100 Received: from 94-192-233-223.zone6.bethere.co.uk ([94.192.233.223] helo=localhost) by smtp.qmul.ac.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1Sv6uI-0001Qm-8U; Sat, 28 Jul 2012 14:18:11 +0100 From: Mark Walters To: Austin Clements , notmuch@notmuchmail.org Subject: Re: [PATCH v2 01/13] test: Uniformly canonicalize actual and expected JSON In-Reply-To: <1343449754-9010-2-git-send-email-amdragon@mit.edu> References: <1343449754-9010-1-git-send-email-amdragon@mit.edu> <1343449754-9010-2-git-send-email-amdragon@mit.edu> User-Agent: Notmuch/0.13.2+93~gf33b188 (http://notmuchmail.org) Emacs/23.4.1 (x86_64-pc-linux-gnu) Date: Sat, 28 Jul 2012 14:18:09 +0100 Message-ID: <87lii4uir2.fsf@qmul.ac.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Sender-Host-Address: 94.192.233.223 X-QM-SPAM-Info: Sender has good ham record. :) X-QM-Body-MD5: bee0de2a259038a02d453a38c150ea76 (of first 20000 bytes) X-SpamAssassin-Score: -1.8 X-SpamAssassin-SpamBar: - X-SpamAssassin-Report: The QM spam filters have analysed this message to determine if it is spam. We require at least 5.0 points to mark a message as spam. This message scored -1.8 points. Summary of the scoring: * -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, * medium trust * [138.37.6.40 listed in list.dnswl.org] * 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider * (markwalters1009[at]gmail.com) * -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay * domain * 0.5 AWL AWL: From: address is in the auto white-list X-QM-Scan-Virus: ClamAV says the message is clean Cc: tomi.ollila@iki.fi X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 Jul 2012 13:18:19 -0000 This looks good to me. I have read the test patches too now and they look fine. I just have one possible thought (see below) which is definitely not worth holding up this series for. Best wishes=20 Mark On Sat, 28 Jul 2012, Austin Clements wrote: > Previously, we used a variety of ad-hoc canonicalizations for JSON > output in the test suite, but were ultimately very sensitive to JSON > irrelevancies such as whitespace. This introduces a new test > comparison function, test_expect_equal_json, that first pretty-prints > *both* the actual and expected JSON and the compares the result. > > The current implementation of this simply uses Python's json.tool to > perform pretty-printing (with a fallback to the identity function if > parsing fails). However, since the interface it introduces is > semantically high-level, we could swap in other mechanisms in the > future, such as another pretty-printer or something that does not > re-order object keys (if we decide that we care about that). > > In general, this patch does not remove the existing ad-hoc > canonicalization because it does no harm. We do have to remove the > newline-after-comma rule from notmuch_json_show_sanitize and > filter_show_json because it results in invalid JSON that cannot be > pretty-printed. > > Most of this patch simply replaces test_expect_equal and > test_expect_equal_file with test_expect_equal_json. It changes the > expected JSON in a few places where sanitizers had placed newlines > after commas inside strings. > --- > test/crypto | 37 +++++++++++++++---------------------- > test/json | 14 +++++++------- > test/maildir-sync | 11 ++++------- > test/multipart | 34 +++++++++++++++------------------- > test/search-output | 2 +- > test/test-lib.sh | 17 +++++++++++++---- > 6 files changed, 55 insertions(+), 60 deletions(-) > > diff --git a/test/crypto b/test/crypto > index be752b1..5dd14c4 100755 > --- a/test/crypto > +++ b/test/crypto > @@ -51,8 +51,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test signed message 001", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "sigstatus": [{"status": "good", > "fingerprint": "'$FINGERPRINT'", > @@ -64,7 +63,7 @@ expected=3D'[[[{"id": "XXXXX", > {"id": 3, > "content-type": "application/pgp-signature"}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" >=20=20 > @@ -85,8 +84,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test signed message 001", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "sigstatus": [{"status": "good", > "fingerprint": "'$FINGERPRINT'", > @@ -99,7 +97,7 @@ expected=3D'[[[{"id": "XXXXX", > {"id": 3, > "content-type": "application/pgp-signature"}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" >=20=20 > @@ -119,8 +117,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test signed message 001", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "sigstatus": [{"status": "error", > "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", > @@ -132,7 +129,7 @@ expected=3D'[[[{"id": "XXXXX", > {"id": 3, > "content-type": "application/pgp-signature"}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" > mv "${GNUPGHOME}"{.bak,} > @@ -193,8 +190,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test encrypted message 001", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "encstatus": [{"status": "good"}], > "sigstatus": [], > @@ -210,7 +206,7 @@ expected=3D'[[[{"id": "XXXXX", > "content-type": "application/octet-stream", > "filename": "TESTATTACHMENT"}]}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" >=20=20 > @@ -221,7 +217,7 @@ output=3D$(notmuch show --format=3Djson --part=3D4 --= decrypt subject:"test encrypted m > expected=3D'{"id": 4, > "content-type": "text/plain", > "content": "This is a test encrypted message.\n"}' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" >=20=20 > @@ -248,8 +244,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test encrypted message 001", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "encstatus": [{"status": "bad"}], > "content-type": "multipart/encrypted", > @@ -258,7 +253,7 @@ expected=3D'[[[{"id": "XXXXX", > {"id": 3, > "content-type": "application/octet-stream"}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" > mv "${GNUPGHOME}"{.bak,} > @@ -283,8 +278,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test encrypted message 002", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "encstatus": [{"status": "good"}], > "sigstatus": [{"status": "good", > @@ -298,7 +292,7 @@ expected=3D'[[[{"id": "XXXXX", > "content-type": "text/plain", > "content": "This is another test encrypted message.\n"}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" >=20=20 > @@ -338,8 +332,7 @@ expected=3D'[[[{"id": "XXXXX", > "headers": {"Subject": "test signed message 001", > "From": "Notmuch Test Suite ", > "To": "test_suite@notmuchmail.org", > - "Date": "Sat, > - 01 Jan 2000 12:00:00 +0000"}, > + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, > "body": [{"id": 1, > "sigstatus": [{"status": "error", > "keyid": "6D92612D94E46381", > @@ -351,7 +344,7 @@ expected=3D'[[[{"id": "XXXXX", > {"id": 3, > "content-type": "application/pgp-signature"}]}]}, > []]]]' > -test_expect_equal \ > +test_expect_equal_json \ > "$output" \ > "$expected" >=20=20 > diff --git a/test/json b/test/json > index 831e105..d86ee46 100755 > --- a/test/json > +++ b/test/json > @@ -5,21 +5,21 @@ test_description=3D"--format=3Djson output" > test_begin_subtest "Show message: json" > add_message "[subject]=3D\"json-show-subject\"" "[date]=3D\"Sat, 01 Jan = 2000 12:00:00 -0000\"" "[body]=3D\"json-show-message\"" > output=3D$(notmuch show --format=3Djson "json-show-message") > -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": t= rue, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestam= p\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"u= nread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Not= much Test Suite \", \"To\": \"Notmuch Test Suit= e \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +00= 00\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\"= : \"json-show-message\n\"}]}, []]]]" > +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match= \": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"tim= estamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\= ",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": = \"Notmuch Test Suite \", \"To\": \"Notmuch Test= Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:0= 0 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"cont= ent\": \"json-show-message\n\"}]}, []]]]" Since test_expect_equal_json does not care about whitespace (outside of strings) would it be worth splitting the expected output for each of these tests into multiple lines? > # This should be the same output as above. > test_begin_subtest "Show message: json --body=3Dtrue" > output=3D$(notmuch show --format=3Djson --body=3Dtrue "json-show-message= ") > -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": t= rue, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestam= p\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"u= nread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Not= much Test Suite \", \"To\": \"Notmuch Test Suit= e \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +00= 00\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\"= : \"json-show-message\n\"}]}, []]]]" > +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match= \": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"tim= estamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\= ",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": = \"Notmuch Test Suite \", \"To\": \"Notmuch Test= Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:0= 0 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"cont= ent\": \"json-show-message\n\"}]}, []]]]" >=20=20 > test_begin_subtest "Show message: json --body=3Dfalse" > output=3D$(notmuch show --format=3Djson --body=3Dfalse "json-show-messag= e") > -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": t= rue, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestam= p\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"u= nread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Not= much Test Suite \", \"To\": \"Notmuch Test Suit= e \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +00= 00\"}}, []]]]" > +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match= \": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"tim= estamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\= ",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": = \"Notmuch Test Suite \", \"To\": \"Notmuch Test= Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:0= 0 +0000\"}}, []]]]" >=20=20 > test_begin_subtest "Search message: json" > add_message "[subject]=3D\"json-search-subject\"" "[date]=3D\"Sat, 01 Ja= n 2000 12:00:00 -0000\"" "[body]=3D\"json-search-message\"" > output=3D$(notmuch search --format=3Djson "json-search-message" | notmuc= h_json_show_sanitize | notmuch_search_sanitize) > -test_expect_equal "$output" "[{\"thread\": \"XXX\", > +test_expect_equal_json "$output" "[{\"thread\": \"XXX\", > \"timestamp\": 946728000, > \"date_relative\": \"2000-01-01\", > \"matched\": 1, > @@ -32,7 +32,7 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\", > test_begin_subtest "Show message: json, utf-8" > add_message "[subject]=3D\"json-show-utf8-body-s=C3=BCbj=C3=A9ct\"" "[da= te]=3D\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=3D\"js=C3=B6n-show-m=C3= =A9ssage\"" > output=3D$(notmuch show --format=3Djson "js=C3=B6n-show-m=C3=A9ssage") > -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": t= rue, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestam= p\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"u= nread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-s=C3=BCbj=C3=A9c= t\", \"From\": \"Notmuch Test Suite \", \"To\":= \"Notmuch Test Suite \", \"Date\": \"Sat, 01 J= an 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/= plain\", \"content\": \"js=C3=B6n-show-m=C3=A9ssage\n\"}]}, []]]]" > +test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match= \": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"tim= estamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\= ",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-s=C3=BCbj= =C3=A9ct\", \"From\": \"Notmuch Test Suite \", = \"To\": \"Notmuch Test Suite \", \"Date\": \"Sa= t, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": = \"text/plain\", \"content\": \"js=C3=B6n-show-m=C3=A9ssage\n\"}]}, []]]]" >=20=20 > test_begin_subtest "Show message: json, inline attachment filename" > subject=3D'json-show-inline-attachment-filename' > @@ -45,12 +45,12 @@ emacs_deliver_message \ > (insert \"Message-ID: <$id>\n\")" > output=3D$(notmuch show --format=3Djson "id:$id") > filename=3D$(notmuch search --output=3Dfiles "id:$id") > -test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"exc= luded\": false, \"filename\": \"$filename\", \"timestamp\": 946728000, \"da= te_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subje= ct\": \"$subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 200= 0 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/m= ixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"conte= nt\": \"This is a test message with inline attachment with a filename\"}, {= \"id\": 3, \"content-type\": \"application/octet-stream\", \"filename\": \"= README\"}]}]}, []]]]" > +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 \", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Ja= n 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multip= art/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\"}]}]}, []]]]" >=20=20 > test_begin_subtest "Search message: json, utf-8" > add_message "[subject]=3D\"json-search-utf8-body-s=C3=BCbj=C3=A9ct\"" "[= date]=3D\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=3D\"js=C3=B6n-search-m= =C3=A9ssage\"" > output=3D$(notmuch search --format=3Djson "js=C3=B6n-search-m=C3=A9ssage= " | notmuch_json_show_sanitize | notmuch_search_sanitize) > -test_expect_equal "$output" "[{\"thread\": \"XXX\", > +test_expect_equal_json "$output" "[{\"thread\": \"XXX\", > \"timestamp\": 946728000, > \"date_relative\": \"2000-01-01\", > \"matched\": 1, > diff --git a/test/maildir-sync b/test/maildir-sync > index 01348d3..b748d04 100755 > --- a/test/maildir-sync > +++ b/test/maildir-sync > @@ -4,11 +4,9 @@ test_description=3D"maildir synchronization" >=20=20 > . ./test-lib.sh >=20=20 > -# Much easier to examine differences if the "notmuch show > -# --format=3Djson" output includes some newlines. Also, need to avoid > -# including the local value of MAIL_DIR in the result. > +# Avoid including the local value of MAIL_DIR in the result. > filter_show_json() { > - sed -e 's/, /,\n/g' | sed -e "s|${MAIL_DIR}/|MAIL_DIR/|" > + sed -e "s|${MAIL_DIR}/|MAIL_DIR/|" > echo > } >=20=20 > @@ -44,7 +42,7 @@ test_expect_equal "$output" "adding-replied-tag:2,RS" >=20=20 > test_begin_subtest "notmuch show works with renamed file (without notmuc= h new)" > output=3D$(notmuch show --format=3Djson id:${gen_msg_id} | filter_show_j= son) > -test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-= suite", > +test_expect_equal_json "$output" '[[[{"id": "adding-replied-tag@notmuch-= test-suite", > "match": true, > "excluded": false, > "filename": "MAIL_DIR/cur/adding-replied-tag:2,RS", > @@ -54,8 +52,7 @@ test_expect_equal "$output" '[[[{"id": "adding-replied-= tag@notmuch-test-suite", > "headers": {"Subject": "Adding replied tag", > "From": "Notmuch Test Suite ", > "To": "Notmuch Test Suite ", > -"Date": "Fri, > -05 Jan 2001 15:43:57 +0000"}, > +"Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, > "body": [{"id": 1, > "content-type": "text/plain", > "content": "This is just a test message (#3)\n"}]}, > diff --git a/test/multipart b/test/multipart > index 72d3927..3ccf27f 100755 > --- a/test/multipart > +++ b/test/multipart > @@ -334,7 +334,7 @@ cat <EXPECTED > {"id": 8, "content-type": "text/plain", "content": "And this message is = signed.\n\n-Carl\n"}]},=20 > {"id": 9, "content-type": "application/pgp-signature"}]}]} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D1, message body" > notmuch show --format=3Djson --part=3D1 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -351,7 +351,7 @@ cat <EXPECTED > {"id": 8, "content-type": "text/plain", "content": "And this message is = signed.\n\n-Carl\n"}]},=20 > {"id": 9, "content-type": "application/pgp-signature"}]} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D2, multipart/mixed" > notmuch show --format=3Djson --part=3D2 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -366,7 +366,7 @@ cat <EXPECTED > {"id": 7, "content-type": "text/plain", "filename": "attachment", "conte= nt": "This is a text attachment.\n"},=20 > {"id": 8, "content-type": "text/plain", "content": "And this message is = signed.\n\n-Carl\n"}]} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D3, rfc822 part" > notmuch show --format=3Djson --part=3D3 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -378,7 +378,7 @@ cat <EXPECTED > {"id": 5, "content-type": "text/html"},=20 > {"id": 6, "content-type": "text/plain", "content": "This is an embedded = message, with a multipart/alternative part.\n"}]}]}]} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D4, rfc822's multipart/alter= native" > notmuch show --format=3Djson --part=3D4 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -389,7 +389,7 @@ cat <EXPECTED > {"id": 5, "content-type": "text/html"},=20 > {"id": 6, "content-type": "text/plain", "content": "This is an embedded = message, with a multipart/alternative part.\n"}]} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D5, rfc822's html part" > notmuch show --format=3Djson --part=3D5 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -398,7 +398,7 @@ cat <EXPECTED >=20=20 > {"id": 5, "content-type": "text/html"} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D6, rfc822's text part" > notmuch show --format=3Djson --part=3D6 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -407,7 +407,7 @@ cat <EXPECTED >=20=20 > {"id": 6, "content-type": "text/plain", "content": "This is an embedded = message, with a multipart/alternative part.\n"} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D7, inline attachment" > notmuch show --format=3Djson --part=3D7 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -416,7 +416,7 @@ cat <EXPECTED >=20=20 > {"id": 7, "content-type": "text/plain", "filename": "attachment", "conte= nt": "This is a text attachment.\n"} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D8, plain text part" > notmuch show --format=3Djson --part=3D8 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -425,7 +425,7 @@ cat <EXPECTED >=20=20 > {"id": 8, "content-type": "text/plain", "content": "And this message is = signed.\n\n-Carl\n"} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--format=3Djson --part=3D9, pgp signature (unverifie= d)" > notmuch show --format=3Djson --part=3D9 'id:87liy5ap00.fsf@yoom.home.cwo= rth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT > @@ -434,7 +434,7 @@ cat <EXPECTED >=20=20 > {"id": 9, "content-type": "application/pgp-signature"} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_expect_success \ > "--format=3Djson --part=3D10, no part, expect error" \ > @@ -617,8 +617,7 @@ notmuch reply --format=3Djson 'id:87liy5ap00.fsf@yoom= .home.cworth.org' | notmuch_j > cat <EXPECTED > {"reply-headers": {"Subject": "Re: Multipart message", > "From": "Notmuch Test Suite ", > - "To": "Carl Worth , > - cworth@cworth.org", > + "To": "Carl Worth , cworth@cworth.org", > "In-reply-to": "<87liy5ap00.fsf@yoom.home.cworth.org>", > "References": " <87liy5ap00.fsf@yoom.home.cworth.org>"}, > "original": {"id": "XXXXX", > @@ -631,8 +630,7 @@ cat <EXPECTED > "headers": {"Subject": "Multipart message", > "From": "Carl Worth ", > "To": "cworth@cworth.org", > - "Date": "Fri, > - 05 Jan 2001 15:43:57 +0000"}, > + "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, > "body": [{"id": 1, > "content-type": "multipart/signed", > "content": [{"id": 2, > @@ -642,16 +640,14 @@ cat <EXPECTED > "content": [{"headers": {"Subject": "html message", > "From": "Carl Worth ", > "To": "cworth@cworth.org", > - "Date": "Fri, > - 05 Jan 2001 15:42:57 +0000"}, > + "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, > "body": [{"id": 4, > "content-type": "multipart/alternative", > "content": [{"id": 5, > "content-type": "text/html"}, > {"id": 6, > "content-type": "text/plain", > - "content": "This is an embedded message, > - with a multipart/alternative part.\n"}]}]}]}, > + "content": "This is an embedded message, with a multipart/alternative p= art.\n"}]}]}]}, > {"id": 7, > "content-type": "text/plain", > "filename": "YYYYY", > @@ -662,7 +658,7 @@ cat <EXPECTED > {"id": 9, > "content-type": "application/pgp-signature"}]}]}} > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "'notmuch show --part' does not corrupt a part with C= RLF pair" > notmuch show --format=3Draw --part=3D3 id:base64-part-with-crlf > crlf.o= ut > diff --git a/test/search-output b/test/search-output > index 8b57a43..c2a87eb 100755 > --- a/test/search-output > +++ b/test/search-output > @@ -62,7 +62,7 @@ cat <EXPECTED > "THREADID", > "THREADID"] > EOF > -test_expect_equal_file OUTPUT EXPECTED > +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" >=20=20 > test_begin_subtest "--output=3Dmessages" > notmuch search --output=3Dmessages '*' >OUTPUT > diff --git a/test/test-lib.sh b/test/test-lib.sh > index 06aaea2..791d2dc 100644 > --- a/test/test-lib.sh > +++ b/test/test-lib.sh > @@ -512,6 +512,16 @@ test_expect_equal_file () > fi > } >=20=20 > +# Like test_expect_equal, but arguments are JSON expressions to be > +# canonicalized before diff'ing. If an argument cannot be parsed, it > +# is used unchanged so that there's something to diff against. > +test_expect_equal_json () { > + output=3D$(echo "$1" | python -mjson.tool || echo "$1") > + expected=3D$(echo "$2" | python -mjson.tool || echo "$2") > + shift 2 > + test_expect_equal "$output" "$expected" "$@" > +} > + > test_emacs_expect_t () { > test "$#" =3D 2 && { prereq=3D$1; shift; } || prereq=3D > test "$#" =3D 1 || > @@ -565,10 +575,9 @@ notmuch_show_sanitize_all () >=20=20 > notmuch_json_show_sanitize () > { > - sed -e 's|, |,\n |g' | \ > - sed \ > - -e 's|"id": "[^"]*",|"id": "XXXXX",|' \ > - -e 's|"filename": "[^"]*",|"filename": "YYYYY",|' > + sed \ > + -e 's|"id": "[^"]*",|"id": "XXXXX",|g' \ > + -e 's|"filename": "[^"]*",|"filename": "YYYYY",|g' > } >=20=20 > # End of notmuch helper functions > --=20 > 1.7.10