* [PATCH] test: Port atomicity test to Python
@ 2014-10-03 16:58 Austin Clements
2014-10-03 17:00 ` Austin Clements
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Austin Clements @ 2014-10-03 16:58 UTC (permalink / raw)
To: notmuch; +Cc: Austin Clements
Previously, this was implemented using a horrible GDB script (because
there is no such thing as a non-horrible GDB script). This GDB script
often broke with newer versions of GDB for mysterious reasons. Port
the test script to GDB's Python API, which makes the code much cleaner
and, hopefully, more stable.
---
Hi Amadeusz. Does this patch fix the problem for you? I don't have
GDB 7.8, so I can't test against it, but the Python interface is less
fragile than the GDB scripting language. (Even if this doesn't fix
your problem, I think we should switch to the Python interface.)
test/T380-atomicity.sh | 2 +-
test/atomicity.gdb | 54 --------------------------------------
test/atomicity.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 55 deletions(-)
delete mode 100644 test/atomicity.gdb
create mode 100644 test/atomicity.py
diff --git a/test/T380-atomicity.sh b/test/T380-atomicity.sh
index 2daef90..ee1e2f4 100755
--- a/test/T380-atomicity.sh
+++ b/test/T380-atomicity.sh
@@ -64,7 +64,7 @@ if test_require_external_prereq gdb; then
# -tty /dev/null works around a conflict between the 'timeout' wrapper
# and gdb's attempt to control the TTY.
export MAIL_DIR
- gdb -tty /dev/null -batch -x $TEST_DIRECTORY/atomicity.gdb notmuch 1>gdb.out 2>&1
+ gdb -tty /dev/null -batch -x $TEST_DIRECTORY/atomicity.py notmuch 1>gdb.out 2>&1
# Get the final, golden output
notmuch search '*' > expected
diff --git a/test/atomicity.gdb b/test/atomicity.gdb
deleted file mode 100644
index 15adb16..0000000
--- a/test/atomicity.gdb
+++ /dev/null
@@ -1,54 +0,0 @@
-# This gdb script runs notmuch new and simulates killing and
-# restarting notmuch new after every Xapian commit. To simulate this
-# more efficiently, this script runs notmuch new and, immediately
-# after every Xapian commit, it *pauses* the running notmuch new,
-# copies the entire database and maildir to a snapshot directory, and
-# executes a full notmuch new on that snapshot, comparing the final
-# results with the expected output. It can then resume the paused
-# notmuch new, which is still running on the original maildir, and
-# repeat this process.
-
-set args new
-
-# Make Xapian commit after every operation instead of batching
-set environment XAPIAN_FLUSH_THRESHOLD = 1
-
-# gdb can't keep track of a simple integer. This is me weeping.
-shell echo 0 > outcount
-
-shell touch inodes
-
-# work around apparent issue with lazy library loading on some
-# platforms
-set breakpoint pending on
-
-break rename
-commands
-# As an optimization, only consider snapshots after a Xapian commit.
-# Xapian overwrites record.base? as the last step in the commit.
-shell echo > gdbcmd
-shell stat -c %i $MAIL_DIR/.notmuch/xapian/record.base* > inodes.new
-shell if cmp inodes inodes.new; then echo cont > gdbcmd; fi
-shell mv inodes.new inodes
-source gdbcmd
-
-# Save a backtrace in case the test does fail
-set logging file backtrace
-set logging on
-backtrace
-set logging off
-shell mv backtrace backtrace.`cat outcount`
-
-# Snapshot the database
-shell rm -r $MAIL_DIR.snap/.notmuch
-shell cp -r $MAIL_DIR/.notmuch $MAIL_DIR.snap/.notmuch
-# Restore the mtime of $MAIL_DIR.snap, which we just changed
-shell touch -r $MAIL_DIR $MAIL_DIR.snap
-# Run notmuch new to completion on the snapshot
-shell NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap XAPIAN_FLUSH_THRESHOLD=1000 notmuch new > /dev/null
-shell NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap notmuch search '*' > search.`cat outcount` 2>&1
-shell echo $(expr $(cat outcount) + 1) > outcount
-cont
-end
-
-run
diff --git a/test/atomicity.py b/test/atomicity.py
new file mode 100644
index 0000000..01a4205
--- /dev/null
+++ b/test/atomicity.py
@@ -0,0 +1,71 @@
+# This gdb Python script runs notmuch new and simulates killing and
+# restarting notmuch new after every Xapian commit. To simulate this
+# more efficiently, this script runs notmuch new and, immediately
+# after every Xapian commit, it *pauses* the running notmuch new,
+# copies the entire database and maildir to a snapshot directory, and
+# executes a full notmuch new on that snapshot, comparing the final
+# results with the expected output. It can then resume the paused
+# notmuch new, which is still running on the original maildir, and
+# repeat this process.
+
+import gdb
+import os
+import glob
+import shutil
+import subprocess
+
+gdb.execute('set args new')
+
+# Make Xapian commit after every operation instead of batching
+gdb.execute('set environment XAPIAN_FLUSH_THRESHOLD = 1')
+
+maildir = os.environ['MAIL_DIR']
+
+# Trap calls to rename, which happens just before Xapian commits
+class RenameBreakpoint(gdb.Breakpoint):
+ def __init__(self, *args, **kwargs):
+ super(RenameBreakpoint, self).__init__(*args, **kwargs)
+ self.last_inodes = {}
+ self.n = 0
+
+ def stop(self):
+ # As an optimization, only consider snapshots after a Xapian
+ # has really committed. Xapian overwrites record.base? as the
+ # last step in the commit, so keep an eye on their inumbers.
+ inodes = {}
+ for path in glob.glob('%s/.notmuch/xapian/record.base*' % maildir):
+ inodes[path] = os.stat(path).st_ino
+ if inodes == self.last_inodes:
+ # Continue
+ return False
+ self.last_inodes = inodes
+
+ # Save a backtrace in case the test does fail
+ backtrace = gdb.execute('backtrace', to_string=True)
+ open('backtrace.%d' % self.n, 'w').write(backtrace)
+
+ # Snapshot the database
+ shutil.rmtree('%s.snap/.notmuch' % maildir)
+ shutil.copytree('%s/.notmuch' % maildir, '%s.snap/.notmuch' % maildir)
+ # Restore the mtime of $MAIL_DIR.snap/
+ shutil.copystat('%s/.notmuch' % maildir, '%s.snap/.notmuch' % maildir)
+
+ # Run notmuch new to completion on the snapshot
+ env = os.environ.copy()
+ env.update(NOTMUCH_CONFIG=os.environ['NOTMUCH_CONFIG'] + '.snap',
+ XAPIAN_FLUSH_THRESHOLD='1000')
+ subprocess.check_call(
+ ['notmuch', 'new'], env=env, stdout=open('/dev/null', 'w'))
+ subprocess.check_call(
+ ['notmuch', 'search', '*'], env=env,
+ stdout=open('search.%d' % self.n, 'w'))
+
+ # Tell the shell how far we've gotten
+ open('outcount', 'w').write(str(self.n + 1))
+
+ # Continue
+ self.n += 1
+ return False
+RenameBreakpoint('rename')
+
+gdb.execute('run')
--
2.1.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] test: Port atomicity test to Python
2014-10-03 16:58 [PATCH] test: Port atomicity test to Python Austin Clements
@ 2014-10-03 17:00 ` Austin Clements
2014-10-04 6:37 ` David Bremner
2014-10-05 5:33 ` David Bremner
2 siblings, 0 replies; 4+ messages in thread
From: Austin Clements @ 2014-10-03 17:00 UTC (permalink / raw)
To: notmuch
On Fri, 03 Oct 2014, Austin Clements <aclements@csail.mit.edu> wrote:
> Previously, this was implemented using a horrible GDB script (because
> there is no such thing as a non-horrible GDB script). This GDB script
> often broke with newer versions of GDB for mysterious reasons. Port
> the test script to GDB's Python API, which makes the code much cleaner
> and, hopefully, more stable.
> ---
>
> Hi Amadeusz. Does this patch fix the problem for you? I don't have
> GDB 7.8, so I can't test against it, but the Python interface is less
> fragile than the GDB scripting language. (Even if this doesn't fix
> your problem, I think we should switch to the Python interface.)
Oops. I meant this to be a reply to
id:87sijovhuf.fsf@freja.aidecoe.name. Sorry for any confusion.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] test: Port atomicity test to Python
2014-10-03 16:58 [PATCH] test: Port atomicity test to Python Austin Clements
2014-10-03 17:00 ` Austin Clements
@ 2014-10-04 6:37 ` David Bremner
2014-10-05 5:33 ` David Bremner
2 siblings, 0 replies; 4+ messages in thread
From: David Bremner @ 2014-10-04 6:37 UTC (permalink / raw)
To: Austin Clements, notmuch; +Cc: Austin Clements
Austin Clements <aclements@csail.mit.edu> writes:
>
> Hi Amadeusz. Does this patch fix the problem for you? I don't have
> GDB 7.8, so I can't test against it, but the Python interface is less
> fragile than the GDB scripting language. (Even if this doesn't fix
> your problem, I think we should switch to the Python interface.)
I can confirm this new version runs with gdb 7.8 (and python3) on
debian. I also runs with gdb 7.7.1+dfsg-3 and python2.
> + shutil.copytree('%s/.notmuch' % maildir, '%s.snap/.notmuch' % maildir)
I hesitate to have an opinion on python style, but for whatever reason I
have a mild preference for str.format(args) versus str % args. Not
enough of a preference to redo the patch.
I also agree that this version is easier to follow than the one it
replaces.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] test: Port atomicity test to Python
2014-10-03 16:58 [PATCH] test: Port atomicity test to Python Austin Clements
2014-10-03 17:00 ` Austin Clements
2014-10-04 6:37 ` David Bremner
@ 2014-10-05 5:33 ` David Bremner
2 siblings, 0 replies; 4+ messages in thread
From: David Bremner @ 2014-10-05 5:33 UTC (permalink / raw)
To: Austin Clements, notmuch
Austin Clements <aclements@csail.mit.edu> writes:
> Previously, this was implemented using a horrible GDB script (because
> there is no such thing as a non-horrible GDB script). This GDB script
> often broke with newer versions of GDB for mysterious reasons. Port
> the test script to GDB's Python API, which makes the code much cleaner
> and, hopefully, more stable.
pushed,
d
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-10-05 5:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-03 16:58 [PATCH] test: Port atomicity test to Python Austin Clements
2014-10-03 17:00 ` Austin Clements
2014-10-04 6:37 ` David Bremner
2014-10-05 5:33 ` David Bremner
Code repositories for project(s) associated with this public inbox
https://yhetil.org/notmuch.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).