1 Return-Path: <prvs=310563a60d=amthrax@drake.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 2D0DE431FB6
\r
6 for <notmuch@notmuchmail.org>; Wed, 4 May 2011 13:32:22 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]
\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 ENqVoKGana1U for <notmuch@notmuchmail.org>;
\r
16 Wed, 4 May 2011 13:32:21 -0700 (PDT)
\r
17 Received: from dmz-mailsec-scanner-3.mit.edu (DMZ-MAILSEC-SCANNER-3.MIT.EDU
\r
19 by olra.theworths.org (Postfix) with ESMTP id 4A1BD431FB5
\r
20 for <notmuch@notmuchmail.org>; Wed, 4 May 2011 13:32:21 -0700 (PDT)
\r
21 X-AuditID: 1209190e-b7c80ae0000047dd-57-4dc1b7d98d6f
\r
22 Received: from mailhub-auth-2.mit.edu ( [18.7.62.36])
\r
23 by dmz-mailsec-scanner-3.mit.edu (Symantec Messaging Gateway) with SMTP
\r
24 id 52.33.18397.9D7B1CD4; Wed, 4 May 2011 16:32:25 -0400 (EDT)
\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])
\r
26 by mailhub-auth-2.mit.edu (8.13.8/8.9.2) with ESMTP id p44KWII8021336;
\r
27 Wed, 4 May 2011 16:32:18 -0400
\r
28 Received: from drake.mit.edu (26-4-180.dynamic.csail.mit.edu [18.26.4.180])
\r
29 (authenticated bits=0)
\r
30 (User authenticated as amdragon@ATHENA.MIT.EDU)
\r
31 by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id p44KWGmm023656
\r
32 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);
\r
33 Wed, 4 May 2011 16:32:18 -0400 (EDT)
\r
34 Received: from amthrax by drake.mit.edu with local (Exim 4.72)
\r
35 (envelope-from <amthrax@drake.mit.edu>)
\r
36 id 1QHik4-0000bb-AM; Wed, 04 May 2011 16:32:16 -0400
\r
37 From: Austin Clements <amdragon@MIT.EDU>
\r
38 To: notmuch@notmuchmail.org
\r
39 Subject: [PATCH 01/10 v2] test: Test atomicity of notmuch new.
\r
40 Date: Wed, 4 May 2011 16:32:03 -0400
\r
41 Message-Id: <1304541123-2237-1-git-send-email-amdragon@mit.edu>
\r
42 X-Mailer: git-send-email 1.7.4.1
\r
43 In-Reply-To: <1298015940-31986-2-git-send-email-amdragon@mit.edu>
\r
44 References: <1298015940-31986-2-git-send-email-amdragon@mit.edu>
\r
45 X-Brightmail-Tracker:
\r
46 H4sIAAAAAAAAA+NgFnrOIsWRmVeSWpSXmKPExsUixG6nontz+0Ffg+8/DSyu35zJ7MDo8WzV
\r
47 LeYAxihum6TEkrLgzPQ8fbsE7ozt+3YxFmy0r1h14BpLA2O3aRcjJ4eEgInE9obFLBC2mMSF
\r
48 e+vZuhi5OIQE9jFKPJy/kRXCWc8ose3bJijnGJPEqo3XocrmM0qcv3aICaSfTUBDYtv+5Ywg
\r
49 toiAtMTOu7OBOjg4mAVEJN7NBCsRFrCT2Hv4BNg6FgFViSt/2llBbF4Be4kVM5+wQpyhILHg
\r
50 3ls2EJtTwFHidMdusJFCAg4Sr3bcZpvAyL+AkWEVo2xKbpVubmJmTnFqsm5xcmJeXmqRrrFe
\r
51 bmaJXmpK6SZGUOBwSvLtYPx6UOkQowAHoxIPL1PyQV8h1sSy4srcQ4ySHExKorylm4FCfEn5
\r
52 KZUZicUZ8UWlOanFhxglOJiVRHh39ALleFMSK6tSi/JhUtIcLErivDMl1X2FBNITS1KzU1ML
\r
53 UotgsjIcHEoSvBe2ATUKFqWmp1akZeaUIKSZODhBhnNJiRSn5qWkFiWWlmTEg2IpvhgYTSAp
\r
54 HqC9RttB9hYXJOYCRSFaTzFacjzYcGo/I8flRWeB5LJVQFKIJS8/L1VKnFcHpEEApCGjNA9u
\r
55 HSx9vGIUB/pemPcnyFU8wNQDN/UV0EImoIVezQdAFpYkIqSkGhjb87r83sn3b2QtW3kiyXh/
\r
56 84zZykeyHx+Sql72hW3rlTMTyi9xlkcuOh1//QjbEcb8rm6H00smJTzOfr3kPfvBED2L6Gz5
\r
57 lj2XBYsORHWriufyezqL7w0tDnv31m6Td+hs3drjipK630JnuvB4Hj1bOyvh2qJVX7rDlY58
\r
58 nHv69/X0adnP+o4osRRnJBpqMRcVJwIAzbTj4/oCAAA=
\r
59 Cc: amdragon@mit.edu
\r
60 X-BeenThere: notmuch@notmuchmail.org
\r
61 X-Mailman-Version: 2.1.13
\r
63 List-Id: "Use and development of the notmuch mail system."
\r
64 <notmuch.notmuchmail.org>
\r
65 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
66 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
67 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
68 List-Post: <mailto:notmuch@notmuchmail.org>
\r
69 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
70 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
71 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
72 X-List-Received-Date: Wed, 04 May 2011 20:32:22 -0000
\r
74 This tests notmuch new's ability to recover from arbitrary stopping
\r
75 failures. It interrupts notmuch new after every database commit and,
\r
76 on every resulting database snapshot, re-runs notmuch new to
\r
77 completion and checks that the final database state is invariant.
\r
79 This addresses a timing bug in the atomicity test found by jrollins
\r
80 and also adds additional comments.
\r
82 test/atomicity | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++
\r
83 test/atomicity.gdb | 50 +++++++++++++++++++++++++++
\r
85 test/notmuch-test | 1 +
\r
86 4 files changed, 150 insertions(+), 1 deletions(-)
\r
87 create mode 100755 test/atomicity
\r
88 create mode 100644 test/atomicity.gdb
\r
90 diff --git a/test/atomicity b/test/atomicity
\r
91 new file mode 100755
\r
92 index 0000000..b7ae505
\r
94 +++ b/test/atomicity
\r
97 +test_description='atomicity'
\r
100 +# This script tests the effects of killing and restarting "notmuch
\r
101 +# new" at arbitrary points. If notmuch new is properly atomic, the
\r
102 +# final database contents should be the same regardless of when (or
\r
103 +# if) it is killed and restarted.
\r
105 +# Create a maildir structure to also stress flag synchronization
\r
106 +mkdir $MAIL_DIR/cur
\r
107 +mkdir $MAIL_DIR/new
\r
108 +mkdir $MAIL_DIR/tmp
\r
109 +mkdir $MAIL_DIR/.remove-dir
\r
111 +# Prepare the initial database
\r
112 +generate_message [subject]='Duplicate' [filename]='duplicate:2,' [dir]=cur
\r
113 +generate_message [subject]='Remove' [filename]='remove:2,' [dir]=cur
\r
114 +generate_message [subject]='"Remove duplicate"' [filename]='remove-duplicate:2,' [dir]=cur
\r
115 +cp $MAIL_DIR/cur/remove-duplicate:2, $MAIL_DIR/cur/remove-duplicate-copy:2,
\r
116 +generate_message [subject]='Rename' [filename]='rename:2,' [dir]=cur
\r
117 +generate_message [subject]='"Rename duplicate"' [filename]='rename-duplicate:2,' [dir]=cur
\r
118 +generate_message [subject]='"Move 1"' [filename]='move1:2,' [dir]=cur
\r
119 +generate_message [subject]='"Move 2"' [filename]='move2:2,' [dir]=new
\r
120 +generate_message [subject]='Flag' [filename]='flag:2,' [dir]=cur
\r
121 +generate_message [subject]='"Flag duplicate"' [filename]='flag-duplicate:2,' [dir]=cur
\r
122 +cp $MAIL_DIR/cur/flag-duplicate:2, $MAIL_DIR/cur/flag-duplicate-copy:2,F
\r
123 +generate_message [subject]='"Remove directory"' [filename]='remove-directory:2,' [dir]=.remove-dir
\r
124 +generate_message [subject]='"Remove directory duplicate"' [filename]='remove-directory-duplicate:2,' [dir]=.remove-dir
\r
125 +cp $MAIL_DIR/.remove-dir/remove-directory-duplicate:2, $MAIL_DIR/cur/
\r
126 +notmuch new > /dev/null
\r
128 +# Make all maildir changes, but *don't* update the database
\r
129 +generate_message [subject]='Added' [filename]='added:2,' [dir]=cur
\r
130 +cp $MAIL_DIR/cur/duplicate:2, $MAIL_DIR/cur/duplicate-copy:2,
\r
131 +generate_message [subject]='"Add duplicate"' [filename]='add-duplicate:2,' [dir]=cur
\r
132 +generate_message [subject]='"Add duplicate copy"' [filename]='add-duplicate-copy:2,' [dir]=cur
\r
133 +rm $MAIL_DIR/cur/remove:2,
\r
134 +rm $MAIL_DIR/cur/remove-duplicate-copy:2,
\r
135 +mv $MAIL_DIR/cur/rename:2, $MAIL_DIR/cur/renamed:2,
\r
136 +mv $MAIL_DIR/cur/rename-duplicate:2, $MAIL_DIR/cur/renamed-duplicate:2,
\r
137 +mv $MAIL_DIR/cur/move1:2, $MAIL_DIR/new/move1:2,
\r
138 +mv $MAIL_DIR/new/move2:2, $MAIL_DIR/cur/move2:2,
\r
139 +mv $MAIL_DIR/cur/flag:2, $MAIL_DIR/cur/flag:2,F
\r
140 +rm $MAIL_DIR/cur/flag-duplicate-copy:2,F
\r
141 +rm $MAIL_DIR/.remove-dir/remove-directory:2,
\r
142 +rm $MAIL_DIR/.remove-dir/remove-directory-duplicate:2,
\r
143 +rmdir $MAIL_DIR/.remove-dir
\r
144 +increment_mtime $MAIL_DIR/cur
\r
145 +increment_mtime $MAIL_DIR/new
\r
146 +increment_mtime $MAIL_DIR
\r
148 +# Prepare a snapshot of the updated maildir. The gdb script will
\r
149 +# update the database in this snapshot as it goes.
\r
150 +cp -ra $MAIL_DIR $MAIL_DIR.snap
\r
151 +cp ${NOTMUCH_CONFIG} ${NOTMUCH_CONFIG}.snap
\r
152 +NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap notmuch config set database.path $MAIL_DIR.snap
\r
155 +test_begin_subtest '"notmuch new" is idempotent under arbitrary aborts'
\r
157 +# Execute notmuch new and, at every call to rename, snapshot the
\r
158 +# database, run notmuch new again on the snapshot, and capture the
\r
159 +# results of search.
\r
161 +gdb -batch -x ../atomicity.gdb notmuch > /dev/null 2>&1
\r
163 +# Get the final, golden output
\r
164 +notmuch search '*' > expected
\r
166 +# Check output against golden output
\r
167 +outcount=$(cat outcount)
\r
168 +echo -n > searchall
\r
169 +echo -n > expectall
\r
170 +for ((i = 0; i < $outcount; i++)); do
\r
171 + if ! cmp -s search.$i expected; then
\r
172 + # Find the range of interruptions that match this output
\r
173 + for ((end = $i + 1 ; end < $outcount; end++)); do
\r
174 + if ! cmp -s search.$i search.$end; then
\r
178 + echo "When interrupted after $test/backtrace.$(expr $i - 1) (abort points $i-$(expr $end - 1))" >> searchall
\r
179 + cat search.$i >> searchall
\r
180 + cat expected >> expectall
\r
181 + echo >> searchall
\r
182 + echo >> expectall
\r
184 + i=$(expr $end - 1)
\r
187 +test_expect_equal_failure "$(cat searchall)" "$(cat expectall)"
\r
189 +test_expect_success "detected $outcount>10 abort points" "test $outcount -gt 10"
\r
192 diff --git a/test/atomicity.gdb b/test/atomicity.gdb
\r
193 new file mode 100644
\r
194 index 0000000..fd67525
\r
196 +++ b/test/atomicity.gdb
\r
198 +# This gdb script runs notmuch new and simulates killing and
\r
199 +# restarting notmuch new after every Xapian commit. To simulate this
\r
200 +# more efficiently, this script runs notmuch new and, immediately
\r
201 +# after every Xapian commit, it *pauses* the running notmuch new,
\r
202 +# copies the entire database and maildir to a snapshot directory, and
\r
203 +# executes a full notmuch new on that snapshot, comparing the final
\r
204 +# results with the expected output. It can then resume the paused
\r
205 +# notmuch new, which is still running on the original maildir, and
\r
206 +# repeat this process.
\r
210 +# Make Xapian commit after every operation instead of batching
\r
211 +set environment XAPIAN_FLUSH_THRESHOLD = 1
\r
213 +# gdb can't keep track of a simple integer. This is me weeping.
\r
214 +shell echo 0 > outcount
\r
216 +shell touch inodes
\r
220 +# As an optimization, only consider snapshots after a Xapian commit.
\r
221 +# Xapian overwrites record.base? as the last step in the commit.
\r
222 +shell echo > gdbcmd
\r
223 +shell stat -c %i $MAIL_DIR/.notmuch/xapian/record.base* > inodes.new
\r
224 +shell if cmp inodes inodes.new; then echo cont > gdbcmd; fi
\r
225 +shell mv inodes.new inodes
\r
228 +# Save a backtrace in case the test does fail
\r
229 +set logging file backtrace
\r
233 +shell mv backtrace backtrace.`cat outcount`
\r
235 +# Snapshot the database
\r
236 +shell rm -r $MAIL_DIR.snap/.notmuch
\r
237 +shell cp -r $MAIL_DIR/.notmuch $MAIL_DIR.snap/.notmuch
\r
238 +# Restore the mtime of $MAIL_DIR.snap, which we just changed
\r
239 +shell touch -r $MAIL_DIR $MAIL_DIR.snap
\r
240 +# Run notmuch new to completion on the snapshot
\r
241 +shell NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap XAPIAN_FLUSH_THRESHOLD=1000 notmuch new > /dev/null
\r
242 +shell NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap notmuch search '*' > search.`cat outcount` 2>&1
\r
243 +shell echo $(expr $(cat outcount) + 1) > outcount
\r
248 diff --git a/test/basic b/test/basic
\r
249 index 3b43ad9..f9d5fc3 100755
\r
252 @@ -57,7 +57,9 @@ available=$(ls -1 ../ | \
\r
253 sed -r -e "/^(aggregate-results.sh|Makefile|Makefile.local|notmuch-test)/d" \
\r
254 -e "/^(README|test-lib.sh|test-results|tmp.*|valgrind|corpus*)/d" \
\r
255 -e "/^(emacs.expected-output|smtp-dummy|smtp-dummy.c|test-verbose)/d" \
\r
256 - -e "/^(test.expected-output|.*~)/d" | sort)
\r
257 + -e "/^(test.expected-output|.*~)/d" \
\r
258 + -e "/^(atomicity.gdb)/d" \
\r
260 test_expect_equal "$tests_in_suite" "$available"
\r
262 EXPECTED=../test.expected-output
\r
263 diff --git a/test/notmuch-test b/test/notmuch-test
\r
264 index 8dd9c1e..5b22fa8 100755
\r
265 --- a/test/notmuch-test
\r
266 +++ b/test/notmuch-test
\r
267 @@ -38,6 +38,7 @@ TESTS="
\r
269 emacs-large-search-buffer
\r
274 # Clean up any results from a previous run
\r