--- /dev/null
+Return-Path: <amdragon@mit.edu>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 16FC2431FBF\r
+ for <notmuch@notmuchmail.org>; Tue, 22 Apr 2014 15:11:28 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id aNtJlpsaqTVU for <notmuch@notmuchmail.org>;\r
+ Tue, 22 Apr 2014 15:11:20 -0700 (PDT)\r
+Received: from dmz-mailsec-scanner-7.mit.edu (dmz-mailsec-scanner-7.mit.edu\r
+ [18.7.68.36])\r
+ (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id 7BAF5431FBD\r
+ for <notmuch@notmuchmail.org>; Tue, 22 Apr 2014 15:11:20 -0700 (PDT)\r
+X-AuditID: 12074424-f79e26d000000c70-85-5356e90777b0\r
+Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
+ (using TLS with cipher AES256-SHA (256/256 bits))\r
+ (Client did not present a certificate)\r
+ by dmz-mailsec-scanner-7.mit.edu (Symantec Messaging Gateway) with SMTP\r
+ id E7.DA.03184.709E6535; Tue, 22 Apr 2014 18:11:19 -0400 (EDT)\r
+Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11])\r
+ by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id s3MMBHKP024357; \r
+ Tue, 22 Apr 2014 18:11:18 -0400\r
+Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
+ (authenticated bits=0)\r
+ (User authenticated as amdragon@ATHENA.MIT.EDU)\r
+ by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id s3MMBFnZ001951\r
+ (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT);\r
+ Tue, 22 Apr 2014 18:11:16 -0400\r
+Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.80)\r
+ (envelope-from <amdragon@mit.edu>)\r
+ id 1WciuJ-0003bH-9t; Tue, 22 Apr 2014 18:11:15 -0400\r
+Date: Tue, 22 Apr 2014 18:11:15 -0400\r
+From: Austin Clements <amdragon@MIT.EDU>\r
+To: Mark Walters <markwalters1009@gmail.com>\r
+Subject: Re: [PATCH v2] test: Test thread linking in all possible delivery\r
+ orders\r
+Message-ID: <20140422221115.GH25817@mit.edu>\r
+References: <87y4zhfmrn.fsf@maritornes.cs.unb.ca>\r
+ <1398110291-15832-1-git-send-email-amdragon@mit.edu>\r
+ <87wqehaw69.fsf@qmul.ac.uk>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=us-ascii\r
+Content-Disposition: inline\r
+In-Reply-To: <87wqehaw69.fsf@qmul.ac.uk>\r
+User-Agent: Mutt/1.5.21 (2010-09-15)\r
+X-Brightmail-Tracker:\r
+ H4sIAAAAAAAAA+NgFupmleLIzCtJLcpLzFFi42IR4hTV1mV/GRZs8HKxmsWN1m5Gi9VzeSyu\r
+ 35zJ7MDssXPWXXaPZ6tuMXtsOfSeOYA5issmJTUnsyy1SN8ugSvj5+L0grk6FW+PXmBrYJyl\r
+ 2MXIySEhYCLx4tJdRghbTOLCvfVsXYxcHEICs5kkNh7/zArhbGSUOPX7ATuEc5pJYt2OLVDO\r
+ EkaJlRd2AfVwcLAIqEqcehUOMopNQENi2/7lYGNFBHQkbh9awA5iMwvoSbTPesYEUi4sECwx\r
+ 54kUSJgXqOTp7UaoZW2MEn09PYwQCUGJkzOfsED0aknc+PcSrJdZQFpi+T8OkDAn0Kp9n9Yw\r
+ g9iiAioSU05uY5vAKDQLSfcsJN2zELoXMDKvYpRNya3SzU3MzClOTdYtTk7My0st0jXXy80s\r
+ 0UtNKd3ECApzdheVHYzNh5QOMQpwMCrx8BauDAsWYk0sK67MPcQoycGkJMrr+wAoxJeUn1KZ\r
+ kVicEV9UmpNafIhRgoNZSYRXejVQjjclsbIqtSgfJiXNwaIkzvvW2ipYSCA9sSQ1OzW1ILUI\r
+ JivDwaEkwZv6AqhRsCg1PbUiLTOnBCHNxMEJMpwHaLg2SA1vcUFibnFmOkT+FKOilDhvNUhC\r
+ ACSRUZoH1wtLQ68YxYFeEeZNBqniAaYwuO5XQIOZgAY/2RICMrgkESEl1cCYENp+aP4nzTvr\r
+ vBmFqxlNztxeFioU03Fr29qt0y8w/ct4EmLufmq3kF365IDr702jFbLrMlK3Bmop/ur/l+HA\r
+ emrfzjUlW1QnHXdckvTnQttNsWnLTq68bGb6R/xzzyGnT2nn/3ZFFDPeFMpSmhJ/Ja9Cd+YV\r
+ +fCuz3dPf3BtDbpR+GjCtcR+JZbijERDLeai4kQAIAMk8B4DAAA=\r
+Cc: notmuch@notmuchmail.org\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Tue, 22 Apr 2014 22:11:28 -0000\r
+\r
+The intent was to produce distinct trees, but obviously combinatorics\r
+is not my strong suit. Any ideas how to fix/rewrite the algorithm,\r
+other than just uniq'ing the output?\r
+\r
+Quoth Mark Walters on Apr 22 at 10:31 pm:\r
+> \r
+> Hi\r
+> \r
+> Broadly this looks good but I am somewhat confused by the python\r
+> part. Is it intended to produce the same tree multiple times? It does\r
+> seem to produce all the possible trees (*) so it doesn't matter but\r
+> might be worth a comment.\r
+> \r
+> Best wishes\r
+> \r
+> Mark\r
+> \r
+> (*) I think there should be 64 rooted trees (16 trees and 4 possible\r
+> roots) and the python generates 144 lines. Piping the output to sort and\r
+> uniq gives 64 lines.\r
+> \r
+> \r
+> \r
+> On Mon, 21 Apr 2014, Austin Clements <amdragon@MIT.EDU> wrote:\r
+> > These tests deliver all possible (single-root) four-message threads in\r
+> > all possible orders and check that notmuch successfully links them\r
+> > into threads.\r
+> >\r
+> > There are two variants of the test: one delivers messages that\r
+> > reference only their immediate parent and the other delivers messages\r
+> > that reference all of their parents. The latter test is currently\r
+> > known-broken.\r
+> >\r
+> > This is introduced as a new test (rather than just adding it to\r
+> > T050-new) because it's much easier for this to start with an empty\r
+> > database.\r
+> > ---\r
+> >\r
+> > This version hopefully addresses David's comments in\r
+> > id:87y4zhfmrn.fsf@maritornes.cs.unb.ca and adds a second test that\r
+> > demonstrates the bug Mark in figured out in\r
+> > id:8738h7kv2q.fsf@qmul.ac.uk.\r
+> >\r
+> > test/T051-new-linking.sh | 91 ++++++++++++++++++++++++++++++++++++++++++++++++\r
+> > 1 file changed, 91 insertions(+)\r
+> > create mode 100755 test/T051-new-linking.sh\r
+> >\r
+> > diff --git a/test/T051-new-linking.sh b/test/T051-new-linking.sh\r
+> > new file mode 100755\r
+> > index 0000000..9ccbc52\r
+> > --- /dev/null\r
+> > +++ b/test/T051-new-linking.sh\r
+> > @@ -0,0 +1,91 @@\r
+> > +#!/usr/bin/env bash\r
+> > +test_description='"notmuch new" thread linking'\r
+> > +\r
+> > +. ./test-lib.sh\r
+> > +\r
+> > +# Generate all possible single-root four message thread structures.\r
+> > +# Each line in THREADS is a thread structure, where the n'th field is\r
+> > +# the parent of message n. We'll use this for multiple tests below.\r
+> > +THREADS=$(python -c '\r
+> > +def mkTrees(free, tree={}):\r
+> > + if free == set():\r
+> > + print(" ".join(map(str, [msg[1] for msg in sorted(tree.items())])))\r
+> > + return\r
+> > + # Attach each free message to each message in the tree (if there is\r
+> > + # no tree, make the free message the root), backtracking after each\r
+> > + for msg in sorted(free):\r
+> > + parents = sorted(tree.keys()) if tree else ["none"]\r
+> > + for parent in parents:\r
+> > + ntree = tree.copy()\r
+> > + ntree[msg] = parent\r
+> > + mkTrees(free - set([msg]), ntree)\r
+> > +mkTrees(set(range(4)))')\r
+> > +nthreads=$(wc -l <<< "$THREADS")\r
+> > +\r
+> > +test_begin_subtest "All four-message threads get linked in all delivery orders (one parent)"\r
+> > +# In the first variant, this delivers messages that reference only\r
+> > +# their immediate parent. Hence, we should only expect threads to be\r
+> > +# fully joined at the end.\r
+> > +for ((n = 0; n < 4; n++)); do\r
+> > + # Deliver the n'th message of every thread\r
+> > + thread=0\r
+> > + while read -a parents; do\r
+> > + parent=${parents[$n]}\r
+> > + generate_message \\r
+> > + [id]=m$n@t$thread [in-reply-to]="\<m$parent@t$thread\>" \\r
+> > + [subject]=p$thread [from]=m$n\r
+> > + thread=$((thread + 1))\r
+> > + done <<< "$THREADS"\r
+> > + notmuch new > /dev/null\r
+> > +done\r
+> > +output=$(notmuch search --sort=newest-first '*' | notmuch_search_sanitize)\r
+> > +expected=$(for ((i = 0; i < $nthreads; i++)); do\r
+> > + echo "thread:XXX 2001-01-05 [4/4] m3, m2, m1, m0; p$i (inbox unread)"\r
+> > + done)\r
+> > +test_expect_equal "$output" "$expected"\r
+> > +\r
+> > +test_begin_subtest "The same (full parent linkage)"\r
+> > +test_subtest_known_broken\r
+> > +# Here we do the same thing as the previous test, but each message\r
+> > +# references all of its parents. Since every message references the\r
+> > +# root of the thread, each thread should always be fully joined. This\r
+> > +# is currently broken because of the bug detailed in\r
+> > +# id:8738h7kv2q.fsf@qmul.ac.uk.\r
+> > +rm ${MAIL_DIR}/*\r
+> > +notmuch new\r
+> > +output=""\r
+> > +expected=""\r
+> > +for ((n = 0; n < 4; n++)); do\r
+> > + # Deliver the n'th message of every thread\r
+> > + thread=0\r
+> > + while read -a parents; do\r
+> > + references=""\r
+> > + parent=${parents[$n]}\r
+> > + while [[ $parent != none ]]; do\r
+> > + references="<m$parent@t$thread> $references"\r
+> > + parent=${parents[$parent]}\r
+> > + done\r
+> > +\r
+> > + generate_message \\r
+> > + [id]=m$n@t$thread [references]="'$references'" \\r
+> > + [subject]=p$thread [from]=m$n\r
+> > + thread=$((thread + 1))\r
+> > + done <<< "$THREADS"\r
+> > + notmuch new > /dev/null\r
+> > +\r
+> > + output="$output\r
+> > +$(notmuch search --sort=newest-first '*' | notmuch_search_sanitize)"\r
+> > +\r
+> > + # Construct expected output\r
+> > + template="thread:XXX 2001-01-05 [$((n+1))/$((n+1))]"\r
+> > + for ((m = n; m > 0; m--)); do\r
+> > + template="$template m$m,"\r
+> > + done\r
+> > + expected="$expected\r
+> > +$(for ((i = 0; i < $nthreads; i++)); do\r
+> > + echo "$template m0; p$i (inbox unread)"\r
+> > + done)"\r
+> > +done\r
+> > +test_expect_equal "$output" "$expected"\r
+> > +\r
+> > +test_done\r