As Daniel Kahn Gillmor <dkg@fifthhorseman.net> reports in
id:87d1ngv95p.fsf@alice.fifthhorseman.net, notmuch show combines
multiple Cc: fields into one, while notmuch reply does not. While such
messages are in violation of RFC 5322, it would be reasonable to
expect notmuch to be consistent. Add a known broken test to document
this expectation.
This also starts a new "broken" corpus for messages which are broken.
Details:
The original message is formatted using the message printing in
notmuch-show.c. For Cc:, it uses g_mime_message_get_recipients(),
which apparently combines all Cc: fields into one internally.
The addresses in the reply headers, OTOH, are based on headers queried
through libnotmuch. It boils down to g_mime_object_get_header() in
lib/message-file.c, which returns only the first occurence of header.
We largely use the corpus under test/corpus for
testing. Unfortunately, many of our tests have grown to depend on
having exactly this set of messages, making it hard to add new message
files for testing specific cases.
We do use a lot of add_message from within the tests, but it's not
possible to use that for adding broken messages, and adding several
messages at once can get unwieldy.
Move the basic corpus under tests/corpora/default, and make it
possible to add new, independent corpora along its side. This means
tons of renames with a few tweaks to add_email_corpus function in
test-lib.sh to let tests specify which corpus to use.
Originally the intent was to make the test more robust against changing
test keys. It turns out that (unscientifically) gpg --with-colons output
changes more often than our test key. Rather than making the script more
complex, just hard code the fingerprint.
This fixes Debian bug #847013; I expect similar test failures as other
distros adopt gnupg 2.1.15
With all the preparation it is now simple to add the actual insert
code. Since insert can fail for many reasons we let the user decide
interactively deal with it.
We modify test-lib.el to set file fcc, so that all the old tests and
emacs_fcc_message from test-lib.sh still work
gdb sometimes writes warnings to stdout, which we don't need/want, and
for some reason --batch-silent isn't enough to hide. So in this commit
we write them to a log file, which is probably better for debugging
anyway. To see an illustrative test failure before this change, run
% make
% touch notmuch-count.c
% cd test && ./T060-count.sh
(cherry picked from commit f45fa5bdd3)
The User-Agent: header can be fun and interesting, but it also leaks
quite a bit of information about the user and their software stack.
This represents a potential security risk (attackers can target the
particular stack) and also an anonymity risk (a user trying to
preserve their anonymity by sending mail from a non-associated account
might reveal quite a lot of information if their choice of mail user
agent is exposed).
This change also avoids hiding the User-Agent header by default, so
that people who decide they want to send it will at least see it (and
can edit it if they want to) before sending.
It makes sense to have safer defaults.
Previously notmuch-wash made the width of the text (approximately) the
window-width minus the depth in thread. This is correct for the
default indentation of 1 per message depth, but is incorrect for any
other setting of notmuch-show-indent-messages-width.
As notmuch-show-indent-messages-width is customisable, and notmuch-tree
sets it to zero to avoid indenting messages in the message pane, this
bug can show up in real use.
Two of the tests had to be updated: when
notmuch-show-indent-messages-width is 0, then the new (correct) word
wrapping happens later, when notmuch-show-indent-messages-width is 4,
then the new word wrapping happens sooner.
gdb sometimes writes warnings to stdout, which we don't need/want, and
for some reason --batch-silent isn't enough to hide. So in this commit
we write them to a log file, which is probably better for debugging
anyway. To see an illustrative test failure before this change, run
% make
% touch notmuch-count.c
% cd test && ./T060-count.sh
This has been wrong since bbbdf0478e, but the race condition was not
previously been (often?) triggered in the tests. With the DB_RETRY_LOCK
patches, it manifests itself as a deadlock.
This support will be present only if the appropriate version of xapian
is available _and_ the user did not disable the feature when
building. So there really needs to be some way for the user to check.
This has been wrong since bbbdf0478e, but the race condition was not
previously been (often?) triggered in the tests. With the DB_RETRY_LOCK
patches, it manifests itself as a deadlock.
A few simple things that applies well to test/notmuch-test.sh
- Shell does pathname expansion also without doing `echo ...` in subshell.
- Redirections >/dev/null 2>/dev/null hide (improbable but) potential
serious errors; adding -f to rm instead.
- Inter-file capitalization consistency in comments.
- Unnecesary space removal.
The trick of having a common header file doesn't work to share between
test scripts, so make an include file in the test directory.
The use of #include <notmuch-test.h> looks slightly pretentious, but
the include file is not actually in the current (temporary) directory.
Place PYTHONPATH to the environment when python is executed in a way
that current shell environment is not affected. This also allows adding
the old value of PYTHONPATH to the end of the new value (otherwise it
would have been appended again and again when test_python is called).
At the same time, use -B option to avoid writing .pyc files to
bindings/python/* (which are not cleared out by distclean).
Drop the (unused) prefix code which preserved the original stdout of the
python program and opened sys.stdout to OUTPUT. In place of that there
is now note how (debug) information can be printed to original stdout.
Previously LD_LIBRARY_PATH was exported (and environment changed)
in the middle of test case execution, when a function setting it
was called.
Previously the old contents of LD_LIBRARY_PATH was lost (if any)
when it was re-set and exported. In some systems the old contents of
LD_LIBRARY_PATH was needed to e.g. locate suitable gmime library.
In scripts that include test-lib-common.sh but not test-lib.sh
the die() implementation needs to be a bit different due to
fd redirection differences. test-lib-common.sh implements die()
only if it was not implemented already.
Added die() function to test-lib.sh with the following first use of it:
If notmuch new fails during email corpus addition the database is
most probably inexistent or broken and the added corpus would be
unusable while running single tests, giving misleading failures
("only" full 'make test' cleans out old corpus).
Many of the external links found in the notmuch source can be resolved
using https instead of http. This changeset addresses as many as i
could find, without touching the e-mail corpus or expected outputs
found in tests.
Most of the infrastructure here is general, only the validation/dispatch
is hardcoded to a particular prefix.
A notable change in behaviour is that notmuch-config now opens the
database e.g. on every call to list, which fails with an error message
if the database doesn't exit yet.
Since xapian provides the ability to restrict the iterator to a given
prefix, we expose this ability to the user. Otherwise we mimic the other
iterator interfances in notmuch (e.g. tags.c).
This is a thin wrapper around the Xapian metadata API. The job of this
layer is to keep the config key value pairs from colliding with other
metadata by transparently prefixing the keys, along with the usual glue
to provide a C interface.
The split of _get_config into two functions is to allow returning of the
return value with different memory ownership semantics.
The Ruby bindings were missing a way to get all the tags of the
database. Now you should be able to access this with the public
instance method `all_tags` of your database object.
Example of use:
notmuchdb = Notmuch::Database.new path, { :create => false,
:mode => Notmuch::MODE_READ_ONLY }
my_tags = notmuchdb.all_tags
my_tags.each { |tag|
print tag
}
my_tags.destroy!
Amended by db: improve error reporting, add test
Files in test directories had only copyright of a single individual,
of which code was adapted here as a base of the test system.
Since then many Notmuch Developers have contributed to the test
system, which is now acknowledged with a constant string in some
of the test files.
The README file in test directory instructed new files contain a
copyright notice, but that has never been done (and it is also not
needed). To simplify things a bit (and lessen confusion) this
instruction is now removed.
As a side enchangement, all of the 3 entries in the whole source
tree cd'ing to `dirname` of "$0" now uses syntax cd "$(dirname "$0")".
This makes these particular lines work when current working directory
is e.g. /c/Program Files/notmuch/test/.
(Probably it would fail elsewhere, though.)
In case of notmuch reply and notmuch show --part=N it is required that
search terms match to one message. If match count was != 1, error
message "Error: search term did not match precisely one message"
was too vague to explain what happened.
By appending (matched <num> messages) to the error message it
makes the problem more understandable (e.g when <num> is '0'
user reckons the query had a typo in it).
To fully complete the ghost-on-removal-when-shared-thread-exists
proposal, we need to clear all ghost messages when the last active
message is removed from a thread.
Amended by db: Remove the last test of T530, as it no longer makes sense
if we are garbage collecting ghost messages.
implement ghost-on-removal, the solution to T590-thread-breakage.sh
that just adds a ghost message after removing each message.
It leaks information about whether we've ever seen a given message id,
but it's a fairly simple implementation.
Note that _resolve_message_id_to_thread_id already introduces new
message_ids to the database, so i think just searching for a given
message ID may introduce the same metadata leakage.
This test (T590-thread-breakage.sh) has known-broken subtests.
If you have a two-message thread where message "B" is in-reply-to "A",
notmuch rightly sees this as a single thread.
But if you:
* remove "A" from the message store
* run "notmuch new"
* add "A" back into the message store
* re-run "notmuch new"
Then notmuch sees the messages as distinct threads.
This happens because if you insert "B" initially (before anything is
known about "A"), then a "ghost message" gets added to the database in
reference to "A" that is in the same thread, which "A" takes over when
it appears.
But if "A" is subsequently removed, no ghost message is retained, so
when "A" appears, it is treated as a new thread.
I see a few options to fix this:
ghost-on-removal
----------------
We could unilaterally add a ghost upon message removal. This has a
few disadvantages: the message index would leak information about what
messages the user has ever been exposed to, and we also create a
perpetually-growing dataset -- the ghosts can never be removed.
ghost-on-removal-when-shared-thread-exists
------------------------------------------
We could add a ghost upon message removal iff there are other
non-ghost messages with the same thread ID.
We'd also need to remove all ghost messages that share a thread when
the last non-ghost message in that thread is removed.
This still has a bit of information leakage, though: the message index
would reveal that i've seen a newer message in a thread, even if i had
deleted it from my message store
track-dependencies
------------------
rather than a simple "ghost-message" we could store all the (A,B)
message-reference pairs internally, showing which messages A reference
which other messages B.
Then removal of message X would require deleting all message-reference
pairs (X,B), and only deleting a ghost message if no (A,X) reference
pair exists.
This requires modifying the database by adding a new and fairly weird
table that would need to be indexed by both columns. I don't know
whether xapian has nice ways to do that.
scan-dependencies
-----------------
Without modifying the database, we could do something less efficient.
Upon removal of message X, we could scan the headers of all non-ghost
messages that share a thread with X. If any of those messages refers
to X, we would add a ghost message. If none of them do, then we would
just drop X entirely from the table.
---------------------
One risk of attempted fixes to this problem is that we could fail to
remove the search term indexes entirely. This test contains
additional subtests to guard against that.
This test also ensures that the right number of ghost messages exist
in each situation; this will help us ensure we don't accumulate ghosts
indefinitely or leak too much information about what messages we've
seen or not seen, while still making it easy to reassemble threads
when messages come in out-of-order.
The code to skip multiple slashes in _notmuch_database_split_path()
skips back one character too much. This is compensated by a +1 in the
length parameter to the strndup() call. Mostly this works fine, but if
the path is to a file under a top level directory with one character
long name, the directory part is mistaken to be part of the file name
(slash == path in code). The returned directory name will be the empty
string and the basename will be the full path, breaking the indexing
logic in notmuch new.
Fix the multiple slash skipping to keep the slash variable pointing at
the last slash, and adjust strndup() accordingly.
The bug was introduced in
commit e890b0cf40
Author: Carl Worth <cworth@cworth.org>
Date: Sat Dec 19 13:20:26 2009 -0800
database: Store the parent ID for each directory document.
just a little over two months after the initial commit in the Notmuch
code history, making this the longest living bug in Notmuch to date.
In several places in the test suite we intentionally corrupt the Xapian
database in order to test error handling. This corruption is specific to
the on-disk organization of the database, and that changed with the
glass backend. We use the previously computed default backend to make
the tests adapt to changing names.
This is mainly for the test suite. We already expect the tests to be
run in the same environment as configure was run, at least to get the
name of the python interpreter. So we are not really imposing a new
restriction.
This should potentially be updated to have an equivalent optimization
for the glass backend, but it in my unscientific tests, the glass backend
without the optimization is faster then the chert backend with.
When no decryption or signature examination is
happening (i.e. `notmuch-crypto-process-mime' is `nil') insert buttons
that indicate this, rather than remaining silent.
in d27d90875d (2016-02-20) notmuch-mua-reply-insert-header-p-function
was set to notmuch-show-reply-insert-header-p-never as its default was
changed to something else. Now that default is set back to *-never so
this change done in d27d90875d is not needed anymore.
We only need a long string, not a single long term to trigger batch
mode. The giant term triggers a bug/incompatibility in Xapian 1.3.4
that throws an exception because it is longer than the Xapian term size
limit.
Move the brief help text at the bottom of the hello screen to the
notmuch-hello-mode help, and promote '?' as the universal help key
across Notmuch. This unclutters the hello screen, and allows for a
more verbose description in the mode help. Hopefully, this change is
useful for both experienced and new users alike.
While at it, improve the links to Notmuch and hello screen
customization.
A while ago test script names were changed to format
Tddd-basename.sh. Update README to reflect that.
While at it, included some small requirements updates.
Add a customizable function specifying which parts get a header when
replying, and give some sensible possiblities. These are,
1) all parts except multipart/*. (Subparts of a multipart part do
receive a header button.)
2) only included text/* parts.
3) Exactly as in the show buffer.
4) None at all. This means the reply contains a mish-mash of all the
original message's parts.
In the test suite we set the choice to option 4 to match the
previous behaviour.
Use the message display code to generate message text to cite in
replies.
For now we set insert-headers-p function to
notmuch-show-reply-insert-header-p-never so that, as before, we don't
insert part buttons.
With that choice of insert-headers-p function there is only one
failing test: this test has a text part (an email message) listed as
application/octet-stream. Notmuch show displays this part, but the
reply code omitted it as it had type application/octet-stream. The new
code correctly includes it. Thus update the expected output to match.